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.

1705 lines
56 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. objsup.c
  5. Abstract:
  6. This module contains the object support routine for the NT I/O system.
  7. Author:
  8. Darryl E. Havens (darrylh) 30-May-1989
  9. Environment:
  10. Kernel mode only
  11. Revision History:
  12. --*/
  13. #include "iomgr.h"
  14. NTSTATUS
  15. IopSetDeviceSecurityDescriptors(
  16. IN PDEVICE_OBJECT OriginalDeviceObject,
  17. IN PDEVICE_OBJECT DeviceObject,
  18. IN PSECURITY_INFORMATION SecurityInformation,
  19. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  20. IN POOL_TYPE PoolType,
  21. IN PGENERIC_MAPPING GenericMapping
  22. );
  23. NTSTATUS
  24. IopSetDeviceSecurityDescriptor(
  25. IN PDEVICE_OBJECT DeviceObject,
  26. IN PSECURITY_INFORMATION SecurityInformation,
  27. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  28. IN POOL_TYPE PoolType,
  29. IN PGENERIC_MAPPING GenericMapping
  30. );
  31. #ifdef ALLOC_PRAGMA
  32. #pragma alloc_text(PAGE, IopCloseFile)
  33. #pragma alloc_text(PAGE, IopDeleteFile)
  34. #pragma alloc_text(PAGE, IopDeleteDevice)
  35. #pragma alloc_text(PAGE, IopDeleteDriver)
  36. #pragma alloc_text(PAGE, IopGetSetSecurityObject)
  37. #pragma alloc_text(PAGE, IopSetDeviceSecurityDescriptors)
  38. #pragma alloc_text(PAGE, IopSetDeviceSecurityDescriptor)
  39. #endif
  40. VOID
  41. IopCloseFile(
  42. IN PEPROCESS Process OPTIONAL,
  43. IN PVOID Object,
  44. IN ULONG GrantedAccess,
  45. IN ULONG ProcessHandleCount,
  46. IN ULONG SystemHandleCount
  47. )
  48. /*++
  49. Routine Description:
  50. This routine is invoked whenever a handle to a file is deleted. If the
  51. handle being deleted is the last handle to the file (the ProcessHandleCount
  52. parameter is one), then all locks for the file owned by the specified
  53. process must be released.
  54. Likewise, if the SystemHandleCount is one then this is the last handle
  55. for this for file object across all processes. For this case, the file
  56. system is notified so that it can perform any necessary cleanup on the
  57. file.
  58. Arguments:
  59. Process - A pointer to the process that closed the handle.
  60. Object - A pointer to the file object that the handle referenced.
  61. GrantedAccess - Access that was granted to the object through the handle.
  62. ProcessHandleCount - Count of handles outstanding to the object for the
  63. process specified by the Process argument. If the count is one
  64. then this is the last handle to this file by that process.
  65. SystemHandleCount - Count of handles outstanding to the object for the
  66. entire system. If the count is one then this is the last handle
  67. to this file in the system.
  68. Return Value:
  69. None.
  70. --*/
  71. {
  72. PIRP irp;
  73. PIO_STACK_LOCATION irpSp;
  74. PDEVICE_OBJECT deviceObject;
  75. PFAST_IO_DISPATCH fastIoDispatch;
  76. NTSTATUS status;
  77. KEVENT event;
  78. PFILE_OBJECT fileObject;
  79. KIRQL irql;
  80. UNREFERENCED_PARAMETER( Process );
  81. UNREFERENCED_PARAMETER( GrantedAccess );
  82. PAGED_CODE();
  83. //
  84. // If the handle count is not one then this is not the last close of
  85. // this file for the specified process so there is nothing to do.
  86. //
  87. if (ProcessHandleCount != 1) {
  88. return;
  89. }
  90. fileObject = (PFILE_OBJECT) Object;
  91. if (fileObject->LockOperation && SystemHandleCount != 1) {
  92. IO_STATUS_BLOCK localIoStatus;
  93. //
  94. // This is the last handle for the specified process and the process
  95. // called the NtLockFile or NtUnlockFile system services at least once.
  96. // Also, this is not the last handle for this file object system-wide
  97. // so unlock all of the pending locks for this process. Note that
  98. // this check causes an optimization so that if this is the last
  99. // system-wide handle to this file object the cleanup code will take
  100. // care of releasing any locks on the file rather than having to
  101. // send the file system two different packets to get them shut down.
  102. //
  103. // Get the address of the target device object and the Fast I/O dispatch
  104. //
  105. if (!(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
  106. deviceObject = IoGetRelatedDeviceObject( fileObject );
  107. } else {
  108. deviceObject = IoGetAttachedDevice( fileObject->DeviceObject );
  109. }
  110. fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
  111. //
  112. // If this file is open for synchronous I/O, wait until this thread
  113. // owns it exclusively since there may still be a thread using it.
  114. // This occurs when a system service owns the file because it owns
  115. // the semaphore, but the I/O completion code has already dereferenced
  116. // the file object itself. Without waiting here for the same semaphore
  117. // there would be a race condition in the service who owns it now. The
  118. // service needs to be able to access the object w/o it going away after
  119. // its wait for the file event is satisfied.
  120. //
  121. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  122. BOOLEAN interrupted;
  123. if (!IopAcquireFastLock( fileObject )) {
  124. (VOID) IopAcquireFileObjectLock( fileObject,
  125. KernelMode,
  126. FALSE,
  127. &interrupted );
  128. }
  129. }
  130. //
  131. // Turbo unlock support. If the fast Io Dispatch specifies a fast lock
  132. // routine then we'll first try and calling it with the specified lock
  133. // parameters. If this is all successful then we do not need to do
  134. // the Irp based unlock all call.
  135. //
  136. if (fastIoDispatch &&
  137. fastIoDispatch->FastIoUnlockAll &&
  138. fastIoDispatch->FastIoUnlockAll( fileObject,
  139. PsGetCurrentProcess(),
  140. &localIoStatus,
  141. deviceObject )) {
  142. NOTHING;
  143. } else {
  144. //
  145. // Initialize the local event that will be used to synchronize access
  146. // to the driver completing this I/O operation.
  147. //
  148. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  149. //
  150. // Reset the event in the file object.
  151. //
  152. KeClearEvent( &fileObject->Event );
  153. //
  154. // Allocate and initialize the I/O Request Packet (IRP) for this
  155. // operation.
  156. //
  157. irp = IopAllocateIrpMustSucceed( deviceObject->StackSize );
  158. irp->Tail.Overlay.OriginalFileObject = fileObject;
  159. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  160. irp->RequestorMode = KernelMode;
  161. //
  162. // Fill in the service independent parameters in the IRP.
  163. //
  164. irp->UserEvent = &event;
  165. irp->UserIosb = &irp->IoStatus;
  166. irp->Flags = IRP_SYNCHRONOUS_API;
  167. irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL;
  168. //
  169. // Get a pointer to the stack location for the first driver. This will
  170. // be used to pass the original function codes and parameters. No
  171. // function-specific parameters are required for this operation.
  172. //
  173. irpSp = IoGetNextIrpStackLocation( irp );
  174. irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL;
  175. irpSp->MinorFunction = IRP_MN_UNLOCK_ALL;
  176. irpSp->FileObject = fileObject;
  177. //
  178. // Reference the fileobject again for the IRP (cleared on completion)
  179. //
  180. ObReferenceObject( fileObject );
  181. //
  182. // Insert the packet at the head of the IRP list for the thread.
  183. //
  184. IopQueueThreadIrp( irp );
  185. //
  186. // Invoke the driver at its appropriate dispatch entry with the IRP.
  187. //
  188. status = IoCallDriver( deviceObject, irp );
  189. //
  190. // If no error was incurred, wait for the I/O operation to complete.
  191. //
  192. if (status == STATUS_PENDING) {
  193. (VOID) KeWaitForSingleObject( &event,
  194. UserRequest,
  195. KernelMode,
  196. FALSE,
  197. (PLARGE_INTEGER) NULL );
  198. }
  199. }
  200. //
  201. // If this operation was a synchronous I/O operation, release the
  202. // semaphore so that the file can be used by other threads.
  203. //
  204. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  205. IopReleaseFileObjectLock( fileObject );
  206. }
  207. }
  208. if (SystemHandleCount == 1) {
  209. //
  210. // The last handle to this file object for all of the processes in the
  211. // system has just been closed, so invoke the driver's "cleanup" handler
  212. // for this file. This is the file system's opportunity to remove any
  213. // share access information for the file, to indicate that if the file
  214. // is opened for a caching operation and this is the last file object
  215. // to the file, then it can do whatever it needs with memory management
  216. // to cleanup any information.
  217. //
  218. // Begin by getting the address of the target device object.
  219. //
  220. if (!(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
  221. deviceObject = IoGetRelatedDeviceObject( fileObject );
  222. } else {
  223. deviceObject = IoGetAttachedDevice( fileObject->DeviceObject );
  224. }
  225. //
  226. // Ensure that the I/O system believes that this file has a handle
  227. // associated with it in case it doesn't actually get one from the
  228. // Object Manager. This is done because sometimes the Object Manager
  229. // actually creates a handle, but the I/O system never finds out
  230. // about it so it attempts to send two cleanups for the same file.
  231. //
  232. fileObject->Flags |= FO_HANDLE_CREATED;
  233. //
  234. // If this file is open for synchronous I/O, wait until this thread
  235. // owns it exclusively since there may still be a thread using it.
  236. // This occurs when a system service owns the file because it owns
  237. // the semaphore, but the I/O completion code has already dereferenced
  238. // the file object itself. Without waiting here for the same semaphore
  239. // there would be a race condition in the service who owns it now. The
  240. // service needs to be able to access the object w/o it going away after
  241. // its wait for the file event is satisfied.
  242. //
  243. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  244. BOOLEAN interrupted;
  245. if (!IopAcquireFastLock( fileObject )) {
  246. (VOID) IopAcquireFileObjectLock( fileObject,
  247. KernelMode,
  248. FALSE,
  249. &interrupted );
  250. }
  251. }
  252. //
  253. // Initialize the local event that will be used to synchronize access
  254. // to the driver completing this I/O operation.
  255. //
  256. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  257. //
  258. // Reset the event in the file object.
  259. //
  260. KeClearEvent( &fileObject->Event );
  261. //
  262. // Allocate and initialize the I/O Request Packet (IRP) for this
  263. // operation.
  264. //
  265. irp = IopAllocateIrpMustSucceed( deviceObject->StackSize );
  266. irp->Tail.Overlay.OriginalFileObject = fileObject;
  267. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  268. irp->RequestorMode = KernelMode;
  269. //
  270. // Fill in the service independent parameters in the IRP.
  271. //
  272. irp->UserEvent = &event;
  273. irp->UserIosb = &irp->IoStatus;
  274. irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL;
  275. irp->Flags = IRP_SYNCHRONOUS_API | IRP_CLOSE_OPERATION;
  276. //
  277. // Get a pointer to the stack location for the first driver. This will
  278. // be used to pass the original function codes and parameters. No
  279. // function-specific parameters are required for this operation.
  280. //
  281. irpSp = IoGetNextIrpStackLocation( irp );
  282. irpSp->MajorFunction = IRP_MJ_CLEANUP;
  283. irpSp->FileObject = fileObject;
  284. //
  285. // Insert the packet at the head of the IRP list for the thread.
  286. //
  287. IopQueueThreadIrp( irp );
  288. //
  289. // Update the operation count statistic for the current process for
  290. // operations other than read and write.
  291. //
  292. IopUpdateOtherOperationCount();
  293. //
  294. // Invoke the driver at its appropriate dispatch entry with the IRP.
  295. //
  296. status = IoCallDriver( deviceObject, irp );
  297. //
  298. // If no error was incurred, wait for the I/O operation to complete.
  299. //
  300. if (status == STATUS_PENDING) {
  301. (VOID) KeWaitForSingleObject( &event,
  302. UserRequest,
  303. KernelMode,
  304. FALSE,
  305. (PLARGE_INTEGER) NULL );
  306. }
  307. //
  308. // The following code tears down the IRP by hand since it may not
  309. // either be possible to it to be completed (because this code was
  310. // invoked as APC_LEVEL in the first place - or because the reference
  311. // count on the object cannot be incremented due to this routine
  312. // being invoked by the delete file procedure below). Cleanup IRPs
  313. // therefore use close sematics (the close operation flag is set
  314. // in the IRP) so that the I/O complete request routine itself sets
  315. // the event to the Signaled state.
  316. //
  317. KeRaiseIrql( APC_LEVEL, &irql );
  318. IopDequeueThreadIrp( irp );
  319. KeLowerIrql( irql );
  320. //
  321. // Also, free the IRP.
  322. //
  323. IoFreeIrp( irp );
  324. //
  325. // If this operation was a synchronous I/O operation, release the
  326. // semaphore so that the file can be used by other threads.
  327. //
  328. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  329. IopReleaseFileObjectLock( fileObject );
  330. }
  331. }
  332. return;
  333. }
  334. VOID
  335. IopDeleteFile(
  336. IN PVOID Object
  337. )
  338. /*++
  339. Routine Description:
  340. This routine is invoked when the last handle to a specific file handle is
  341. being closed and the file object is going away. It is the responsibility
  342. of this routine to perform the following functions:
  343. o Notify the device driver that the file object is open on that the
  344. file is being closed.
  345. o Dereference the user's error port for the file object, if there
  346. is one associated with the file object.
  347. o Decrement the device object reference count.
  348. Arguments:
  349. Object - Pointer to the file object being deleted.
  350. Return Value:
  351. None.
  352. --*/
  353. {
  354. PIRP irp;
  355. PIO_STACK_LOCATION irpSp;
  356. PDEVICE_OBJECT deviceObject;
  357. PDEVICE_OBJECT fsDevice = NULL;
  358. IO_STATUS_BLOCK ioStatusBlock;
  359. KIRQL irql;
  360. NTSTATUS status;
  361. PFILE_OBJECT fileObject;
  362. KEVENT event;
  363. PVPB vpb;
  364. BOOLEAN referenceCountDecremented;
  365. //
  366. // Obtain a pointer to the file object.
  367. //
  368. fileObject = (PFILE_OBJECT) Object;
  369. //
  370. // Get a pointer to the first device driver which should be notified that
  371. // this file is going away. If the device driver field is NULL, then this
  372. // file is being shut down due to an error attempting to get it open in the
  373. // first place, so do not do any further processing.
  374. //
  375. if (fileObject->DeviceObject) {
  376. if (!(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
  377. deviceObject = IoGetRelatedDeviceObject( fileObject );
  378. } else {
  379. deviceObject = IoGetAttachedDevice( fileObject->DeviceObject );
  380. }
  381. //
  382. // If this file has never had a file handle created for it, and yet
  383. // it exists, invoke the close file procedure so that the file system
  384. // gets the cleanup IRP it is expecting before sending the close IRP.
  385. //
  386. if (!(fileObject->Flags & FO_HANDLE_CREATED)) {
  387. IopCloseFile( (PEPROCESS) NULL,
  388. Object,
  389. 0,
  390. 1,
  391. 1 );
  392. }
  393. //
  394. // If this file is open for synchronous I/O, wait until this thread
  395. // owns it exclusively since there may still be a thread using it.
  396. // This occurs when a system service owns the file because it owns
  397. // the semaphore, but the I/O completion code has already dereferenced
  398. // the file object itself. Without waiting here for the same semaphore
  399. // there would be a race condition in the service who owns it now. The
  400. // service needs to be able to access the object w/o it going away after
  401. // its wait for the file event is satisfied.
  402. //
  403. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  404. BOOLEAN interrupted;
  405. if (!IopAcquireFastLock( fileObject )) {
  406. (VOID) IopAcquireFileObjectLock( fileObject,
  407. KernelMode,
  408. FALSE,
  409. &interrupted );
  410. }
  411. }
  412. //
  413. // Reset a local event that can be used to wait for the device driver
  414. // to close the file.
  415. //
  416. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  417. //
  418. // Reset the event in the file object.
  419. //
  420. KeClearEvent( &fileObject->Event );
  421. //
  422. // Allocate an I/O Request Packet (IRP) to be used in communicating with
  423. // the appropriate device driver that the file is being closed. Notice
  424. // that the allocation of this packet is done without charging quota so
  425. // that the operation will not fail. This is done because there is no
  426. // way to return an error to the caller at this point.
  427. //
  428. irp = IoAllocateIrp( deviceObject->StackSize, FALSE );
  429. if (!irp) {
  430. irp = IopAllocateIrpMustSucceed( deviceObject->StackSize );
  431. }
  432. //
  433. // Get a pointer to the stack location for the first driver. This is
  434. // where the function codes and parameters are placed.
  435. //
  436. irpSp = IoGetNextIrpStackLocation( irp );
  437. //
  438. // Fill in the IRP, indicating that this file object is being deleted.
  439. //
  440. irpSp->MajorFunction = IRP_MJ_CLOSE;
  441. irpSp->FileObject = fileObject;
  442. irp->UserIosb = &ioStatusBlock;
  443. irp->UserEvent = &event;
  444. irp->Tail.Overlay.OriginalFileObject = fileObject;
  445. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  446. irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
  447. irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
  448. //
  449. // Place this packet in the thread's I/O pending queue.
  450. //
  451. IopQueueThreadIrp( irp );
  452. //
  453. // Decrement the reference count on the VPB, if necessary. We
  454. // have to do this BEFORE handing the Irp to the file system
  455. // because of a trick the file systems play with close, and
  456. // believe me, you really don't want to know what it is.
  457. //
  458. // Since there is not a error path here (close cannot fail),
  459. // and the file system is the only ome who can actually synchronize
  460. // with the actual completion of close processing, the file system
  461. // is the one responsible for Vpb deletion.
  462. //
  463. vpb = fileObject->Vpb;
  464. if (vpb && !(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
  465. IopInterlockedDecrementUlong( LockQueueIoVpbLock,
  466. &vpb->ReferenceCount );
  467. //
  468. // Bump the handle count of the filesystem volume device object.
  469. // This will prevent the filesystem filter stack from being torn down
  470. // until after the close IRP completes.
  471. //
  472. fsDevice = vpb->DeviceObject;
  473. if (fsDevice) {
  474. IopInterlockedIncrementUlong( LockQueueIoDatabaseLock,
  475. &fsDevice->ReferenceCount );
  476. }
  477. }
  478. //
  479. // If this device object has stated for a fact that it knows it will
  480. // never have the final non-zero reference count among the other
  481. // device objects associated with our driver object, then decrement
  482. // our reference count here BEFORE calling the file system. This
  483. // is required because for a special class of device objects, the
  484. // file system may delete them.
  485. //
  486. if (fileObject->DeviceObject->Flags & DO_NEVER_LAST_DEVICE) {
  487. IopInterlockedDecrementUlong( LockQueueIoDatabaseLock,
  488. &fileObject->DeviceObject->ReferenceCount );
  489. referenceCountDecremented = TRUE;
  490. } else {
  491. referenceCountDecremented = FALSE;
  492. }
  493. //
  494. // Give the device driver the packet. If this request does not work,
  495. // there is nothing that can be done about it. This is unfortunate
  496. // because the driver may have had problems that it was about to
  497. // report about other operations (e.g., write behind failures, etc.)
  498. // that it can no longer report. The reason is that this routine
  499. // is really initially invoked by NtClose, which has already closed
  500. // the caller's handle, and that's what the return status from close
  501. // indicates: the handle has successfully been closed.
  502. //
  503. status = IoCallDriver( deviceObject, irp );
  504. if (status == STATUS_PENDING) {
  505. (VOID) KeWaitForSingleObject( &event,
  506. Executive,
  507. KernelMode,
  508. FALSE,
  509. (PLARGE_INTEGER) NULL );
  510. }
  511. //
  512. // Perform any completion operations that need to be performed on
  513. // the IRP that was used for this request. This is done here as
  514. // as opposed to in normal completion code because there is a race
  515. // condition between when this routine executes if it was invoked
  516. // from a special kernel APC (e.g., some IRP was just completed and
  517. // dereferenced this file object for the last time), and when the
  518. // special kernel APC because of this packet's completion executing.
  519. //
  520. // This problem is solved by not having to queue a special kernel
  521. // APC routine for completion of this packet. Rather, it is treated
  522. // much like a synchronous paging I/O operation, except that the
  523. // packet is not even freed during I/O completion. This is because
  524. // the packet is still in this thread's queue, and there is no way
  525. // to get it out except at APC_LEVEL. Unfortunately, the part of
  526. // I/O completion that needs to dequeue the packet is running at
  527. // DISPATCH_LEVEL.
  528. //
  529. // Hence, the packet must be removed from the queue (synchronized,
  530. // of course), and then it must be freed.
  531. //
  532. KeRaiseIrql( APC_LEVEL, &irql );
  533. IopDequeueThreadIrp( irp );
  534. KeLowerIrql( irql );
  535. IoFreeIrp( irp );
  536. //
  537. // Free the file name string buffer if there was one.
  538. //
  539. if (fileObject->FileName.Length != 0) {
  540. ExFreePool( fileObject->FileName.Buffer );
  541. }
  542. //
  543. // If there was an completion port associated w/this file object, dereference
  544. // it now, and deallocate the completion context pool.
  545. //
  546. if (fileObject->CompletionContext) {
  547. ObDereferenceObject( fileObject->CompletionContext->Port );
  548. ExFreePool( fileObject->CompletionContext );
  549. }
  550. //
  551. // Free the file context control structure if it exists.
  552. //
  553. if (fileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) {
  554. FsRtlPTeardownPerFileObjectContexts(fileObject);
  555. }
  556. //
  557. // Get a pointer to the real device object so its reference count
  558. // can be decremented.
  559. //
  560. deviceObject = fileObject->DeviceObject;
  561. //
  562. // Decrement the reference count on the device object. Note that
  563. // if the driver has been marked for an unload operation, and the
  564. // reference count goes to zero, then the driver may need to be
  565. // unloaded at this point.
  566. //
  567. // Note: only do this if the reference count was not already done
  568. // above. The device object may be gone in this case.
  569. //
  570. if (!referenceCountDecremented) {
  571. IopDecrementDeviceObjectRef(
  572. deviceObject,
  573. FALSE,
  574. !ObIsObjectDeletionInline(Object)
  575. );
  576. }
  577. //
  578. // Decrement the filesystem's volume device object handle count
  579. // so that deletes can proceed.
  580. //
  581. if (fsDevice && vpb) {
  582. IopDecrementDeviceObjectRef(fsDevice,
  583. FALSE,
  584. !ObIsObjectDeletionInline(Object)
  585. );
  586. }
  587. }
  588. }
  589. VOID
  590. IopDeleteDriver(
  591. IN PVOID Object
  592. )
  593. /*++
  594. Routine Description:
  595. This routine is invoked when the reference count for a driver object
  596. becomes zero. That is, the last reference for the driver has gone away.
  597. This routine ensures that the object is cleaned up and the driver
  598. unloaded.
  599. Arguments:
  600. Object - Pointer to the driver object whose reference count has gone
  601. to zero.
  602. Return value:
  603. None.
  604. --*/
  605. {
  606. PDRIVER_OBJECT driverObject = (PDRIVER_OBJECT) Object;
  607. PIO_CLIENT_EXTENSION extension;
  608. PIO_CLIENT_EXTENSION nextExtension;
  609. PAGED_CODE();
  610. ASSERT( !driverObject->DeviceObject );
  611. //
  612. // Free any client driver object extensions.
  613. //
  614. extension = driverObject->DriverExtension->ClientDriverExtension;
  615. while (extension != NULL) {
  616. nextExtension = extension->NextExtension;
  617. ExFreePool( extension );
  618. extension = nextExtension;
  619. }
  620. //
  621. // If there is a driver section then unload the driver.
  622. //
  623. if (driverObject->DriverSection != NULL) {
  624. //
  625. // Make sure any DPC's that may be running inside the driver have completed
  626. //
  627. #if !defined(NT_UP)
  628. KeFlushQueuedDpcs ();
  629. #endif
  630. MmUnloadSystemImage( driverObject->DriverSection );
  631. }
  632. //
  633. // Free the pool associated with the name of the driver.
  634. //
  635. if (driverObject->DriverName.Buffer) {
  636. ExFreePool( driverObject->DriverName.Buffer );
  637. }
  638. //
  639. // Free the pool associated with the service key name of the driver.
  640. //
  641. if (driverObject->DriverExtension->ServiceKeyName.Buffer) {
  642. ExFreePool( driverObject->DriverExtension->ServiceKeyName.Buffer );
  643. }
  644. //
  645. // Free the pool associated with the FsFilterCallbacks structure.
  646. //
  647. if (driverObject->DriverExtension->FsFilterCallbacks) {
  648. ExFreePool( driverObject->DriverExtension->FsFilterCallbacks );
  649. }
  650. }
  651. VOID
  652. IopDeleteDevice(
  653. IN PVOID Object
  654. )
  655. /*++
  656. Routine Description:
  657. This routine is invoked when the reference count for a device object
  658. becomes zero. That is, the last reference for the device has gone away.
  659. This routine ensures that the object is cleaned up and the driver object
  660. is dereferenced.
  661. Arguments:
  662. Object - Pointer to the driver object whose reference count has gone
  663. to zero.
  664. Return value:
  665. None.
  666. --*/
  667. {
  668. PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Object;
  669. PVPB vpb = NULL;
  670. PAGED_CODE();
  671. IopDestroyDeviceNode(deviceObject->DeviceObjectExtension->DeviceNode);
  672. //
  673. // If there's still a VPB attached then free it.
  674. //
  675. vpb = InterlockedExchangePointer(&(deviceObject->Vpb), vpb);
  676. if(vpb != NULL) {
  677. ASSERTMSG("Unreferenced device object to be deleted is still in use",
  678. ((vpb->Flags & (VPB_MOUNTED | VPB_LOCKED)) == 0));
  679. ASSERT(vpb->ReferenceCount == 0);
  680. ExFreePool(vpb);
  681. }
  682. if (deviceObject->DriverObject != NULL) {
  683. ObDereferenceObject( deviceObject->DriverObject );
  684. }
  685. }
  686. PDEVICE_OBJECT
  687. IopGetDevicePDO(
  688. IN PDEVICE_OBJECT DeviceObject
  689. )
  690. /*++
  691. Routine Description:
  692. Call this routine to obtain the Base PDO for a device object
  693. Arguments:
  694. DeviceObject - pointer to device object to get PDO for
  695. ReturnValue:
  696. PDO if DeviceObject is attached to a PDO, otherwise NULL
  697. The returned PDO is reference-counted
  698. --*/
  699. {
  700. PDEVICE_OBJECT deviceBaseObject;
  701. KIRQL irql;
  702. ASSERT(DeviceObject);
  703. irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );
  704. deviceBaseObject = IopGetDeviceAttachmentBase(DeviceObject);
  705. if ((deviceBaseObject->Flags & DO_BUS_ENUMERATED_DEVICE) != 0) {
  706. //
  707. // we have determined that this is attached to a PDO
  708. //
  709. ObReferenceObject( deviceBaseObject );
  710. } else {
  711. //
  712. // not a PDO
  713. //
  714. deviceBaseObject = NULL;
  715. }
  716. KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
  717. return deviceBaseObject;
  718. }
  719. NTSTATUS
  720. IopSetDeviceSecurityDescriptor(
  721. IN PDEVICE_OBJECT DeviceObject,
  722. IN PSECURITY_INFORMATION SecurityInformation,
  723. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  724. IN POOL_TYPE PoolType,
  725. IN PGENERIC_MAPPING GenericMapping
  726. )
  727. /*++
  728. Routine Description:
  729. This routine sets the security descriptor on a single device object
  730. Arguments:
  731. DeviceObject - pointer to base device object
  732. SecurityInformation - Fields of SD to change
  733. SecurityDescriptor - New security descriptor
  734. PoolType - Pool type for alloctions
  735. GenericMapping - Generic mapping for this object
  736. ReturnValue:
  737. success, or error while setting the descriptor for the device object.
  738. --*/
  739. {
  740. PSECURITY_DESCRIPTOR OldDescriptor;
  741. PSECURITY_DESCRIPTOR NewDescriptor;
  742. PSECURITY_DESCRIPTOR CachedDescriptor;
  743. NTSTATUS Status;
  744. PKTHREAD CurrentThread;
  745. PAGED_CODE();
  746. //
  747. // In order to preserve some protected fields in the SD (like the SACL) we need to make sure that only one
  748. // thread updates it at any one time. If we didn't do this another modification could wipe out a SACL
  749. // an administrator was adding.
  750. //
  751. CurrentThread = KeGetCurrentThread ();
  752. while (1) {
  753. //
  754. // Reference the security descriptor
  755. //
  756. KeEnterCriticalRegionThread(CurrentThread);
  757. ExAcquireResourceSharedLite( &IopSecurityResource, TRUE );
  758. OldDescriptor = DeviceObject->SecurityDescriptor;
  759. if (OldDescriptor != NULL) {
  760. ObReferenceSecurityDescriptor( OldDescriptor, 1 );
  761. }
  762. ExReleaseResourceLite( &IopSecurityResource );
  763. KeLeaveCriticalRegionThread(CurrentThread);
  764. NewDescriptor = OldDescriptor;
  765. Status = SeSetSecurityDescriptorInfo( NULL,
  766. SecurityInformation,
  767. SecurityDescriptor,
  768. &NewDescriptor,
  769. PoolType,
  770. GenericMapping );
  771. //
  772. // If we successfully set the new security descriptor then we
  773. // need to log it in our database and get yet another pointer
  774. // to the finaly security descriptor
  775. //
  776. if ( NT_SUCCESS( Status )) {
  777. Status = ObLogSecurityDescriptor( NewDescriptor,
  778. &CachedDescriptor,
  779. 1 );
  780. ExFreePool( NewDescriptor );
  781. if ( NT_SUCCESS( Status )) {
  782. //
  783. // Now we need to see if anyone else update this security descriptor inside the
  784. // gap where we didn't hold the lock. If they did then we just try it all again.
  785. //
  786. KeEnterCriticalRegionThread(CurrentThread);
  787. ExAcquireResourceExclusiveLite( &IopSecurityResource, TRUE );
  788. if (DeviceObject->SecurityDescriptor == OldDescriptor) {
  789. //
  790. // Do the swap
  791. //
  792. DeviceObject->SecurityDescriptor = CachedDescriptor;
  793. ExReleaseResourceLite( &IopSecurityResource );
  794. KeLeaveCriticalRegionThread(CurrentThread);
  795. //
  796. // If there was an original object then we need to work out how many
  797. // cached references there were (if any) and return them.
  798. //
  799. ObDereferenceSecurityDescriptor( OldDescriptor, 2 );
  800. break;
  801. } else {
  802. ExReleaseResourceLite( &IopSecurityResource );
  803. KeLeaveCriticalRegionThread(CurrentThread);
  804. ObDereferenceSecurityDescriptor( OldDescriptor, 1 );
  805. ObDereferenceSecurityDescriptor( CachedDescriptor, 1);
  806. }
  807. } else {
  808. //
  809. // Dereference old SecurityDescriptor
  810. //
  811. ObDereferenceSecurityDescriptor( OldDescriptor, 1 );
  812. break;
  813. }
  814. } else {
  815. //
  816. // Dereference old SecurityDescriptor
  817. //
  818. if (OldDescriptor != NULL) {
  819. ObDereferenceSecurityDescriptor( OldDescriptor, 1 );
  820. }
  821. break;
  822. }
  823. }
  824. //
  825. // And return to our caller
  826. //
  827. return( Status );
  828. }
  829. NTSTATUS
  830. IopSetDeviceSecurityDescriptors(
  831. IN PDEVICE_OBJECT OriginalDeviceObject,
  832. IN PDEVICE_OBJECT DeviceObject,
  833. IN PSECURITY_INFORMATION SecurityInformation,
  834. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  835. IN POOL_TYPE PoolType,
  836. IN PGENERIC_MAPPING GenericMapping
  837. )
  838. /*++
  839. Routine Description:
  840. This routine sets the security descriptor on all the devices on the
  841. device stack for a PNP device. Ideally when the object manager asks the
  842. IO manager to set the security descriptor of a device object the IO manager
  843. should set the descriptor only on that device object. This is the classical
  844. behaviour.
  845. Unfortunately for PNP devices there may be multiple devices on a device
  846. stack with names.
  847. If the descriptor is applied to only one of the devices on the stack its
  848. opens up a security hole as there may be other devices with name on the
  849. stack which can be opened by a random program.
  850. To protect against this the descriptor is applied to all device objects on
  851. the stack.
  852. Its important that to protect compatibility we need to return the same
  853. status as what would have been returned if only the requested device
  854. object's descriptor was set.
  855. Arguments:
  856. OriginalDeviceObject - Pointer to the device object passed by the object manager
  857. DeviceObject - pointer to base device object (first one to set)
  858. SecurityInformation )_ passed directly from IopGetSetSecurityObject
  859. SecurityDescriptor )
  860. PoolType )
  861. GenericMapping )
  862. ReturnValue:
  863. success, or error while setting the descriptor for the original device object.
  864. --*/
  865. {
  866. PDEVICE_OBJECT NewDeviceObject = NULL;
  867. PSECURITY_DESCRIPTOR OldSecurityDescriptor, NewSecurityDescriptor, CachedSecurityDescriptor;
  868. KIRQL irql;
  869. NTSTATUS status;
  870. NTSTATUS returnStatus = STATUS_SUCCESS;
  871. ASSERT(DeviceObject);
  872. PAGED_CODE();
  873. //
  874. // pre-reference this object to match the dereference later
  875. //
  876. ObReferenceObject( DeviceObject );
  877. do {
  878. //
  879. // Reference the existing security descriptor so it can't be reused.
  880. // We will only do the final security change if nobody else changes
  881. // the security while we don't hold the lock. Doing this prevents
  882. // privileged information being lost like the SACL.
  883. //
  884. //
  885. // Save away and return the device status only for the main device object
  886. // For example if OldSecurityDescriptor is NULL the IO manager should
  887. // return STATUS_NO_SECURITY_ON_OBJECT.
  888. //
  889. status = IopSetDeviceSecurityDescriptor( DeviceObject,
  890. SecurityInformation,
  891. SecurityDescriptor,
  892. PoolType,
  893. GenericMapping );
  894. if (DeviceObject == OriginalDeviceObject) {
  895. returnStatus = status;
  896. }
  897. //
  898. // We don't need to acquire the database lock because
  899. // we have a handle to this device stack.
  900. //
  901. NewDeviceObject = DeviceObject->AttachedDevice;
  902. if ( NewDeviceObject != NULL ) {
  903. ObReferenceObject( NewDeviceObject );
  904. }
  905. ObDereferenceObject( DeviceObject );
  906. DeviceObject = NewDeviceObject;
  907. } while (NewDeviceObject);
  908. return returnStatus;
  909. }
  910. NTSTATUS
  911. IopGetSetSecurityObject(
  912. IN PVOID Object,
  913. IN SECURITY_OPERATION_CODE OperationCode,
  914. IN PSECURITY_INFORMATION SecurityInformation,
  915. IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
  916. IN OUT PULONG CapturedLength,
  917. IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
  918. IN POOL_TYPE PoolType,
  919. IN PGENERIC_MAPPING GenericMapping
  920. )
  921. /*++
  922. Routine Description:
  923. This routine is invoked to either query or set the security descriptor
  924. for a file, directory, volume, or device. It implements these functions
  925. by either performing an in-line check if the file is a device or a
  926. volume, or an I/O Request Packet (IRP) is generated and given to the
  927. driver to perform the operation.
  928. Arguments:
  929. Object - Pointer to the file or device object representing the open object.
  930. SecurityInformation - Information about what is being done to or obtained
  931. from the object's security descriptor.
  932. SecurityDescriptor - Supplies the base security descriptor and returns
  933. the final security descriptor. Note that if this buffer is coming
  934. from user space, it has already been probed by the object manager
  935. to length "CapturedLength", otherwise it points to kernel space and
  936. should not be probed. It must, however, be referenced in a try
  937. clause.
  938. CapturedLength - For a query operation this specifies the size, in
  939. bytes, of the output security descriptor buffer and on return
  940. contains the number of bytes needed to store the complete security
  941. descriptor. If the length needed is greater than the length
  942. supplied the operation will fail. This parameter is ignored for
  943. the set and delete operations. It is expected to point into
  944. system space, ie, it need not be probed and it will not change.
  945. ObjectsSecurityDescriptor - Supplies and returns the object's security
  946. descriptor.
  947. PoolType - Specifies from which type of pool memory is to be allocated.
  948. GenericMapping - Supplies the generic mapping for the object type.
  949. Return Value:
  950. The final status of the operation is returned as the function value.
  951. --*/
  952. {
  953. NTSTATUS status;
  954. PFILE_OBJECT fileObject;
  955. PDEVICE_OBJECT deviceObject;
  956. PDEVICE_OBJECT devicePDO = NULL;
  957. BOOLEAN synchronousIo;
  958. PSECURITY_DESCRIPTOR oldSecurityDescriptor, CachedSecurityDescriptor;
  959. PETHREAD CurrentThread;
  960. UNREFERENCED_PARAMETER( ObjectsSecurityDescriptor );
  961. UNREFERENCED_PARAMETER( PoolType );
  962. PAGED_CODE();
  963. //
  964. // Begin by determining whether the security operation is to be performed
  965. // in this routine or by the driver. This is based upon whether the
  966. // object represents a device object, or it represents a file object
  967. // to a device, or a file on the device. If the open is a direct device
  968. // open then use the device object.
  969. //
  970. if (((PDEVICE_OBJECT) (Object))->Type == IO_TYPE_DEVICE) {
  971. deviceObject = (PDEVICE_OBJECT) Object;
  972. fileObject = (PFILE_OBJECT) NULL;
  973. } else {
  974. fileObject = (PFILE_OBJECT) Object;
  975. deviceObject = fileObject->DeviceObject;
  976. }
  977. if (!fileObject ||
  978. (!fileObject->FileName.Length && !fileObject->RelatedFileObject) ||
  979. (fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
  980. //
  981. // This security operation is for the device itself, either through
  982. // a file object, or directly to the device object. For the latter
  983. // case, assignment operations are also possible. Also note that
  984. // this may be a stream file object, which do not have security.
  985. // The security for a stream file is actually represented by the
  986. // security descriptor on the file itself, or the volume, or the
  987. // device.
  988. //
  989. if (OperationCode == AssignSecurityDescriptor) {
  990. //
  991. // Simply assign the security descriptor to the device object,
  992. // if this is a device object.
  993. //
  994. status = STATUS_SUCCESS;
  995. if (fileObject == NULL || !(fileObject->Flags & FO_STREAM_FILE)) {
  996. status = ObLogSecurityDescriptor( SecurityDescriptor,
  997. &CachedSecurityDescriptor,
  998. 1 );
  999. ExFreePool (SecurityDescriptor);
  1000. if (NT_SUCCESS( status )) {
  1001. CurrentThread = PsGetCurrentThread ();
  1002. KeEnterCriticalRegionThread(&CurrentThread->Tcb);
  1003. ExAcquireResourceExclusiveLite( &IopSecurityResource, TRUE );
  1004. deviceObject->SecurityDescriptor = CachedSecurityDescriptor;
  1005. ExReleaseResourceLite( &IopSecurityResource );
  1006. KeLeaveCriticalRegionThread(&CurrentThread->Tcb);
  1007. }
  1008. }
  1009. } else if (OperationCode == SetSecurityDescriptor) {
  1010. //
  1011. // This is a set operation. The SecurityInformation parameter
  1012. // determines what part of the SecurityDescriptor is going to
  1013. // be applied to the ObjectsSecurityDescriptor.
  1014. //
  1015. //
  1016. // if this deviceObject is attached to a PDO then we want
  1017. // to modify the security on the PDO and apply it up the
  1018. // device chain. This applies to PNP device objects only. See
  1019. // comment in IopSetDeviceSecurityDescriptors
  1020. //
  1021. devicePDO = IopGetDevicePDO(deviceObject);
  1022. if (devicePDO) {
  1023. //
  1024. // set PDO and all attached device objects
  1025. //
  1026. status = IopSetDeviceSecurityDescriptors(
  1027. deviceObject,
  1028. devicePDO,
  1029. SecurityInformation,
  1030. SecurityDescriptor,
  1031. PoolType,
  1032. GenericMapping );
  1033. ObDereferenceObject( devicePDO );
  1034. } else {
  1035. //
  1036. // set this device object only
  1037. //
  1038. status = IopSetDeviceSecurityDescriptor( deviceObject,
  1039. SecurityInformation,
  1040. SecurityDescriptor,
  1041. PoolType,
  1042. GenericMapping );
  1043. }
  1044. } else if (OperationCode == QuerySecurityDescriptor) {
  1045. //
  1046. // This is a get operation. The SecurityInformation parameter
  1047. // determines what part of the SecurityDescriptor is going to
  1048. // be returned from the ObjectsSecurityDescriptor.
  1049. //
  1050. CurrentThread = PsGetCurrentThread ();
  1051. KeEnterCriticalRegionThread(&CurrentThread->Tcb);
  1052. ExAcquireResourceSharedLite( &IopSecurityResource, TRUE );
  1053. oldSecurityDescriptor = deviceObject->SecurityDescriptor;
  1054. if (oldSecurityDescriptor != NULL) {
  1055. ObReferenceSecurityDescriptor( oldSecurityDescriptor, 1 );
  1056. }
  1057. ExReleaseResourceLite( &IopSecurityResource );
  1058. KeLeaveCriticalRegionThread(&CurrentThread->Tcb);
  1059. status = SeQuerySecurityDescriptorInfo( SecurityInformation,
  1060. SecurityDescriptor,
  1061. CapturedLength,
  1062. &oldSecurityDescriptor );
  1063. if (oldSecurityDescriptor != NULL) {
  1064. ObDereferenceSecurityDescriptor( oldSecurityDescriptor, 1 );
  1065. }
  1066. } else {
  1067. //
  1068. // This is a delete operation. Simply indicate that everything
  1069. // worked just fine.
  1070. //
  1071. status = STATUS_SUCCESS;
  1072. }
  1073. } else if (OperationCode == DeleteSecurityDescriptor) {
  1074. //
  1075. // This is a delete operation for the security descriptor on a file
  1076. // object. This function will be performed by the file system once
  1077. // the FCB itself is deleted. Simply indicate that the operation
  1078. // was successful.
  1079. //
  1080. status = STATUS_SUCCESS;
  1081. } else {
  1082. PIRP irp;
  1083. IO_STATUS_BLOCK localIoStatus;
  1084. KEVENT event;
  1085. PIO_STACK_LOCATION irpSp;
  1086. KPROCESSOR_MODE requestorMode;
  1087. //
  1088. // This file object does not refer to the device itself. Rather, it
  1089. // refers to either a file or a directory on the device. This means
  1090. // that the request must be passed to the file system for processing.
  1091. // Note that the only requests that are passed through in this manner
  1092. // are SET or QUERY security operations. DELETE operations have
  1093. // already been taken care of above since the file system which just
  1094. // drop the storage on the floor when it really needs to, and ASSIGN
  1095. // operations are irrelevant to file systems since they never
  1096. // generate one because they never assign the security descriptor
  1097. // to the object in the first place, they just assign it to the FCB.
  1098. //
  1099. CurrentThread = PsGetCurrentThread ();
  1100. requestorMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
  1101. //
  1102. // Begin by referencing the object by pointer. Note that the object
  1103. // handle has already been checked for the appropriate access by the
  1104. // object system caller. This reference must be performed because
  1105. // standard I/O completion will dereference the object.
  1106. //
  1107. ObReferenceObject( fileObject );
  1108. //
  1109. // Make a special check here to determine whether this is a synchronous
  1110. // I/O operation. If it is, then wait here until the file is owned by
  1111. // the current thread. If this is not a (serialized) synchronous I/O
  1112. // operation, then initialize the local event.
  1113. //
  1114. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  1115. BOOLEAN interrupted;
  1116. if (!IopAcquireFastLock( fileObject )) {
  1117. status = IopAcquireFileObjectLock( fileObject,
  1118. requestorMode,
  1119. (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0),
  1120. &interrupted );
  1121. if (interrupted) {
  1122. ObDereferenceObject( fileObject );
  1123. return status;
  1124. }
  1125. }
  1126. synchronousIo = TRUE;
  1127. } else {
  1128. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  1129. synchronousIo = FALSE;
  1130. }
  1131. //
  1132. // Set the file object to the Not-Signaled state.
  1133. //
  1134. KeClearEvent( &fileObject->Event );
  1135. //
  1136. // Get the address of the target device object.
  1137. //
  1138. deviceObject = IoGetRelatedDeviceObject( fileObject );
  1139. //
  1140. // Allocate and initialize the I/O Request Packet (IRP) for this
  1141. // operation. The allocation is performed with an exception handler
  1142. // in case the caller does not have enough quota to allocate the packet.
  1143. irp = IoAllocateIrp( deviceObject->StackSize, TRUE );
  1144. if (!irp) {
  1145. //
  1146. // An IRP could not be allocated. Cleanup and return an
  1147. // appropriate error status code.
  1148. //
  1149. IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL );
  1150. return STATUS_INSUFFICIENT_RESOURCES;
  1151. }
  1152. irp->Tail.Overlay.OriginalFileObject = fileObject;
  1153. irp->Tail.Overlay.Thread = CurrentThread;
  1154. irp->RequestorMode = requestorMode;
  1155. //
  1156. // Fill in the service independent parameters in the IRP.
  1157. //
  1158. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  1159. irp->UserEvent = (PKEVENT) NULL;
  1160. } else {
  1161. irp->UserEvent = &event;
  1162. irp->Flags = IRP_SYNCHRONOUS_API;
  1163. }
  1164. irp->UserIosb = &localIoStatus;
  1165. irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL;
  1166. //
  1167. // Get a pointer to the stack location for the first driver. This will
  1168. // be used to pass the original function codes and parameters.
  1169. //
  1170. irpSp = IoGetNextIrpStackLocation( irp );
  1171. //
  1172. // Now determine whether this is a set or a query operation.
  1173. //
  1174. if (OperationCode == QuerySecurityDescriptor) {
  1175. //
  1176. // This is a query operation. Fill in the appropriate fields in
  1177. // the stack location for the packet, as well as the fixed part
  1178. // of the packet. Note that each of these parameters has been
  1179. // captured as well, so there is no need to perform any probing.
  1180. // The only exception is the UserBuffer memory may change, but
  1181. // that is the file system's responsibility to check. Note that
  1182. // it has already been probed, so the pointer is at least not
  1183. // in an address space that the caller should not be accessing
  1184. // because of mode.
  1185. //
  1186. irpSp->MajorFunction = IRP_MJ_QUERY_SECURITY;
  1187. irpSp->Parameters.QuerySecurity.SecurityInformation = *SecurityInformation;
  1188. irpSp->Parameters.QuerySecurity.Length = *CapturedLength;
  1189. irp->UserBuffer = SecurityDescriptor;
  1190. } else {
  1191. //
  1192. // This is a set operation. Fill in the appropriate fields in
  1193. // the stack location for the packet. Note that access to the
  1194. // SecurityInformation parameter is safe, as the parameter was
  1195. // captured by the caller. Likewise, the SecurityDescriptor
  1196. // refers to a captured copy of the descriptor.
  1197. //
  1198. irpSp->MajorFunction = IRP_MJ_SET_SECURITY;
  1199. irpSp->Parameters.SetSecurity.SecurityInformation = *SecurityInformation;
  1200. irpSp->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;
  1201. }
  1202. irpSp->FileObject = fileObject;
  1203. //
  1204. // Insert the packet at the head of the IRP list for the thread.
  1205. //
  1206. IopQueueThreadIrp( irp );
  1207. //
  1208. // Update the operation count statistic for the current process for
  1209. // operations other than read and write.
  1210. //
  1211. IopUpdateOtherOperationCount();
  1212. //
  1213. // Everything has been properly set up, so simply invoke the driver.
  1214. //
  1215. status = IoCallDriver( deviceObject, irp );
  1216. //
  1217. // If this operation was a synchronous I/O operation, check the return
  1218. // status to determine whether or not to wait on the file object. If
  1219. // the file object is to be waited on, wait for the operation to be
  1220. // completed and obtain the final status from the file object itself.
  1221. //
  1222. if (synchronousIo) {
  1223. if (status == STATUS_PENDING) {
  1224. (VOID) KeWaitForSingleObject( &fileObject->Event,
  1225. Executive,
  1226. KernelMode,
  1227. FALSE,
  1228. (PLARGE_INTEGER) NULL );
  1229. status = fileObject->FinalStatus;
  1230. }
  1231. IopReleaseFileObjectLock( fileObject );
  1232. } else {
  1233. //
  1234. // This is a normal synchronous I/O operation, as opposed to a
  1235. // serialized synchronous I/O operation. For this case, wait
  1236. // for the local event and return the final status information
  1237. // back to the caller.
  1238. //
  1239. if (status == STATUS_PENDING) {
  1240. (VOID) KeWaitForSingleObject( &event,
  1241. Executive,
  1242. KernelMode,
  1243. FALSE,
  1244. (PLARGE_INTEGER) NULL );
  1245. status = localIoStatus.Status;
  1246. }
  1247. }
  1248. //
  1249. // If this operation was just attempted on a file system or a device
  1250. // driver of some kind that does not implement security, then return
  1251. // a normal null security descriptor.
  1252. //
  1253. if (status == STATUS_INVALID_DEVICE_REQUEST) {
  1254. //
  1255. // The file system does not implement a security policy. Determine
  1256. // what type of operation this was and implement the correct
  1257. // semantics for the file system.
  1258. //
  1259. if (OperationCode == QuerySecurityDescriptor) {
  1260. //
  1261. // The operation is a query. If the caller's buffer is too
  1262. // small, then indicate that this is the case and let him know
  1263. // what size buffer is required. Otherwise, attempt to return
  1264. // a null security descriptor.
  1265. //
  1266. try {
  1267. status = SeAssignWorldSecurityDescriptor(
  1268. SecurityDescriptor,
  1269. CapturedLength,
  1270. SecurityInformation
  1271. );
  1272. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1273. //
  1274. // An exception was incurred while attempting to
  1275. // access the caller's buffer. Clean everything
  1276. // up and return an appropriate status code.
  1277. //
  1278. status = GetExceptionCode();
  1279. }
  1280. } else {
  1281. //
  1282. // This was an operation other than a query. Simply indicate
  1283. // that the operation was successful.
  1284. //
  1285. status = STATUS_SUCCESS;
  1286. }
  1287. } else if (OperationCode == QuerySecurityDescriptor) {
  1288. //
  1289. // The final return status from the file system was something
  1290. // other than invalid device request. This means that the file
  1291. // system actually implemented the query. Copy the size of the
  1292. // returned data, or the size of the buffer required in order
  1293. // to query the security descriptor. Note that once again the
  1294. // assignment is performed inside of an exception handler in case
  1295. // the caller's buffer is inaccessible. Also note that in order
  1296. // for the Information field of the I/O status block to be set,
  1297. // the file system must return a warning status. Return the
  1298. // status that the caller expects if the buffer really is too
  1299. // small.
  1300. //
  1301. if (status == STATUS_BUFFER_OVERFLOW) {
  1302. status = STATUS_BUFFER_TOO_SMALL;
  1303. }
  1304. try {
  1305. *CapturedLength = (ULONG) localIoStatus.Information;
  1306. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1307. status = GetExceptionCode();
  1308. }
  1309. }
  1310. }
  1311. return status;
  1312. }