5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2009 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
.ComponentModel
;
35 using System
.Runtime
.InteropServices
;
36 using System
.Security
.AccessControl
;
37 using System
.Security
.Permissions
;
38 using System
.Security
.Principal
;
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;
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
)
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
) {
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
129 if (name_cache
!= null)
133 byte [] un
= new byte [200];
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)
141 un
= new byte [un
.Length
* 10];
143 name_cache
= Encoding
.Default
.GetString (un
);
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
;
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
;
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);
186 Func
<SafePipeHandle
> opener
;
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");
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 ());
217 public int NumberOfServerInstances
{
221 if (!Win32Marshal
.GetNamedPipeHandleState (Handle
, out s
, out c
, out m
, out t
, un
, 0))
222 throw new Win32Exception (Marshal
.GetLastWin32Error ());
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
);
245 if ((rights
& PipeAccessRights
.ReadData
) != 0)
247 if ((rights
& PipeAccessRights
.WriteData
) != 0)
249 if ((options
& PipeOptions
.WriteThrough
) != 0)
250 openMode
|= 0x80000000;
252 if ((owner
.TransmissionMode
& PipeTransmissionMode
.Message
) != 0)
254 //if ((readTransmissionMode & PipeTransmissionMode.Message) != 0)
256 if ((options
& PipeOptions
.Asynchronous
) != 0)
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
)
295 SecurityDescriptor
= IntPtr
.Zero
;
296 Inheritable
= inheritable
;
300 static class Win32Marshal
302 internal static bool IsWindows
{
304 switch (Environment
.OSVersion
.Platform
) {
305 case PlatformID
.Win32S
:
306 case PlatformID
.Win32Windows
:
307 case PlatformID
.Win32NT
:
308 case PlatformID
.WinCE
:
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
);