2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Core / System.IO.Pipes / PipeWin32.cs
blob9df34ad0d0f16e92399adae8b5f3ceb7368c611a
1 //
2 // PipeWin32.cs
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2009 Novell, Inc. http://www.novell.com
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
29 #if !BOOTSTRAP_BASIC
31 using System;
32 using System.ComponentModel;
33 using System.IO;
34 using System.Linq;
35 using System.Runtime.InteropServices;
36 using System.Security.AccessControl;
37 using System.Security.Permissions;
38 using System.Security.Principal;
39 using System.Text;
40 using Microsoft.Win32;
41 using Microsoft.Win32.SafeHandles;
43 namespace System.IO.Pipes
45 abstract class Win32AnonymousPipe : IPipe
47 protected Win32AnonymousPipe ()
51 public abstract SafePipeHandle Handle { get; }
53 public void WaitForPipeDrain ()
55 throw new NotImplementedException ();
59 class Win32AnonymousPipeClient : Win32AnonymousPipe, IAnonymousPipeClient
61 // AnonymousPipeClientStream owner;
63 public Win32AnonymousPipeClient (AnonymousPipeClientStream owner, SafePipeHandle handle)
65 // this.owner = owner;
67 this.handle = handle;
70 SafePipeHandle handle;
72 public override SafePipeHandle Handle {
73 get { return handle; }
77 class Win32AnonymousPipeServer : Win32AnonymousPipe, IAnonymousPipeServer
79 // AnonymousPipeServerStream owner;
81 public Win32AnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize)
83 IntPtr r, w;
84 SecurityAttributesHack att = new SecurityAttributesHack (inheritability == HandleInheritability.Inheritable);
85 if (!Win32Marshal.CreatePipe (out r, out w, ref att, bufferSize))
86 throw new Win32Exception (Marshal.GetLastWin32Error ());
88 var rh = new SafePipeHandle (r, true);
89 var wh = new SafePipeHandle (w, true);
91 if (direction == PipeDirection.Out) {
92 server_handle = wh;
93 client_handle = rh;
94 } else {
95 server_handle = rh;
96 client_handle = wh;
100 public Win32AnonymousPipeServer (AnonymousPipeServerStream owner, SafePipeHandle serverHandle, SafePipeHandle clientHandle)
102 // this.owner = owner;
103 this.server_handle = serverHandle;
104 this.client_handle = clientHandle;
107 SafePipeHandle server_handle, client_handle;
109 public override SafePipeHandle Handle {
110 get { return server_handle; }
113 public SafePipeHandle ClientHandle {
114 get { return client_handle; }
117 public void DisposeLocalCopyOfClientHandle ()
119 throw new NotImplementedException ();
123 abstract class Win32NamedPipe : IPipe
125 string name_cache;
127 public string Name {
128 get {
129 if (name_cache != null)
130 return name_cache;
132 int s, c, m, t;
133 byte [] un = new byte [200];
134 while (true) {
135 if (!Win32Marshal.GetNamedPipeHandleState (Handle, out s, out c, out m, out t, un, un.Length)) {
136 var xxx = Marshal.GetLastWin32Error ();
137 throw new Win32Exception (xxx);
139 if (un [un.Length - 1] == 0)
140 break;
141 un = new byte [un.Length * 10];
143 name_cache = Encoding.Default.GetString (un);
144 return name_cache;
148 public abstract SafePipeHandle Handle { get; }
150 public void WaitForPipeDrain ()
152 throw new NotImplementedException ();
156 class Win32NamedPipeClient : Win32NamedPipe, INamedPipeClient
158 NamedPipeClientStream owner;
160 // .ctor with existing handle
161 public Win32NamedPipeClient (NamedPipeClientStream owner, SafePipeHandle safePipeHandle)
163 this.handle = safePipeHandle;
164 this.owner = owner;
166 // FIXME: retrieve is_async from state?
169 // .ctor without handle - create new
170 public Win32NamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
172 name = String.Format ("\\\\{0}\\pipe\\{1}", serverName, pipeName);
173 var att = new SecurityAttributesHack (inheritability == HandleInheritability.Inheritable);
174 is_async = (options & PipeOptions.Asynchronous) != PipeOptions.None;
176 opener = delegate {
177 var ret = Win32Marshal.CreateFile (name, desiredAccessRights, 0, ref att, 3, 0, IntPtr.Zero);
178 if (ret == new IntPtr (-1L))
179 throw new Win32Exception (Marshal.GetLastWin32Error ());
181 return new SafePipeHandle (ret, true);
183 this.owner = owner;
186 Func<SafePipeHandle> opener;
187 bool is_async;
188 string name;
189 SafePipeHandle handle;
191 public override SafePipeHandle Handle {
192 get { return handle; }
195 public bool IsAsync {
196 get { return is_async; }
199 public void Connect ()
201 if (owner.IsConnected)
202 throw new InvalidOperationException ("The named pipe is already connected");
204 handle = opener ();
207 public void Connect (int timeout)
209 if (owner.IsConnected)
210 throw new InvalidOperationException ("The named pipe is already connected");
212 if (!Win32Marshal.WaitNamedPipe (name, timeout))
213 throw new Win32Exception (Marshal.GetLastWin32Error ());
214 Connect ();
217 public int NumberOfServerInstances {
218 get {
219 int s, c, m, t;
220 byte [] un = null;
221 if (!Win32Marshal.GetNamedPipeHandleState (Handle, out s, out c, out m, out t, un, 0))
222 throw new Win32Exception (Marshal.GetLastWin32Error ());
223 return c;
228 class Win32NamedPipeServer : Win32NamedPipe, INamedPipeServer
230 //NamedPipeServerStream owner;
232 // .ctor with existing handle
233 public Win32NamedPipeServer (NamedPipeServerStream owner, SafePipeHandle safePipeHandle)
235 handle = safePipeHandle;
236 //this.owner = owner;
239 // .ctor without handle - create new
240 public Win32NamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options, int inBufferSize, int outBufferSize, HandleInheritability inheritability)
242 string name = String.Format ("\\\\.\\pipe\\{0}", pipeName);
244 uint openMode = 0;
245 if ((rights & PipeAccessRights.ReadData) != 0)
246 openMode |= 1;
247 if ((rights & PipeAccessRights.WriteData) != 0)
248 openMode |= 2;
249 if ((options & PipeOptions.WriteThrough) != 0)
250 openMode |= 0x80000000;
251 int pipeMode = 0;
252 if ((owner.TransmissionMode & PipeTransmissionMode.Message) != 0)
253 pipeMode |= 4;
254 //if ((readTransmissionMode & PipeTransmissionMode.Message) != 0)
255 // pipeMode |= 2;
256 if ((options & PipeOptions.Asynchronous) != 0)
257 pipeMode |= 1;
259 // FIXME: is nDefaultTimeout = 0 ok?
260 var att = new SecurityAttributesHack (inheritability == HandleInheritability.Inheritable);
261 var ret = Win32Marshal.CreateNamedPipe (name, openMode, pipeMode, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref att, IntPtr.Zero);
262 if (ret == new IntPtr (-1L))
263 throw new Win32Exception (Marshal.GetLastWin32Error ());
264 handle = new SafePipeHandle (ret, true);
267 SafePipeHandle handle;
269 public override SafePipeHandle Handle {
270 get { return handle; }
273 public void Disconnect ()
275 Win32Marshal.DisconnectNamedPipe (Handle);
278 public void WaitForConnection ()
280 if (!Win32Marshal.ConnectNamedPipe (Handle, IntPtr.Zero))
281 throw new Win32Exception (Marshal.GetLastWin32Error ());
285 [StructLayout (LayoutKind.Sequential)]
286 struct SecurityAttributesHack
288 public readonly int Length;
289 public readonly IntPtr SecurityDescriptor;
290 public readonly bool Inheritable;
292 public SecurityAttributesHack (bool inheritable)
294 Length = 0;
295 SecurityDescriptor = IntPtr.Zero;
296 Inheritable = inheritable;
300 static class Win32Marshal
302 internal static bool IsWindows {
303 get {
304 switch (Environment.OSVersion.Platform) {
305 case PlatformID.Win32S:
306 case PlatformID.Win32Windows:
307 case PlatformID.Win32NT:
308 case PlatformID.WinCE:
309 return true;
310 default:
311 return false;
316 // http://msdn.microsoft.com/en-us/library/aa365152%28VS.85%29.aspx
317 [DllImport ("kernel32")]
318 internal static extern bool CreatePipe (out IntPtr readHandle, out IntPtr writeHandle, ref SecurityAttributesHack pipeAtts, int size);
320 // http://msdn.microsoft.com/en-us/library/aa365150%28VS.85%29.aspx
321 [DllImport ("kernel32")]
322 internal static extern IntPtr CreateNamedPipe (string name, uint openMode, int pipeMode, int maxInstances, int outBufferSize, int inBufferSize, int defaultTimeout, ref SecurityAttributesHack securityAttributes, IntPtr atts);
324 // http://msdn.microsoft.com/en-us/library/aa365146%28VS.85%29.aspx
325 [DllImport ("kernel32")]
326 internal static extern bool ConnectNamedPipe (SafePipeHandle handle, IntPtr overlapped);
328 // http://msdn.microsoft.com/en-us/library/aa365166%28VS.85%29.aspx
329 [DllImport ("kernel32")]
330 internal static extern bool DisconnectNamedPipe (SafePipeHandle handle);
332 // http://msdn.microsoft.com/en-us/library/aa365443%28VS.85%29.aspx
333 [DllImport ("kernel32")]
334 internal static extern bool GetNamedPipeHandleState (SafePipeHandle handle, out int state, out int curInstances, out int maxCollectionCount, out int collectDateTimeout, byte [] userName, int maxUserNameSize);
336 // http://msdn.microsoft.com/en-us/library/aa365800%28VS.85%29.aspx
337 [DllImport ("kernel32")]
338 internal static extern bool WaitNamedPipe (string name, int timeout);
340 // http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx
341 [DllImport ("kernel32")]
342 internal static extern IntPtr CreateFile (string name, PipeAccessRights desiredAccess, FileShare fileShare, ref SecurityAttributesHack atts, int creationDisposition, int flags, IntPtr templateHandle);
347 #endif