|
|
@@ -42,6 +42,22 @@ using Microsoft.Win32.SafeHandles;
|
|
|
|
|
|
namespace System.IO.Pipes
|
|
|
{
|
|
|
+ static class Win32PipeError
|
|
|
+ {
|
|
|
+ public static Exception GetException ()
|
|
|
+ {
|
|
|
+ return GetException (Marshal.GetLastWin32Error ());
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Exception GetException (int errorCode)
|
|
|
+ {
|
|
|
+ switch (errorCode) {
|
|
|
+ case 5: return new UnauthorizedAccessException ();
|
|
|
+ default: return new Win32Exception (errorCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
abstract class Win32AnonymousPipe : IPipe
|
|
|
{
|
|
|
protected Win32AnonymousPipe ()
|
|
|
@@ -78,12 +94,21 @@ namespace System.IO.Pipes
|
|
|
{
|
|
|
// AnonymousPipeServerStream owner;
|
|
|
|
|
|
- public Win32AnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize)
|
|
|
+ public unsafe Win32AnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction,
|
|
|
+ HandleInheritability inheritability, int bufferSize,
|
|
|
+ PipeSecurity pipeSecurity)
|
|
|
{
|
|
|
IntPtr r, w;
|
|
|
- SecurityAttributesHack att = new SecurityAttributesHack (inheritability == HandleInheritability.Inheritable);
|
|
|
- if (!Win32Marshal.CreatePipe (out r, out w, ref att, bufferSize))
|
|
|
- throw new Win32Exception (Marshal.GetLastWin32Error ());
|
|
|
+
|
|
|
+ byte[] securityDescriptor = null;
|
|
|
+ if (pipeSecurity != null)
|
|
|
+ securityDescriptor = pipeSecurity.GetSecurityDescriptorBinaryForm ();
|
|
|
+
|
|
|
+ fixed (byte* securityDescriptorPtr = securityDescriptor) {
|
|
|
+ SecurityAttributes att = new SecurityAttributes (inheritability, (IntPtr)securityDescriptorPtr);
|
|
|
+ if (!Win32Marshal.CreatePipe (out r, out w, ref att, bufferSize))
|
|
|
+ throw Win32PipeError.GetException ();
|
|
|
+ }
|
|
|
|
|
|
var rh = new SafePipeHandle (r, true);
|
|
|
var wh = new SafePipeHandle (w, true);
|
|
|
@@ -132,10 +157,9 @@ namespace System.IO.Pipes
|
|
|
int s, c, m, t;
|
|
|
byte [] un = new byte [200];
|
|
|
while (true) {
|
|
|
- if (!Win32Marshal.GetNamedPipeHandleState (Handle, out s, out c, out m, out t, un, un.Length)) {
|
|
|
- var xxx = Marshal.GetLastWin32Error ();
|
|
|
- throw new Win32Exception (xxx);
|
|
|
- }
|
|
|
+ if (!Win32Marshal.GetNamedPipeHandleState (Handle, out s, out c, out m, out t, un, un.Length))
|
|
|
+ throw Win32PipeError.GetException ();
|
|
|
+
|
|
|
if (un [un.Length - 1] == 0)
|
|
|
break;
|
|
|
un = new byte [un.Length * 10];
|
|
|
@@ -167,16 +191,18 @@ namespace System.IO.Pipes
|
|
|
}
|
|
|
|
|
|
// .ctor without handle - create new
|
|
|
- public Win32NamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability)
|
|
|
+ public Win32NamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName,
|
|
|
+ PipeAccessRights desiredAccessRights, PipeOptions options,
|
|
|
+ HandleInheritability inheritability)
|
|
|
{
|
|
|
name = String.Format ("\\\\{0}\\pipe\\{1}", serverName, pipeName);
|
|
|
- var att = new SecurityAttributesHack (inheritability == HandleInheritability.Inheritable);
|
|
|
+ var att = new SecurityAttributes (inheritability, IntPtr.Zero);
|
|
|
is_async = (options & PipeOptions.Asynchronous) != PipeOptions.None;
|
|
|
|
|
|
opener = delegate {
|
|
|
var ret = Win32Marshal.CreateFile (name, desiredAccessRights, 0, ref att, 3, 0, IntPtr.Zero);
|
|
|
if (ret == new IntPtr (-1L))
|
|
|
- throw new Win32Exception (Marshal.GetLastWin32Error ());
|
|
|
+ throw Win32PipeError.GetException ();
|
|
|
|
|
|
return new SafePipeHandle (ret, true);
|
|
|
};
|
|
|
@@ -210,7 +236,7 @@ namespace System.IO.Pipes
|
|
|
throw new InvalidOperationException ("The named pipe is already connected");
|
|
|
|
|
|
if (!Win32Marshal.WaitNamedPipe (name, timeout))
|
|
|
- throw new Win32Exception (Marshal.GetLastWin32Error ());
|
|
|
+ throw Win32PipeError.GetException ();
|
|
|
Connect ();
|
|
|
}
|
|
|
|
|
|
@@ -219,7 +245,7 @@ namespace System.IO.Pipes
|
|
|
int s, c, m, t;
|
|
|
byte [] un = null;
|
|
|
if (!Win32Marshal.GetNamedPipeHandleState (Handle, out s, out c, out m, out t, un, 0))
|
|
|
- throw new Win32Exception (Marshal.GetLastWin32Error ());
|
|
|
+ throw Win32PipeError.GetException ();
|
|
|
return c;
|
|
|
}
|
|
|
}
|
|
|
@@ -237,17 +263,16 @@ namespace System.IO.Pipes
|
|
|
}
|
|
|
|
|
|
// .ctor without handle - create new
|
|
|
- public Win32NamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options, int inBufferSize, int outBufferSize, HandleInheritability inheritability)
|
|
|
+ public unsafe Win32NamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances,
|
|
|
+ PipeTransmissionMode transmissionMode, PipeAccessRights rights,
|
|
|
+ PipeOptions options, int inBufferSize, int outBufferSize,
|
|
|
+ PipeSecurity pipeSecurity, HandleInheritability inheritability)
|
|
|
{
|
|
|
string name = String.Format ("\\\\.\\pipe\\{0}", pipeName);
|
|
|
|
|
|
- uint openMode = 0;
|
|
|
- if ((rights & PipeAccessRights.ReadData) != 0)
|
|
|
- openMode |= 1;
|
|
|
- if ((rights & PipeAccessRights.WriteData) != 0)
|
|
|
- openMode |= 2;
|
|
|
- if ((options & PipeOptions.WriteThrough) != 0)
|
|
|
- openMode |= 0x80000000;
|
|
|
+ uint openMode;
|
|
|
+ openMode = (uint)rights | (uint)options; // Enum values match Win32 flags exactly.
|
|
|
+
|
|
|
int pipeMode = 0;
|
|
|
if ((owner.TransmissionMode & PipeTransmissionMode.Message) != 0)
|
|
|
pipeMode |= 4;
|
|
|
@@ -256,12 +281,19 @@ namespace System.IO.Pipes
|
|
|
if ((options & PipeOptions.Asynchronous) != 0)
|
|
|
pipeMode |= 1;
|
|
|
|
|
|
- // FIXME: is nDefaultTimeout = 0 ok?
|
|
|
- var att = new SecurityAttributesHack (inheritability == HandleInheritability.Inheritable);
|
|
|
- var ret = Win32Marshal.CreateNamedPipe (name, openMode, pipeMode, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref att, IntPtr.Zero);
|
|
|
- if (ret == new IntPtr (-1L))
|
|
|
- throw new Win32Exception (Marshal.GetLastWin32Error ());
|
|
|
- handle = new SafePipeHandle (ret, true);
|
|
|
+ byte[] securityDescriptor = null;
|
|
|
+ if (pipeSecurity != null)
|
|
|
+ securityDescriptor = pipeSecurity.GetSecurityDescriptorBinaryForm ();
|
|
|
+
|
|
|
+ fixed (byte* securityDescriptorPtr = securityDescriptor) {
|
|
|
+ // FIXME: is nDefaultTimeout = 0 ok?
|
|
|
+ var att = new SecurityAttributes (inheritability, (IntPtr)securityDescriptorPtr);
|
|
|
+ var ret = Win32Marshal.CreateNamedPipe (name, openMode, pipeMode, maxNumberOfServerInstances,
|
|
|
+ outBufferSize, inBufferSize, 0, ref att, IntPtr.Zero);
|
|
|
+ if (ret == new IntPtr (-1L))
|
|
|
+ throw Win32PipeError.GetException ();
|
|
|
+ handle = new SafePipeHandle (ret, true);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
SafePipeHandle handle;
|
|
|
@@ -278,22 +310,22 @@ namespace System.IO.Pipes
|
|
|
public void WaitForConnection ()
|
|
|
{
|
|
|
if (!Win32Marshal.ConnectNamedPipe (Handle, IntPtr.Zero))
|
|
|
- throw new Win32Exception (Marshal.GetLastWin32Error ());
|
|
|
+ throw Win32PipeError.GetException ();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
[StructLayout (LayoutKind.Sequential)]
|
|
|
- struct SecurityAttributesHack
|
|
|
+ struct SecurityAttributes
|
|
|
{
|
|
|
public readonly int Length;
|
|
|
public readonly IntPtr SecurityDescriptor;
|
|
|
public readonly bool Inheritable;
|
|
|
|
|
|
- public SecurityAttributesHack (bool inheritable)
|
|
|
+ public SecurityAttributes (HandleInheritability inheritability, IntPtr securityDescriptor)
|
|
|
{
|
|
|
- Length = 0;
|
|
|
- SecurityDescriptor = IntPtr.Zero;
|
|
|
- Inheritable = inheritable;
|
|
|
+ Length = Marshal.SizeOf (typeof (SecurityAttributes));
|
|
|
+ SecurityDescriptor = securityDescriptor;
|
|
|
+ Inheritable = inheritability == HandleInheritability.Inheritable;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -314,32 +346,39 @@ namespace System.IO.Pipes
|
|
|
}
|
|
|
|
|
|
// http://msdn.microsoft.com/en-us/library/aa365152%28VS.85%29.aspx
|
|
|
- [DllImport ("kernel32")]
|
|
|
- internal static extern bool CreatePipe (out IntPtr readHandle, out IntPtr writeHandle, ref SecurityAttributesHack pipeAtts, int size);
|
|
|
+ [DllImport ("kernel32", SetLastError=true)]
|
|
|
+ internal static extern bool CreatePipe (out IntPtr readHandle, out IntPtr writeHandle,
|
|
|
+ ref SecurityAttributes pipeAtts, int size);
|
|
|
|
|
|
// http://msdn.microsoft.com/en-us/library/aa365150%28VS.85%29.aspx
|
|
|
- [DllImport ("kernel32")]
|
|
|
- internal static extern IntPtr CreateNamedPipe (string name, uint openMode, int pipeMode, int maxInstances, int outBufferSize, int inBufferSize, int defaultTimeout, ref SecurityAttributesHack securityAttributes, IntPtr atts);
|
|
|
+ [DllImport ("kernel32", SetLastError=true)]
|
|
|
+ internal static extern IntPtr CreateNamedPipe (string name, uint openMode, int pipeMode, int maxInstances,
|
|
|
+ int outBufferSize, int inBufferSize, int defaultTimeout,
|
|
|
+ ref SecurityAttributes securityAttributes, IntPtr atts);
|
|
|
|
|
|
// http://msdn.microsoft.com/en-us/library/aa365146%28VS.85%29.aspx
|
|
|
- [DllImport ("kernel32")]
|
|
|
+ [DllImport ("kernel32", SetLastError=true)]
|
|
|
internal static extern bool ConnectNamedPipe (SafePipeHandle handle, IntPtr overlapped);
|
|
|
|
|
|
// http://msdn.microsoft.com/en-us/library/aa365166%28VS.85%29.aspx
|
|
|
- [DllImport ("kernel32")]
|
|
|
+ [DllImport ("kernel32", SetLastError=true)]
|
|
|
internal static extern bool DisconnectNamedPipe (SafePipeHandle handle);
|
|
|
|
|
|
// http://msdn.microsoft.com/en-us/library/aa365443%28VS.85%29.aspx
|
|
|
- [DllImport ("kernel32")]
|
|
|
- internal static extern bool GetNamedPipeHandleState (SafePipeHandle handle, out int state, out int curInstances, out int maxCollectionCount, out int collectDateTimeout, byte [] userName, int maxUserNameSize);
|
|
|
+ [DllImport ("kernel32", SetLastError=true)]
|
|
|
+ internal static extern bool GetNamedPipeHandleState (SafePipeHandle handle,
|
|
|
+ out int state, out int curInstances,
|
|
|
+ out int maxCollectionCount, out int collectDateTimeout,
|
|
|
+ byte [] userName, int maxUserNameSize);
|
|
|
|
|
|
// http://msdn.microsoft.com/en-us/library/aa365800%28VS.85%29.aspx
|
|
|
- [DllImport ("kernel32")]
|
|
|
+ [DllImport ("kernel32", SetLastError=true)]
|
|
|
internal static extern bool WaitNamedPipe (string name, int timeout);
|
|
|
|
|
|
// http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx
|
|
|
- [DllImport ("kernel32")]
|
|
|
- internal static extern IntPtr CreateFile (string name, PipeAccessRights desiredAccess, FileShare fileShare, ref SecurityAttributesHack atts, int creationDisposition, int flags, IntPtr templateHandle);
|
|
|
+ [DllImport ("kernel32", SetLastError=true)]
|
|
|
+ internal static extern IntPtr CreateFile (string name, PipeAccessRights desiredAccess, FileShare fileShare,
|
|
|
+ ref SecurityAttributes atts, int creationDisposition, int flags, IntPtr templateHandle);
|
|
|
|
|
|
}
|
|
|
}
|