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.

1147 lines
31 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. srio.c
  5. Abstract:
  6. This files contains the routines that generate IO
  7. for the SR filter driver.
  8. Author:
  9. Molly Brown (MollyBro) 07-Nov-2000
  10. Revision History:
  11. Added routines to post & wait for ops - ravisp 12/6/2000
  12. --*/
  13. #include "precomp.h"
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text( PAGE, SrQueryInformationFile )
  16. #pragma alloc_text( PAGE, SrSetInformationFile )
  17. #pragma alloc_text( PAGE, SrQueryVolumeInformationFile )
  18. #pragma alloc_text( PAGE, SrQueryEaFile )
  19. #pragma alloc_text( PAGE, SrQuerySecurityObject )
  20. #pragma alloc_text( PAGE, SrFlushBuffers )
  21. #pragma alloc_text( PAGE, SrSyncOpWorker )
  22. #pragma alloc_text( PAGE, SrPostSyncOperation )
  23. #endif // ALLOC_PRAGMA
  24. NTSTATUS
  25. SrSyncIoCompletion (
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN PIRP Irp,
  28. IN PKEVENT Event
  29. )
  30. /*++
  31. Routine Description:
  32. This routine does the cleanup necessary once the IO request
  33. is completed by the file system.
  34. Arguments:
  35. DeviceObject - This will be NULL since we originated this
  36. Irp.
  37. Irp - The io request structure containing the information
  38. about the current state of our file name query.
  39. Event - The event to signal to notify the
  40. originator of this request that the operation is
  41. complete.
  42. Return Value:
  43. Returns STATUS_MORE_PROCESSING_REQUIRED so that IO Manager
  44. will not try to free the Irp again.
  45. --*/
  46. {
  47. UNREFERENCED_PARAMETER( DeviceObject );
  48. //
  49. // Make sure that the Irp status is copied over to the user's
  50. // IO_STATUS_BLOCK so that the originator of this irp will know
  51. // the final status of this operation.
  52. //
  53. ASSERT( NULL != Irp->UserIosb );
  54. *Irp->UserIosb = Irp->IoStatus;
  55. //
  56. // Signal SynchronizingEvent so that the originator of this
  57. // Irp know that the operation is completed.
  58. //
  59. KeSetEvent( Event, IO_NO_INCREMENT, FALSE );
  60. //
  61. // We are now done, so clean up the irp that we allocated.
  62. //
  63. IoFreeIrp( Irp );
  64. //
  65. // If we return STATUS_SUCCESS here, the IO Manager will
  66. // perform the cleanup work that it thinks needs to be done
  67. // for this IO operation. This cleanup work includes:
  68. // * Copying data from the system buffer to the user's buffer
  69. // if this was a buffered IO operation.
  70. // * Freeing any MDLs that are in the Irp.
  71. // * Copying the Irp->IoStatus to Irp->UserIosb so that the
  72. // originator of this irp can see the final status of the
  73. // operation.
  74. // * If this was an asynchronous request or this was a
  75. // synchronous request that got pending somewhere along the
  76. // way, the IO Manager will signal the Irp->UserEvent, if one
  77. // exists, otherwise it will signal the FileObject->Event.
  78. // (This can have REALLY bad implications if the irp originator
  79. // did not an Irp->UserEvent and the irp originator is not
  80. // waiting on the FileObject->Event. It would not be that
  81. // farfetched to believe that someone else in the system is
  82. // waiting on FileObject->Event and who knows who will be
  83. // awoken as a result of the IO Manager signaling this event.
  84. //
  85. // Since some of these operations require the originating thread's
  86. // context (e.g., the IO Manager need the UserBuffer address to
  87. // be valid when copy is done), the IO Manager queues this work
  88. // to an APC on the Irp's orginating thread.
  89. //
  90. // Since SR allocated and initialized this irp, we know
  91. // what cleanup work needs to be done. We can do this cleanup
  92. // work more efficiently than the IO Manager since we are handling
  93. // a very specific case. Therefore, it is better for us to
  94. // perform the cleanup work here then free the irp than passing
  95. // control back to the IO Manager to do this work.
  96. //
  97. // By returning STATUS_MORE_PROCESS_REQUIRED, we tell the IO Manager
  98. // to stop processing this irp until it is told to restart processing
  99. // with a call to IoCompleteRequest. Since the IO Manager has
  100. // already performed all the work we want it to do on this
  101. // irp, we do the cleanup work, return STATUS_MORE_PROCESSING_REQUIRED,
  102. // and ask the IO Manager to resume processing by calling
  103. // IoCompleteRequest.
  104. //
  105. return STATUS_MORE_PROCESSING_REQUIRED;
  106. }
  107. NTSTATUS
  108. SrQueryInformationFile (
  109. IN PDEVICE_OBJECT NextDeviceObject,
  110. IN PFILE_OBJECT FileObject,
  111. OUT PVOID FileInformation,
  112. IN ULONG Length,
  113. IN FILE_INFORMATION_CLASS FileInformationClass,
  114. OUT PULONG LengthReturned OPTIONAL
  115. )
  116. /*++
  117. Routine Description:
  118. This routine returns the requested information about a specified file.
  119. The information returned is determined by the FileInformationClass that
  120. is specified, and it is placed into the caller's FileInformation buffer.
  121. This routine only supports the following FileInformationClasses:
  122. FileBasicInformation
  123. FileStandardInformation
  124. FileStreamInformation
  125. FileAlternateNameInformation
  126. FileNameInformation
  127. Arguments:
  128. NextDeviceObject - Supplies the device object where this IO should start
  129. in the device stack.
  130. FileObject - Supplies the file object about which the requested
  131. information should be returned.
  132. FileInformation - Supplies a buffer to receive the requested information
  133. returned about the file. This must be a buffer allocated from kernel
  134. space.
  135. Length - Supplies the length, in bytes, of the FileInformation buffer.
  136. FileInformationClass - Specifies the type of information which should be
  137. returned about the file.
  138. LengthReturned - the number of bytes returned if the operation was
  139. successful.
  140. Return Value:
  141. The status returned is the final completion status of the operation.
  142. --*/
  143. {
  144. PIRP irp = NULL;
  145. PIO_STACK_LOCATION irpSp = NULL;
  146. IO_STATUS_BLOCK ioStatusBlock;
  147. KEVENT event;
  148. NTSTATUS status;
  149. PAGED_CODE();
  150. //
  151. // In DBG builds, make sure that we have valid parameters before we do
  152. // any work here.
  153. //
  154. ASSERT( NULL != NextDeviceObject );
  155. ASSERT( NULL != FileObject );
  156. ASSERT( NULL != FileInformation );
  157. ASSERT( (FileInformationClass == FileBasicInformation) ||
  158. (FileInformationClass == FileStandardInformation) ||
  159. (FileInformationClass == FileStreamInformation) ||
  160. (FileInformationClass == FileAlternateNameInformation) ||
  161. (FileInformationClass == FileNameInformation) ||
  162. (FileInformationClass == FileInternalInformation) );
  163. //
  164. // The parameters look ok, so setup the Irp.
  165. //
  166. KeInitializeEvent( &event, NotificationEvent, FALSE );
  167. ioStatusBlock.Status = STATUS_SUCCESS;
  168. ioStatusBlock.Information = 0;
  169. irp = IoAllocateIrp( NextDeviceObject->StackSize, FALSE );
  170. if (irp == NULL) {
  171. return STATUS_INSUFFICIENT_RESOURCES;
  172. }
  173. //
  174. // Set our current thread as the thread for this
  175. // irp so that the IO Manager always knows which
  176. // thread to return to if it needs to get back into
  177. // the context of the thread that originated this
  178. // irp.
  179. //
  180. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  181. //
  182. // Set that this irp originated from the kernel so that
  183. // the IO Manager knows that the buffers do not
  184. // need to be probed.
  185. //
  186. irp->RequestorMode = KernelMode;
  187. //
  188. // Initialize the UserIosb and UserEvent in the
  189. irp->UserIosb = &ioStatusBlock;
  190. irp->UserEvent = NULL;
  191. //
  192. // Set the IRP_SYNCHRONOUS_API to denote that this
  193. // is a synchronous IO request.
  194. //
  195. irp->Flags = IRP_SYNCHRONOUS_API;
  196. irpSp = IoGetNextIrpStackLocation( irp );
  197. irpSp->MajorFunction = IRP_MJ_QUERY_INFORMATION;
  198. irpSp->FileObject = FileObject;
  199. //
  200. // Setup the parameters for IRP_MJ_QUERY_INFORMATION. These
  201. // were supplied by the caller of this routine.
  202. // The buffer we want to be filled in should be placed in
  203. // the system buffer.
  204. //
  205. irp->AssociatedIrp.SystemBuffer = FileInformation;
  206. irpSp->Parameters.QueryFile.Length = Length;
  207. irpSp->Parameters.QueryFile.FileInformationClass = FileInformationClass;
  208. //
  209. // Set up the completion routine so that we know when our
  210. // request for the file name is completed. At that time,
  211. // we can free the irp.
  212. //
  213. IoSetCompletionRoutine( irp,
  214. SrSyncIoCompletion,
  215. &event,
  216. TRUE,
  217. TRUE,
  218. TRUE );
  219. status = IoCallDriver( NextDeviceObject, irp );
  220. (VOID) KeWaitForSingleObject( &event,
  221. Executive,
  222. KernelMode,
  223. FALSE,
  224. NULL );
  225. if (LengthReturned != NULL) {
  226. *LengthReturned = (ULONG) ioStatusBlock.Information;
  227. }
  228. #if DBG
  229. if (STATUS_OBJECT_NAME_NOT_FOUND == ioStatusBlock.Status ||
  230. STATUS_INVALID_PARAMETER == ioStatusBlock.Status)
  231. {
  232. return ioStatusBlock.Status;
  233. }
  234. #endif
  235. RETURN( ioStatusBlock.Status );
  236. }
  237. NTSTATUS
  238. SrSetInformationFile (
  239. IN PDEVICE_OBJECT NextDeviceObject,
  240. IN PFILE_OBJECT FileObject,
  241. IN PVOID FileInformation,
  242. IN ULONG Length,
  243. IN FILE_INFORMATION_CLASS FileInformationClass
  244. )
  245. /*++
  246. Routine Description:
  247. This routine changes the provided information about a specified file. The
  248. information that is changed is determined by the FileInformationClass that
  249. is specified. The new information is taken from the FileInformation buffer.
  250. Arguments:
  251. NextDeviceObject - Supplies the device object where this IO should start
  252. in the device stack.
  253. FileObject - Supplies the file object about which the requested
  254. information should be changed.
  255. FileInformation - Supplies a buffer containing the information which should
  256. be changed on the file.
  257. Length - Supplies the length, in bytes, of the FileInformation buffer.
  258. FileInformationClass - Specifies the type of information which should be
  259. changed about the file.
  260. Return Value:
  261. The status returned is the final completion status of the operation.
  262. --*/
  263. {
  264. PIRP irp;
  265. PIO_STACK_LOCATION irpSp;
  266. IO_STATUS_BLOCK ioStatusBlock;
  267. KEVENT event;
  268. NTSTATUS status;
  269. PAGED_CODE();
  270. //
  271. // In DBG builds, make sure the parameters are valid.
  272. //
  273. ASSERT( NULL != NextDeviceObject );
  274. ASSERT( NULL != FileObject );
  275. ASSERT( NULL != FileInformation );
  276. //
  277. // The parameters look ok, so setup the Irp.
  278. //
  279. KeInitializeEvent( &event, NotificationEvent, FALSE );
  280. ioStatusBlock.Status = STATUS_SUCCESS;
  281. ioStatusBlock.Information = 0;
  282. irp = IoAllocateIrp( NextDeviceObject->StackSize, FALSE );
  283. if (irp == NULL) {
  284. return STATUS_INSUFFICIENT_RESOURCES;
  285. }
  286. //
  287. // Set our current thread as the thread for this
  288. // irp so that the IO Manager always knows which
  289. // thread to return to if it needs to get back into
  290. // the context of the thread that originated this
  291. // irp.
  292. //
  293. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  294. //
  295. // Set that this irp originated from the kernel so that
  296. // the IO Manager knows that the buffers do not
  297. // need to be probed.
  298. //
  299. irp->RequestorMode = KernelMode;
  300. //
  301. // Initialize the UserIosb and UserEvent in the
  302. irp->UserIosb = &ioStatusBlock;
  303. irp->UserEvent = NULL;
  304. //
  305. // Set the IRP_SYNCHRONOUS_API to denote that this
  306. // is a synchronous IO request.
  307. //
  308. irp->Flags = IRP_SYNCHRONOUS_API;
  309. irpSp = IoGetNextIrpStackLocation( irp );
  310. irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
  311. irpSp->FileObject = FileObject;
  312. //
  313. // Setup the parameters for IRP_MJ_QUERY_INFORMATION. These
  314. // were supplied by the caller of this routine.
  315. // The buffer we want to be filled in should be placed in
  316. // the system buffer.
  317. //
  318. irp->AssociatedIrp.SystemBuffer = FileInformation;
  319. irpSp->Parameters.SetFile.Length = Length;
  320. irpSp->Parameters.SetFile.FileInformationClass = FileInformationClass;
  321. irpSp->Parameters.SetFile.FileObject = NULL;
  322. irpSp->Parameters.SetFile.DeleteHandle = NULL;
  323. //
  324. // Set up the completion routine so that we know when our
  325. // request for the file name is completed. At that time,
  326. // we can free the irp.
  327. //
  328. IoSetCompletionRoutine( irp,
  329. SrSyncIoCompletion,
  330. &event,
  331. TRUE,
  332. TRUE,
  333. TRUE );
  334. status = IoCallDriver( NextDeviceObject, irp );
  335. (VOID) KeWaitForSingleObject( &event,
  336. Executive,
  337. KernelMode,
  338. FALSE,
  339. NULL );
  340. #if DBG
  341. if (ioStatusBlock.Status == STATUS_CANNOT_DELETE ||
  342. ioStatusBlock.Status == STATUS_DIRECTORY_NOT_EMPTY)
  343. {
  344. //
  345. // bug#186511: STATUS_CANNOT_DELETE can be returned for some crazy
  346. // reason by the fsd if the file is already deleted. it should return
  347. // already deleted or simple return success, but it returns this
  348. // instead. callers of this function know to test for this.
  349. // don't DbgBreak.
  350. //
  351. return ioStatusBlock.Status;
  352. }
  353. #endif
  354. RETURN( ioStatusBlock.Status );
  355. }
  356. NTSTATUS
  357. SrQueryVolumeInformationFile (
  358. IN PDEVICE_OBJECT NextDeviceObject,
  359. IN PFILE_OBJECT FileObject,
  360. OUT PVOID FsInformation,
  361. IN ULONG Length,
  362. IN FS_INFORMATION_CLASS FsInformationClass,
  363. OUT PULONG LengthReturned OPTIONAL
  364. )
  365. /*++
  366. Routine Description:
  367. This routine returns information about the volume associated with the
  368. FileObject parameter. The information returned in the buffer is defined
  369. by the FsInformationClass parameter. The legal values for this parameter
  370. are as follows:
  371. o FileFsVolumeInformation
  372. o FileFsSizeInformation
  373. o FileFsDeviceInformation
  374. o FileFsAttributeInformation
  375. Note: Currently this routine only supports the following
  376. FsInformationClasses:
  377. FileFsVolumeInformation
  378. FileFsSizeInformation
  379. Arguments:
  380. NextDeviceObject - Supplies the device object where this IO should start
  381. in the device stack.
  382. FileObject - Supplies a fileobject to an open volume, directory, or file
  383. for which information about the volume is returned.
  384. FsInformation - Supplies a buffer to receive the requested information
  385. returned about the volume. This must be a buffer allocated from
  386. kernel space.
  387. Length - Supplies the length, in bytes, of the FsInformation buffer.
  388. FsInformationClass - Specifies the type of information which should be
  389. returned about the volume.
  390. LengthReturned - The number of bytes returned if the operation was
  391. successful.
  392. Return Value:
  393. The status returned is the final completion status of the operation.
  394. --*/
  395. {
  396. PIRP irp = NULL;
  397. PIO_STACK_LOCATION irpSp = NULL;
  398. IO_STATUS_BLOCK ioStatusBlock;
  399. KEVENT event;
  400. NTSTATUS status;
  401. PAGED_CODE();
  402. //
  403. // In DBG builds, make sure that we have valid parameters before
  404. // we do any work here.
  405. //
  406. ASSERT( NextDeviceObject != NULL );
  407. ASSERT( FileObject != NULL );
  408. ASSERT( FsInformation != NULL );
  409. ASSERT( (FsInformationClass == FileFsVolumeInformation) ||
  410. (FsInformationClass == FileFsSizeInformation) ||
  411. (FsInformationClass == FileFsAttributeInformation) );
  412. //
  413. // The parameters look ok, so setup the Irp.
  414. //
  415. KeInitializeEvent( &event, NotificationEvent, FALSE );
  416. ioStatusBlock.Status = STATUS_SUCCESS;
  417. ioStatusBlock.Information = 0;
  418. irp = IoAllocateIrp( NextDeviceObject->StackSize, FALSE );
  419. if (irp == NULL) {
  420. return STATUS_INSUFFICIENT_RESOURCES;
  421. }
  422. //
  423. // Set our current thread as the thread for this
  424. // irp so that the IO Manager always knows which
  425. // thread to return to if it needs to get back into
  426. // the context of the thread that originated this
  427. // irp.
  428. //
  429. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  430. //
  431. // Set that this irp originated from the kernel so that
  432. // the IO Manager knows that the buffers do not
  433. // need to be probed.
  434. //
  435. irp->RequestorMode = KernelMode;
  436. //
  437. // Initialize the UserIosb and UserEvent in the
  438. irp->UserIosb = &ioStatusBlock;
  439. irp->UserEvent = NULL;
  440. //
  441. // Set the IRP_SYNCHRONOUS_API to denote that this
  442. // is a synchronous IO request.
  443. //
  444. irp->Flags = IRP_SYNCHRONOUS_API;
  445. irpSp = IoGetNextIrpStackLocation( irp );
  446. irpSp->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
  447. irpSp->FileObject = FileObject;
  448. //
  449. // Setup the parameters for IRP_MJ_QUERY_VOLUME_INFORMATION. These
  450. // were supplied by the caller of this routine.
  451. // The buffer we want to be filled in should be placed in
  452. // the system buffer.
  453. //
  454. irp->AssociatedIrp.SystemBuffer = FsInformation;
  455. irpSp->Parameters.QueryVolume.Length = Length;
  456. irpSp->Parameters.QueryVolume.FsInformationClass = FsInformationClass;
  457. //
  458. // Set up the completion routine so that we know when our
  459. // request for the file name is completed. At that time,
  460. // we can free the irp.
  461. //
  462. IoSetCompletionRoutine( irp,
  463. SrSyncIoCompletion,
  464. &event,
  465. TRUE,
  466. TRUE,
  467. TRUE );
  468. status = IoCallDriver( NextDeviceObject, irp );
  469. (VOID) KeWaitForSingleObject( &event,
  470. Executive,
  471. KernelMode,
  472. FALSE,
  473. NULL );
  474. if (LengthReturned != NULL) {
  475. *LengthReturned = (ULONG) ioStatusBlock.Information;
  476. }
  477. RETURN( ioStatusBlock.Status );
  478. }
  479. NTSTATUS
  480. SrQueryEaFile (
  481. IN PDEVICE_OBJECT NextDeviceObject,
  482. IN PFILE_OBJECT FileObject,
  483. OUT PVOID Buffer,
  484. IN ULONG Length,
  485. OUT PULONG LengthReturned OPTIONAL
  486. )
  487. /*++
  488. Routine Description:
  489. This routine returns the Extended Attributes (EAs) associated with the
  490. file specified by the FileObject parameter. The amount of information
  491. returned is based on the size of the EAs, and the size of the buffer.
  492. That is, either all of the EAs are written to the buffer, or the buffer
  493. is filled with complete EAs if the buffer is not large enough to contain
  494. all of the EAs. Only complete EAs are ever written to the buffer; no
  495. partial EAs will ever be returned.
  496. NOTE: This routine will always return EAs starting at the being of the
  497. file's EA List. It will also always return as many EAs as possible in the
  498. buffer. THIS BEHAVIOR IS A LIMITED VERSION OF ZwQueryEaFile.
  499. Arguments:
  500. NextDeviceObject - Supplies the device object where this IO should start
  501. in the device stack.
  502. FileObject - Supplies a fileobject to the file for which the EAs are returned.
  503. IoStatusBlock - Address of the caller's I/O status block.
  504. Buffer - Supplies a buffer to receive the EAs for the file.
  505. Length - Supplies the length, in bytes, of the buffer.
  506. LengthReturned - The number of bytes returned if the operation is
  507. successful.
  508. Return Value:
  509. The status returned is the final completion status of the operation.
  510. --*/
  511. {
  512. PIRP irp = NULL;
  513. PIO_STACK_LOCATION irpSp = NULL;
  514. IO_STATUS_BLOCK ioStatusBlock;
  515. KEVENT event;
  516. NTSTATUS status;
  517. PAGED_CODE();
  518. //
  519. // In DBG builds, make sure that we have valid parameters before we do
  520. // any work here.
  521. //
  522. ASSERT( NULL != NextDeviceObject );
  523. ASSERT( NULL != FileObject );
  524. ASSERT( NULL != Buffer );
  525. //
  526. // The parameters look ok, so setup the Irp.
  527. //
  528. KeInitializeEvent( &event, NotificationEvent, FALSE );
  529. ioStatusBlock.Status = STATUS_SUCCESS;
  530. ioStatusBlock.Information = 0;
  531. irp = IoAllocateIrp( NextDeviceObject->StackSize, FALSE );
  532. if (NULL == irp) {
  533. return STATUS_INSUFFICIENT_RESOURCES;
  534. }
  535. //
  536. // Set our current thread as the thread for this
  537. // irp so that the IO Manager always knows which
  538. // thread to return to if it needs to get back into
  539. // the context of the thread that originated this
  540. // irp.
  541. //
  542. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  543. //
  544. // Set that this irp originated from the kernel so that
  545. // the IO Manager knows that the buffers do not
  546. // need to be probed.
  547. //
  548. irp->RequestorMode = KernelMode;
  549. //
  550. // Initialize the UserIosb and UserEvent in the
  551. irp->UserIosb = &ioStatusBlock;
  552. irp->UserEvent = NULL;
  553. //
  554. // Set the IRP_SYNCHRONOUS_API to denote that this
  555. // is a synchronous IO request.
  556. //
  557. irp->Flags = IRP_SYNCHRONOUS_API;
  558. irpSp = IoGetNextIrpStackLocation( irp );
  559. irpSp->MajorFunction = IRP_MJ_QUERY_EA;
  560. irpSp->FileObject = FileObject;
  561. //
  562. // Setup the parameters for IRP_MJ_QUERY_EA. These
  563. // were supplied by the caller of this routine.
  564. // The buffer we want to be filled in should be placed in
  565. // the user buffer.
  566. //
  567. irp->UserBuffer = Buffer;
  568. irpSp->Parameters.QueryEa.Length = Length;
  569. irpSp->Parameters.QueryEa.EaList = NULL;
  570. irpSp->Parameters.QueryEa.EaListLength = 0;
  571. irpSp->Parameters.QueryEa.EaIndex = 0;
  572. irpSp->Flags = SL_RESTART_SCAN;
  573. //
  574. // Set up the completion routine so that we know when our
  575. // request for the file name is completed. At that time,
  576. // we can free the irp.
  577. //
  578. IoSetCompletionRoutine( irp,
  579. SrSyncIoCompletion,
  580. &event,
  581. TRUE,
  582. TRUE,
  583. TRUE );
  584. status = IoCallDriver( NextDeviceObject, irp );
  585. (VOID) KeWaitForSingleObject( &event,
  586. Executive,
  587. KernelMode,
  588. FALSE,
  589. NULL );
  590. if (LengthReturned != NULL) {
  591. *LengthReturned = (ULONG) ioStatusBlock.Information;
  592. }
  593. RETURN( ioStatusBlock.Status );
  594. }
  595. NTSTATUS
  596. SrQuerySecurityObject (
  597. IN PDEVICE_OBJECT NextDeviceObject,
  598. IN PFILE_OBJECT FileObject,
  599. IN SECURITY_INFORMATION SecurityInformation,
  600. OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
  601. IN ULONG Length,
  602. OUT PULONG LengthNeeded
  603. )
  604. /*++
  605. Routine Description:
  606. This routine is used to invoke an object's security routine. It
  607. is used to set the object's security state.
  608. Arguments:
  609. NextDeviceObject - Supplies the device object where this IO should start
  610. in the device stack.
  611. FileObject - Supplies the file object for the object being modified
  612. SecurityInformation - Indicates the type of information we are
  613. interested in getting. e.g., owner, group, dacl, or sacl.
  614. SecurityDescriptor - Supplies a pointer to where the information
  615. should be returned. This must be a buffer allocated from kernel
  616. space.
  617. Length - Supplies the size, in bytes, of the output buffer
  618. LengthNeeded - Receives the length, in bytes, needed to store
  619. the output security descriptor
  620. Return Value:
  621. An appropriate NTSTATUS value
  622. --*/
  623. {
  624. PIRP irp = NULL;
  625. PIO_STACK_LOCATION irpSp = NULL;
  626. IO_STATUS_BLOCK ioStatusBlock;
  627. KEVENT event;
  628. NTSTATUS status;
  629. PAGED_CODE();
  630. //
  631. // Make sure that we have valid parameters before we do any work here.
  632. //
  633. ASSERT( NextDeviceObject != NULL );
  634. ASSERT( FileObject != NULL );
  635. ASSERT( SecurityDescriptor != NULL );
  636. ASSERT( LengthNeeded != NULL );
  637. //
  638. // The parameters look ok, so setup the Irp.
  639. //
  640. KeInitializeEvent( &event, NotificationEvent, FALSE );
  641. ioStatusBlock.Status = STATUS_SUCCESS;
  642. ioStatusBlock.Information = 0;
  643. irp = IoAllocateIrp( NextDeviceObject->StackSize, FALSE );
  644. if (irp == NULL) {
  645. return STATUS_INSUFFICIENT_RESOURCES;
  646. }
  647. //
  648. // Set our current thread as the thread for this
  649. // irp so that the IO Manager always knows which
  650. // thread to return to if it needs to get back into
  651. // the context of the thread that originated this
  652. // irp.
  653. //
  654. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  655. //
  656. // Set that this irp originated from the kernel so that
  657. // the IO Manager knows that the buffers do not
  658. // need to be probed.
  659. //
  660. irp->RequestorMode = KernelMode;
  661. //
  662. // Initialize the UserIosb and UserEvent in the
  663. irp->UserIosb = &ioStatusBlock;
  664. irp->UserEvent = NULL;
  665. //
  666. // Set the IRP_SYNCHRONOUS_API to denote that this
  667. // is a synchronous IO request.
  668. //
  669. irp->Flags = IRP_SYNCHRONOUS_API;
  670. irpSp = IoGetNextIrpStackLocation( irp );
  671. irpSp->MajorFunction = IRP_MJ_QUERY_SECURITY;
  672. irpSp->FileObject = FileObject;
  673. //
  674. // Setup the parameters for IRP_MJ_QUERY_SECURITY_INFORMATION. These
  675. // were supplied by the caller of this routine.
  676. // The buffer we want to be filled in should be placed in
  677. // the User buffer.
  678. //
  679. irp->UserBuffer = SecurityDescriptor;
  680. irpSp->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
  681. irpSp->Parameters.QuerySecurity.Length = Length;
  682. //
  683. // Set up the completion routine so that we know when our
  684. // request for the file name is completed. At that time,
  685. // we can free the irp.
  686. //
  687. IoSetCompletionRoutine( irp,
  688. SrSyncIoCompletion,
  689. &event,
  690. TRUE,
  691. TRUE,
  692. TRUE );
  693. status = IoCallDriver( NextDeviceObject, irp );
  694. (VOID) KeWaitForSingleObject( &event,
  695. Executive,
  696. KernelMode,
  697. FALSE,
  698. NULL );
  699. status = ioStatusBlock.Status;
  700. if (status == STATUS_BUFFER_OVERFLOW) {
  701. status = STATUS_BUFFER_TOO_SMALL;
  702. //
  703. // The buffer was too small, so return the size needed for the
  704. // security descriptor.
  705. //
  706. *LengthNeeded = (ULONG) ioStatusBlock.Information;
  707. }
  708. #if DBG
  709. if (status == STATUS_BUFFER_TOO_SMALL) {
  710. return status;
  711. }
  712. #endif
  713. RETURN( status );
  714. }
  715. NTSTATUS
  716. SrFlushBuffers (
  717. PDEVICE_OBJECT NextDeviceObject,
  718. PFILE_OBJECT FileObject
  719. )
  720. {
  721. PIRP irp = NULL;
  722. PIO_STACK_LOCATION irpSp = NULL;
  723. IO_STATUS_BLOCK ioStatusBlock;
  724. KEVENT event;
  725. NTSTATUS status;
  726. PAGED_CODE();
  727. //
  728. // Make sure that we have valid parameters before we do any work here.
  729. //
  730. ASSERT( NextDeviceObject != NULL );
  731. ASSERT( FileObject != NULL );
  732. //
  733. // The parameters look ok, so setup the Irp.
  734. //
  735. KeInitializeEvent( &event, NotificationEvent, FALSE );
  736. ioStatusBlock.Status = STATUS_SUCCESS;
  737. ioStatusBlock.Information = 0;
  738. irp = IoBuildAsynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS,
  739. NextDeviceObject,
  740. NULL,
  741. 0,
  742. NULL,
  743. &ioStatusBlock );
  744. if (irp == NULL) {
  745. return STATUS_INSUFFICIENT_RESOURCES;
  746. }
  747. irpSp = IoGetNextIrpStackLocation( irp );
  748. irpSp->FileObject = FileObject;
  749. //
  750. // Set up the completion routine so that we know when our
  751. // request for the file name is completed. At that time,
  752. // we can free the irp.
  753. //
  754. IoSetCompletionRoutine( irp,
  755. SrSyncIoCompletion,
  756. &event,
  757. TRUE,
  758. TRUE,
  759. TRUE );
  760. status = IoCallDriver( NextDeviceObject, irp );
  761. if (status == STATUS_PENDING)
  762. {
  763. (VOID) KeWaitForSingleObject( &event,
  764. Executive,
  765. KernelMode,
  766. FALSE,
  767. NULL );
  768. }
  769. RETURN( ioStatusBlock.Status );
  770. }
  771. //
  772. //++
  773. // Function:
  774. // SrSyncOpWorker
  775. //
  776. // Description:
  777. // This function is the generic worker routine
  778. // that calls the real caller-passed work routine,
  779. // and sets the event for synchronization with the main
  780. // thread
  781. //
  782. // Arguments:
  783. //
  784. // Context
  785. //
  786. // Return Value:
  787. //
  788. // None
  789. //--
  790. //
  791. VOID
  792. SrSyncOpWorker(
  793. IN PSR_WORK_CONTEXT WorkContext
  794. )
  795. {
  796. PAGED_CODE();
  797. ASSERT(WorkContext != NULL);
  798. ASSERT(WorkContext->SyncOpRoutine != NULL);
  799. //
  800. // Call the 'real' posted routine
  801. //
  802. WorkContext->Status = (*WorkContext->SyncOpRoutine)(WorkContext->Parameter);
  803. //
  804. // Signal the main-thread about completion
  805. //
  806. KeSetEvent(&WorkContext->SyncEvent,
  807. EVENT_INCREMENT,
  808. FALSE);
  809. }
  810. //++
  811. // Function:
  812. // SrPostSyncOperation
  813. //
  814. // Description:
  815. // This function posts work to a worker thread
  816. // and waits for completion
  817. //
  818. // WARNING: Be VERY careful about acquiring locks in the
  819. // operation that is being posted. This may lead to deadlocks.
  820. //
  821. //
  822. // Arguments:
  823. //
  824. // Pointer to worker routine that handles the work
  825. // Context to be passed to worker routine
  826. //
  827. // Return Value:
  828. // This function returns status of the work routine
  829. //--
  830. NTSTATUS
  831. SrPostSyncOperation(
  832. IN PSR_SYNCOP_ROUTINE SyncOpRoutine,
  833. IN PVOID Parameter
  834. )
  835. {
  836. SR_WORK_CONTEXT workContext;
  837. NTSTATUS status;
  838. PAGED_CODE();
  839. //
  840. // Initialize the workContext
  841. //
  842. workContext.SyncOpRoutine = SyncOpRoutine;
  843. workContext.Parameter = Parameter;
  844. KeInitializeEvent(&workContext.SyncEvent,
  845. NotificationEvent,
  846. FALSE);
  847. //
  848. // Initialize and queue off the SyncOp Worker
  849. //
  850. ExInitializeWorkItem(&workContext.WorkItem,
  851. SrSyncOpWorker,
  852. &workContext);
  853. ExQueueWorkItem(&workContext.WorkItem,
  854. CriticalWorkQueue );
  855. //
  856. // Now just wait for the worker to fire and complete
  857. //
  858. status = KeWaitForSingleObject(&workContext.SyncEvent,
  859. Executive,
  860. KernelMode,
  861. FALSE,
  862. NULL);
  863. ASSERT(status == STATUS_SUCCESS);
  864. //
  865. // We're done free the work context and return the status of the
  866. // operation.
  867. //
  868. return workContext.Status;
  869. }