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.

662 lines
16 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. create.c
  5. Abstract:
  6. This module implements the file create routine for MSFS called by the
  7. dispatch driver.
  8. Author:
  9. Manny Weiser (mannyw) 16-Jan-1991
  10. Revision History:
  11. --*/
  12. #include "mailslot.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_CREATE)
  17. //
  18. // Local procedure prototypes
  19. //
  20. NTSTATUS
  21. MsCommonCreate (
  22. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  23. IN PIRP Irp
  24. );
  25. IO_STATUS_BLOCK
  26. MsCreateClientEnd(
  27. IN PFCB Fcb,
  28. IN PFILE_OBJECT FileObject,
  29. IN ACCESS_MASK DesiredAccess,
  30. IN USHORT ShareAccess,
  31. IN PACCESS_STATE AccessState,
  32. IN KPROCESSOR_MODE RequestorMode,
  33. IN PETHREAD UserThread
  34. );
  35. IO_STATUS_BLOCK
  36. MsOpenMailslotFileSystem (
  37. IN PVCB Vcb,
  38. IN PFILE_OBJECT FileObject,
  39. IN ACCESS_MASK DesiredAccess,
  40. IN USHORT ShareAccess
  41. );
  42. IO_STATUS_BLOCK
  43. MsOpenMailslotRootDirectory (
  44. IN PROOT_DCB RootDcb,
  45. IN PFILE_OBJECT FileObject,
  46. IN ACCESS_MASK DesiredAccess,
  47. IN USHORT ShareAccess
  48. );
  49. #ifdef ALLOC_PRAGMA
  50. #pragma alloc_text( PAGE, MsCommonCreate )
  51. #pragma alloc_text( PAGE, MsCreateClientEnd )
  52. #pragma alloc_text( PAGE, MsFsdCreate )
  53. #pragma alloc_text( PAGE, MsOpenMailslotFileSystem )
  54. #pragma alloc_text( PAGE, MsOpenMailslotRootDirectory )
  55. #endif
  56. NTSTATUS
  57. MsFsdCreate (
  58. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  59. IN PIRP Irp
  60. )
  61. /*++
  62. Routine Description:
  63. This routine implements the FSD part of the NtCreateFile and NtOpenFile
  64. API calls.
  65. Arguments:
  66. MsfsDeviceObject - Supplies the device object to use.
  67. Irp - Supplies the Irp being processed
  68. Return Value:
  69. NTSTATUS - The Fsd status for the IRP.
  70. --*/
  71. {
  72. NTSTATUS status;
  73. PAGED_CODE();
  74. DebugTrace(+1, Dbg, "MsFsdCreate\n", 0);
  75. //
  76. // Call the common create routine.
  77. //
  78. FsRtlEnterFileSystem();
  79. status = MsCommonCreate( MsfsDeviceObject, Irp );
  80. FsRtlExitFileSystem();
  81. //
  82. // Return to the caller.
  83. //
  84. DebugTrace(-1, Dbg, "MsFsdCreate -> %08lx\n", status );
  85. return status;
  86. }
  87. NTSTATUS
  88. MsCommonCreate (
  89. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  90. IN PIRP Irp
  91. )
  92. /*++
  93. Routine Description:
  94. This is the common routine for creating/opening a file.
  95. Arguments:
  96. Irp - Supplies the Irp to process
  97. Return Value:
  98. NTSTATUS - the return status for the operation.
  99. --*/
  100. {
  101. NTSTATUS status;
  102. PIO_STACK_LOCATION irpSp;
  103. PFILE_OBJECT fileObject;
  104. PFILE_OBJECT relatedFileObject;
  105. UNICODE_STRING fileName;
  106. ACCESS_MASK desiredAccess;
  107. USHORT shareAccess;
  108. BOOLEAN caseInsensitive = TRUE; //**** Make all searches case insensitive
  109. PVCB vcb;
  110. PFCB fcb;
  111. UNICODE_STRING remainingPart;
  112. PAGED_CODE();
  113. //
  114. // Make local copies of our input parameters to make things easier.
  115. //
  116. irpSp = IoGetCurrentIrpStackLocation( Irp );
  117. fileObject = irpSp->FileObject;
  118. relatedFileObject = irpSp->FileObject->RelatedFileObject;
  119. fileName = *(PUNICODE_STRING)&irpSp->FileObject->FileName;
  120. desiredAccess = irpSp->Parameters.Create.SecurityContext->DesiredAccess;
  121. shareAccess = irpSp->Parameters.Create.ShareAccess;
  122. DebugTrace(+1, Dbg, "MsCommonCreate\n", 0 );
  123. DebugTrace( 0, Dbg, "MsfsDeviceObject = %08lx\n", (ULONG)MsfsDeviceObject );
  124. DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp );
  125. DebugTrace( 0, Dbg, "FileObject = %08lx\n", (ULONG)fileObject );
  126. DebugTrace( 0, Dbg, "relatedFileObject = %08lx\n", (ULONG)relatedFileObject );
  127. DebugTrace( 0, Dbg, "FileName = %wZ\n", (ULONG)&fileName );
  128. DebugTrace( 0, Dbg, "DesiredAccess = %08lx\n", desiredAccess );
  129. DebugTrace( 0, Dbg, "ShareAccess = %08lx\n", shareAccess );
  130. //
  131. // Get the VCB we are trying to access.
  132. //
  133. vcb = &MsfsDeviceObject->Vcb;
  134. //
  135. // Acquire exclusive access to the VCB.
  136. //
  137. MsAcquireExclusiveVcb( vcb );
  138. try {
  139. //
  140. // Check if we are trying to open the mailslot file system
  141. // (i.e., the Vcb).
  142. //
  143. if ((fileName.Length == 0) &&
  144. ((relatedFileObject == NULL) || (
  145. NodeType(relatedFileObject->FsContext) == MSFS_NTC_VCB))) {
  146. DebugTrace(0, Dbg, "Open mailslot file system\n", 0);
  147. Irp->IoStatus = MsOpenMailslotFileSystem( vcb,
  148. fileObject,
  149. desiredAccess,
  150. shareAccess );
  151. status = Irp->IoStatus.Status;
  152. try_return( NOTHING );
  153. }
  154. //
  155. // Check if we are trying to open the root directory.
  156. //
  157. if (((fileName.Length == sizeof(WCHAR)) &&
  158. (fileName.Buffer[0] == L'\\') &&
  159. (relatedFileObject == NULL))
  160. ||
  161. ((fileName.Length == 0) && (NodeType(
  162. relatedFileObject->FsContext) == MSFS_NTC_ROOT_DCB))) {
  163. DebugTrace(0, Dbg, "Open root directory system\n", 0);
  164. Irp->IoStatus = MsOpenMailslotRootDirectory( vcb->RootDcb,
  165. fileObject,
  166. desiredAccess,
  167. shareAccess );
  168. status = Irp->IoStatus.Status;
  169. try_return( NOTHING );
  170. }
  171. //
  172. // If there is a related file object then this is a relative open
  173. // and it better be the root DCB. Both the then and the else clause
  174. // return an FCB.
  175. //
  176. if (relatedFileObject != NULL) {
  177. PDCB dcb;
  178. dcb = relatedFileObject->FsContext;
  179. if (NodeType(dcb) != MSFS_NTC_ROOT_DCB) {
  180. DebugTrace(0, Dbg, "Bad file name\n", 0);
  181. try_return( status = STATUS_OBJECT_NAME_INVALID );
  182. }
  183. status = MsFindRelativePrefix( dcb,
  184. &fileName,
  185. caseInsensitive,
  186. &remainingPart,
  187. &fcb );
  188. if (!NT_SUCCESS (status)) {
  189. try_return( NOTHING );
  190. }
  191. } else {
  192. //
  193. // The only nonrelative name we allow are of the form
  194. // "\mailslot-name".
  195. //
  196. if ((fileName.Length <= sizeof( WCHAR )) || (fileName.Buffer[0] != L'\\')) {
  197. DebugTrace(0, Dbg, "Bad file name\n", 0);
  198. try_return( status = STATUS_OBJECT_NAME_INVALID );
  199. }
  200. fcb = MsFindPrefix( vcb,
  201. &fileName,
  202. caseInsensitive,
  203. &remainingPart );
  204. }
  205. //
  206. // If the remaining name is not empty then we have an error, either
  207. // we have an illegal name or a non-existent name.
  208. //
  209. if (remainingPart.Length != 0) {
  210. if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) {
  211. //
  212. // We were given a name such as "\mailslot-name\another-name"
  213. //
  214. DebugTrace(0, Dbg, "Illegal object name\n", 0);
  215. status = STATUS_OBJECT_NAME_INVALID;
  216. } else {
  217. //
  218. // We were given a non-existent name
  219. //
  220. DebugTrace(0, Dbg, "non-existent name\n", 0);
  221. status = STATUS_OBJECT_NAME_NOT_FOUND;
  222. }
  223. } else {
  224. //
  225. // The remaining name is empty so we better have an FCB otherwise
  226. // we have an invalid object name.
  227. //
  228. if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) {
  229. DebugTrace(0,
  230. Dbg,
  231. "Create client end mailslot, Fcb = %08lx\n",
  232. (ULONG)fcb );
  233. Irp->IoStatus = MsCreateClientEnd( fcb,
  234. fileObject,
  235. desiredAccess,
  236. shareAccess,
  237. irpSp->Parameters.Create.SecurityContext->AccessState,
  238. Irp->RequestorMode,
  239. Irp->Tail.Overlay.Thread
  240. );
  241. status = Irp->IoStatus.Status;
  242. } else {
  243. DebugTrace(0, Dbg, "Illegal object name\n", 0);
  244. status = STATUS_OBJECT_NAME_INVALID;
  245. }
  246. }
  247. try_exit: NOTHING;
  248. } finally {
  249. MsReleaseVcb( vcb );
  250. //
  251. // Complete the IRP and return to the caller.
  252. //
  253. MsCompleteRequest( Irp, status );
  254. DebugTrace(-1, Dbg, "MsCommonCreate -> %08lx\n", status);
  255. }
  256. return status;
  257. }
  258. IO_STATUS_BLOCK
  259. MsCreateClientEnd (
  260. IN PFCB Fcb,
  261. IN PFILE_OBJECT FileObject,
  262. IN ACCESS_MASK DesiredAccess,
  263. IN USHORT ShareAccess,
  264. IN PACCESS_STATE AccessState,
  265. IN KPROCESSOR_MODE RequestorMode,
  266. IN PETHREAD UserThread
  267. )
  268. /*++
  269. Routine Description:
  270. This routine performs the operation for opening the client end of a
  271. mailslot. This routine does not complete the IRP, it performs the
  272. function and then returns a status.
  273. Arguments:
  274. Fcb - Supplies the FCB for the mailslot being accessed.
  275. FileObject - Supplies the file object associated with the client end.
  276. DesiredAccess - Supplies the caller's desired access.
  277. ShareAccess - Supplies the caller's share access.
  278. Return Value:
  279. IO_STATUS_BLOCK - Returns the appropriate status for the operation
  280. --*/
  281. {
  282. IO_STATUS_BLOCK iosb;
  283. PCCB ccb;
  284. BOOLEAN accessGranted;
  285. ACCESS_MASK grantedAccess;
  286. UNICODE_STRING name;
  287. PPRIVILEGE_SET Privileges = NULL;
  288. PAGED_CODE();
  289. DebugTrace(+1, Dbg, "MsCreateClientEnd\n", 0 );
  290. try {
  291. //
  292. // Lock out mods to the FCB's security descriptor.
  293. //
  294. MsAcquireSharedFcb( Fcb );
  295. SeLockSubjectContext( &AccessState->SubjectSecurityContext );
  296. //
  297. // First do an access check for the user against the Fcb
  298. //
  299. accessGranted = SeAccessCheck( Fcb->SecurityDescriptor,
  300. &AccessState->SubjectSecurityContext,
  301. TRUE, // Tokens are locked
  302. DesiredAccess,
  303. 0,
  304. &Privileges,
  305. IoGetFileObjectGenericMapping(),
  306. RequestorMode,
  307. &grantedAccess,
  308. &iosb.Status );
  309. if (Privileges != NULL) {
  310. (VOID) SeAppendPrivileges(
  311. AccessState,
  312. Privileges
  313. );
  314. SeFreePrivileges( Privileges );
  315. }
  316. if (accessGranted) {
  317. AccessState->PreviouslyGrantedAccess |= grantedAccess;
  318. AccessState->RemainingDesiredAccess &= ~(grantedAccess | MAXIMUM_ALLOWED);
  319. }
  320. RtlInitUnicodeString( &name, L"Mailslot" );
  321. SeOpenObjectAuditAlarm( &name,
  322. NULL,
  323. &FileObject->FileName,
  324. Fcb->SecurityDescriptor,
  325. AccessState,
  326. FALSE,
  327. accessGranted,
  328. RequestorMode,
  329. &AccessState->GenerateOnClose );
  330. SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
  331. MsReleaseFcb( Fcb );
  332. if (!accessGranted) {
  333. DebugTrace(0, Dbg, "Access Denied\n", 0 );
  334. try_return( iosb.Status );
  335. }
  336. //
  337. // Now make sure our share access is okay.
  338. //
  339. ASSERT (MsIsAcquiredExclusiveVcb(Fcb->Vcb));
  340. if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( grantedAccess,
  341. ShareAccess,
  342. FileObject,
  343. &Fcb->ShareAccess,
  344. TRUE ))) {
  345. DebugTrace(0, Dbg, "Sharing violation\n", 0);
  346. try_return( NOTHING );
  347. }
  348. //
  349. // Create a CCB for this client.
  350. //
  351. iosb.Status = MsCreateCcb( Fcb, &ccb );
  352. if (!NT_SUCCESS (iosb.Status)) {
  353. IoRemoveShareAccess( FileObject, &Fcb->ShareAccess );
  354. try_return( iosb.Status);
  355. }
  356. //
  357. // Set the file object back pointers and our pointer to the
  358. // server file object.
  359. //
  360. MsSetFileObject( FileObject, ccb, NULL );
  361. ccb->FileObject = FileObject;
  362. //
  363. // And set our return status
  364. //
  365. iosb.Status = STATUS_SUCCESS;
  366. iosb.Information = FILE_OPENED;
  367. try_exit: NOTHING;
  368. } finally {
  369. DebugTrace(-1, Dbg, "MsCreateClientEnd -> %08lx\n", iosb.Status);
  370. }
  371. return iosb;
  372. }
  373. IO_STATUS_BLOCK
  374. MsOpenMailslotFileSystem (
  375. IN PVCB Vcb,
  376. IN PFILE_OBJECT FileObject,
  377. IN ACCESS_MASK DesiredAccess,
  378. IN USHORT ShareAccess
  379. )
  380. {
  381. IO_STATUS_BLOCK iosb = {0};
  382. PAGED_CODE();
  383. DebugTrace(+1, Dbg, "MsOpenMailslotFileSystem, Vcb = %p\n", Vcb);
  384. //
  385. // Set the new share access
  386. //
  387. ASSERT (MsIsAcquiredExclusiveVcb(Vcb));
  388. if (NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess,
  389. ShareAccess,
  390. FileObject,
  391. &Vcb->ShareAccess,
  392. TRUE ))) {
  393. //
  394. // Supply the file object with a referenced pointer to the VCB.
  395. //
  396. MsReferenceVcb (Vcb);
  397. MsSetFileObject( FileObject, Vcb, NULL );
  398. //
  399. // Set the return status.
  400. //
  401. iosb.Status = STATUS_SUCCESS;
  402. iosb.Information = FILE_OPENED;
  403. }
  404. DebugTrace(-1, Dbg, "MsOpenMailslotFileSystem -> Iosb.Status = %08lx\n", iosb.Status);
  405. //
  406. // Return to the caller.
  407. //
  408. return iosb;
  409. }
  410. IO_STATUS_BLOCK
  411. MsOpenMailslotRootDirectory(
  412. IN PROOT_DCB RootDcb,
  413. IN PFILE_OBJECT FileObject,
  414. IN ACCESS_MASK DesiredAccess,
  415. IN USHORT ShareAccess
  416. )
  417. {
  418. IO_STATUS_BLOCK iosb = {0};
  419. PROOT_DCB_CCB ccb;
  420. PAGED_CODE();
  421. DebugTrace( +1,
  422. Dbg,
  423. "MsOpenMailslotRootDirectory, RootDcb = %08lx\n",
  424. (ULONG)RootDcb);
  425. try {
  426. //
  427. // Create a root DCB CCB
  428. //
  429. ccb = MsCreateRootDcbCcb (RootDcb, RootDcb->Vcb);
  430. if (ccb == NULL) {
  431. iosb.Status = STATUS_INSUFFICIENT_RESOURCES;
  432. try_return( NOTHING );
  433. }
  434. //
  435. // Set the new share access.
  436. //
  437. ASSERT (MsIsAcquiredExclusiveVcb(RootDcb->Vcb));
  438. if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess(
  439. DesiredAccess,
  440. ShareAccess,
  441. FileObject,
  442. &RootDcb->ShareAccess,
  443. TRUE ))) {
  444. DebugTrace(0, Dbg, "bad share access\n", 0);
  445. //
  446. // Drop ccb
  447. //
  448. MsDereferenceCcb ((PCCB) ccb);
  449. try_return( NOTHING );
  450. }
  451. MsSetFileObject( FileObject, RootDcb, ccb );
  452. //
  453. // Set the return status.
  454. //
  455. iosb.Status = STATUS_SUCCESS;
  456. iosb.Information = FILE_OPENED;
  457. try_exit: NOTHING;
  458. } finally {
  459. DebugTrace(-1, Dbg, "MsOpenMailslotRootDirectory -> iosb.Status = %08lx\n", iosb.Status);
  460. }
  461. //
  462. // Return to the caller.
  463. //
  464. return iosb;
  465. }