System.Drawing: added email to icon and test file headers
[mono.git] / mcs / class / System.Core / System.IO.Pipes / PipeWin32.cs
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.
27 //
28
29 #if !BOOTSTRAP_BASIC
30
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;
42
43 namespace System.IO.Pipes
44 {
45         abstract class Win32AnonymousPipe : IPipe
46         {
47                 protected Win32AnonymousPipe ()
48                 {
49                 }
50
51                 public abstract SafePipeHandle Handle { get; }
52
53                 public void WaitForPipeDrain ()
54                 {
55                         throw new NotImplementedException ();
56                 }
57         }
58
59         class Win32AnonymousPipeClient : Win32AnonymousPipe, IAnonymousPipeClient
60         {
61                 // AnonymousPipeClientStream owner;
62
63                 public Win32AnonymousPipeClient (AnonymousPipeClientStream owner, SafePipeHandle handle)
64                 {
65                         // this.owner = owner;
66
67                         this.handle = handle;
68                 }
69
70                 SafePipeHandle handle;
71
72                 public override SafePipeHandle Handle {
73                         get { return handle; }
74                 }
75         }
76
77         class Win32AnonymousPipeServer : Win32AnonymousPipe, IAnonymousPipeServer
78         {
79                 // AnonymousPipeServerStream owner;
80
81                 public Win32AnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize)
82                 {
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 ());
87
88                         var rh = new SafePipeHandle (r, true);
89                         var wh = new SafePipeHandle (w, true);
90
91                         if (direction == PipeDirection.Out) {
92                                 server_handle = wh;
93                                 client_handle = rh;
94                         } else {
95                                 server_handle = rh;
96                                 client_handle = wh;
97                         }
98                 }
99
100                 public Win32AnonymousPipeServer (AnonymousPipeServerStream owner, SafePipeHandle serverHandle, SafePipeHandle clientHandle)
101                 {
102                         // this.owner = owner;
103                         this.server_handle = serverHandle;
104                         this.client_handle = clientHandle;
105                 }
106
107                 SafePipeHandle server_handle, client_handle;
108
109                 public override SafePipeHandle Handle {
110                         get { return server_handle; }
111                 }
112
113                 public SafePipeHandle ClientHandle {
114                         get { return client_handle; }
115                 }
116
117                 public void DisposeLocalCopyOfClientHandle ()
118                 {
119                         throw new NotImplementedException ();
120                 }
121         }
122
123         abstract class Win32NamedPipe : IPipe
124         {
125                 string name_cache;
126
127                 public string Name {
128                         get {
129                                 if (name_cache != null)
130                                         return name_cache;
131
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);
138                                         }
139                                         if (un [un.Length - 1] == 0)
140                                                 break;
141                                         un = new byte [un.Length * 10];
142                                 }
143                                 name_cache = Encoding.Default.GetString (un);
144                                 return name_cache;
145                         }
146                 }
147
148                 public abstract SafePipeHandle Handle { get; }
149
150                 public void WaitForPipeDrain ()
151                 {
152                         throw new NotImplementedException ();
153                 }
154         }
155
156         class Win32NamedPipeClient : Win32NamedPipe, INamedPipeClient
157         {
158                 NamedPipeClientStream owner;
159
160                 // .ctor with existing handle
161                 public Win32NamedPipeClient (NamedPipeClientStream owner, SafePipeHandle safePipeHandle)
162                 {
163                         this.handle = safePipeHandle;
164                         this.owner = owner;
165
166                         // FIXME: retrieve is_async from state?
167                 }
168
169                 // .ctor without handle - create new
170                 public Win32NamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
171                 {
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;
175
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 ());
180
181                                 return new SafePipeHandle (ret, true);
182                         };
183                         this.owner = owner;
184                 }
185
186                 Func<SafePipeHandle> opener;
187                 bool is_async;
188                 string name;
189                 SafePipeHandle handle;
190
191                 public override SafePipeHandle Handle {
192                         get { return handle; }
193                 }
194
195                 public bool IsAsync {
196                         get { return is_async; }
197                 }
198
199                 public void Connect ()
200                 {
201                         if (owner.IsConnected)
202                                 throw new InvalidOperationException ("The named pipe is already connected");
203
204                         handle = opener ();
205                 }
206
207                 public void Connect (int timeout)
208                 {
209                         if (owner.IsConnected)
210                                 throw new InvalidOperationException ("The named pipe is already connected");
211
212                         if (!Win32Marshal.WaitNamedPipe (name, timeout))
213                                 throw new Win32Exception (Marshal.GetLastWin32Error ());
214                         Connect ();
215                 }
216
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;
224                         }
225                 }
226         }
227
228         class Win32NamedPipeServer : Win32NamedPipe, INamedPipeServer
229         {
230                 //NamedPipeServerStream owner;
231
232                 // .ctor with existing handle
233                 public Win32NamedPipeServer (NamedPipeServerStream owner, SafePipeHandle safePipeHandle)
234                 {
235                         handle = safePipeHandle;
236                         //this.owner = owner;
237                 }
238
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)
241                 {
242                         string name = String.Format ("\\\\.\\pipe\\{0}", pipeName);
243
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;
258
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);
265                 }
266
267                 SafePipeHandle handle;
268
269                 public override SafePipeHandle Handle {
270                         get { return handle; }
271                 }
272
273                 public void Disconnect ()
274                 {
275                         Win32Marshal.DisconnectNamedPipe (Handle);
276                 }
277
278                 public void WaitForConnection ()
279                 {
280                         if (!Win32Marshal.ConnectNamedPipe (Handle, IntPtr.Zero))
281                                 throw new Win32Exception (Marshal.GetLastWin32Error ());
282                 }
283         }
284
285         [StructLayout (LayoutKind.Sequential)]
286         struct SecurityAttributesHack
287         {
288                 public readonly int Length;
289                 public readonly IntPtr SecurityDescriptor;
290                 public readonly bool Inheritable;
291
292                 public SecurityAttributesHack (bool inheritable)
293                 {
294                         Length = 0;
295                         SecurityDescriptor = IntPtr.Zero;
296                         Inheritable = inheritable;
297                 }
298         }
299
300         static class Win32Marshal
301         {
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;
312                                 }
313                         }
314                 }
315
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);
319
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);
323
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);
327
328                 // http://msdn.microsoft.com/en-us/library/aa365166%28VS.85%29.aspx
329                 [DllImport ("kernel32")]
330                 internal static extern bool DisconnectNamedPipe (SafePipeHandle handle);
331
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);
335
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);
339
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);
343
344         }
345 }
346
347 #endif