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.

557 lines
14 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. createms.c
  5. Abstract:
  6. This module implements the file create mailslot routine for MSFS called
  7. by the dispatch driver.
  8. Author:
  9. Manny Weiser (mannyw) 17-Jan-1991
  10. Revision History:
  11. --*/
  12. #include "mailslot.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_CREATE_MAILSLOT)
  17. //
  18. // local procedure prototypes
  19. //
  20. NTSTATUS
  21. MsCommonCreateMailslot (
  22. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  23. IN PIRP Irp
  24. );
  25. IO_STATUS_BLOCK
  26. MsCreateMailslot (
  27. IN PROOT_DCB RootDcb,
  28. IN PFILE_OBJECT FileObject,
  29. IN UNICODE_STRING FileName,
  30. IN ACCESS_MASK DesiredAccess,
  31. IN ULONG CreateDisposition,
  32. IN USHORT ShareAccess,
  33. IN ULONG MailslotQuota,
  34. IN ULONG MaximumMessageSize,
  35. IN LARGE_INTEGER ReadTimeout,
  36. IN PEPROCESS CreatorProcess,
  37. IN PACCESS_STATE AccessState
  38. );
  39. BOOLEAN
  40. MsIsNameValid (
  41. PUNICODE_STRING Name
  42. );
  43. #ifdef ALLOC_PRAGMA
  44. #pragma alloc_text( PAGE, MsCommonCreateMailslot )
  45. #pragma alloc_text( PAGE, MsCreateMailslot )
  46. #pragma alloc_text( PAGE, MsFsdCreateMailslot )
  47. #pragma alloc_text( PAGE, MsIsNameValid )
  48. #endif
  49. NTSTATUS
  50. MsFsdCreateMailslot (
  51. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  52. IN PIRP Irp
  53. )
  54. /*++
  55. Routine Description:
  56. This routine implements the FSD part of the NtCreateMailslotFile
  57. API call.
  58. Arguments:
  59. MsfsDeviceObject - Supplies the device object to use.
  60. Irp - Supplies the Irp being processed
  61. Return Value:
  62. NTSTATUS - The Fsd status for the Irp
  63. --*/
  64. {
  65. NTSTATUS status;
  66. PAGED_CODE();
  67. DebugTrace(+1, Dbg, "MsFsdCreateMailslot\n", 0);
  68. //
  69. // Call the common create routine.
  70. //
  71. FsRtlEnterFileSystem();
  72. status = MsCommonCreateMailslot( MsfsDeviceObject, Irp );
  73. FsRtlExitFileSystem();
  74. //
  75. // Return to the caller.
  76. //
  77. DebugTrace(-1, Dbg, "MsFsdCreateMailslot -> %08lx\n", status );
  78. return status;
  79. }
  80. NTSTATUS
  81. MsCommonCreateMailslot (
  82. IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
  83. IN PIRP Irp
  84. )
  85. /*++
  86. Routine Description:
  87. This is the common routine for creating a mailslot.
  88. Arguments:
  89. Irp - Supplies the Irp to process
  90. Return Value:
  91. NTSTATUS - the return status for the operation
  92. --*/
  93. {
  94. NTSTATUS status;
  95. PIO_STACK_LOCATION irpSp;
  96. PFILE_OBJECT fileObject;
  97. PFILE_OBJECT relatedFileObject;
  98. UNICODE_STRING fileName;
  99. ACCESS_MASK desiredAccess;
  100. ULONG options;
  101. USHORT shareAccess;
  102. PMAILSLOT_CREATE_PARAMETERS parameters;
  103. ULONG mailslotQuota;
  104. ULONG maximumMessageSize;
  105. PEPROCESS creatorProcess;
  106. LARGE_INTEGER readTimeout;
  107. BOOLEAN caseInsensitive = TRUE; //**** Make all searches case insensitive
  108. PVCB vcb;
  109. PFCB fcb;
  110. ULONG createDisposition;
  111. UNICODE_STRING remainingPart;
  112. PAGED_CODE();
  113. //
  114. // Make local copies of the 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.CreateMailslot.SecurityContext->DesiredAccess;
  121. options = irpSp->Parameters.CreateMailslot.Options;
  122. shareAccess = irpSp->Parameters.CreateMailslot.ShareAccess;
  123. parameters = irpSp->Parameters.CreateMailslot.Parameters;
  124. mailslotQuota = parameters->MailslotQuota;
  125. maximumMessageSize = parameters->MaximumMessageSize;
  126. if (parameters->TimeoutSpecified) {
  127. readTimeout = parameters->ReadTimeout;
  128. } else {
  129. readTimeout.QuadPart = -1;
  130. }
  131. creatorProcess = IoGetRequestorProcess( Irp );
  132. DebugTrace(+1, Dbg, "MsCommonCreateMailslot\n", 0 );
  133. DebugTrace( 0, Dbg, "MsfsDeviceObject = %08lx\n", (ULONG)MsfsDeviceObject );
  134. DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp );
  135. DebugTrace( 0, Dbg, "FileObject = %08lx\n", (ULONG)fileObject );
  136. DebugTrace( 0, Dbg, "RelatedFileObject = %08lx\n", (ULONG)relatedFileObject );
  137. DebugTrace( 0, Dbg, "FileName = %wZ\n", (ULONG)&fileName );
  138. DebugTrace( 0, Dbg, "DesiredAccess = %08lx\n", desiredAccess );
  139. DebugTrace( 0, Dbg, "Options = %08lx\n", options );
  140. DebugTrace( 0, Dbg, "ShareAccess = %08lx\n", shareAccess );
  141. DebugTrace( 0, Dbg, "Parameters = %08lx\n", (ULONG)parameters );
  142. DebugTrace( 0, Dbg, "MailslotQuota = %08lx\n", mailslotQuota );
  143. DebugTrace( 0, Dbg, "MaximumMesssageSize = %08lx\n", maximumMessageSize );
  144. DebugTrace( 0, Dbg, "CreatorProcess = %08lx\n", (ULONG)creatorProcess );
  145. //
  146. // Get the VCB we are trying to access and extract the
  147. // create disposition.
  148. //
  149. vcb = &MsfsDeviceObject->Vcb;
  150. createDisposition = (options >> 24) & 0x000000ff;
  151. //
  152. // Acquire exclusive access to the VCB.
  153. //
  154. MsAcquireExclusiveVcb( vcb );
  155. try {
  156. //
  157. // If there is a related file object then this is a relative open
  158. // and it better be the root DCB. Both the then and the else clause
  159. // return an FCB.
  160. //
  161. if (relatedFileObject != NULL) {
  162. PDCB dcb;
  163. dcb = relatedFileObject->FsContext;
  164. if (NodeType(dcb) != MSFS_NTC_ROOT_DCB ||
  165. fileName.Length < sizeof( WCHAR ) || fileName.Buffer[0] == L'\\') {
  166. DebugTrace(0, Dbg, "Bad file name\n", 0);
  167. try_return( status = STATUS_OBJECT_NAME_INVALID );
  168. }
  169. status = MsFindRelativePrefix( dcb,
  170. &fileName,
  171. caseInsensitive,
  172. &remainingPart,
  173. &fcb );
  174. if (!NT_SUCCESS (status)) {
  175. try_return( NOTHING );
  176. }
  177. } else {
  178. //
  179. // The only nonrelative name we allow are of the form
  180. // "\mailslot-name".
  181. //
  182. if ((fileName.Length <= sizeof( WCHAR )) || (fileName.Buffer[0] != L'\\')) {
  183. DebugTrace(0, Dbg, "Bad file name\n", 0);
  184. try_return( status = STATUS_OBJECT_NAME_INVALID );
  185. }
  186. fcb = MsFindPrefix(
  187. vcb,
  188. &fileName,
  189. caseInsensitive,
  190. &remainingPart
  191. );
  192. }
  193. //
  194. // If the remaining name is empty then we better have an FCB
  195. // otherwise we were given a illegal object name.
  196. //
  197. if (remainingPart.Length == 0) {
  198. if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) {
  199. DebugTrace(0,
  200. Dbg,
  201. "Attempt to create an existing mailslot, "
  202. "Fcb = %08lx\n",
  203. (ULONG)fcb );
  204. status = STATUS_OBJECT_NAME_COLLISION;
  205. } else {
  206. DebugTrace(0, Dbg, "Illegal object name\n", 0);
  207. status = STATUS_OBJECT_NAME_INVALID;
  208. }
  209. } else {
  210. //
  211. // The remaining name is not empty so we better have the root DCB
  212. // and then have a valid object path.
  213. //
  214. if ( fcb->Header.NodeTypeCode == MSFS_NTC_ROOT_DCB &&
  215. MsIsNameValid( &remainingPart ) ) {
  216. DebugTrace(0,
  217. Dbg,
  218. "Create new mailslot, Fcb = %08lx\n",
  219. (ULONG)fcb );
  220. Irp->IoStatus = MsCreateMailslot(
  221. fcb,
  222. fileObject,
  223. fileName,
  224. desiredAccess,
  225. createDisposition,
  226. shareAccess,
  227. mailslotQuota,
  228. maximumMessageSize,
  229. readTimeout,
  230. creatorProcess,
  231. irpSp->Parameters.CreateMailslot.SecurityContext->AccessState
  232. );
  233. status = Irp->IoStatus.Status;
  234. } else {
  235. DebugTrace(0, Dbg, "Illegal object name\n", 0);
  236. status = STATUS_OBJECT_NAME_INVALID;
  237. }
  238. }
  239. try_exit: NOTHING;
  240. } finally {
  241. MsReleaseVcb( vcb );
  242. //
  243. // Complete the IRP and return to the caller.
  244. //
  245. MsCompleteRequest( Irp, status );
  246. }
  247. DebugTrace(-1, Dbg, "MsCommonCreateMailslot -> %08lx\n", status);
  248. return status;
  249. }
  250. IO_STATUS_BLOCK
  251. MsCreateMailslot (
  252. IN PROOT_DCB RootDcb,
  253. IN PFILE_OBJECT FileObject,
  254. IN UNICODE_STRING FileName,
  255. IN ACCESS_MASK DesiredAccess,
  256. IN ULONG CreateDisposition,
  257. IN USHORT ShareAccess,
  258. IN ULONG MailslotQuota,
  259. IN ULONG MaximumMessageSize,
  260. IN LARGE_INTEGER ReadTimeout,
  261. IN PEPROCESS CreatorProcess,
  262. IN PACCESS_STATE AccessState
  263. )
  264. /*++
  265. Routine Description:
  266. This routine performs the operation for creating a new mailslot
  267. Fcb. This routine does not complete any IRP, it preforms its
  268. function and then returns an iosb.
  269. Arguments:
  270. RootDcb - Supplies the root dcb where this is going to be added.
  271. FileObject - Supplies the file object associated with the mailslot.
  272. FileName - Supplies the name of the mailslot (not qualified i.e.,
  273. simply "mailslot-name" and not "\mailslot-name".
  274. DesiredAccess - Supplies the caller's desired access.
  275. CreateDisposition - Supplies the caller's create disposition flags.
  276. ShareAccess - Supplies the caller specified share access.
  277. MailslotQuota - Supplies the mailslot quota amount.
  278. MaximumMessageSize - Supplies the size of the largest message that
  279. can be written to this mailslot.
  280. CreatorProcess - Supplies the process creating the mailslot.
  281. Return Value:
  282. IO_STATUS_BLOCK - Returns the status of the operation.
  283. --*/
  284. {
  285. IO_STATUS_BLOCK iosb={0};
  286. PFCB fcb;
  287. NTSTATUS status;
  288. PAGED_CODE();
  289. DebugTrace(+1, Dbg, "MsCreateMailslot\n", 0 );
  290. //
  291. // Check the parameters that must be supplied for a mailslot
  292. //
  293. if (CreateDisposition == FILE_OPEN) {
  294. iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND;
  295. return iosb;
  296. }
  297. //
  298. // Create a new FCB for the mailslot.
  299. //
  300. status = MsCreateFcb( RootDcb->Vcb,
  301. RootDcb,
  302. &FileName,
  303. CreatorProcess,
  304. MailslotQuota,
  305. MaximumMessageSize,
  306. &fcb );
  307. if (!NT_SUCCESS (status)) {
  308. iosb.Status = status;
  309. return iosb;
  310. }
  311. fcb->Specific.Fcb.ReadTimeout = ReadTimeout;
  312. //
  313. // Set the security descriptor in the Fcb
  314. //
  315. SeLockSubjectContext( &AccessState->SubjectSecurityContext );
  316. status = SeAssignSecurity( NULL,
  317. AccessState->SecurityDescriptor,
  318. &fcb->SecurityDescriptor,
  319. FALSE,
  320. &AccessState->SubjectSecurityContext,
  321. IoGetFileObjectGenericMapping(),
  322. PagedPool );
  323. SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
  324. if (!NT_SUCCESS(status)) {
  325. DebugTrace(0, Dbg, "Error calling SeAssignSecurity\n", 0 );
  326. MsRemoveFcbName( fcb );
  327. MsDereferenceFcb( fcb );
  328. iosb.Status = status;
  329. return iosb;
  330. }
  331. //
  332. // Set the new share access.
  333. //
  334. ASSERT (MsIsAcquiredExclusiveVcb(fcb->Vcb));
  335. IoSetShareAccess( DesiredAccess,
  336. ShareAccess,
  337. FileObject,
  338. &fcb->ShareAccess );
  339. //
  340. // Set the file object back pointers and our pointer to the
  341. // server file object.
  342. //
  343. MsSetFileObject( FileObject, fcb, NULL );
  344. fcb->FileObject = FileObject;
  345. //
  346. // Update the FCB timestamps.
  347. //
  348. KeQuerySystemTime( &fcb->Specific.Fcb.CreationTime );
  349. fcb->Specific.Fcb.LastModificationTime = fcb->Specific.Fcb.CreationTime;
  350. fcb->Specific.Fcb.LastAccessTime = fcb->Specific.Fcb.CreationTime;
  351. fcb->Specific.Fcb.LastChangeTime = fcb->Specific.Fcb.CreationTime;
  352. //
  353. // Set the return status.
  354. //
  355. iosb.Status = STATUS_SUCCESS;
  356. iosb.Information = FILE_CREATED;
  357. //
  358. // The root directory has changed. Complete any notify change
  359. // directory requests.
  360. //
  361. MsCheckForNotify( fcb->ParentDcb, TRUE, STATUS_SUCCESS );
  362. //
  363. // Return to the caller.
  364. //
  365. DebugTrace(-1, Dbg, "MsCreateMailslot -> %08lx\n", iosb.Status);
  366. return iosb;
  367. }
  368. BOOLEAN
  369. MsIsNameValid (
  370. PUNICODE_STRING Name
  371. )
  372. /*++
  373. Routine Description:
  374. This routine tests for illegal characters in a name. The same character
  375. set as Npfs/Ntfs is used. Also preceding backslashes, wildcards, and
  376. path names are not allowed.
  377. Arguments:
  378. Name - The name to search for illegal characters
  379. Return Value:
  380. BOOLEAN - TRUE if the name is valid, FALSE otherwise.
  381. --*/
  382. {
  383. ULONG i;
  384. WCHAR Char = L'\\';
  385. PAGED_CODE();
  386. for (i=0; i < Name->Length / sizeof(WCHAR); i += 1) {
  387. Char = Name->Buffer[i];
  388. if ( (Char <= 0xff) && (Char != L'\\') &&
  389. !FsRtlIsAnsiCharacterLegalNtfs(Char, FALSE) ) {
  390. return FALSE;
  391. }
  392. }
  393. //
  394. // If the last char of the name was slash, we have an illegal name
  395. //
  396. return (Char != L'\\');
  397. }