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.

450 lines
12 KiB

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