Windows NT 4.0 source code leak
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.

389 lines
11 KiB

4 years ago
  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation.
  4. //
  5. // File: CLOSE.C
  6. //
  7. // Contents: This module implements the File Close and Cleanup routines for
  8. // Dsfs called by the dispatch driver.
  9. //
  10. // Functions: DfsFsdClose - FSD entry point for Close IRP
  11. // DfsFsdCleanup - FSD entry point for Cleanup IRP
  12. // DfsFspClose - FSP entry point for Close IRP
  13. // DfsCommonClose - Common close IRP handler
  14. //
  15. // History: 12 Nov 1991 AlanW Created from CDFS souce.
  16. //-----------------------------------------------------------------------------
  17. #include "dfsprocs.h"
  18. #include "fcbsup.h"
  19. //
  20. // The local debug trace level
  21. //
  22. #define Dbg (DEBUG_TRACE_CLOSE)
  23. //
  24. // Local procedure prototypes
  25. //
  26. NTSTATUS
  27. DfsCommonClose (
  28. IN PIRP_CONTEXT IrpContext,
  29. IN PIRP Irp
  30. );
  31. #ifdef ALLOC_PRAGMA
  32. #pragma alloc_text( PAGE, DfsFsdClose )
  33. #pragma alloc_text( PAGE, DfsFsdCleanup )
  34. #pragma alloc_text( PAGE, DfsFspClose )
  35. #pragma alloc_text( PAGE, DfsCommonClose )
  36. #endif // ALLOC_PRAGMA
  37. //+-------------------------------------------------------------------
  38. //
  39. // Function: DfsFsdClose, public
  40. //
  41. // Synopsis: This routine implements the FSD part of closing down the
  42. // last reference to a file object.
  43. //
  44. // Arguments: [DeviceObject] -- Supplies the device object where the
  45. // file being closed exists
  46. // [Irp] - Supplies the Irp being processed
  47. //
  48. // Returns: NTSTATUS - The FSD status for the IRP
  49. //
  50. // Notes: Even when the close is through the attached device
  51. // object, we need to check if the file is one of ours,
  52. // since files opened via the logical root device
  53. // object get switched over to the attached device for
  54. // local volumes.
  55. //
  56. //--------------------------------------------------------------------
  57. NTSTATUS
  58. DfsFsdClose (
  59. IN PDEVICE_OBJECT DeviceObject,
  60. IN PIRP Irp
  61. ) {
  62. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  63. NTSTATUS Status;
  64. PIRP_CONTEXT IrpContext;
  65. DfsDbgTrace(+1, Dbg, "DfsFsdClose: Entered\n", 0);
  66. ASSERT(IoIsOperationSynchronous(Irp) == TRUE);
  67. if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME) {
  68. if (DfsLookupFcb(IrpSp->FileObject) == NULL) {
  69. Status = DfsVolumePassThrough(DeviceObject, Irp);
  70. DfsDbgTrace(-1, Dbg, "DfsFsdClose: Exit -> %08lx\n", Status );
  71. return Status;
  72. }
  73. }
  74. //
  75. // Call the common close routine, with blocking allowed if synchronous
  76. //
  77. FsRtlEnterFileSystem();
  78. try {
  79. IrpContext = DfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
  80. Status = DfsCommonClose( IrpContext, Irp );
  81. } except(DfsExceptionFilter( IrpContext, GetExceptionCode(), GetExceptionInformation() )) {
  82. //
  83. // We had some trouble trying to perform the requested
  84. // operation, so we'll abort the I/O request with
  85. // the error status that we get back from the
  86. // execption code
  87. //
  88. Status = DfsProcessException( IrpContext, Irp, GetExceptionCode() );
  89. }
  90. FsRtlExitFileSystem();
  91. //
  92. // And return to our caller
  93. //
  94. DfsDbgTrace(-1, Dbg, "DfsFsdClose: Exit -> %08lx\n", Status);
  95. return Status;
  96. }
  97. //+-------------------------------------------------------------------
  98. //
  99. // Function: DfsFsdCleanup, public
  100. //
  101. // Synopsis: This routine implements the FSD part of closing down the
  102. // last user handle to a file object.
  103. //
  104. // Arguments: [DeviceObject] -- Supplies the device object where the
  105. // file being closed exists
  106. // [Irp] - Supplies the Irp being processed
  107. //
  108. // Returns: NTSTATUS - The FSD status for the IRP
  109. //
  110. //--------------------------------------------------------------------
  111. NTSTATUS
  112. DfsFsdCleanup (
  113. IN PDEVICE_OBJECT DeviceObject,
  114. IN PIRP Irp
  115. ) {
  116. NTSTATUS Status;
  117. PIRP_CONTEXT IrpContext;
  118. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  119. PFILE_OBJECT FileObject = IrpSp->FileObject;
  120. TYPE_OF_OPEN TypeOfOpen;
  121. PDFS_VCB Vcb;
  122. PDFS_FCB Fcb;
  123. DfsDbgTrace(+1, Dbg, "DfsFsdCleanup: Entered\n", 0);
  124. ASSERT(IoIsOperationSynchronous(Irp) == TRUE);
  125. //
  126. // Now, pass through to the device that opened the file for us if the
  127. // file was a redirected open of some kind.
  128. //
  129. if (DeviceObject->DeviceType == FILE_DEVICE_DFS) {
  130. TypeOfOpen = DfsDecodeFileObject( FileObject, &Vcb, &Fcb);
  131. if (TypeOfOpen == RedirectedFileOpen) {
  132. Status = DfsVolumePassThrough(DeviceObject, Irp);
  133. DfsDbgTrace(-1, Dbg, "DfsFsdCleanup: RedirectedOpen.Exit -> %08lx\n", Status );
  134. return Status;
  135. }
  136. }
  137. //
  138. // TypeOfOpen != RedirectedFileOpen. We do nothing special for cleanup;
  139. // everything is done in the close routine.
  140. //
  141. FsRtlEnterFileSystem();
  142. Status = STATUS_SUCCESS;
  143. DfsCompleteRequest( NULL, Irp, Status );
  144. FsRtlExitFileSystem();
  145. //
  146. // And return to our caller
  147. //
  148. DfsDbgTrace(-1, Dbg, "DfsFsdCleanup: Exit -> %08lx\n", Status);
  149. return Status;
  150. }
  151. //+-------------------------------------------------------------------
  152. //
  153. // Function: DfsFspClose, public
  154. //
  155. // Synopsis: This routine implements the FSP part of closing down the
  156. // last reference to a file object.
  157. //
  158. // Arguments: [IrpContext] -- Supplies the IRP context for the request
  159. // being processed.
  160. // [Irp] - Supplies the Irp being processed
  161. //
  162. // Returns: PDEVICE_OBJECT - Returns the volume device object
  163. // of the volume just processed by this operation.
  164. // This value is used by the Fsp dispatcher to examine
  165. // the device object's overflow queue
  166. //
  167. //--------------------------------------------------------------------
  168. VOID
  169. DfsFspClose (
  170. IN PIRP_CONTEXT IrpContext,
  171. IN PIRP Irp
  172. ) {
  173. DfsDbgTrace(+1, Dbg, "DfsFspClose: Entered\n", 0);
  174. //
  175. // Call the common close routine.
  176. //
  177. (VOID)DfsCommonClose( IrpContext, Irp );
  178. //
  179. // And return to our caller
  180. //
  181. DfsDbgTrace(-1, Dbg, "DfsFspClose: Exit -> VOID\n", 0);
  182. }
  183. //+-------------------------------------------------------------------
  184. //
  185. // Function: DfsCommonClose, local
  186. //
  187. // Synopsis: This is the common routine for closing a file/directory
  188. // called by both the fsd and fsp threads.
  189. //
  190. // Close is invoked whenever the last reference to a file
  191. // object is deleted. Cleanup is invoked when the last handle
  192. // to a file object is closed, and is called before close.
  193. //
  194. // The function of close is to completely tear down and
  195. // remove the DFS_FCB structures associated with the
  196. // file object.
  197. //
  198. // Arguments: [Irp] -- Supplies the Irp to process
  199. //
  200. // Returns: NTSTATUS - The return status for the operation
  201. //
  202. //--------------------------------------------------------------------
  203. NTSTATUS
  204. DfsCommonClose (
  205. IN PIRP_CONTEXT IrpContext,
  206. IN PIRP Irp
  207. ) {
  208. NTSTATUS Status;
  209. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  210. PFILE_OBJECT FileObject = IrpSp->FileObject;
  211. TYPE_OF_OPEN TypeOfOpen;
  212. PDFS_VCB Vcb;
  213. PDFS_FCB Fcb;
  214. BOOLEAN DontComplete = FALSE;
  215. BOOLEAN pktLocked;
  216. DfsDbgTrace(+1, Dbg, "DfsCommonClose: Entered\n", 0);
  217. DfsDbgTrace( 0, Dbg, "Irp = %08lx\n", Irp);
  218. DfsDbgTrace( 0, Dbg, "->FileObject = %08lx\n", FileObject);
  219. //
  220. // This action is a noop for unopened file objects. Nothing needs
  221. // to be done for FS device opens, either.
  222. //
  223. TypeOfOpen = DfsDecodeFileObject( FileObject, &Vcb, &Fcb);
  224. if (TypeOfOpen == UnopenedFileObject ||
  225. TypeOfOpen == FilesystemDeviceOpen ) {
  226. DfsDbgTrace(-1, Dbg, "DfsCommonClose: Filesystem file object\n", 0);
  227. DfsCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
  228. return STATUS_SUCCESS;
  229. }
  230. try {
  231. //
  232. // Case on the type of open that we are trying to close.
  233. //
  234. switch (TypeOfOpen) {
  235. case LogicalRootDeviceOpen:
  236. DfsDbgTrace(0, Dbg, "DfsCommonClose: Close LogicalRootDevice\n", 0);
  237. ExInterlockedDecrementLong(&Vcb->DirectAccessOpenCount, &DfsData.DfsLock);
  238. ExInterlockedDecrementLong(&Vcb->OpenFileCount, &DfsData.DfsLock);
  239. if (Vcb->VcbState & VCB_STATE_FLAG_LOCKED) {
  240. ASSERT (Vcb->FileObjectWithVcbLocked == FileObject);
  241. Vcb->VcbState &= ~VCB_STATE_FLAG_LOCKED;
  242. Vcb->FileObjectWithVcbLocked = NULL;
  243. }
  244. try_return( Status = STATUS_SUCCESS );
  245. case RedirectedFileOpen:
  246. DfsDbgTrace(0, Dbg, "DfsCommonClose: File -> %wZ\n", &Fcb->FullFileName);
  247. //
  248. // Decrement the OpenFileCount for the Vcb through which this
  249. // file was opened.
  250. //
  251. ExInterlockedDecrementLong(&Vcb->OpenFileCount, &DfsData.DfsLock);
  252. //
  253. // Decrement the RefCount on the DFS_MACHINE_ENTRY through which
  254. // this file was opened
  255. //
  256. PktAcquireExclusive( TRUE, &pktLocked );
  257. ExAcquireResourceExclusive( &DfsData.Resource, TRUE );
  258. DfsDecrementMachEntryCount(Fcb->DfsMachineEntry, TRUE);
  259. ExReleaseResource( &DfsData.Resource );
  260. PktRelease();
  261. //
  262. // Close the redirected file by simply passing through
  263. // to the redirected device. We detach the DFS_FCB from the
  264. // file object before the close so it cannot be looked
  265. // up in some other thread.
  266. //
  267. DfsDetachFcb( FileObject, Fcb);
  268. Status = DfsFilePassThrough(Fcb, Irp);
  269. DontComplete = TRUE;
  270. DfsDeleteFcb( IrpContext, Fcb );
  271. break;
  272. default:
  273. BugCheck("Dfs close, unexpected open type");
  274. }
  275. Status = STATUS_SUCCESS;
  276. try_exit: NOTHING;
  277. } finally {
  278. //
  279. // If this is a normal termination, then complete the request.
  280. // Even if we're not to complete the IRP, we still need to
  281. // delete the IRP_CONTEXT.
  282. //
  283. if (!AbnormalTermination()) {
  284. if (DontComplete) {
  285. DfsCompleteRequest( IrpContext, NULL, 0 );
  286. } else {
  287. DfsCompleteRequest( IrpContext, Irp, Status );
  288. }
  289. }
  290. DfsDbgTrace(-1, Dbg, "DfsCommonClose: Exit -> %08lx\n", Status);
  291. }
  292. return Status;
  293. }