VOID DokanUnload(__in PDRIVER_OBJECT DriverObject) /*++ Routine Description: This routine gets called to remove the driver from the system. Arguments: DriverObject - the system supplied driver object. Return Value: NTSTATUS --*/ { PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject; WCHAR symbolicLinkBuf[] = DOKAN_GLOBAL_SYMBOLIC_LINK_NAME; UNICODE_STRING symbolicLinkName; PDOKAN_GLOBAL dokanGlobal; DDbgPrint("==> DokanUnload\n"); PAGED_CODE(); dokanGlobal = deviceObject->DeviceExtension; if (GetIdentifierType(dokanGlobal) == DGL) { DDbgPrint(" Delete Global DeviceObject\n"); KeSetEvent(&dokanGlobal->KillDeleteDeviceEvent, 0, FALSE); RtlInitUnicodeString(&symbolicLinkName, symbolicLinkBuf); IoDeleteSymbolicLink(&symbolicLinkName); IoUnregisterFileSystem(dokanGlobal->FsDiskDeviceObject); IoUnregisterFileSystem(dokanGlobal->FsCdDeviceObject); IoDeleteDevice(dokanGlobal->FsDiskDeviceObject); IoDeleteDevice(dokanGlobal->FsCdDeviceObject); IoDeleteDevice(deviceObject); } ExDeleteNPagedLookasideList(&DokanIrpEntryLookasideList); ExDeleteLookasideListEx(&g_DokanCCBLookasideList); ExDeleteLookasideListEx(&g_DokanFCBLookasideList); ExDeleteLookasideListEx(&g_DokanEResourceLookasideList); DDbgPrint("<== DokanUnload\n"); }
// // IOCTL_PREPARE_TO_UNLOAD // NTSTATUS LklPrepareToUnload(PDEVICE_OBJECT device,PIRP irp) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN acq_resource = FALSE; CHECK_OUT(device != lklfsd.device, STATUS_INVALID_DEVICE_REQUEST); ExAcquireResourceExclusiveLite(&lklfsd.global_resource, TRUE); acq_resource = TRUE; CHECK_OUT_MSG(FLAG_ON(lklfsd.flags, VFS_UNLOAD_PENDING), STATUS_ACCESS_DENIED, "Aldready ready to unload"); CHECK_OUT_MSG(!IsListEmpty(&lklfsd.vcb_list), STATUS_ACCESS_DENIED, "Mounted volumes exists"); DbgPrint("Unloading LklVfs"); IoUnregisterFileSystem(lklfsd.device); //unload_linux_kernel(); IoDeleteDevice(lklfsd.device); lklfsd.driver->DriverUnload = DriverUnload; SET_FLAG(lklfsd.flags, VFS_UNLOAD_PENDING); try_exit: if (acq_resource) RELEASE(&lklfsd.global_resource); return status; }
VOID CleanupGlobalDiskDevice(PDOKAN_GLOBAL dokanGlobal) { WCHAR symbolicLinkBuf[] = DOKAN_GLOBAL_SYMBOLIC_LINK_NAME; UNICODE_STRING symbolicLinkName; KeSetEvent(&dokanGlobal->KillDeleteDeviceEvent, 0, FALSE); RtlInitUnicodeString(&symbolicLinkName, symbolicLinkBuf); IoDeleteSymbolicLink(&symbolicLinkName); IoUnregisterFileSystem(dokanGlobal->FsDiskDeviceObject); IoUnregisterFileSystem(dokanGlobal->FsCdDeviceObject); IoDeleteDevice(dokanGlobal->FsDiskDeviceObject); IoDeleteDevice(dokanGlobal->FsCdDeviceObject); IoDeleteDevice(dokanGlobal->DeviceObject); ExDeleteResourceLite(&dokanGlobal->Resource); }
NTSTATUS NTAPI FsRecLoadFileSystem(IN PDEVICE_OBJECT DeviceObject, IN PWCHAR DriverServiceName) { UNICODE_STRING DriverName; PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; NTSTATUS Status = STATUS_IMAGE_ALREADY_LOADED; PAGED_CODE(); /* Make sure we haven't already been called */ if (DeviceExtension->State != Loaded) { /* Acquire the load lock */ KeWaitForSingleObject(FsRecLoadSync, Executive, KernelMode, FALSE, NULL); KeEnterCriticalRegion(); /* Make sure we're active */ if (DeviceExtension->State == Pending) { /* Load the FS driver */ RtlInitUnicodeString(&DriverName, DriverServiceName); Status = ZwLoadDriver(&DriverName); /* Loop all the linked recognizer objects */ while (DeviceExtension->State != Unloading) { /* Set them to the unload state */ DeviceExtension->State = Unloading; /* Go to the next one */ DeviceObject = DeviceExtension->Alternate; DeviceExtension = DeviceObject->DeviceExtension; } } /* Make sure that we haven't already loaded the FS */ if (DeviceExtension->State != Loaded) { /* Unregiser us, and set us as loaded */ IoUnregisterFileSystem(DeviceObject); DeviceExtension->State = Loaded; } /* Release the lock */ KeSetEvent(FsRecLoadSync, 0, FALSE); KeLeaveCriticalRegion(); } /* Return */ return Status; }
__drv_mustHoldCriticalRegion NTSTATUS FatCommonShutdown ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for shutdown called by both the fsd and fsp threads. Arguments: Irp - Supplies the Irp being processed Return Value: NTSTATUS - The return status for the operation --*/ { KEVENT Event; PLIST_ENTRY Links; PVCB Vcb; PIRP NewIrp; IO_STATUS_BLOCK Iosb; BOOLEAN VcbDeleted; PAGED_CODE(); // // Make sure we don't get any pop-ups, and write everything through. // SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS | IRP_CONTEXT_FLAG_WRITE_THROUGH); // // Initialize an event for doing calls down to // our target device objects. // KeInitializeEvent( &Event, NotificationEvent, FALSE ); // // Indicate that shutdown has started. This is used in FatFspClose. // FatData.ShutdownStarted = TRUE; // // Get everyone else out of the way // ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); #pragma prefast( push ) #pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" ) #pragma prefast( disable: 28193, "this will always wait" ) (VOID) FatAcquireExclusiveGlobal( IrpContext ); #pragma prefast( pop ) try { // // For every volume that is mounted we will flush the // volume and then shutdown the target device objects. // Links = FatData.VcbQueue.Flink; while (Links != &FatData.VcbQueue) { Vcb = CONTAINING_RECORD(Links, VCB, VcbLinks); Links = Links->Flink; // // If we have already been called before for this volume // (and yes this does happen), skip this volume as no writes // have been allowed since the first shutdown. // if ( FlagOn( Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN) || (Vcb->VcbCondition != VcbGood) ) { continue; } FatAcquireExclusiveVolume( IrpContext, Vcb ); try { (VOID)FatFlushVolume( IrpContext, Vcb, Flush ); // // The volume is now clean, note it. We purge the // volume file cache map before marking the volume // clean incase there is a stale Bpb in the cache. // if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) { CcPurgeCacheSection( &Vcb->SectionObjectPointers, NULL, 0, FALSE ); FatMarkVolume( IrpContext, Vcb, VolumeClean ); } } except( EXCEPTION_EXECUTE_HANDLER ) { FatResetExceptionState( IrpContext ); } // // Sometimes we take an excepion while flushing the volume, such // as when autoconv has converted the volume and is rebooting. // Even in that case we want to send the shutdown irp to the // target device so it can know to flush its cache, if it has one. // try { NewIrp = IoBuildSynchronousFsdRequest( IRP_MJ_SHUTDOWN, Vcb->TargetDeviceObject, NULL, 0, NULL, &Event, &Iosb ); if (NewIrp != NULL) { if (NT_SUCCESS(IoCallDriver( Vcb->TargetDeviceObject, NewIrp ))) { (VOID) KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); KeClearEvent( &Event ); } } } except( EXCEPTION_EXECUTE_HANDLER ) { FatResetExceptionState( IrpContext ); } SetFlag( Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN ); // // Attempt to punch the volume down. // VcbDeleted = FatCheckForDismount( IrpContext, Vcb, FALSE ); if (!VcbDeleted) { #pragma prefast( suppress:28107, "prefast is having trouble figuring out that Vcb is acquired" ) FatReleaseVolume( IrpContext, Vcb ); } } } finally { FatReleaseGlobal( IrpContext ); // // Unregister the file system. // IoUnregisterFileSystem( FatDiskFileSystemDeviceObject); IoUnregisterFileSystem( FatCdromFileSystemDeviceObject); IoDeleteDevice( FatDiskFileSystemDeviceObject); IoDeleteDevice( FatCdromFileSystemDeviceObject); FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); } // // And return to our caller // DebugTrace(-1, Dbg, "FatFsdShutdown -> STATUS_SUCCESS\n", 0); return STATUS_SUCCESS; }
NTSTATUS CdCommonShutdown ( _Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp ) /*++ Routine Description: This is the common routine for handling shutdown operation called by both the fsd and fsp threads Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ { KEVENT Event; PLIST_ENTRY Links; PVCB Vcb; PIRP NewIrp; IO_STATUS_BLOCK Iosb; BOOLEAN VcbPresent; NTSTATUS Status; PAGED_CODE(); // // Make sure we don't get any pop-ups. // SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS ); // // Initialize an event for doing calls down to // our target device objects. // KeInitializeEvent( &Event, NotificationEvent, FALSE ); // // Indicate that shutdown has started. // SetFlag( CdData.Flags, CD_FLAGS_SHUTDOWN ); // // Get everyone else out of the way // CdAcquireCdData( IrpContext ); // // Now walk through all the mounted Vcb's and shutdown the target // device objects. // Links = CdData.VcbQueue.Flink; while (Links != &CdData.VcbQueue) { Vcb = CONTAINING_RECORD( Links, VCB, VcbLinks ); // // Move to the next link now since the current Vcb may be deleted. // Links = Links->Flink; // // If we have already been called before for this volume // (and yes this does happen), skip this volume as no writes // have been allowed since the first shutdown. // if (FlagOn( Vcb->VcbState, VCB_STATE_SHUTDOWN ) || (Vcb->VcbCondition != VcbMounted)) { continue; } #pragma prefast(suppress: 28103) CdAcquireVcbExclusive( IrpContext, Vcb, FALSE ); CdPurgeVolume( IrpContext, Vcb, FALSE ); // // Build an irp for this volume stack - our own irp is probably too small and // each stack may have a different stack size. // NewIrp = IoBuildSynchronousFsdRequest( IRP_MJ_SHUTDOWN, Vcb->TargetDeviceObject, NULL, 0, NULL, &Event, &Iosb ); if (NewIrp != NULL) { Status = IoCallDriver( Vcb->TargetDeviceObject, NewIrp ); if (Status == STATUS_PENDING) { (VOID)KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); } KeClearEvent( &Event ); } SetFlag( Vcb->VcbState, VCB_STATE_SHUTDOWN ); // // Attempt to punch the volume down. // VcbPresent = CdCheckForDismount( IrpContext, Vcb, FALSE ); if (VcbPresent) { CdReleaseVcb( IrpContext, Vcb ); } } CdReleaseCdData( IrpContext ); IoUnregisterFileSystem( CdData.FileSystemDeviceObject ); IoDeleteDevice( CdData.FileSystemDeviceObject ); CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); return STATUS_SUCCESS; }
NTSTATUS Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; BOOLEAN GlobalDataResourceAcquired = FALSE; __try { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } ExAcquireResourceExclusiveLite( &Ext2Global->Resource, TRUE ); GlobalDataResourceAcquired = TRUE; if (FlagOn(Ext2Global->Flags, EXT2_UNLOAD_PENDING)) { DEBUG(DL_ERR, ( "Ext2PrepareUnload: Already ready to unload.\n")); Status = STATUS_ACCESS_DENIED; __leave; } { PEXT2_VCB Vcb; PLIST_ENTRY ListEntry; ListEntry = Ext2Global->VcbList.Flink; while (ListEntry != &(Ext2Global->VcbList)) { Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next); ListEntry = ListEntry->Flink; if (Vcb && (!Vcb->ReferenceCount) && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { Ext2RemoveVcb(Vcb); Ext2ClearVpbFlag(Vcb->Vpb, VPB_MOUNTED); Ext2DestroyVcb(Vcb); } } } if (!IsListEmpty(&(Ext2Global->VcbList))) { DEBUG(DL_ERR, ( "Ext2PrepareUnload: Mounted volumes exists.\n")); Status = STATUS_ACCESS_DENIED; __leave; } IoUnregisterFileSystem(Ext2Global->DiskdevObject); IoUnregisterFileSystem(Ext2Global->CdromdevObject); Ext2Global->DriverObject->DriverUnload = DriverUnload; SetLongFlag(Ext2Global->Flags ,EXT2_UNLOAD_PENDING); Status = STATUS_SUCCESS; DEBUG(DL_INF, ( "Ext2PrepareToUnload: Driver is ready to unload.\n")); } __finally { if (GlobalDataResourceAcquired) { ExReleaseResourceLite(&Ext2Global->Resource); } if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, Status); } } return Status; }