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.

595 lines
12 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. cleanup.c
  5. Abstract:
  6. This module implements the file cleanup routine for Netware Redirector.
  7. Author:
  8. Manny Weiser (mannyw) 9-Feb-1993
  9. Revision History:
  10. --*/
  11. #include "procs.h"
  12. //
  13. // The debug trace level
  14. //
  15. #define Dbg (DEBUG_TRACE_CLEANUP)
  16. //
  17. // local procedure prototypes
  18. //
  19. NTSTATUS
  20. NwCommonCleanup (
  21. IN PIRP_CONTEXT IrpContext
  22. );
  23. NTSTATUS
  24. NwCleanupRcb (
  25. IN PIRP Irp,
  26. IN PRCB Rcb
  27. );
  28. NTSTATUS
  29. NwCleanupScb (
  30. IN PIRP Irp,
  31. IN PSCB Scb
  32. );
  33. NTSTATUS
  34. NwCleanupIcb (
  35. IN PIRP_CONTEXT IrpContext,
  36. IN PIRP Irp,
  37. IN PICB Icb
  38. );
  39. #ifdef ALLOC_PRAGMA
  40. #pragma alloc_text( PAGE, NwFsdCleanup )
  41. #pragma alloc_text( PAGE, NwCommonCleanup )
  42. #pragma alloc_text( PAGE, NwCleanupScb )
  43. #ifndef QFE_BUILD
  44. #pragma alloc_text( PAGE1, NwCleanupIcb )
  45. #endif
  46. #endif
  47. #if 0 // Not pageable
  48. NwCleanupRcb
  49. // see ifndef QFE_BUILD above
  50. #endif
  51. NTSTATUS
  52. NwFsdCleanup (
  53. IN PDEVICE_OBJECT DeviceObject,
  54. IN PIRP Irp
  55. )
  56. /*++
  57. Routine Description:
  58. This routine implements the FSD part of the NtCleanupFile API calls.
  59. Arguments:
  60. DeviceObject - Supplies the device object to use.
  61. Irp - Supplies the Irp being processed
  62. Return Value:
  63. NTSTATUS - The Fsd status for the Irp
  64. --*/
  65. {
  66. NTSTATUS status;
  67. PIRP_CONTEXT IrpContext = NULL;
  68. BOOLEAN TopLevel;
  69. PAGED_CODE();
  70. DebugTrace(+1, Dbg, "NwFsdCleanup\n", 0);
  71. //
  72. // Call the common cleanup routine.
  73. //
  74. TopLevel = NwIsIrpTopLevel( Irp );
  75. FsRtlEnterFileSystem();
  76. try {
  77. IrpContext = AllocateIrpContext( Irp );
  78. status = NwCommonCleanup( IrpContext );
  79. } except(NwExceptionFilter( Irp, GetExceptionInformation() )) {
  80. if ( IrpContext == NULL ) {
  81. //
  82. // If we couldn't allocate an irp context, just complete
  83. // irp without any fanfare.
  84. //
  85. status = STATUS_INSUFFICIENT_RESOURCES;
  86. Irp->IoStatus.Status = status;
  87. Irp->IoStatus.Information = 0;
  88. IoCompleteRequest ( Irp, IO_NETWORK_INCREMENT );
  89. } else {
  90. //
  91. // We had some trouble trying to perform the requested
  92. // operation, so we'll abort the I/O request with
  93. // the error status that we get back from the
  94. // execption code.
  95. //
  96. status = NwProcessException( IrpContext, GetExceptionCode() );
  97. }
  98. }
  99. if ( IrpContext ) {
  100. NwCompleteRequest( IrpContext, status );
  101. }
  102. if ( TopLevel ) {
  103. NwSetTopLevelIrp( NULL );
  104. }
  105. FsRtlExitFileSystem();
  106. //
  107. // Return to our caller.
  108. //
  109. DebugTrace(-1, Dbg, "NwFsdCleanup -> %08lx\n", status );
  110. return status;
  111. }
  112. NTSTATUS
  113. NwCommonCleanup (
  114. IN PIRP_CONTEXT IrpContext
  115. )
  116. /*++
  117. Routine Description:
  118. This is the common routine for cleaning up a file.
  119. Arguments:
  120. IrpContext - Supplies the Irp to process
  121. Return Value:
  122. NTSTATUS - the return status for the operation
  123. --*/
  124. {
  125. PIRP Irp;
  126. PIO_STACK_LOCATION irpSp;
  127. NTSTATUS status;
  128. NODE_TYPE_CODE nodeTypeCode;
  129. PVOID fsContext, fsContext2;
  130. PAGED_CODE();
  131. Irp = IrpContext->pOriginalIrp;
  132. irpSp = IoGetCurrentIrpStackLocation( Irp );
  133. DebugTrace(+1, Dbg, "NwCommonCleanup\n", 0);
  134. DebugTrace( 0, Dbg, "IrpContext = %08lx\n", (ULONG_PTR)IrpContext);
  135. DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG_PTR)Irp);
  136. DebugTrace( 0, Dbg, "FileObject = %08lx\n", (ULONG_PTR)irpSp->FileObject);
  137. try {
  138. //
  139. // Get the a referenced pointer to the node and make sure it is
  140. // not being closed.
  141. //
  142. if ((nodeTypeCode = NwDecodeFileObject( irpSp->FileObject,
  143. &fsContext,
  144. &fsContext2 )) == NTC_UNDEFINED) {
  145. DebugTrace(0, Dbg, "The file is disconnected\n", 0);
  146. status = STATUS_INVALID_HANDLE;
  147. DebugTrace(-1, Dbg, "NwCommonCleanup -> %08lx\n", status );
  148. try_return( NOTHING );
  149. }
  150. //
  151. // Decide how to handle this IRP.
  152. //
  153. switch (nodeTypeCode) {
  154. case NW_NTC_RCB: // Cleanup the file system
  155. status = NwCleanupRcb( Irp, (PRCB)fsContext2 );
  156. break;
  157. case NW_NTC_SCB: // Cleanup the server control block
  158. status = NwCleanupScb( Irp, (PSCB)fsContext2 );
  159. break;
  160. case NW_NTC_ICB: // Cleanup the remote file
  161. case NW_NTC_ICB_SCB: // Cleanup the server
  162. status = NwCleanupIcb( IrpContext, Irp, (PICB)fsContext2 );
  163. break;
  164. #ifdef NWDBG
  165. default:
  166. //
  167. // This is not one of ours.
  168. //
  169. KeBugCheck( RDR_FILE_SYSTEM );
  170. break;
  171. #endif
  172. }
  173. try_exit: NOTHING;
  174. } finally {
  175. DebugTrace(-1, Dbg, "NwCommonCleanup -> %08lx\n", status);
  176. }
  177. return status;
  178. }
  179. NTSTATUS
  180. NwCleanupRcb (
  181. IN PIRP Irp,
  182. IN PRCB Rcb
  183. )
  184. /*++
  185. Routine Description:
  186. The routine cleans up a RCB.
  187. This routine grabs a spinlock so must not be paged out while running.
  188. Do not reference the code section since this will start the timer and
  189. we don't stop it in the rcb close path.
  190. Arguments:
  191. Irp - Supplies the IRP associated with the cleanup.
  192. Rcb - Supplies the RCB for MSFS.
  193. Return Value:
  194. NTSTATUS - An appropriate completion status
  195. --*/
  196. {
  197. NTSTATUS status;
  198. PIO_STACK_LOCATION irpSp;
  199. PFILE_OBJECT closingFileObject;
  200. BOOLEAN OwnRcb;
  201. BOOLEAN OwnMessageLock = FALSE;
  202. KIRQL OldIrql;
  203. PLIST_ENTRY listEntry, nextListEntry;
  204. PIRP_CONTEXT pTestIrpContext;
  205. PIO_STACK_LOCATION pTestIrpSp;
  206. PIRP pTestIrp;
  207. DebugTrace(+1, Dbg, "NwCleanupRcb...\n", 0);
  208. //
  209. // Now acquire exclusive access to the Rcb
  210. //
  211. NwAcquireExclusiveRcb( Rcb, TRUE );
  212. OwnRcb = TRUE;
  213. status = STATUS_SUCCESS;
  214. try {
  215. irpSp = IoGetCurrentIrpStackLocation( Irp );
  216. IoRemoveShareAccess( irpSp->FileObject,
  217. &Rcb->ShareAccess );
  218. NwReleaseRcb( Rcb );
  219. OwnRcb = FALSE;
  220. closingFileObject = irpSp->FileObject;
  221. //
  222. // Walk the message queue and complete any outstanding Get Message IRPs
  223. //
  224. KeAcquireSpinLock( &NwMessageSpinLock, &OldIrql );
  225. OwnMessageLock = TRUE;
  226. for ( listEntry = NwGetMessageList.Flink;
  227. listEntry != &NwGetMessageList;
  228. listEntry = nextListEntry ) {
  229. nextListEntry = listEntry->Flink;
  230. //
  231. // If the file object of the queued request, matches the file object
  232. // that is being closed, remove the IRP from the queue, and
  233. // complete it with an error.
  234. //
  235. pTestIrpContext = CONTAINING_RECORD( listEntry, IRP_CONTEXT, NextRequest );
  236. pTestIrp = pTestIrpContext->pOriginalIrp;
  237. pTestIrpSp = IoGetCurrentIrpStackLocation( pTestIrp );
  238. if ( pTestIrpSp->FileObject == closingFileObject ) {
  239. RemoveEntryList( listEntry );
  240. IoAcquireCancelSpinLock( &pTestIrp->CancelIrql );
  241. IoSetCancelRoutine( pTestIrp, NULL );
  242. IoReleaseCancelSpinLock( pTestIrp->CancelIrql );
  243. NwCompleteRequest( pTestIrpContext, STATUS_INVALID_HANDLE );
  244. }
  245. }
  246. KeReleaseSpinLock( &NwMessageSpinLock, OldIrql );
  247. OwnMessageLock = FALSE;
  248. } finally {
  249. if ( OwnRcb ) {
  250. NwReleaseRcb( Rcb );
  251. }
  252. if ( OwnMessageLock ) {
  253. KeReleaseSpinLock( &NwMessageSpinLock, OldIrql );
  254. }
  255. DebugTrace(-1, Dbg, "NwCleanupRcb -> %08lx\n", status);
  256. }
  257. //
  258. // And return to our caller
  259. //
  260. return status;
  261. }
  262. NTSTATUS
  263. NwCleanupScb (
  264. IN PIRP Irp,
  265. IN PSCB Scb
  266. )
  267. /*++
  268. Routine Description:
  269. The routine cleans up an ICB.
  270. Arguments:
  271. Irp - Supplies the IRP associated with the cleanup.
  272. Scb - Supplies the SCB to cleanup.
  273. Return Value:
  274. NTSTATUS - An appropriate completion status
  275. --*/
  276. {
  277. NTSTATUS Status;
  278. PAGED_CODE();
  279. DebugTrace(+1, Dbg, "NwCleanupScb...\n", 0);
  280. Status = STATUS_SUCCESS;
  281. try {
  282. //
  283. // Ensure that this SCB is still active.
  284. //
  285. NwVerifyScb( Scb );
  286. //
  287. // Cancel any IO on this SCB.
  288. //
  289. } finally {
  290. DebugTrace(-1, Dbg, "NwCleanupScb -> %08lx\n", Status);
  291. }
  292. //
  293. // And return to our caller
  294. //
  295. return Status;
  296. }
  297. NTSTATUS
  298. NwCleanupIcb (
  299. IN PIRP_CONTEXT pIrpContext,
  300. IN PIRP Irp,
  301. IN PICB Icb
  302. )
  303. /*++
  304. Routine Description:
  305. The routine cleans up an ICB.
  306. Arguments:
  307. Irp - Supplies the IRP associated with the cleanup.
  308. Rcb - Supplies the RCB for MSFS.
  309. Return Value:
  310. NTSTATUS - An appropriate completion status
  311. --*/
  312. {
  313. NTSTATUS Status;
  314. PNONPAGED_FCB NpFcb;
  315. DebugTrace(+1, Dbg, "NwCleanupIcb...\n", 0);
  316. Status = STATUS_SUCCESS;
  317. try {
  318. Icb->State = ICB_STATE_CLEANED_UP;
  319. //
  320. // Cancel any IO on this ICB.
  321. //
  322. #if 0
  323. // HACKHACK
  324. if ( Icb->SuperType.Fcb->NodeTypeCode == NW_NTC_DCB ) {
  325. PLIST_ENTRY listEntry;
  326. NwAcquireExclusiveRcb( &NwRcb, TRUE );
  327. for ( listEntry = FnList.Flink; listEntry != &FnList ; listEntry = listEntry->Flink ) {
  328. PIRP_CONTEXT IrpContext;
  329. IrpContext = CONTAINING_RECORD( listEntry, IRP_CONTEXT, NextRequest );
  330. if ( IrpContext->Icb == Icb ) {
  331. PIRP irp = pIrpContext->pOriginalIrp;
  332. IoAcquireCancelSpinLock( &irp->CancelIrql );
  333. IoSetCancelRoutine( irp, NULL );
  334. IoReleaseCancelSpinLock( irp->CancelIrql );
  335. RemoveEntryList( &IrpContext->NextRequest );
  336. NwCompleteRequest( IrpContext, STATUS_NOT_SUPPORTED );
  337. break;
  338. }
  339. }
  340. NwReleaseRcb( &NwRcb );
  341. }
  342. #endif
  343. //
  344. // If this is a remote file clear all the cache garbage.
  345. //
  346. if ( Icb->NodeTypeCode == NW_NTC_ICB ) {
  347. if ( Icb->HasRemoteHandle ) {
  348. //
  349. // Free all of file lock structures that are still hanging around.
  350. //
  351. pIrpContext->pScb = Icb->SuperType.Fcb->Scb;
  352. pIrpContext->pNpScb = Icb->SuperType.Fcb->Scb->pNpScb;
  353. NwFreeLocksForIcb( pIrpContext, Icb );
  354. NwDequeueIrpContext( pIrpContext, FALSE );
  355. //
  356. //
  357. //
  358. // If this is an executable opened over the net, then
  359. // its possible that the executables image section
  360. // might still be kept open.
  361. //
  362. // Ask MM to flush the section closed. This will fail
  363. // if the executable in question is still running.
  364. //
  365. NpFcb = Icb->SuperType.Fcb->NonPagedFcb;
  366. MmFlushImageSection(&NpFcb->SegmentObject, MmFlushForWrite);
  367. //
  368. // There is also a possiblity that there is a user section
  369. // open on this file, in which case we need to force the
  370. // section closed to make sure that they are cleaned up.
  371. //
  372. MmForceSectionClosed(&NpFcb->SegmentObject, TRUE);
  373. }
  374. //
  375. // Acquire the fcb and remove shared access.
  376. //
  377. NwAcquireExclusiveFcb( Icb->SuperType.Fcb->NonPagedFcb, TRUE );
  378. IoRemoveShareAccess(
  379. Icb->FileObject,
  380. &Icb->SuperType.Fcb->ShareAccess );
  381. NwReleaseFcb( Icb->SuperType.Fcb->NonPagedFcb );
  382. }
  383. } finally {
  384. DebugTrace(-1, Dbg, "NwCleanupIcb -> %08lx\n", Status);
  385. }
  386. //
  387. // And return to our caller
  388. //
  389. return Status;
  390. }