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.

663 lines
17 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. //
  123. // Get the VCB we are trying to access.
  124. //
  125. vcb = &MsfsDeviceObject->Vcb;
  126. //
  127. // Acquire exclusive access to the VCB.
  128. //
  129. MsAcquireExclusiveVcb( vcb );
  130. try {
  131. //
  132. // Check if we are trying to open the mailslot file system
  133. // (i.e., the Vcb).
  134. //
  135. if ((fileName.Length == 0) &&
  136. ((relatedFileObject == NULL) || (
  137. NodeType(relatedFileObject->FsContext) == MSFS_NTC_VCB))) {
  138. DebugTrace(0, Dbg, "Open mailslot file system\n", 0);
  139. Irp->IoStatus = MsOpenMailslotFileSystem( vcb,
  140. fileObject,
  141. desiredAccess,
  142. shareAccess );
  143. status = Irp->IoStatus.Status;
  144. try_return( NOTHING );
  145. }
  146. //
  147. // Check if we are trying to open the root directory.
  148. //
  149. if (((fileName.Length == sizeof(WCHAR)) &&
  150. (fileName.Buffer[0] == L'\\') &&
  151. (relatedFileObject == NULL))
  152. ||
  153. ((fileName.Length == 0) && (NodeType(
  154. relatedFileObject->FsContext) == MSFS_NTC_ROOT_DCB))) {
  155. DebugTrace(0, Dbg, "Open root directory system\n", 0);
  156. Irp->IoStatus = MsOpenMailslotRootDirectory( vcb->RootDcb,
  157. fileObject,
  158. desiredAccess,
  159. shareAccess );
  160. status = Irp->IoStatus.Status;
  161. try_return( NOTHING );
  162. }
  163. //
  164. // If there is a related file object then this is a relative open
  165. // and it better be the root DCB. Both the then and the else clause
  166. // return an FCB.
  167. //
  168. if (relatedFileObject != NULL) {
  169. PDCB dcb;
  170. dcb = relatedFileObject->FsContext;
  171. if (NodeType(dcb) == MSFS_NTC_ROOT_DCB) {
  172. status = MsFindRelativePrefix( dcb,
  173. &fileName,
  174. caseInsensitive,
  175. &remainingPart,
  176. &fcb );
  177. if (!NT_SUCCESS (status)) {
  178. try_return( NOTHING );
  179. }
  180. } else if (NodeType(dcb) == MSFS_NTC_CCB && fileName.Length == 0) {
  181. fcb = ((PCCB) dcb)->Fcb;
  182. remainingPart.Length = 0;
  183. } else if (NodeType(dcb) == MSFS_NTC_FCB && fileName.Length == 0) {
  184. fcb = (PFCB) dcb;
  185. remainingPart.Length = 0;
  186. } else {
  187. DebugTrace(0, Dbg, "Bad file name\n", 0);
  188. try_return( status = STATUS_OBJECT_NAME_INVALID );
  189. }
  190. } else {
  191. //
  192. // The only nonrelative name we allow are of the form
  193. // "\mailslot-name".
  194. //
  195. if ((fileName.Length <= sizeof( WCHAR )) || (fileName.Buffer[0] != L'\\')) {
  196. DebugTrace(0, Dbg, "Bad file name\n", 0);
  197. try_return( status = STATUS_OBJECT_NAME_INVALID );
  198. }
  199. fcb = MsFindPrefix( vcb,
  200. &fileName,
  201. caseInsensitive,
  202. &remainingPart );
  203. }
  204. //
  205. // If the remaining name is not empty then we have an error, either
  206. // we have an illegal name or a non-existent name.
  207. //
  208. if (remainingPart.Length != 0) {
  209. if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) {
  210. //
  211. // We were given a name such as "\mailslot-name\another-name"
  212. //
  213. DebugTrace(0, Dbg, "Illegal object name\n", 0);
  214. status = STATUS_OBJECT_NAME_INVALID;
  215. } else {
  216. //
  217. // We were given a non-existent name
  218. //
  219. DebugTrace(0, Dbg, "non-existent name\n", 0);
  220. status = STATUS_OBJECT_NAME_NOT_FOUND;
  221. }
  222. } else {
  223. //
  224. // The remaining name is empty so we better have an FCB otherwise
  225. // we have an invalid object name.
  226. //
  227. if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) {
  228. DebugTrace(0,
  229. Dbg,
  230. "Create client end mailslot, Fcb = %08lx\n",
  231. (ULONG)fcb );
  232. Irp->IoStatus = MsCreateClientEnd( fcb,
  233. fileObject,
  234. desiredAccess,
  235. shareAccess,
  236. irpSp->Parameters.Create.SecurityContext->AccessState,
  237. Irp->RequestorMode,
  238. Irp->Tail.Overlay.Thread
  239. );
  240. status = Irp->IoStatus.Status;
  241. } else {
  242. DebugTrace(0, Dbg, "Illegal object name\n", 0);
  243. status = STATUS_OBJECT_NAME_INVALID;
  244. }
  245. }
  246. try_exit: NOTHING;
  247. } finally {
  248. MsReleaseVcb( vcb );
  249. //
  250. // Complete the IRP and return to the caller.
  251. //
  252. MsCompleteRequest( Irp, status );
  253. DebugTrace(-1, Dbg, "MsCommonCreate -> %08lx\n", status);
  254. }
  255. return status;
  256. }
  257. IO_STATUS_BLOCK
  258. MsCreateClientEnd (
  259. IN PFCB Fcb,
  260. IN PFILE_OBJECT FileObject,
  261. IN ACCESS_MASK DesiredAccess,
  262. IN USHORT ShareAccess,
  263. IN PACCESS_STATE AccessState,
  264. IN KPROCESSOR_MODE RequestorMode,
  265. IN PETHREAD UserThread
  266. )
  267. /*++
  268. Routine Description:
  269. This routine performs the operation for opening the client end of a
  270. mailslot. This routine does not complete the IRP, it performs the
  271. function and then returns a status.
  272. Arguments:
  273. Fcb - Supplies the FCB for the mailslot being accessed.
  274. FileObject - Supplies the file object associated with the client end.
  275. DesiredAccess - Supplies the caller's desired access.
  276. ShareAccess - Supplies the caller's share access.
  277. Return Value:
  278. IO_STATUS_BLOCK - Returns the appropriate status for the operation
  279. --*/
  280. {
  281. IO_STATUS_BLOCK iosb;
  282. PCCB ccb;
  283. BOOLEAN accessGranted;
  284. ACCESS_MASK grantedAccess;
  285. UNICODE_STRING name;
  286. PPRIVILEGE_SET Privileges = NULL;
  287. PAGED_CODE();
  288. DebugTrace(+1, Dbg, "MsCreateClientEnd\n", 0 );
  289. try {
  290. //
  291. // Lock out mods to the FCB's security descriptor.
  292. //
  293. MsAcquireSharedFcb( Fcb );
  294. SeLockSubjectContext( &AccessState->SubjectSecurityContext );
  295. //
  296. // First do an access check for the user against the Fcb
  297. //
  298. accessGranted = SeAccessCheck( Fcb->SecurityDescriptor,
  299. &AccessState->SubjectSecurityContext,
  300. TRUE, // Tokens are locked
  301. DesiredAccess,
  302. 0,
  303. &Privileges,
  304. IoGetFileObjectGenericMapping(),
  305. RequestorMode,
  306. &grantedAccess,
  307. &iosb.Status );
  308. if (Privileges != NULL) {
  309. (VOID) SeAppendPrivileges(
  310. AccessState,
  311. Privileges
  312. );
  313. SeFreePrivileges( Privileges );
  314. }
  315. if (accessGranted) {
  316. AccessState->PreviouslyGrantedAccess |= grantedAccess;
  317. AccessState->RemainingDesiredAccess &= ~(grantedAccess | MAXIMUM_ALLOWED);
  318. }
  319. RtlInitUnicodeString( &name, L"Mailslot" );
  320. SeOpenObjectAuditAlarm( &name,
  321. NULL,
  322. &FileObject->FileName,
  323. Fcb->SecurityDescriptor,
  324. AccessState,
  325. FALSE,
  326. accessGranted,
  327. RequestorMode,
  328. &AccessState->GenerateOnClose );
  329. SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
  330. MsReleaseFcb( Fcb );
  331. if (!accessGranted) {
  332. DebugTrace(0, Dbg, "Access Denied\n", 0 );
  333. try_return( iosb.Status );
  334. }
  335. //
  336. // Now make sure our share access is okay.
  337. //
  338. ASSERT (MsIsAcquiredExclusiveVcb(Fcb->Vcb));
  339. if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( grantedAccess,
  340. ShareAccess,
  341. FileObject,
  342. &Fcb->ShareAccess,
  343. TRUE ))) {
  344. DebugTrace(0, Dbg, "Sharing violation\n", 0);
  345. try_return( NOTHING );
  346. }
  347. //
  348. // Create a CCB for this client.
  349. //
  350. iosb.Status = MsCreateCcb( Fcb, &ccb );
  351. if (!NT_SUCCESS (iosb.Status)) {
  352. IoRemoveShareAccess( FileObject, &Fcb->ShareAccess );
  353. try_return( iosb.Status);
  354. }
  355. //
  356. // Set the file object back pointers and our pointer to the
  357. // server file object.
  358. //
  359. MsSetFileObject( FileObject, ccb, NULL );
  360. ccb->FileObject = FileObject;
  361. //
  362. // And set our return status
  363. //
  364. iosb.Status = STATUS_SUCCESS;
  365. iosb.Information = FILE_OPENED;
  366. try_exit: NOTHING;
  367. } finally {
  368. DebugTrace(-1, Dbg, "MsCreateClientEnd -> %08lx\n", iosb.Status);
  369. }
  370. return iosb;
  371. }
  372. IO_STATUS_BLOCK
  373. MsOpenMailslotFileSystem (
  374. IN PVCB Vcb,
  375. IN PFILE_OBJECT FileObject,
  376. IN ACCESS_MASK DesiredAccess,
  377. IN USHORT ShareAccess
  378. )
  379. {
  380. IO_STATUS_BLOCK iosb = {0};
  381. PAGED_CODE();
  382. DebugTrace(+1, Dbg, "MsOpenMailslotFileSystem, Vcb = %p\n", Vcb);
  383. //
  384. // Set the new share access
  385. //
  386. ASSERT (MsIsAcquiredExclusiveVcb(Vcb));
  387. if (NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess,
  388. ShareAccess,
  389. FileObject,
  390. &Vcb->ShareAccess,
  391. TRUE ))) {
  392. //
  393. // Supply the file object with a referenced pointer to the VCB.
  394. //
  395. MsReferenceVcb (Vcb);
  396. MsSetFileObject( FileObject, Vcb, NULL );
  397. //
  398. // Set the return status.
  399. //
  400. iosb.Status = STATUS_SUCCESS;
  401. iosb.Information = FILE_OPENED;
  402. }
  403. DebugTrace(-1, Dbg, "MsOpenMailslotFileSystem -> Iosb.Status = %08lx\n", iosb.Status);
  404. //
  405. // Return to the caller.
  406. //
  407. return iosb;
  408. }
  409. IO_STATUS_BLOCK
  410. MsOpenMailslotRootDirectory(
  411. IN PROOT_DCB RootDcb,
  412. IN PFILE_OBJECT FileObject,
  413. IN ACCESS_MASK DesiredAccess,
  414. IN USHORT ShareAccess
  415. )
  416. {
  417. IO_STATUS_BLOCK iosb = {0};
  418. PROOT_DCB_CCB ccb;
  419. PAGED_CODE();
  420. DebugTrace( +1,
  421. Dbg,
  422. "MsOpenMailslotRootDirectory, RootDcb = %08lx\n",
  423. (ULONG)RootDcb);
  424. try {
  425. //
  426. // Create a root DCB CCB
  427. //
  428. ccb = MsCreateRootDcbCcb (RootDcb, RootDcb->Vcb);
  429. if (ccb == NULL) {
  430. iosb.Status = STATUS_INSUFFICIENT_RESOURCES;
  431. try_return( NOTHING );
  432. }
  433. //
  434. // Set the new share access.
  435. //
  436. ASSERT (MsIsAcquiredExclusiveVcb(RootDcb->Vcb));
  437. if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess(
  438. DesiredAccess,
  439. ShareAccess,
  440. FileObject,
  441. &RootDcb->ShareAccess,
  442. TRUE ))) {
  443. DebugTrace(0, Dbg, "bad share access\n", 0);
  444. //
  445. // Drop ccb
  446. //
  447. MsDereferenceCcb ((PCCB) ccb);
  448. try_return( NOTHING );
  449. }
  450. MsSetFileObject( FileObject, RootDcb, ccb );
  451. //
  452. // Set the return status.
  453. //
  454. iosb.Status = STATUS_SUCCESS;
  455. iosb.Information = FILE_OPENED;
  456. try_exit: NOTHING;
  457. } finally {
  458. DebugTrace(-1, Dbg, "MsOpenMailslotRootDirectory -> iosb.Status = %08lx\n", iosb.Status);
  459. }
  460. //
  461. // Return to the caller.
  462. //
  463. return iosb;
  464. }