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.

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