VOID NTAPI NpDeleteFcb(IN PNP_FCB Fcb, IN PLIST_ENTRY ListEntry) { PNP_DCB Dcb; PAGED_CODE(); Dcb = Fcb->ParentDcb; if (Fcb->CurrentInstances) NpBugCheck(0, 0, 0); NpCancelWaiter(&NpVcb->WaitQueue, &Fcb->FullName, STATUS_OBJECT_NAME_NOT_FOUND, ListEntry); RemoveEntryList(&Fcb->DcbEntry); if (Fcb->SecurityDescriptor) { ObDereferenceSecurityDescriptor(Fcb->SecurityDescriptor, 1); } RtlRemoveUnicodePrefix(&NpVcb->PrefixTable, &Fcb->PrefixTableEntry); ExFreePool(Fcb->FullName.Buffer); ExFreePool(Fcb); NpCheckForNotify(Dcb, TRUE, ListEntry); }
VOID MsDeleteRootDcb ( IN PROOT_DCB RootDcb ) /*++ Routine Description: This routine deallocates and removes the ROOT DCB record from our in-memory data structures. It also will remove all associated underlings (i.e., Notify queues and child FCB records). Arguments: RootDcb - Supplies the ROOT DCB to be removed Return Value: None --*/ { PLIST_ENTRY links; PIRP irp; PAGED_CODE(); DebugTrace(+1, Dbg, "MsDeleteRootDcb, RootDcb = %08lx\n", (ULONG)RootDcb); // // We can only delete this record if the reference count is zero. // if (RootDcb->Header.ReferenceCount != 0) { DebugDump("Error deleting RootDcb, Still Open\n", 0, RootDcb); KeBugCheck( MAILSLOT_FILE_SYSTEM ); } // // Remove every notify IRP from the two notify queues. // while (!IsListEmpty(&RootDcb->Specific.Dcb.NotifyFullQueue)) { links = RemoveHeadList( &RootDcb->Specific.Dcb.NotifyFullQueue ); irp = CONTAINING_RECORD( links, IRP, Tail.Overlay.ListEntry ); MsCompleteRequest( irp, STATUS_FILE_FORCED_CLOSED ); } while (!IsListEmpty(&RootDcb->Specific.Dcb.NotifyPartialQueue)) { links = RemoveHeadList( &RootDcb->Specific.Dcb.NotifyPartialQueue ); irp = CONTAINING_RECORD( links, IRP, Tail.Overlay.ListEntry ); MsCompleteRequest( irp, STATUS_FILE_FORCED_CLOSED ); } // // We can only be removed if the no other FCB have us referenced // as a their parent DCB. // if (!IsListEmpty(&RootDcb->Specific.Dcb.ParentDcbQueue)) { DebugDump("Error deleting RootDcb\n", 0, RootDcb); KeBugCheck( MAILSLOT_FILE_SYSTEM ); } // // Remove the entry from the prefix table, and then remove the full // file name. // MsAcquirePrefixTableLock(); RtlRemoveUnicodePrefix( &RootDcb->Vcb->PrefixTable, &RootDcb->PrefixTableEntry ); MsReleasePrefixTableLock(); ExFreePool( RootDcb->FullFileName.Buffer ); // // Free up the resource variable. // ExDeleteResource( &(RootDcb->Resource) ); // // Finally deallocate the DCB record. // ExFreePool( RootDcb ); // // Return to the caller. // DebugTrace(-1, Dbg, "MsDeleteRootDcb -> VOID\n", 0); return; }
NTSTATUS MsCleanupFcb ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp, IN PFCB Fcb ) /*++ Routine Description: This routine cleans up an FCB. All outstanding i/o on the file object are completed with an error status. Arguments: MsfsDeviceObject - A pointer the the mailslot file system device object. Irp - Supplies the IRP associated with the cleanup. Fcb - Supplies the FCB for the mailslot to clean up. Return Value: NTSTATUS - An appropriate completion status --*/ { NTSTATUS status; PDATA_QUEUE dataQueue; PDATA_ENTRY dataEntry; PLIST_ENTRY listEntry; PIRP oldIrp; PCCB ccb; PWORK_CONTEXT workContext; PKTIMER timer; PAGED_CODE(); DebugTrace(+1, Dbg, "MsCleanupFcb, Fcb = %08lx\n", (ULONG)Fcb); // // Acquire exclusive access to the FCB. // MsAcquireExclusiveFcb( Fcb ); status = STATUS_SUCCESS; try { // // Ensure that this FCB still belongs to an active open mailslot. // MsVerifyFcb( Fcb ); // // Remove the entry from the prefix table, and then remove the full // file name. // MsAcquirePrefixTableLock(); RtlRemoveUnicodePrefix( &Fcb->Vcb->PrefixTable, &Fcb->PrefixTableEntry ); MsReleasePrefixTableLock(); // // Remove ourselves from our parent DCB's queue. // RemoveEntryList( &(Fcb->ParentDcbLinks) ); // // Complete all outstanding I/O on this FCB. // dataQueue = &Fcb->DataQueue; dataQueue->QueueState = -1; for (listEntry = MsGetNextDataQueueEntry( dataQueue ); !MsIsDataQueueEmpty(dataQueue); listEntry = MsGetNextDataQueueEntry( dataQueue ) ) { // // This is an outstanding I/O request on this FCB. // Remove it from our queue and complete the request // if one is outstanding. // dataEntry = CONTAINING_RECORD( listEntry, DATA_ENTRY, ListEntry ); // // Cancel the timer if there is a timer for the read request. // workContext = dataEntry->TimeoutWorkContext; if (workContext != NULL) { DebugTrace( 0, Dbg, "Cancelling a timer\n", 0); // // There was a timer on this read operation. Attempt // to cancel the operation. If the cancel operation // is successful, then we must cleanup after the operation. // If it was unsuccessful the timer DPC will run, and // will eventually cleanup. // timer = &workContext->Timer; if (KeCancelTimer( timer ) ) { // // Release the reference to the FCB. // MsDereferenceFcb( workContext->Fcb ); // // Free the memory from the work context, the timer, // and the DPC. // ExFreePool( workContext ); } } oldIrp = MsRemoveDataQueueEntry( dataQueue, dataEntry ); if (oldIrp != NULL) { DebugTrace(0, Dbg, "Completing IRP %08lx\n", (ULONG)oldIrp ); MsCompleteRequest( oldIrp, STATUS_FILE_FORCED_CLOSED ); } } // // Now cleanup all the CCB's on this FCB, to ensure that new // write IRP will not be processed. // MsAcquireCcbListLock(); listEntry = Fcb->Specific.Fcb.CcbQueue.Flink; while( listEntry != &Fcb->Specific.Fcb.CcbQueue ) { ccb = (PCCB)CONTAINING_RECORD( listEntry, CCB, CcbLinks ); ccb->Header.NodeState = NodeStateClosing; // // Get the next CCB on this FCB. // listEntry = listEntry->Flink; } MsReleaseCcbListLock(); // // Cleanup the share access. // IoRemoveShareAccess( Fcb->FileObject, &Fcb->ShareAccess); // // Mark the FCB closing. // Fcb->Header.NodeState = NodeStateClosing; } finally { ASSERT (MsIsDataQueueEmpty(dataQueue)); MsReleaseFcb( Fcb ); DebugTrace(-1, Dbg, "MsCloseFcb -> %08lx\n", status); } // // Return to the caller. // return status; }