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.
32 using System.Runtime.InteropServices;
33 using System.Runtime.Remoting.Messaging;
36 namespace System.Runtime.Remoting.Channels.Ipc.Win32
39 /// Implements a local Named Pipe socket.
41 internal class NamedPipeSocket : IDisposable
46 /// Creates a new socket instance form the specified local Named Pipe handle.
48 /// <param name="hPipe">The handle.</param>
49 internal NamedPipeSocket(IntPtr hPipe)
52 this.info = new NamedPipeSocketInfo(hPipe);
57 ((IDisposable)this).Dispose();
61 /// Gets the NamedPipeSocketInfo of this instance.
63 /// <returns></returns>
64 public NamedPipeSocketInfo Info
72 NamedPipeSocketInfo info;
75 /// Closes the socket.
79 ((IDisposable)this).Dispose();
83 /// Disposes the object.
85 void IDisposable.Dispose()
87 if (hPipe != IntPtr.Zero)
91 // disconnect the pipe
94 NamedPipeHelper.FlushFileBuffers(hPipe);
95 NamedPipeHelper.DisconnectNamedPipe(hPipe);
98 catch (NamedPipeException)
102 NamedPipeHelper.CloseHandle(hPipe);
104 GC.SuppressFinalize(this);
109 /// Returns the stream used to send and receive data.
111 /// <returns></returns>
112 public Stream GetStream()
114 if (hPipe == IntPtr.Zero)
115 throw new ObjectDisposedException(GetType().FullName);
117 return stream == null
118 ? stream = new NamedPipeStream(this, false)
125 /// Returns the stream used to send and receive data. The stream disposes
126 /// the socket on close.
128 /// <returns></returns>
129 public Stream GetClosingStream()
131 if (hPipe == IntPtr.Zero)
132 throw new ObjectDisposedException(GetType().FullName);
134 return new NamedPipeStream(this, true);
138 /// Flushes the socket.
142 if (hPipe == IntPtr.Zero)
143 throw new ObjectDisposedException(GetType().FullName);
145 NamedPipeHelper.FlushFileBuffers(hPipe);
149 /// Receives the specified number of bytes from a socket into
150 /// the specified offset position of the receive buffer.
152 /// <param name="buffer">An array of type Byte that is the storage
153 /// location for received data.</param>
154 /// <param name="offset">The location in buffer to store the received data.</param>
155 /// <param name="count">The number of bytes to receive.</param>
156 /// <returns>The number of bytes received.</returns>
157 public int Receive(byte[] buffer, int offset, int count)
159 if (hPipe == IntPtr.Zero)
160 throw new ObjectDisposedException(GetType().FullName);
162 throw new ArgumentNullException("buffer");
163 if (offset < 0 || count < 0)
164 throw new ArgumentOutOfRangeException("offset and/or count");
165 if (buffer.Length - offset < count)
166 throw new ArgumentException();
170 GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
173 bool res = NamedPipeHelper.ReadFile(
175 Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset),
181 if (!res && read == 0) throw new NamedPipeException();
191 delegate int ReceiveMethod(byte[] buffer, int offset, int count);
193 public IAsyncResult BeginReceive(byte[] buffer, int offset, int count,
194 AsyncCallback callback, object state)
196 return new ReceiveMethod(Receive).BeginInvoke(buffer, offset, count, callback, state);
199 public int EndReceive(IAsyncResult asyncResult)
201 AsyncResult ar = asyncResult as AsyncResult;
202 return ((ReceiveMethod)ar.AsyncDelegate).EndInvoke(asyncResult);
206 /// Sends the specified number of bytes of data to a connected socket,
207 /// starting at the specified offset.
209 /// <param name="buffer">An array of type Byte that contains the data to be sent.</param>
210 /// <param name="offset">The position in the data buffer at which to begin sending data. </param>
211 /// <param name="count">The number of bytes to send.</param>
212 /// <returns>The number of bytes sent.</returns>
213 public int Send(byte[] buffer, int offset, int count)
215 if (hPipe == IntPtr.Zero)
216 throw new ObjectDisposedException(GetType().FullName);
218 throw new ArgumentNullException("buffer");
219 if (offset < 0 || count < 0)
220 throw new ArgumentOutOfRangeException("offset and/or count");
221 if (buffer.Length - offset < count)
222 throw new ArgumentException();
226 GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
229 bool res = NamedPipeHelper.WriteFile(
231 Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset),
237 if (!res) throw new NamedPipeException();
238 return (int) written;
246 delegate int SendMethod(byte[] buffer, int offset, int count);
248 public IAsyncResult BeginSend(byte[] buffer, int offset, int count,
249 AsyncCallback callback, object state)
251 return new SendMethod(Send).BeginInvoke(buffer, offset, count, callback, state);
254 public int EndSend(IAsyncResult asyncResult)
256 AsyncResult ar = asyncResult as AsyncResult;
257 return ((SendMethod)ar.AsyncDelegate).EndInvoke(asyncResult);
261 /// Returns the current NamedPipeSocketState of this instance.
263 /// <returns></returns>
264 public NamedPipeSocketState GetSocketState()
266 if (hPipe == IntPtr.Zero)
267 throw new ObjectDisposedException(GetType().FullName);
269 return new NamedPipeSocketState(hPipe);
273 /// Impersonates the client.
275 public void Impersonate()
277 if (hPipe == IntPtr.Zero)
278 throw new ObjectDisposedException(GetType().FullName);
281 if (!NamedPipeHelper.ImpersonateNamedPipeClient(hPipe))
282 throw new NamedPipeException();
286 /// Reverts the impersonation.
288 public static bool RevertToSelf()
290 return NamedPipeHelper.RevertToSelf();
297 /// Represents local Named Pipe informations.
299 internal class NamedPipeSocketInfo
301 public readonly int Flags;
302 public readonly int OutBufferSize;
303 public readonly int InBufferSize;
304 public readonly int MaxInstances;
310 return (Flags & NamedPipeHelper.PIPE_SERVER_END) != 0;
314 internal NamedPipeSocketInfo(IntPtr hPipe)
316 bool res = NamedPipeHelper.GetNamedPipeInfo(
326 throw new NamedPipeException();
333 /// Represents local Named Pipe state informations.
335 internal class NamedPipeSocketState
337 public readonly int State;
338 public readonly int CurrentInstances;
339 public readonly int MaxCollectionCount;
340 public readonly int CollectDataTimeout;
341 public readonly string UserName;
343 internal NamedPipeSocketState(IntPtr hPipe)
345 StringBuilder userName = new StringBuilder(256);
346 bool res = NamedPipeHelper.GetNamedPipeHandleState(
349 out CurrentInstances,
350 out MaxCollectionCount,
351 out CollectDataTimeout,
358 UserName = userName.ToString();
362 throw new NamedPipeException();