Leaked source code of windows server 2003
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.

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