Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

803 lines
23 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. CreateNp.c
  5. Abstract:
  6. This module implements the File Create Named Pipe routine for NPFS called
  7. by the dispatch driver.
  8. Author:
  9. Gary Kimura [GaryKi] 04-Sep-1990
  10. Revision History:
  11. --*/
  12. #include "NpProcs.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_CREATE_NAMED_PIPE)
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, NpCommonCreateNamedPipe)
  19. #pragma alloc_text(PAGE, NpCreateExistingNamedPipe)
  20. #pragma alloc_text(PAGE, NpCreateNewNamedPipe)
  21. #pragma alloc_text(PAGE, NpFsdCreateNamedPipe)
  22. #endif
  23. NTSTATUS
  24. NpFsdCreateNamedPipe (
  25. IN PNPFS_DEVICE_OBJECT NpfsDeviceObject,
  26. IN PIRP Irp
  27. )
  28. /*++
  29. Routine Description:
  30. This routine implements the FSD part of the NtCreateNamedPipeFile
  31. API call.
  32. Arguments:
  33. NpfsDeviceObject - Supplies the device object to use.
  34. Irp - Supplies the Irp being processed
  35. Return Value:
  36. NTSTATUS - The Fsd status for the Irp
  37. --*/
  38. {
  39. NTSTATUS Status;
  40. PAGED_CODE();
  41. DebugTrace(+1, Dbg, "NpFsdCreateNamedPipe\n", 0);
  42. //
  43. // Call the common create routine.
  44. //
  45. FsRtlEnterFileSystem();
  46. Status = NpCommonCreateNamedPipe( NpfsDeviceObject, Irp );
  47. FsRtlExitFileSystem();
  48. //
  49. // And return to our caller
  50. //
  51. DebugTrace(-1, Dbg, "NpFsdCreateNamedPipe -> %08lx\n", Status );
  52. return Status;
  53. }
  54. //
  55. // Internal support routine
  56. //
  57. NTSTATUS
  58. NpCommonCreateNamedPipe (
  59. IN PNPFS_DEVICE_OBJECT NpfsDeviceObject,
  60. IN PIRP Irp
  61. )
  62. /*++
  63. Routine Description:
  64. This is the common routine for creating/opening a file.
  65. Arguments:
  66. Irp - Supplies the Irp to process
  67. Return Value:
  68. NTSTATUS - the return status for the operation
  69. --*/
  70. {
  71. NTSTATUS Status;
  72. PIO_STACK_LOCATION IrpSp;
  73. PFILE_OBJECT FileObject;
  74. PFILE_OBJECT RelatedFileObject;
  75. UNICODE_STRING FileName;
  76. ACCESS_MASK DesiredAccess;
  77. ULONG Options;
  78. USHORT ShareAccess;
  79. PNAMED_PIPE_CREATE_PARAMETERS Parameters;
  80. NAMED_PIPE_TYPE NamedPipeType;
  81. READ_MODE ServerReadMode;
  82. COMPLETION_MODE ServerCompletionMode;
  83. ULONG MaximumInstances;
  84. ULONG InboundQuota;
  85. ULONG OutboundQuota;
  86. LARGE_INTEGER DefaultTimeout;
  87. BOOLEAN TimeoutSpecified;
  88. PEPROCESS CreatorProcess;
  89. BOOLEAN CaseInsensitive = TRUE; //**** Make all searches case insensitive
  90. PFCB Fcb;
  91. ULONG CreateDisposition;
  92. UNICODE_STRING RemainingPart;
  93. LIST_ENTRY DeferredList;
  94. PAGED_CODE();
  95. InitializeListHead (&DeferredList);
  96. //
  97. // Reference our input parameters to make things easier
  98. //
  99. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  100. FileObject = IrpSp->FileObject;
  101. RelatedFileObject = IrpSp->FileObject->RelatedFileObject;
  102. FileName = *(PUNICODE_STRING)&IrpSp->FileObject->FileName;
  103. DesiredAccess = IrpSp->Parameters.CreatePipe.SecurityContext->DesiredAccess;
  104. Options = IrpSp->Parameters.CreatePipe.Options;
  105. ShareAccess = IrpSp->Parameters.CreatePipe.ShareAccess;
  106. Parameters = IrpSp->Parameters.CreatePipe.Parameters;
  107. NamedPipeType = Parameters->NamedPipeType;
  108. ServerReadMode = Parameters->ReadMode;
  109. ServerCompletionMode = Parameters->CompletionMode;
  110. MaximumInstances = Parameters->MaximumInstances;
  111. InboundQuota = Parameters->InboundQuota;
  112. OutboundQuota = Parameters->OutboundQuota;
  113. DefaultTimeout = Parameters->DefaultTimeout;
  114. TimeoutSpecified = Parameters->TimeoutSpecified;
  115. CreatorProcess = IoGetRequestorProcess( Irp );
  116. DebugTrace(+1, Dbg, "NpCommonCreateNamedPipe\n", 0 );
  117. DebugTrace( 0, Dbg, "NpfsDeviceObject = %08lx\n", NpfsDeviceObject );
  118. DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
  119. DebugTrace( 0, Dbg, "FileObject = %08lx\n", FileObject );
  120. DebugTrace( 0, Dbg, "RelatedFileObject = %08lx\n", RelatedFileObject );
  121. DebugTrace( 0, Dbg, "FileName = %Z\n", &FileName );
  122. DebugTrace( 0, Dbg, "DesiredAccess = %08lx\n", DesiredAccess );
  123. DebugTrace( 0, Dbg, "Options = %08lx\n", Options );
  124. DebugTrace( 0, Dbg, "ShareAccess = %08lx\n", ShareAccess );
  125. DebugTrace( 0, Dbg, "Parameters = %08lx\n", Parameters );
  126. DebugTrace( 0, Dbg, "NamedPipeType = %08lx\n", NamedPipeType );
  127. DebugTrace( 0, Dbg, "ServerReadMode = %08lx\n", ServerReadMode );
  128. DebugTrace( 0, Dbg, "ServerCompletionMode = %08lx\n", ServerCompletionMode );
  129. DebugTrace( 0, Dbg, "MaximumInstances = %08lx\n", MaximumInstances );
  130. DebugTrace( 0, Dbg, "InboundQuota = %08lx\n", InboundQuota );
  131. DebugTrace( 0, Dbg, "OutboundQuota = %08lx\n", OutboundQuota );
  132. DebugTrace( 0, Dbg, "DefaultTimeout = %08lx\n", DefaultTimeout );
  133. DebugTrace( 0, Dbg, "TimeoutSpecified = %08lx\n", TimeoutSpecified );
  134. DebugTrace( 0, Dbg, "CreatorProcess = %08lx\n", CreatorProcess );
  135. //
  136. // Extract the create disposition
  137. //
  138. CreateDisposition = (Options >> 24) & 0x000000ff;
  139. //
  140. // Acquire exclusive access to the Vcb.
  141. //
  142. NpAcquireExclusiveVcb();
  143. try {
  144. //
  145. // If there is a related file object then this is a relative open
  146. // and it better be the root dcb. Both the then and the else clause
  147. // return an Fcb.
  148. //
  149. if (RelatedFileObject != NULL) {
  150. PDCB Dcb;
  151. Dcb = RelatedFileObject->FsContext;
  152. if (NodeType(Dcb) != NPFS_NTC_ROOT_DCB ||
  153. FileName.Length < 2 || FileName.Buffer[0] == L'\\') {
  154. DebugTrace(0, Dbg, "Bad file name\n", 0);
  155. try_return( Status = STATUS_OBJECT_NAME_INVALID );
  156. }
  157. Status = NpFindRelativePrefix( Dcb, &FileName, CaseInsensitive, &RemainingPart, &Fcb);
  158. if (!NT_SUCCESS (Status)) {
  159. try_return(NOTHING);
  160. }
  161. } else {
  162. //
  163. // The only nonrelative name we allow are of the form "\pipe-name"
  164. //
  165. if ((FileName.Length <= 2) || (FileName.Buffer[0] != L'\\')) {
  166. DebugTrace(0, Dbg, "Bad file name\n", 0);
  167. try_return( Status = STATUS_OBJECT_NAME_INVALID );
  168. }
  169. Fcb = NpFindPrefix( &FileName, CaseInsensitive, &RemainingPart );
  170. }
  171. //
  172. // If the remaining name is empty then we better have an fcb
  173. // otherwise we were given a illegal object name.
  174. //
  175. if (RemainingPart.Length == 0) {
  176. if (Fcb->NodeTypeCode == NPFS_NTC_FCB) {
  177. DebugTrace(0, Dbg, "Create existing named pipe, Fcb = %08lx\n", Fcb );
  178. Irp->IoStatus = NpCreateExistingNamedPipe( Fcb,
  179. FileObject,
  180. DesiredAccess,
  181. IrpSp->Parameters.CreatePipe.SecurityContext->AccessState,
  182. (KPROCESSOR_MODE)(FlagOn(IrpSp->Flags, SL_FORCE_ACCESS_CHECK) ?
  183. UserMode : Irp->RequestorMode),
  184. CreateDisposition,
  185. ShareAccess,
  186. ServerReadMode,
  187. ServerCompletionMode,
  188. InboundQuota,
  189. OutboundQuota,
  190. CreatorProcess,
  191. &DeferredList );
  192. Status = Irp->IoStatus.Status;
  193. } else {
  194. DebugTrace(0, Dbg, "Illegal object name\n", 0);
  195. Status = STATUS_OBJECT_NAME_INVALID;
  196. }
  197. } else {
  198. //
  199. // The remaining name is not empty so we better have the root Dcb
  200. //
  201. if (Fcb->NodeTypeCode == NPFS_NTC_ROOT_DCB) {
  202. DebugTrace(0, Dbg, "Create new named pipe, Fcb = %08lx\n", Fcb );
  203. Irp->IoStatus = NpCreateNewNamedPipe( Fcb,
  204. FileObject,
  205. FileName,
  206. DesiredAccess,
  207. IrpSp->Parameters.CreatePipe.SecurityContext->AccessState,
  208. CreateDisposition,
  209. ShareAccess,
  210. NamedPipeType,
  211. ServerReadMode,
  212. ServerCompletionMode,
  213. MaximumInstances,
  214. InboundQuota,
  215. OutboundQuota,
  216. DefaultTimeout,
  217. TimeoutSpecified,
  218. CreatorProcess,
  219. &DeferredList );
  220. Status = Irp->IoStatus.Status;
  221. } else {
  222. DebugTrace(0, Dbg, "Illegal object name\n", 0);
  223. Status = STATUS_OBJECT_NAME_INVALID;
  224. }
  225. }
  226. try_exit: NOTHING;
  227. } finally {
  228. NpReleaseVcb( );
  229. //
  230. // complete any deferred IRPs now we have dropped the locks
  231. //
  232. NpCompleteDeferredIrps (&DeferredList);
  233. NpCompleteRequest( Irp, Status );
  234. DebugTrace(-1, Dbg, "NpCommonCreateNamedPipe -> %08lx\n", Status);
  235. }
  236. return Status;
  237. }
  238. //
  239. // Internal support routine
  240. //
  241. IO_STATUS_BLOCK
  242. NpCreateNewNamedPipe (
  243. IN PROOT_DCB RootDcb,
  244. IN PFILE_OBJECT FileObject,
  245. IN UNICODE_STRING FileName,
  246. IN ACCESS_MASK DesiredAccess,
  247. IN PACCESS_STATE AccessState,
  248. IN ULONG CreateDisposition,
  249. IN USHORT ShareAccess,
  250. IN ULONG NamedPipeType,
  251. IN ULONG ServerReadMode,
  252. IN ULONG ServerCompletionMode,
  253. IN ULONG MaximumInstances,
  254. IN ULONG InboundQuota,
  255. IN ULONG OutboundQuota,
  256. IN LARGE_INTEGER DefaultTimeout,
  257. IN BOOLEAN TimeoutSpecified,
  258. IN PEPROCESS CreatorProcess,
  259. IN PLIST_ENTRY DeferredList
  260. )
  261. /*++
  262. Routine Description:
  263. This routine performs the operation for creating a new named pipe
  264. Fcb and its first instance. This routine does not complete any
  265. IRP, it preforms its function and then returns an iosb.
  266. Arguments:
  267. RootDcb - Supplies the root dcb where this is going to be added
  268. FileObject - Supplies the file object associated with the first
  269. instance of the named pipe
  270. FileName - Supplies the name of the named pipe (not qualified i.e.,
  271. simply "pipe-name" and not "\pipe-name"
  272. DesiredAccess - Supplies the callers desired access
  273. AccessState - Supplies the access state from the irp
  274. CreateDisposition - Supplies the callers create disposition flags
  275. ShareAccess - Supplies the caller specified share access
  276. NamedPipeType - Supplies the named type type
  277. ServerReadMode - Supplies the named pipe read mode
  278. ServerCompletionMode - Supplies the named pipe completion mode
  279. MaximumInstances - Supplies the maximum instances for the named pipe
  280. InboundQuota - Supplies the inbound quota amount
  281. OutboundQuota - Supplies the outbound quota amount
  282. DefaultTimeout - Supplies the default time out value
  283. TimeoutSpecified - Indicates if the time out value was supplied by the
  284. caller.
  285. CreatorProcess - Supplies the process creating the named pipe
  286. DeferredList - List of IRP's to complete after we release the locks
  287. Return Value:
  288. IO_STATUS_BLOCK - Returns the appropriate status for the operation
  289. --*/
  290. {
  291. IO_STATUS_BLOCK Iosb={0};
  292. NAMED_PIPE_CONFIGURATION NamedPipeConfiguration;
  293. PSECURITY_DESCRIPTOR NewSecurityDescriptor, CachedSecurityDescriptor;
  294. PFCB Fcb;
  295. PCCB Ccb;
  296. PAGED_CODE();
  297. DebugTrace(+1, Dbg, "NpCreateNewNamedPipe\n", 0 );
  298. //
  299. // Check the parameters that must be supplied for a new named pipe
  300. // (i.e., the create disposition, timeout, and max instances better
  301. // be greater than zero)
  302. //
  303. if (!TimeoutSpecified || MaximumInstances <= 0) {
  304. Iosb.Status = STATUS_INVALID_PARAMETER;
  305. return Iosb;
  306. }
  307. //
  308. // The default timeout needs to be less than zero otherwise it
  309. // is an absolute time out which doesn't make sense.
  310. //
  311. if (DefaultTimeout.QuadPart >= 0) {
  312. Iosb.Status = STATUS_INVALID_PARAMETER;
  313. return Iosb;
  314. }
  315. if (CreateDisposition == FILE_OPEN) {
  316. Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND;
  317. return Iosb;
  318. }
  319. //
  320. // Determine the pipe configuration
  321. //
  322. if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE)) {
  323. NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX;
  324. } else if (ShareAccess == FILE_SHARE_READ) {
  325. NamedPipeConfiguration = FILE_PIPE_OUTBOUND;
  326. } else if (ShareAccess == FILE_SHARE_WRITE) {
  327. NamedPipeConfiguration = FILE_PIPE_INBOUND;
  328. } else {
  329. Iosb.Status = STATUS_INVALID_PARAMETER;
  330. return Iosb;
  331. }
  332. //
  333. // Check that if named pipe type is byte stream then the read mode is
  334. // not message mode
  335. //
  336. if ((NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE) &&
  337. (ServerReadMode == FILE_PIPE_MESSAGE_MODE)) {
  338. Iosb.Status = STATUS_INVALID_PARAMETER;
  339. return Iosb;
  340. }
  341. //
  342. // Create a new fcb and ccb for the named pipe
  343. //
  344. Iosb.Status = NpCreateFcb( RootDcb,
  345. &FileName,
  346. MaximumInstances,
  347. DefaultTimeout,
  348. NamedPipeConfiguration,
  349. NamedPipeType,
  350. &Fcb );
  351. if (!NT_SUCCESS (Iosb.Status)) {
  352. return Iosb;
  353. }
  354. Iosb.Status = NpCreateCcb( Fcb,
  355. FileObject,
  356. FILE_PIPE_LISTENING_STATE,
  357. ServerReadMode,
  358. ServerCompletionMode,
  359. InboundQuota,
  360. OutboundQuota,
  361. &Ccb );
  362. if (!NT_SUCCESS (Iosb.Status)) {
  363. NpDeleteFcb( Fcb, DeferredList );
  364. return Iosb;
  365. }
  366. //
  367. // Set the security descriptor in the Fcb
  368. //
  369. SeLockSubjectContext( &AccessState->SubjectSecurityContext );
  370. Iosb.Status = SeAssignSecurity( NULL,
  371. AccessState->SecurityDescriptor,
  372. &NewSecurityDescriptor,
  373. FALSE,
  374. &AccessState->SubjectSecurityContext,
  375. IoGetFileObjectGenericMapping(),
  376. PagedPool );
  377. SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
  378. if (!NT_SUCCESS(Iosb.Status)) {
  379. DebugTrace(0, Dbg, "Error calling SeAssignSecurity\n", 0 );
  380. NpDeleteCcb( Ccb, DeferredList );
  381. NpDeleteFcb( Fcb, DeferredList );
  382. return Iosb;
  383. }
  384. Iosb.Status = ObLogSecurityDescriptor (NewSecurityDescriptor,
  385. &CachedSecurityDescriptor,
  386. 1);
  387. NpFreePool (NewSecurityDescriptor);
  388. if (!NT_SUCCESS(Iosb.Status)) {
  389. DebugTrace(0, Dbg, "Error calling ObLogSecurityDescriptor\n", 0 );
  390. NpDeleteCcb( Ccb, DeferredList );
  391. NpDeleteFcb( Fcb, DeferredList );
  392. return Iosb;
  393. }
  394. Fcb->SecurityDescriptor = CachedSecurityDescriptor;
  395. //
  396. // Set the file object back pointers and our pointer to the
  397. // server file object.
  398. //
  399. NpSetFileObject( FileObject, Ccb, Ccb->NonpagedCcb, FILE_PIPE_SERVER_END );
  400. Ccb->FileObject[ FILE_PIPE_SERVER_END ] = FileObject;
  401. //
  402. // Check to see if we need to notify outstanding Irps for any
  403. // changes (i.e., we just added a named pipe).
  404. //
  405. NpCheckForNotify( RootDcb, TRUE, DeferredList );
  406. //
  407. // Set our return status
  408. //
  409. Iosb.Status = STATUS_SUCCESS;
  410. Iosb.Information = FILE_CREATED;
  411. DebugTrace(-1, Dbg, "NpCreateNewNamedPipe -> %08lx\n", Iosb.Status);
  412. return Iosb;
  413. }
  414. //
  415. // Internal support routine
  416. //
  417. IO_STATUS_BLOCK
  418. NpCreateExistingNamedPipe (
  419. IN PFCB Fcb,
  420. IN PFILE_OBJECT FileObject,
  421. IN ACCESS_MASK DesiredAccess,
  422. IN PACCESS_STATE AccessState,
  423. IN KPROCESSOR_MODE RequestorMode,
  424. IN ULONG CreateDisposition,
  425. IN USHORT ShareAccess,
  426. IN ULONG ServerReadMode,
  427. IN ULONG ServerCompletionMode,
  428. IN ULONG InboundQuota,
  429. IN ULONG OutboundQuota,
  430. IN PEPROCESS CreatorProcess,
  431. IN PLIST_ENTRY DeferredList
  432. )
  433. /*++
  434. Routine Description:
  435. This routine performs the operation for creating a new instance of
  436. an existing named pipe. This routine does not complete any
  437. IRP, it preforms its function and then returns an iosb.
  438. Arguments:
  439. Fcb - Supplies the Fcb for the named pipe being created
  440. FileObject - Supplies the file object associated with this
  441. instance of the named pipe
  442. DesiredAccess - Supplies the callers desired access
  443. CreateDisposition - Supplies the callers create disposition flags
  444. ShareAccess - Supplies the caller specified share access
  445. ServerReadMode - Supplies the named pipe read mode
  446. ServerCompletionMode - Supplies the named pipe completion mode
  447. InboundQuota - Supplies the inbound quota amount
  448. OutboundQuota - Supplies the outbound quota amount
  449. CreatorProcess - Supplies the process creating the named pipe
  450. DeferredList - List of IRP's to complete after we release the locks
  451. Return Value:
  452. IO_STATUS_BLOCK - Returns the appropriate status for the operation
  453. --*/
  454. {
  455. IO_STATUS_BLOCK Iosb;
  456. BOOLEAN AccessGranted;
  457. ACCESS_MASK GrantedAccess;
  458. UNICODE_STRING Name;
  459. PCCB Ccb;
  460. NAMED_PIPE_CONFIGURATION NamedPipeConfiguration;
  461. USHORT OriginalShareAccess;
  462. PPRIVILEGE_SET Privileges = NULL;
  463. PAGED_CODE();
  464. DebugTrace(+1, Dbg, "NpCreateExistingNamedPipe\n", 0 );
  465. //
  466. // To create a new instance of a named pipe the caller
  467. // must have "create pipe instance" access. Even if the
  468. // caller didn't explicitly request this access, the call
  469. // to us implicitly requests the bit. So now jam the bit
  470. // into the desired access field
  471. //
  472. DesiredAccess |= FILE_CREATE_PIPE_INSTANCE;
  473. //
  474. // First do an access check for the user against the Fcb
  475. //
  476. SeLockSubjectContext( &AccessState->SubjectSecurityContext );
  477. AccessGranted = SeAccessCheck( Fcb->SecurityDescriptor,
  478. &AccessState->SubjectSecurityContext,
  479. TRUE, // Tokens are locked
  480. DesiredAccess,
  481. 0,
  482. &Privileges,
  483. IoGetFileObjectGenericMapping(),
  484. RequestorMode,
  485. &GrantedAccess,
  486. &Iosb.Status );
  487. if (Privileges != NULL) {
  488. (VOID) SeAppendPrivileges(
  489. AccessState,
  490. Privileges
  491. );
  492. SeFreePrivileges( Privileges );
  493. }
  494. //
  495. // Transfer over the access masks from what is desired to
  496. // what we just granted. Also patch up the maximum allowed
  497. // case because we just did the mapping for it. Note that if
  498. // the user didn't ask for maximum allowed then the following
  499. // code is still okay because we'll just zero a zero bit.
  500. //
  501. if (AccessGranted) {
  502. AccessState->PreviouslyGrantedAccess |= GrantedAccess;
  503. AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
  504. }
  505. RtlInitUnicodeString( &Name, L"NamedPipe" );
  506. SeOpenObjectAuditAlarm( &Name,
  507. NULL,
  508. &FileObject->FileName,
  509. Fcb->SecurityDescriptor,
  510. AccessState,
  511. FALSE,
  512. AccessGranted,
  513. RequestorMode,
  514. &AccessState->GenerateOnClose );
  515. SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
  516. if (!AccessGranted) {
  517. DebugTrace(0, Dbg, "Access Denied\n", 0 );
  518. return Iosb;
  519. }
  520. //
  521. // Check that we're still under the maximum instances count
  522. //
  523. if (Fcb->OpenCount >= Fcb->Specific.Fcb.MaximumInstances) {
  524. Iosb.Status = STATUS_INSTANCE_NOT_AVAILABLE;
  525. return Iosb;
  526. }
  527. if (CreateDisposition == FILE_CREATE) {
  528. Iosb.Status = STATUS_ACCESS_DENIED;
  529. return Iosb;
  530. }
  531. //
  532. // From the pipe configuration determine the share access specified
  533. // on the first instance of this pipe. All subsequent instances must
  534. // specify the same share access.
  535. //
  536. NamedPipeConfiguration = Fcb->Specific.Fcb.NamedPipeConfiguration;
  537. if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND) {
  538. OriginalShareAccess = FILE_SHARE_READ;
  539. } else if (NamedPipeConfiguration == FILE_PIPE_INBOUND) {
  540. OriginalShareAccess = FILE_SHARE_WRITE;
  541. } else {
  542. OriginalShareAccess = (FILE_SHARE_READ | FILE_SHARE_WRITE);
  543. }
  544. if (OriginalShareAccess != ShareAccess) {
  545. Iosb.Status = STATUS_ACCESS_DENIED;
  546. return Iosb;
  547. }
  548. //
  549. // Create a new ccb for the named pipe
  550. //
  551. Iosb.Status = NpCreateCcb( Fcb,
  552. FileObject,
  553. FILE_PIPE_LISTENING_STATE,
  554. ServerReadMode,
  555. ServerCompletionMode,
  556. InboundQuota,
  557. OutboundQuota,
  558. &Ccb );
  559. if (!NT_SUCCESS (Iosb.Status)) {
  560. return Iosb;
  561. }
  562. //
  563. // Wake up anyone waiting for an instance to go into the listening state
  564. //
  565. Iosb.Status = NpCancelWaiter (&NpVcb->WaitQueue,
  566. &Fcb->FullFileName,
  567. STATUS_SUCCESS,
  568. DeferredList);
  569. if (!NT_SUCCESS (Iosb.Status)) {
  570. Ccb->Fcb->ServerOpenCount -= 1;
  571. NpDeleteCcb (Ccb, DeferredList);
  572. return Iosb;
  573. }
  574. //
  575. // Set the file object back pointers and our pointer to the
  576. // server file object.
  577. //
  578. NpSetFileObject( FileObject, Ccb, Ccb->NonpagedCcb, FILE_PIPE_SERVER_END );
  579. Ccb->FileObject[ FILE_PIPE_SERVER_END ] = FileObject;
  580. //
  581. // Check to see if we need to notify outstanding Irps for
  582. // changes (i.e., we just added a new instance of a named pipe).
  583. //
  584. NpCheckForNotify( Fcb->ParentDcb, FALSE, DeferredList );
  585. //
  586. // Set our return status
  587. //
  588. Iosb.Status = STATUS_SUCCESS;
  589. Iosb.Information = FILE_CREATED;
  590. return Iosb;
  591. }
  592.