PageRenderTime 49ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/referencesource/System.Core/System/IO/Pipes/Pipe.cs

https://github.com/pruiz/mono
C# | 1013 lines | 683 code | 161 blank | 169 comment | 176 complexity | 7de3f1f26a986ab64dfd4d9207807284 MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. // ==++==
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // ==--==
  6. /*============================================================
  7. **
  8. ** Classes: AnonymousPipeServerStream
  9. ** AnonymousPipeClientStream
  10. ** NamedPipeServerStream
  11. ** NamedPipeClientStream
  12. **
  13. ** Purpose: pipe stream classes.
  14. **
  15. **
  16. ===========================================================*/
  17. using System;
  18. using System.Diagnostics;
  19. using System.Diagnostics.CodeAnalysis;
  20. using System.IO;
  21. using System.Runtime.InteropServices;
  22. using System.Runtime.CompilerServices;
  23. using System.Runtime.ConstrainedExecution;
  24. using System.Runtime.Versioning;
  25. using System.Security;
  26. using System.Security.Permissions;
  27. using System.Security.Principal;
  28. using System.Text;
  29. using System.Threading;
  30. using System.Threading.Tasks;
  31. using Microsoft.Win32;
  32. using Microsoft.Win32.SafeHandles;
  33. namespace System.IO.Pipes {
  34. /// <summary>
  35. /// Anonymous pipe server stream
  36. /// </summary>
  37. [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
  38. public sealed class AnonymousPipeServerStream : PipeStream {
  39. private SafePipeHandle m_clientHandle;
  40. private bool m_clientHandleExposed;
  41. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  42. [SecuritySafeCritical]
  43. public AnonymousPipeServerStream()
  44. : this(PipeDirection.Out, HandleInheritability.None, 0, null) { }
  45. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  46. [SecuritySafeCritical]
  47. public AnonymousPipeServerStream(PipeDirection direction)
  48. : this(direction, HandleInheritability.None, 0) { }
  49. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  50. [SecuritySafeCritical]
  51. public AnonymousPipeServerStream(PipeDirection direction, HandleInheritability inheritability)
  52. : this(direction, inheritability, 0) { }
  53. // bufferSize is used as a suggestion; specify 0 to let OS decide
  54. // This constructor instantiates the PipeSecurity using just the inheritability flag
  55. [SecuritySafeCritical]
  56. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  57. public AnonymousPipeServerStream(PipeDirection direction, HandleInheritability inheritability, int bufferSize)
  58. : base(direction, bufferSize) {
  59. if (direction == PipeDirection.InOut) {
  60. throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional));
  61. }
  62. if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) {
  63. throw new ArgumentOutOfRangeException("inheritability", SR.GetString(SR.ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable));
  64. }
  65. UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability);
  66. Create(direction, secAttrs, bufferSize);
  67. }
  68. // bufferSize is used as a suggestion; specify 0 to let OS decide
  69. // pipeSecurity of null is default security descriptor
  70. [SecuritySafeCritical]
  71. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  72. public AnonymousPipeServerStream(PipeDirection direction, HandleInheritability inheritability, int bufferSize, PipeSecurity pipeSecurity)
  73. : base(direction, bufferSize) {
  74. if (direction == PipeDirection.InOut) {
  75. throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional));
  76. }
  77. if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) {
  78. throw new ArgumentOutOfRangeException("inheritability", SR.GetString(SR.ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable));
  79. }
  80. Object pinningHandle;
  81. UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability, pipeSecurity, out pinningHandle);
  82. try {
  83. Create(direction, secAttrs, bufferSize);
  84. }
  85. finally {
  86. if (pinningHandle != null) {
  87. GCHandle pinHandle = (GCHandle)pinningHandle;
  88. pinHandle.Free();
  89. }
  90. }
  91. }
  92. ~AnonymousPipeServerStream() {
  93. Dispose(false);
  94. }
  95. // Create an AnonymousPipeServerStream from two existing pipe handles.
  96. [SecuritySafeCritical]
  97. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  98. public AnonymousPipeServerStream(PipeDirection direction, SafePipeHandle serverSafePipeHandle, SafePipeHandle clientSafePipeHandle)
  99. : base(direction, 0) {
  100. if (direction == PipeDirection.InOut) {
  101. throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional));
  102. }
  103. if (serverSafePipeHandle == null) {
  104. throw new ArgumentNullException("serverSafePipeHandle");
  105. }
  106. if (clientSafePipeHandle == null) {
  107. throw new ArgumentNullException("clientSafePipeHandle");
  108. }
  109. if (serverSafePipeHandle.IsInvalid) {
  110. throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "serverSafePipeHandle");
  111. }
  112. if (clientSafePipeHandle.IsInvalid) {
  113. throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "clientSafePipeHandle");
  114. }
  115. // Check that these handles are in fact a handles to a pipe.
  116. if (UnsafeNativeMethods.GetFileType(serverSafePipeHandle) != UnsafeNativeMethods.FILE_TYPE_PIPE) {
  117. throw new IOException(SR.GetString(SR.IO_IO_InvalidPipeHandle));
  118. }
  119. if (UnsafeNativeMethods.GetFileType(clientSafePipeHandle) != UnsafeNativeMethods.FILE_TYPE_PIPE) {
  120. throw new IOException(SR.GetString(SR.IO_IO_InvalidPipeHandle));
  121. }
  122. InitializeHandle(serverSafePipeHandle, true, false);
  123. m_clientHandle = clientSafePipeHandle;
  124. m_clientHandleExposed = true;
  125. State = PipeState.Connected;
  126. }
  127. // This method should exist until we add a first class way of passing handles between parent and child
  128. // processes. For now, people do it via command line arguments.
  129. [System.Security.SecurityCritical]
  130. [SuppressMessage("Microsoft.Reliability","CA2001:AvoidCallingProblematicMethods", MessageId="System.Runtime.InteropServices.SafeHandle.DangerousGetHandle", Justification="By design")]
  131. public String GetClientHandleAsString() {
  132. m_clientHandleExposed = true;
  133. return m_clientHandle.DangerousGetHandle().ToString();
  134. }
  135. public SafePipeHandle ClientSafePipeHandle {
  136. [System.Security.SecurityCritical]
  137. get {
  138. m_clientHandleExposed = true;
  139. return m_clientHandle;
  140. }
  141. }
  142. // This method is an annoying one but it has to exist at least until we make passing handles between
  143. // processes first class. We need this because once the child handle is inherited, the OS considers
  144. // the parent and child's handles to be different. Therefore, if a child closes its handle, our
  145. // Read/Write methods won't throw because the OS will think that there is still a child handle around
  146. // that can still Write/Read to/from the other end of the pipe.
  147. //
  148. // Ideally, we would want the Process class to close this handle after it has been inherited. See
  149. // the pipe spec future features section for more information.
  150. //
  151. // Right now, this is the best signal to set the anonymous pipe as connected; if this is called, we
  152. // know the client has been passed the handle and so the connection is live.
  153. [System.Security.SecurityCritical]
  154. public void DisposeLocalCopyOfClientHandle() {
  155. if (m_clientHandle != null && !m_clientHandle.IsClosed) {
  156. m_clientHandle.Dispose();
  157. }
  158. }
  159. [System.Security.SecurityCritical]
  160. protected override void Dispose(bool disposing) {
  161. try {
  162. // We should dispose of the client handle if it was not exposed.
  163. if (!m_clientHandleExposed && m_clientHandle != null && !m_clientHandle.IsClosed) {
  164. m_clientHandle.Dispose();
  165. }
  166. }
  167. finally {
  168. base.Dispose(disposing);
  169. }
  170. }
  171. // Creates the anonymous pipe.
  172. [System.Security.SecurityCritical]
  173. private void Create(PipeDirection direction, UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs, int bufferSize) {
  174. Debug.Assert(direction != PipeDirection.InOut, "Anonymous pipe direction shouldn't be InOut");
  175. Debug.Assert(bufferSize >= 0, "bufferSize is negative");
  176. bool bSuccess;
  177. SafePipeHandle serverHandle;
  178. SafePipeHandle newServerHandle;
  179. // Create the two pipe handles that make up the anonymous pipe.
  180. if (direction == PipeDirection.In) {
  181. bSuccess = UnsafeNativeMethods.CreatePipe(out serverHandle, out m_clientHandle, secAttrs, bufferSize);
  182. }
  183. else {
  184. bSuccess = UnsafeNativeMethods.CreatePipe(out m_clientHandle, out serverHandle, secAttrs, bufferSize);
  185. }
  186. if (!bSuccess) {
  187. __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty);
  188. }
  189. // Duplicate the server handle to make it not inheritable. Note: We need to do this so that the child
  190. // process doesn't end up getting another copy of the server handle. If it were to get a copy, the
  191. // OS wouldn't be able to inform the child that the server has closed its handle because it will see
  192. // that there is still one server handle that is open.
  193. bSuccess = UnsafeNativeMethods.DuplicateHandle(UnsafeNativeMethods.GetCurrentProcess(), serverHandle, UnsafeNativeMethods.GetCurrentProcess(),
  194. out newServerHandle, 0, false, UnsafeNativeMethods.DUPLICATE_SAME_ACCESS);
  195. if (!bSuccess) {
  196. __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty);
  197. }
  198. // Close the inheritable server handle.
  199. serverHandle.Dispose();
  200. InitializeHandle(newServerHandle, false, false);
  201. State = PipeState.Connected;
  202. }
  203. // Anonymous pipes do not support message mode so there is no need to use the base version that P/Invokes here.
  204. public override PipeTransmissionMode TransmissionMode {
  205. [System.Security.SecurityCritical]
  206. get {
  207. return PipeTransmissionMode.Byte;
  208. }
  209. }
  210. public override PipeTransmissionMode ReadMode {
  211. [System.Security.SecurityCritical]
  212. set {
  213. CheckPipePropertyOperations();
  214. if (value < PipeTransmissionMode.Byte || value > PipeTransmissionMode.Message) {
  215. throw new ArgumentOutOfRangeException("value", SR.GetString(SR.ArgumentOutOfRange_TransmissionModeByteOrMsg));
  216. }
  217. if (value == PipeTransmissionMode.Message) {
  218. throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeMessagesNotSupported));
  219. }
  220. }
  221. }
  222. }
  223. /// <summary>
  224. /// Anonymous pipe client. Use this to open the client end of an anonymous pipes created with AnonymousPipeServerStream.
  225. /// </summary>
  226. [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
  227. public sealed class AnonymousPipeClientStream : PipeStream {
  228. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  229. [SecuritySafeCritical]
  230. [SuppressMessage("Microsoft.Naming","CA1720:IdentifiersShouldNotContainTypeNames", MessageId="string", Justification="By design")]
  231. public AnonymousPipeClientStream(String pipeHandleAsString)
  232. : this(PipeDirection.In, pipeHandleAsString) { }
  233. [System.Security.SecurityCritical]
  234. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  235. [SuppressMessage("Microsoft.Naming","CA1720:IdentifiersShouldNotContainTypeNames", MessageId="string", Justification="By design")]
  236. public AnonymousPipeClientStream(PipeDirection direction, String pipeHandleAsString)
  237. : base(direction, 0) {
  238. if (direction == PipeDirection.InOut) {
  239. throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional));
  240. }
  241. if (pipeHandleAsString == null) {
  242. throw new ArgumentNullException("pipeHandleAsString");
  243. }
  244. // Initialize SafePipeHandle from String and check if it's valid. First see if it's parseable
  245. long result = 0;
  246. bool parseable = long.TryParse(pipeHandleAsString, out result);
  247. if (!parseable) {
  248. throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "pipeHandleAsString");
  249. }
  250. // next check whether the handle is invalid
  251. SafePipeHandle safePipeHandle = new SafePipeHandle((IntPtr)result, true);
  252. if (safePipeHandle.IsInvalid) {
  253. throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "pipeHandleAsString");
  254. }
  255. Init(direction, safePipeHandle);
  256. }
  257. [System.Security.SecurityCritical]
  258. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  259. public AnonymousPipeClientStream(PipeDirection direction, SafePipeHandle safePipeHandle)
  260. : base(direction, 0) {
  261. if (direction == PipeDirection.InOut) {
  262. throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional));
  263. }
  264. if (safePipeHandle == null) {
  265. throw new ArgumentNullException("safePipeHandle");
  266. }
  267. if (safePipeHandle.IsInvalid) {
  268. throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "safePipeHandle");
  269. }
  270. Init(direction, safePipeHandle);
  271. }
  272. [System.Security.SecuritySafeCritical]
  273. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  274. private void Init(PipeDirection direction, SafePipeHandle safePipeHandle) {
  275. Debug.Assert(direction != PipeDirection.InOut, "anonymous pipes are unidirectional, caller should have verified before calling Init");
  276. Debug.Assert(safePipeHandle != null && !safePipeHandle.IsInvalid, "safePipeHandle must be valid");
  277. // Check that this handle is infact a handle to a pipe.
  278. if (UnsafeNativeMethods.GetFileType(safePipeHandle) != UnsafeNativeMethods.FILE_TYPE_PIPE) {
  279. throw new IOException(SR.GetString(SR.IO_IO_InvalidPipeHandle));
  280. }
  281. InitializeHandle(safePipeHandle, true, false);
  282. State = PipeState.Connected;
  283. }
  284. ~AnonymousPipeClientStream() {
  285. Dispose(false);
  286. }
  287. // Anonymous pipes do not support message readmode so there is no need to use the base version
  288. // which P/Invokes (and sometimes fails).
  289. public override PipeTransmissionMode TransmissionMode {
  290. [System.Security.SecurityCritical]
  291. get {
  292. return PipeTransmissionMode.Byte;
  293. }
  294. }
  295. public override PipeTransmissionMode ReadMode {
  296. [System.Security.SecurityCritical]
  297. set {
  298. CheckPipePropertyOperations();
  299. if (value < PipeTransmissionMode.Byte || value > PipeTransmissionMode.Message) {
  300. throw new ArgumentOutOfRangeException("value", SR.GetString(SR.ArgumentOutOfRange_TransmissionModeByteOrMsg));
  301. }
  302. if (value == PipeTransmissionMode.Message) {
  303. throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeMessagesNotSupported));
  304. }
  305. }
  306. }
  307. }
  308. // Users will use this delegate to specify a method to call while impersonating the client
  309. // (see NamedPipeServerStream.RunAsClient).
  310. public delegate void PipeStreamImpersonationWorker();
  311. /// <summary>
  312. /// Named pipe server
  313. /// </summary>
  314. [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
  315. public sealed class NamedPipeServerStream : PipeStream {
  316. // Use the maximum number of server instances that the system resources allow
  317. public const int MaxAllowedServerInstances = -1;
  318. [SecurityCritical]
  319. private unsafe static readonly IOCompletionCallback WaitForConnectionCallback =
  320. new IOCompletionCallback(NamedPipeServerStream.AsyncWaitForConnectionCallback);
  321. [System.Security.SecurityCritical]
  322. static NamedPipeServerStream()
  323. {
  324. }
  325. [SecuritySafeCritical]
  326. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  327. public NamedPipeServerStream(String pipeName)
  328. : this(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None, 0, 0, null,
  329. HandleInheritability.None, (PipeAccessRights)0) { }
  330. [SecuritySafeCritical]
  331. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  332. public NamedPipeServerStream(String pipeName, PipeDirection direction)
  333. : this(pipeName, direction, 1, PipeTransmissionMode.Byte, PipeOptions.None, 0, 0, null,
  334. HandleInheritability.None, (PipeAccessRights)0) { }
  335. [SecuritySafeCritical]
  336. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  337. public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances)
  338. : this(pipeName, direction, maxNumberOfServerInstances, PipeTransmissionMode.Byte, PipeOptions.None,
  339. 0, 0, null, HandleInheritability.None, (PipeAccessRights)0) { }
  340. [SecuritySafeCritical]
  341. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  342. public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances,
  343. PipeTransmissionMode transmissionMode)
  344. : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, PipeOptions.None, 0, 0,
  345. null, HandleInheritability.None, (PipeAccessRights)0) { }
  346. [SecuritySafeCritical]
  347. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  348. public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances,
  349. PipeTransmissionMode transmissionMode, PipeOptions options)
  350. : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, 0, 0,
  351. null, HandleInheritability.None, (PipeAccessRights)0) { }
  352. [SecuritySafeCritical]
  353. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  354. public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances,
  355. PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize)
  356. : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize,
  357. null, HandleInheritability.None, (PipeAccessRights)0) { }
  358. [SecuritySafeCritical]
  359. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  360. public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances,
  361. PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
  362. PipeSecurity pipeSecurity)
  363. : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize,
  364. pipeSecurity, HandleInheritability.None, (PipeAccessRights)0) { }
  365. [SecuritySafeCritical]
  366. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  367. public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances,
  368. PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
  369. PipeSecurity pipeSecurity, HandleInheritability inheritability)
  370. : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize,
  371. pipeSecurity, inheritability, (PipeAccessRights)0) { }
  372. /// <summary>
  373. /// Full named pipe server constructor
  374. /// </summary>
  375. /// <param name="pipeName">Pipe name</param>
  376. /// <param name="direction">Pipe direction: In, Out or InOut (duplex).
  377. /// Win32 note: this gets OR'd into dwOpenMode to CreateNamedPipe
  378. /// </param>
  379. /// <param name="maxNumberOfServerInstances">Maximum number of server instances. Specify a fixed value between
  380. /// 1 and 254, or use NamedPipeServerStream.MaxAllowedServerInstances to use the maximum amount allowed by
  381. /// system resources.</param>
  382. /// <param name="transmissionMode">Byte mode or message mode.
  383. /// Win32 note: this gets used for dwPipeMode. CreateNamedPipe allows you to specify PIPE_TYPE_BYTE/MESSAGE
  384. /// and PIPE_READMODE_BYTE/MESSAGE independently, but this sets type and readmode to match.
  385. /// </param>
  386. /// <param name="options">PipeOption enum: None, Asynchronous, or Writethrough
  387. /// Win32 note: this gets passed in with dwOpenMode to CreateNamedPipe. Asynchronous corresponds to
  388. /// FILE_FLAG_OVERLAPPED option. PipeOptions enum doesn't expose FIRST_PIPE_INSTANCE option because
  389. /// this sets that automatically based on the number of instances specified.
  390. /// </param>
  391. /// <param name="inBufferSize">Incoming buffer size, 0 or higher.
  392. /// Note: this size is always advisory; OS uses a suggestion.
  393. /// </param>
  394. /// <param name="outBufferSize">Outgoing buffer size, 0 or higher (see above)</param>
  395. /// <param name="pipeSecurity">PipeSecurity, or null for default security descriptor</param>
  396. /// <param name="inheritability">Whether handle is inheritable</param>
  397. /// <param name="additionalAccessRights">Combination (logical OR) of PipeAccessRights.TakeOwnership,
  398. /// PipeAccessRights.AccessSystemSecurity, and PipeAccessRights.ChangePermissions</param>
  399. [SecuritySafeCritical]
  400. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  401. public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances,
  402. PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
  403. PipeSecurity pipeSecurity, HandleInheritability inheritability, PipeAccessRights additionalAccessRights)
  404. : base(direction, transmissionMode, outBufferSize) {
  405. if (pipeName == null) {
  406. throw new ArgumentNullException("pipeName");
  407. }
  408. if (pipeName.Length == 0) {
  409. throw new ArgumentException(SR.GetString(SR.Argument_NeedNonemptyPipeName));
  410. }
  411. if ((options & ~(PipeOptions.WriteThrough | PipeOptions.Asynchronous)) != 0) {
  412. throw new ArgumentOutOfRangeException("options", SR.GetString(SR.ArgumentOutOfRange_OptionsInvalid));
  413. }
  414. if (inBufferSize < 0) {
  415. throw new ArgumentOutOfRangeException("inBufferSize", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNum));
  416. }
  417. // win32 allows fixed values of 1-254 or 255 to mean max allowed by system. We expose 255 as -1 (unlimited)
  418. // through the MaxAllowedServerInstances constant. This is consistent e.g. with -1 as infinite timeout, etc
  419. if ((maxNumberOfServerInstances < 1 || maxNumberOfServerInstances > 254) && (maxNumberOfServerInstances != MaxAllowedServerInstances)) {
  420. throw new ArgumentOutOfRangeException("maxNumberOfServerInstances", SR.GetString(SR.ArgumentOutOfRange_MaxNumServerInstances));
  421. }
  422. if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) {
  423. throw new ArgumentOutOfRangeException("inheritability", SR.GetString(SR.ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable));
  424. }
  425. // ChangePermissions, TakeOwnership, and AccessSystemSecurity are only legal values user may provide;
  426. // internally this is set to 0 if not provided. This handles both cases.
  427. if ((additionalAccessRights & ~(PipeAccessRights.ChangePermissions | PipeAccessRights.TakeOwnership |
  428. PipeAccessRights.AccessSystemSecurity)) != 0) {
  429. throw new ArgumentOutOfRangeException("additionalAccessRights", SR.GetString(SR.ArgumentOutOfRange_AdditionalAccessLimited));
  430. }
  431. // Named Pipe Servers require Windows NT
  432. if (Environment.OSVersion.Platform == PlatformID.Win32Windows) {
  433. throw new PlatformNotSupportedException(SR.GetString(SR.PlatformNotSupported_NamedPipeServers));
  434. }
  435. string normalizedPipePath = Path.GetFullPath(@"\\.\pipe\" + pipeName);
  436. // Make sure the pipe name isn't one of our reserved names for anonymous pipes.
  437. if (String.Compare(normalizedPipePath, @"\\.\pipe\anonymous", StringComparison.OrdinalIgnoreCase) == 0) {
  438. throw new ArgumentOutOfRangeException("pipeName", SR.GetString(SR.ArgumentOutOfRange_AnonymousReserved));
  439. }
  440. Object pinningHandle = null;
  441. UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability, pipeSecurity, out pinningHandle);
  442. try {
  443. Create(normalizedPipePath, direction, maxNumberOfServerInstances, transmissionMode,
  444. options, inBufferSize, outBufferSize, additionalAccessRights, secAttrs);
  445. }
  446. finally {
  447. if (pinningHandle != null) {
  448. GCHandle pinHandle = (GCHandle)pinningHandle;
  449. pinHandle.Free();
  450. }
  451. }
  452. }
  453. // Create a NamedPipeServerStream from an existing server pipe handle.
  454. [System.Security.SecuritySafeCritical]
  455. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  456. public NamedPipeServerStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle)
  457. : base(direction, PipeTransmissionMode.Byte, 0) {
  458. if (safePipeHandle == null) {
  459. throw new ArgumentNullException("safePipeHandle");
  460. }
  461. if (safePipeHandle.IsInvalid) {
  462. throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "safePipeHandle");
  463. }
  464. // Check that this handle is infact a handle to a pipe.
  465. if (UnsafeNativeMethods.GetFileType(safePipeHandle) != UnsafeNativeMethods.FILE_TYPE_PIPE) {
  466. throw new IOException(SR.GetString(SR.IO_IO_InvalidPipeHandle));
  467. }
  468. InitializeHandle(safePipeHandle, true, isAsync);
  469. if (isConnected) {
  470. State = PipeState.Connected;
  471. }
  472. }
  473. ~NamedPipeServerStream() {
  474. Dispose(false);
  475. }
  476. [System.Security.SecurityCritical]
  477. private void Create(String fullPipeName, PipeDirection direction, int maxNumberOfServerInstances,
  478. PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
  479. PipeAccessRights rights, UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs) {
  480. Debug.Assert(fullPipeName != null && fullPipeName.Length != 0, "fullPipeName is null or empty");
  481. Debug.Assert(direction >= PipeDirection.In && direction <= PipeDirection.InOut, "invalid pipe direction");
  482. Debug.Assert(inBufferSize >= 0, "inBufferSize is negative");
  483. Debug.Assert(outBufferSize >= 0, "outBufferSize is negative");
  484. Debug.Assert((maxNumberOfServerInstances >= 1 && maxNumberOfServerInstances <= 254) || (maxNumberOfServerInstances == MaxAllowedServerInstances), "maxNumberOfServerInstances is invalid");
  485. Debug.Assert(transmissionMode >= PipeTransmissionMode.Byte && transmissionMode <= PipeTransmissionMode.Message, "transmissionMode is out of range");
  486. int openMode = ((int)direction) |
  487. (maxNumberOfServerInstances == 1 ? UnsafeNativeMethods.FILE_FLAG_FIRST_PIPE_INSTANCE : 0) |
  488. (int)options |
  489. (int)rights;
  490. // We automatically set the ReadMode to match the TransmissionMode.
  491. int pipeModes = (int)transmissionMode << 2 | (int)transmissionMode << 1;
  492. // Convert -1 to 255 to match win32 (we asserted that it is between -1 and 254).
  493. if (maxNumberOfServerInstances == MaxAllowedServerInstances) {
  494. maxNumberOfServerInstances = 255;
  495. }
  496. SafePipeHandle handle = UnsafeNativeMethods.CreateNamedPipe(fullPipeName, openMode, pipeModes,
  497. maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, secAttrs);
  498. if (handle.IsInvalid) {
  499. __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty);
  500. }
  501. InitializeHandle(handle, false, (options & PipeOptions.Asynchronous) != 0);
  502. }
  503. // This will wait until the client calls Connect(). If we return from this method, we guarantee that
  504. // the client has returned from its Connect call. The client may have done so before this method
  505. // was called (but not before this server is been created, or, if we were servicing another client,
  506. // not before we called Disconnect), in which case, there may be some buffer already in the pipe waiting
  507. // for us to read. See NamedPipeClientStream.Connect for more information.
  508. [System.Security.SecurityCritical]
  509. [SuppressMessage("Microsoft.Security","CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification="Security model of pipes: demand at creation but no subsequent demands")]
  510. public void WaitForConnection() {
  511. CheckConnectOperationsServer();
  512. if (IsAsync) {
  513. IAsyncResult result = BeginWaitForConnection(null, null);
  514. EndWaitForConnection(result);
  515. }
  516. else {
  517. if (!UnsafeNativeMethods.ConnectNamedPipe(InternalHandle, UnsafeNativeMethods.NULL)) {
  518. int errorCode = Marshal.GetLastWin32Error();
  519. if (errorCode != UnsafeNativeMethods.ERROR_PIPE_CONNECTED) {
  520. __Error.WinIOError(errorCode, String.Empty);
  521. }
  522. // pipe already connected
  523. if (errorCode == UnsafeNativeMethods.ERROR_PIPE_CONNECTED && State == PipeState.Connected) {
  524. throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeAlreadyConnected));
  525. }
  526. // If we reach here then a connection has been established. This can happen if a client
  527. // connects in the interval between the call to CreateNamedPipe and the call to ConnectNamedPipe.
  528. // In this situation, there is still a good connection between client and server, even though
  529. // ConnectNamedPipe returns zero.
  530. }
  531. State = PipeState.Connected;
  532. }
  533. }
  534. public Task WaitForConnectionAsync(CancellationToken cancellationToken) {
  535. if (cancellationToken.IsCancellationRequested) {
  536. return Task.FromCancellation(cancellationToken);
  537. }
  538. if (!IsAsync) {
  539. return Task.Factory.StartNew(WaitForConnection, cancellationToken);
  540. }
  541. // Avoiding allocation if the task cannot be cancelled
  542. IOCancellationHelper cancellationHelper = cancellationToken.CanBeCanceled ? new IOCancellationHelper(cancellationToken) : null;
  543. return Task.Factory.FromAsync(BeginWaitForConnection, EndWaitForConnection, cancellationHelper);
  544. }
  545. public Task WaitForConnectionAsync() {
  546. return WaitForConnectionAsync(CancellationToken.None);
  547. }
  548. // Async version of WaitForConnection. See the comments above for more info.
  549. [System.Security.SecurityCritical]
  550. [HostProtection(ExternalThreading = true)]
  551. public unsafe IAsyncResult BeginWaitForConnection(AsyncCallback callback, Object state) {
  552. CheckConnectOperationsServer();
  553. if (!IsAsync) {
  554. throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeNotAsync));
  555. }
  556. // Create and store async stream class library specific data in the
  557. // async result
  558. PipeAsyncResult asyncResult = new PipeAsyncResult();
  559. asyncResult._handle = InternalHandle;
  560. asyncResult._userCallback = callback;
  561. asyncResult._userStateObject = state;
  562. IOCancellationHelper cancellationHelper = state as IOCancellationHelper;
  563. // Create wait handle and store in async result
  564. ManualResetEvent waitHandle = new ManualResetEvent(false);
  565. asyncResult._waitHandle = waitHandle;
  566. // Create a managed overlapped class
  567. // We will set the file offsets later
  568. Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
  569. // Pack the Overlapped class, and store it in the async result
  570. NativeOverlapped* intOverlapped = overlapped.Pack(WaitForConnectionCallback, null);
  571. asyncResult._overlapped = intOverlapped;
  572. if (!UnsafeNativeMethods.ConnectNamedPipe(InternalHandle, intOverlapped)) {
  573. int errorCode = Marshal.GetLastWin32Error();
  574. if (errorCode == UnsafeNativeMethods.ERROR_IO_PENDING) {
  575. if (cancellationHelper != null) {
  576. cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
  577. }
  578. return asyncResult;
  579. }
  580. // WaitForConnectionCallback will not be called becasue we completed synchronously.
  581. // Either the pipe is already connected, or there was an error. Unpin and free the overlapped again.
  582. Overlapped.Free(intOverlapped);
  583. asyncResult._overlapped = null;
  584. // Did the client already connect to us?
  585. if (errorCode == UnsafeNativeMethods.ERROR_PIPE_CONNECTED) {
  586. if (State == PipeState.Connected) {
  587. throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeAlreadyConnected));
  588. }
  589. asyncResult.CallUserCallback();
  590. return asyncResult;
  591. }
  592. __Error.WinIOError(errorCode, String.Empty);
  593. }
  594. // will set state to Connected when EndWait is called
  595. if (cancellationHelper != null) {
  596. cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
  597. }
  598. return asyncResult;
  599. }
  600. // Async version of WaitForConnection. See comments for WaitForConnection for more info.
  601. [System.Security.SecurityCritical]
  602. public unsafe void EndWaitForConnection(IAsyncResult asyncResult) {
  603. CheckConnectOperationsServer();
  604. if (asyncResult == null) {
  605. throw new ArgumentNullException("asyncResult");
  606. }
  607. if (!IsAsync) {
  608. throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeNotAsync));
  609. }
  610. PipeAsyncResult afsar = asyncResult as PipeAsyncResult;
  611. if (afsar == null) {
  612. __Error.WrongAsyncResult();
  613. }
  614. // Ensure we can't get into any ----s by doing an interlocked
  615. // CompareExchange here. Avoids corrupting memory via freeing the
  616. // NativeOverlapped class or GCHandle twice. --
  617. if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0)) {
  618. __Error.EndWaitForConnectionCalledTwice();
  619. }
  620. IOCancellationHelper cancellationHelper = afsar.AsyncState as IOCancellationHelper;
  621. if (cancellationHelper != null) {
  622. cancellationHelper.SetOperationCompleted();
  623. }
  624. // Obtain the WaitHandle, but don't use public property in case we
  625. // delay initialize the manual reset event in the future.
  626. WaitHandle wh = afsar._waitHandle;
  627. if (wh != null) {
  628. // We must block to ensure that ConnectionIOCallback has completed,
  629. // and we should close the WaitHandle in here. AsyncFSCallback
  630. // and the hand-ported imitation version in COMThreadPool.cpp
  631. // are the only places that set this event.
  632. try {
  633. wh.WaitOne();
  634. Debug.Assert(afsar._isComplete == true, "NamedPipeServerStream::EndWaitForConnection - AsyncFSCallback didn't set _isComplete to true!");
  635. }
  636. finally {
  637. wh.Close();
  638. }
  639. }
  640. // We should have freed the overlapped and set it to null either in the Begin
  641. // method (if ConnectNamedPipe completed synchronously) or in AsyncWaitForConnectionCallback.
  642. // If it is not nulled out, we should not be past the above wait:
  643. Debug.Assert(afsar._overlapped == null);
  644. // Now check for any error during the read.
  645. if (afsar._errorCode != 0) {
  646. if (afsar._errorCode == UnsafeNativeMethods.ERROR_OPERATION_ABORTED) {
  647. if (cancellationHelper != null) {
  648. cancellationHelper.ThrowIOOperationAborted();
  649. }
  650. }
  651. __Error.WinIOError(afsar._errorCode, String.Empty);
  652. }
  653. // Success
  654. State = PipeState.Connected;
  655. }
  656. [System.Security.SecurityCritical]
  657. public void Disconnect() {
  658. CheckDisconnectOperations();
  659. // Disconnect the pipe.
  660. if (!UnsafeNativeMethods.DisconnectNamedPipe(InternalHandle)) {
  661. __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty);
  662. }
  663. State = PipeState.Disconnected;
  664. }
  665. // This method calls a delegate while impersonating the client. Note that we will not have
  666. // access to the client's security token until it has written at least once to the pipe
  667. // (and has set its impersonationLevel argument appropriately).
  668. [System.Security.SecurityCritical]
  669. [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal)]
  670. public void RunAsClient(PipeStreamImpersonationWorker impersonationWorker) {
  671. CheckWriteOperations();
  672. ExecuteHelper execHelper = new ExecuteHelper(impersonationWorker, InternalHandle);
  673. RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, execHelper);
  674. // now handle win32 impersonate/revert specific errors by throwing corresponding exceptions
  675. if (execHelper.m_impersonateErrorCode != 0) {
  676. WinIOError(execHelper.m_impersonateErrorCode);
  677. }
  678. else if (execHelper.m_revertImpersonateErrorCode != 0) {
  679. WinIOError(execHelper.m_revertImpersonateErrorCode);
  680. }
  681. }
  682. // the following are needed for CER
  683. private static RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(ImpersonateAndTryCode);
  684. private static RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(RevertImpersonationOnBackout);
  685. [System.Security.SecurityCritical]
  686. private static void ImpersonateAndTryCode(Object helper) {
  687. ExecuteHelper execHelper = (ExecuteHelper)helper;
  688. RuntimeHelpers.PrepareConstrainedRegions();
  689. try { }
  690. finally {
  691. if (UnsafeNativeMethods.ImpersonateNamedPipeClient(execHelper.m_handle)) {
  692. execHelper.m_mustRevert = true;
  693. }
  694. else {
  695. execHelper.m_impersonateErrorCode = Marshal.GetLastWin32Error();
  696. }
  697. }
  698. if (execHelper.m_mustRevert) { // impersonate passed so run user code
  699. execHelper.m_userCode();
  700. }
  701. }
  702. [System.Security.SecurityCritical]
  703. [PrePrepareMethod]
  704. private static void RevertImpersonationOnBackout(Object helper, bool exceptionThrown) {
  705. ExecuteHelper execHelper = (ExecuteHelper)helper;
  706. if (execHelper.m_mustRevert) {
  707. if (!UnsafeNativeMethods.RevertToSelf()) {
  708. execHelper.m_revertImpersonateErrorCode = Marshal.GetLastWin32Error();
  709. }
  710. }
  711. }
  712. internal class ExecuteHelper {
  713. internal PipeStreamImpersonationWorker m_userCode;
  714. internal SafePipeHandle m_handle;
  715. internal bool m_mustRevert;
  716. internal int m_impersonateErrorCode;
  717. internal int m_revertImpersonateErrorCode;
  718. [System.Security.SecurityCritical]
  719. internal ExecuteHelper(PipeStreamImpersonationWorker userCode, SafePipeHandle handle) {
  720. m_userCode = userCode;
  721. m_handle = handle;
  722. }
  723. }
  724. // Gets the username of the connected client. Not that we will not have access to the client's
  725. // username until it has written at least once to the pipe (and has set its impersonationLevel
  726. // argument appropriately).
  727. [System.Security.SecurityCritical]
  728. [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal)]
  729. public String GetImpersonationUserName() {
  730. CheckWriteOperations();
  731. StringBuilder userName = new StringBuilder(UnsafeNativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1);
  732. if (!UnsafeNativeMethods.GetNamedPipeHandleState(InternalHandle, UnsafeNativeMethods.NULL, UnsafeNativeMethods.NULL,
  733. UnsafeNativeMethods.NULL, UnsafeNativeMethods.NULL, userName, userName.Capacity)) {
  734. WinIOError(Marshal.GetLastWin32Error());
  735. }
  736. return userName.ToString();
  737. }
  738. // Callback to be called by the OS when completing the async WaitForConnection operation.
  739. [System.Security.SecurityCritical]
  740. unsafe private static void AsyncWaitForConnectionCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped) {
  741. // Unpack overlapped
  742. Overlapped overlapped = Overlapped.Unpack(pOverlapped);
  743. // Extract async result from overlapped
  744. PipeAsyncResult asyncResult = (PipeAsyncResult)overlapped.AsyncResult;
  745. // Free the pinned overlapped:
  746. Debug.Assert(asyncResult._overlapped == pOverlapped);
  747. Overlapped.Free(pOverlapped);
  748. asyncResult._overlapped = null;
  749. // Special case for when the client has already connected to us.
  750. if (errorCode == UnsafeNativeMethods.ERROR_PIPE_CONNECTED) {
  751. errorCode = 0;
  752. }
  753. asyncResult._errorCode = (int)errorCode;
  754. // Call the user-provided callback. It can and often should
  755. // call EndWaitForConnection. There's no reason to use an async
  756. // delegate here - we're already on a threadpool thread.
  757. // IAsyncResult's completedSynchronously property must return
  758. // false here, saying the user callback was called on another thread.
  759. asyncResult._completedSynchronously = false;
  760. asyncResult._isComplete = true;
  761. // The OS does not signal this event. We must do it ourselves.
  762. ManualResetEvent wh = asyncResult._waitHandle;
  763. if (wh != null) {
  764. Debug.Assert(!wh.SafeWaitHandle.IsClosed, "ManualResetEvent already closed!");
  765. bool r = wh.Set();
  766. Debug.Assert(r, "ManualResetEvent::Set failed!");
  767. if (!r) {
  768. __Error.WinIOError();
  769. }
  770. }
  771. AsyncCallback userCallback = asyncResult._userCallback;
  772. if (userCallback != null) {
  773. userCallback(asyncResult);
  774. }
  775. }
  776. // Server can only connect from Disconnected state
  777. [System.Security.SecurityCritical]
  778. [SuppressMessage("Microsoft.Security","CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification="Consistent with security model")]
  779. private void CheckConnectOperationsServer() {
  780. // we're not checking whether already connected; this allows us to throw IOException
  781. // "pipe is being closed" if other side is closing (as does win32) or no-op if
  782. // already connected
  783. if (InternalHandle == null) {
  784. throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeHandleNotSet));
  785. }
  786. // object disposed
  787. if (State == PipeState.Closed) {
  788. __Error.PipeNotOpen();
  789. }
  790. if (InternalHandle.IsClosed) {
  791. __Error.PipeNotOpen();
  792. }
  793. // IOException
  794. if (State == PipeState.Broken) {
  795. throw new IOException(SR.GetString(SR.IO_IO_PipeBroken));
  796. }
  797. }
  798. // Server is allowed to disconnect from connected and broken states
  799. [System.Security.SecurityCritical]
  800. private void CheckDisconnectOperations() {
  801. // invalid operation
  802. if (State== PipeState.WaitingToConnect) {
  803. throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeNotYetConnected));
  804. }
  805. if (State == PipeState.Disconnected) {
  806. throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeAlreadyDisconnected));
  807. }
  808. if (InternalHandle == null) {
  809. throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeHandleNotSet));
  810. }
  811. // object disposed
  812. if (State == PipeState.Closed) {
  813. __Error.PipeNotOpen();
  814. }
  815. if (InternalHandle.IsClosed) {
  816. __Error.PipeNotOpen();
  817. }
  818. }
  819. }
  820. // Named pipe client. Use this to open the client end of a named pipes created with
  821. // NamedPipeServerStream.
  822. [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
  823. public sealed class NamedPipeClientStream : PipeStream {
  824. // Maximum interval in miliseconds between which cancellation is checked.
  825. // Used by ConnectInternal. 50ms is fairly responsive time but really long time for processor.
  826. private const int CancellationCheckIntervalInMilliseconds = 50;
  827. private string m_normalizedPipePath;
  828. private TokenImpersonationLevel m_impersonationLevel;
  829. private PipeOptions m_pipeOptions;
  830. private HandleInheritability m_inheritability;
  831. private int m_access;
  832. // Creates a named pipe client using default server (same machine, or "."), and PipeDirection.InOut
  833. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  834. [SecuritySafeCritical]
  835. public NamedPipeClientStream(String pipeName)
  836. : this(".", pipeName, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None, HandleInheritability.None) { }
  837. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  838. [SecuritySafeCritical]
  839. public NamedPipeClientStream(String serverName, String pipeName)
  840. : this(serverName, pipeName, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None, HandleInheritability.None) { }
  841. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  842. [SecuritySafeCritical]
  843. public NamedPipeClientStream(String serverName, String pipeName, PipeDirection direction)
  844. : this(serverName, pipeName, direction, PipeOptions.None, TokenImpersonationLevel.None, HandleInheritability.None) { }
  845. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  846. [SecuritySafeCritical]
  847. public NamedPipeClientStream(String serverName, String pipeName, PipeDirection direction,
  848. PipeOptions options)
  849. : this(serverName, pipeName, direction, options, TokenImpersonationLevel.None, HandleInheritability.None) { }
  850. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  851. [SecuritySafeCritical]
  852. public NamedPipeClientStream(String serverName, String pipeName, PipeDirect