2 // System.Runtime.Remoting.Channels.Ipc.Win32.NamedPipeSocket.cs
4 // Author: Robert Jordan (robertj@gmx.net)
6 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Runtime.InteropServices;
34 using System.Runtime.Remoting.Messaging;
37 namespace System.Runtime.Remoting.Channels.Ipc.Win32
40 /// Implements a local Named Pipe socket.
42 internal class NamedPipeSocket : IDisposable
47 /// Creates a new socket instance form the specified local Named Pipe handle.
49 /// <param name="hPipe">The handle.</param>
50 internal NamedPipeSocket(IntPtr hPipe)
53 this.info = new NamedPipeSocketInfo(hPipe);
58 ((IDisposable)this).Dispose();
62 /// Gets the NamedPipeSocketInfo of this instance.
64 /// <returns></returns>
65 public NamedPipeSocketInfo Info
73 NamedPipeSocketInfo info;
76 /// Closes the socket.
80 ((IDisposable)this).Dispose();
84 /// Disposes the object.
86 void IDisposable.Dispose()
88 if (hPipe != IntPtr.Zero)
92 // disconnect the pipe
95 NamedPipeHelper.FlushFileBuffers(hPipe);
96 NamedPipeHelper.DisconnectNamedPipe(hPipe);
99 catch (NamedPipeException)
103 NamedPipeHelper.CloseHandle(hPipe);
105 GC.SuppressFinalize(this);
110 /// Returns the stream used to send and receive data.
112 /// <returns></returns>
113 public Stream GetStream()
115 if (hPipe == IntPtr.Zero)
116 throw new ObjectDisposedException(GetType().FullName);
118 return stream == null
119 ? stream = new NamedPipeStream(this, false)
126 /// Returns the stream used to send and receive data. The stream disposes
127 /// the socket on close.
129 /// <returns></returns>
130 public Stream GetClosingStream()
132 if (hPipe == IntPtr.Zero)
133 throw new ObjectDisposedException(GetType().FullName);
135 return new NamedPipeStream(this, true);
139 /// Flushes the socket.
143 if (hPipe == IntPtr.Zero)
144 throw new ObjectDisposedException(GetType().FullName);
146 NamedPipeHelper.FlushFileBuffers(hPipe);
150 /// Receives the specified number of bytes from a socket into
151 /// the specified offset position of the receive buffer.
153 /// <param name="buffer">An array of type Byte that is the storage
154 /// location for received data.</param>
155 /// <param name="offset">The location in buffer to store the received data.</param>
156 /// <param name="count">The number of bytes to receive.</param>
157 /// <returns>The number of bytes received.</returns>
158 public int Receive(byte[] buffer, int offset, int count)
160 if (hPipe == IntPtr.Zero)
161 throw new ObjectDisposedException(GetType().FullName);
163 throw new ArgumentNullException("buffer");
164 if (offset < 0 || count < 0)
165 throw new ArgumentOutOfRangeException("offset and/or count");
166 if (buffer.Length - offset < count)
167 throw new ArgumentException();
171 GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
174 bool res = NamedPipeHelper.ReadFile(
176 Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset),
182 if (!res && read == 0) throw new NamedPipeException();
192 delegate int ReceiveMethod(byte[] buffer, int offset, int count);
194 public IAsyncResult BeginReceive(byte[] buffer, int offset, int count,
195 AsyncCallback callback, object state)
197 return new ReceiveMethod(Receive).BeginInvoke(buffer, offset, count, callback, state);
200 public int EndReceive(IAsyncResult asyncResult)
202 AsyncResult ar = asyncResult as AsyncResult;
203 return ((ReceiveMethod)ar.AsyncDelegate).EndInvoke(asyncResult);
207 /// Sends the specified number of bytes of data to a connected socket,
208 /// starting at the specified offset.
210 /// <param name="buffer">An array of type Byte that contains the data to be sent.</param>
211 /// <param name="offset">The position in the data buffer at which to begin sending data. </param>
212 /// <param name="count">The number of bytes to send.</param>
213 /// <returns>The number of bytes sent.</returns>
214 public int Send(byte[] buffer, int offset, int count)
216 if (hPipe == IntPtr.Zero)
217 throw new ObjectDisposedException(GetType().FullName);
219 throw new ArgumentNullException("buffer");
220 if (offset < 0 || count < 0)
221 throw new ArgumentOutOfRangeException("offset and/or count");
222 if (buffer.Length - offset < count)
223 throw new ArgumentException();
227 GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
230 bool res = NamedPipeHelper.WriteFile(
232 Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset),
238 if (!res) throw new NamedPipeException();
239 return (int) written;
247 delegate int SendMethod(byte[] buffer, int offset, int count);
249 public IAsyncResult BeginSend(byte[] buffer, int offset, int count,
250 AsyncCallback callback, object state)
252 return new SendMethod(Send).BeginInvoke(buffer, offset, count, callback, state);
255 public int EndSend(IAsyncResult asyncResult)
257 AsyncResult ar = asyncResult as AsyncResult;
258 return ((SendMethod)ar.AsyncDelegate).EndInvoke(asyncResult);
262 /// Returns the current NamedPipeSocketState of this instance.
264 /// <returns></returns>
265 public NamedPipeSocketState GetSocketState()
267 if (hPipe == IntPtr.Zero)
268 throw new ObjectDisposedException(GetType().FullName);
270 return new NamedPipeSocketState(hPipe);
274 /// Impersonates the client.
276 public void Impersonate()
278 if (hPipe == IntPtr.Zero)
279 throw new ObjectDisposedException(GetType().FullName);
282 if (!NamedPipeHelper.ImpersonateNamedPipeClient(hPipe))
283 throw new NamedPipeException();
287 /// Reverts the impersonation.
289 public static bool RevertToSelf()
291 return NamedPipeHelper.RevertToSelf();
298 /// Represents local Named Pipe informations.
300 internal class NamedPipeSocketInfo
302 public readonly int Flags;
303 public readonly int OutBufferSize;
304 public readonly int InBufferSize;
305 public readonly int MaxInstances;
311 return (Flags & NamedPipeHelper.PIPE_SERVER_END) != 0;
315 internal NamedPipeSocketInfo(IntPtr hPipe)
317 bool res = NamedPipeHelper.GetNamedPipeInfo(
327 throw new NamedPipeException();
334 /// Represents local Named Pipe state informations.
336 internal class NamedPipeSocketState
338 public readonly int State;
339 public readonly int CurrentInstances;
340 public readonly int MaxCollectionCount;
341 public readonly int CollectDataTimeout;
342 public readonly string UserName;
344 internal NamedPipeSocketState(IntPtr hPipe)
346 StringBuilder userName = new StringBuilder(256);
347 bool res = NamedPipeHelper.GetNamedPipeHandleState(
350 out CurrentInstances,
351 out MaxCollectionCount,
352 out CollectDataTimeout,
359 UserName = userName.ToString();
363 throw new NamedPipeException();