mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 01:15:43 +00:00
[NTOSKRNL]
- renamed Io volumes global to match Windows names (in case of debug) - renamed IopDereferenceVpb() to IopDereferenceVpbAndFree(), IopReferenceVpbForVerify() to IopReferenceVerifyVpb(), IopInitializeVpbForMount() to IopMountInitializeVpb(), IopLoadFileSystem() to IopLoadFileSystemDriver() - implemented IopDecrementDeviceObjectHandleCount(), IopInterlockedIncrementUlong(), IopInterlockedDecrementUlong(), IopNotifyAlreadyRegisteredFileSystems() and IoEnumerateRegisteredFiltersList() - halfplemented IopDecrementDeviceObjectRef() - implemented check for already registrered notification in IoRegisterFsRegistrationChange() - implemented sending notifications for already registered drivers to registrant in IoRegisterFsRegistrationChange() - implemented VPB freeing in IopDereferenceVpbAndFree() - acquire Io volumes lists once and forever for system shutdown, instead of keeping acquiring and releasing - reference device object in IopShutdownBaseFileSystems() before sending it the shutdown IRP. To ensure to keep it valid till the end - added a FS driver registration operations counter - use this counter to handle failed mounts - fixed: release locks before calling driver for mounting and reacquire them after - fixed check for boot partition failure (and associated bugcheck): check we are in boot phase 0 or 1 - simplified lock process by using only one lock (ie removed mutex). Also use only critical region where needed - fixed: ensure that locks are properly released when quitting a function - fixed wrong return in IopCreateVpb() - minor fixes around svn path=/trunk/; revision=52065
This commit is contained in:
parent
33a2b85a57
commit
69764dd21a
5 changed files with 401 additions and 119 deletions
|
@ -838,7 +838,7 @@ IopCreateVpb(
|
|||
|
||||
VOID
|
||||
NTAPI
|
||||
IopDereferenceVpb(
|
||||
IopDereferenceVpbAndFree(
|
||||
IN PVPB Vpb
|
||||
);
|
||||
|
||||
|
@ -869,8 +869,15 @@ IopDereferenceDeviceObject(
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject,
|
||||
OUT PDEVICE_OBJECT *DeviceObject
|
||||
IoGetRelatedTargetDevice(
|
||||
IN PFILE_OBJECT FileObject,
|
||||
OUT PDEVICE_OBJECT *DeviceObject
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IopUnloadDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
//
|
||||
|
|
|
@ -19,9 +19,10 @@
|
|||
ULONG IopDeviceObjectNumber = 0;
|
||||
LIST_ENTRY ShutdownListHead, LastChanceShutdownListHead;
|
||||
KSPIN_LOCK ShutdownListLock;
|
||||
extern LIST_ENTRY IopDiskFsListHead;
|
||||
extern LIST_ENTRY IopCdRomFsListHead;
|
||||
extern LIST_ENTRY IopTapeFsListHead;
|
||||
extern LIST_ENTRY IopDiskFileSystemQueueHead;
|
||||
extern LIST_ENTRY IopCdRomFileSystemQueueHead;
|
||||
extern LIST_ENTRY IopTapeFileSystemQueueHead;
|
||||
extern ERESOURCE IopDatabaseResource;
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
|
@ -187,14 +188,17 @@ IoShutdownSystem(IN ULONG Phase)
|
|||
}
|
||||
else if (Phase == 1)
|
||||
{
|
||||
/* Acquire resource forever */
|
||||
ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
|
||||
|
||||
/* Shutdown disk file systems */
|
||||
IopShutdownBaseFileSystems(&IopDiskFsListHead);
|
||||
IopShutdownBaseFileSystems(&IopDiskFileSystemQueueHead);
|
||||
|
||||
/* Shutdown cdrom file systems */
|
||||
IopShutdownBaseFileSystems(&IopCdRomFsListHead);
|
||||
IopShutdownBaseFileSystems(&IopCdRomFileSystemQueueHead);
|
||||
|
||||
/* Shutdown tape filesystems */
|
||||
IopShutdownBaseFileSystems(&IopTapeFsListHead);
|
||||
IopShutdownBaseFileSystems(&IopTapeFileSystemQueueHead);
|
||||
|
||||
/* Loop last-chance shutdown notifications */
|
||||
ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead,
|
||||
|
|
|
@ -479,7 +479,7 @@ IopParseDevice(IN PVOID ParseObject,
|
|||
{
|
||||
/* Dereference the device and VPB, then fail */
|
||||
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
|
||||
if (Vpb) IopDereferenceVpb(Vpb);
|
||||
if (Vpb) IopDereferenceVpbAndFree(Vpb);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
|
@ -577,7 +577,7 @@ IopParseDevice(IN PVOID ParseObject,
|
|||
|
||||
/* Dereference the device and VPB */
|
||||
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
|
||||
if (Vpb) IopDereferenceVpb(Vpb);
|
||||
if (Vpb) IopDereferenceVpbAndFree(Vpb);
|
||||
|
||||
/* We failed, return status */
|
||||
OpenPacket->FinalStatus = Status;
|
||||
|
@ -687,7 +687,7 @@ IopParseDevice(IN PVOID ParseObject,
|
|||
|
||||
/* Dereference the device object and VPB */
|
||||
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
|
||||
if (Vpb) IopDereferenceVpb(Vpb);
|
||||
if (Vpb) IopDereferenceVpbAndFree(Vpb);
|
||||
|
||||
/* Clear the FO and dereference it */
|
||||
FileObject->DeviceObject = NULL;
|
||||
|
@ -783,7 +783,7 @@ IopParseDevice(IN PVOID ParseObject,
|
|||
IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
|
||||
|
||||
/* Unless the driver cancelled the open, dereference the VPB */
|
||||
if (!(OpenCancelled) && (Vpb)) IopDereferenceVpb(Vpb);
|
||||
if (!(OpenCancelled) && (Vpb)) IopDereferenceVpbAndFree(Vpb);
|
||||
|
||||
/* Set the status and return */
|
||||
OpenPacket->FinalStatus = Status;
|
||||
|
@ -806,7 +806,7 @@ IopParseDevice(IN PVOID ParseObject,
|
|||
if (OwnerDevice != DeviceObject)
|
||||
{
|
||||
/* We have to de-reference the VPB we had associated */
|
||||
if (Vpb) IopDereferenceVpb(Vpb);
|
||||
if (Vpb) IopDereferenceVpbAndFree(Vpb);
|
||||
|
||||
/* And re-associate with the actual one */
|
||||
Vpb = FileObject->Vpb;
|
||||
|
|
|
@ -52,19 +52,17 @@ extern LIST_ENTRY ShutdownListHead;
|
|||
extern LIST_ENTRY LastChanceShutdownListHead;
|
||||
extern KSPIN_LOCK ShutdownListLock;
|
||||
extern POBJECT_TYPE IoAdapterObjectType;
|
||||
ERESOURCE IopDatabaseResource;
|
||||
extern ERESOURCE FileSystemListLock;
|
||||
extern ERESOURCE IopDatabaseResource;
|
||||
ERESOURCE IopSecurityResource;
|
||||
extern KGUARDED_MUTEX FsChangeNotifyListLock;
|
||||
extern KGUARDED_MUTEX PnpNotifyListLock;
|
||||
extern LIST_ENTRY IopDiskFsListHead;
|
||||
extern LIST_ENTRY IopCdRomFsListHead;
|
||||
extern LIST_ENTRY IopTapeFsListHead;
|
||||
extern LIST_ENTRY IopNetworkFsListHead;
|
||||
extern LIST_ENTRY IopDiskFileSystemQueueHead;
|
||||
extern LIST_ENTRY IopCdRomFileSystemQueueHead;
|
||||
extern LIST_ENTRY IopTapeFileSystemQueueHead;
|
||||
extern LIST_ENTRY IopNetworkFileSystemQueueHead;
|
||||
extern LIST_ENTRY DriverBootReinitListHead;
|
||||
extern LIST_ENTRY DriverReinitListHead;
|
||||
extern LIST_ENTRY PnpNotifyListHead;
|
||||
extern LIST_ENTRY FsChangeNotifyListHead;
|
||||
extern LIST_ENTRY IopFsNotifyChangeQueueHead;
|
||||
extern LIST_ENTRY IopErrorLogListHead;
|
||||
extern LIST_ENTRY IopTimerQueueHead;
|
||||
extern KDPC IopTimerDpc;
|
||||
|
@ -450,20 +448,18 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
|
||||
/* Initialize all locks and lists */
|
||||
ExInitializeResource(&IopDatabaseResource);
|
||||
ExInitializeResource(&FileSystemListLock);
|
||||
ExInitializeResource(&IopSecurityResource);
|
||||
KeInitializeGuardedMutex(&FsChangeNotifyListLock);
|
||||
KeInitializeGuardedMutex(&PnpNotifyListLock);
|
||||
InitializeListHead(&IopDiskFsListHead);
|
||||
InitializeListHead(&IopCdRomFsListHead);
|
||||
InitializeListHead(&IopTapeFsListHead);
|
||||
InitializeListHead(&IopNetworkFsListHead);
|
||||
InitializeListHead(&IopDiskFileSystemQueueHead);
|
||||
InitializeListHead(&IopCdRomFileSystemQueueHead);
|
||||
InitializeListHead(&IopTapeFileSystemQueueHead);
|
||||
InitializeListHead(&IopNetworkFileSystemQueueHead);
|
||||
InitializeListHead(&DriverBootReinitListHead);
|
||||
InitializeListHead(&DriverReinitListHead);
|
||||
InitializeListHead(&PnpNotifyListHead);
|
||||
InitializeListHead(&ShutdownListHead);
|
||||
InitializeListHead(&LastChanceShutdownListHead);
|
||||
InitializeListHead(&FsChangeNotifyListHead);
|
||||
InitializeListHead(&IopFsNotifyChangeQueueHead);
|
||||
InitializeListHead(&IopErrorLogListHead);
|
||||
KeInitializeSpinLock(&IoStatisticsLock);
|
||||
KeInitializeSpinLock(&DriverReinitListLock);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
* Hervé Poussineau (hpoussin@reactos.org)
|
||||
* Eric Kohl
|
||||
* Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -21,14 +22,60 @@
|
|||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
ERESOURCE FileSystemListLock;
|
||||
LIST_ENTRY IopDiskFsListHead, IopNetworkFsListHead;
|
||||
LIST_ENTRY IopCdRomFsListHead, IopTapeFsListHead;
|
||||
KGUARDED_MUTEX FsChangeNotifyListLock;
|
||||
LIST_ENTRY FsChangeNotifyListHead;
|
||||
ERESOURCE IopDatabaseResource;
|
||||
LIST_ENTRY IopDiskFileSystemQueueHead, IopNetworkFileSystemQueueHead;
|
||||
LIST_ENTRY IopCdRomFileSystemQueueHead, IopTapeFileSystemQueueHead;
|
||||
LIST_ENTRY IopFsNotifyChangeQueueHead;
|
||||
ULONG IopFsRegistrationOps;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
/*
|
||||
* @halfplemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
IopDecrementDeviceObjectRef(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN BOOLEAN UnloadIfUnused)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Acquire lock */
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock);
|
||||
ASSERT(DeviceObject->ReferenceCount > 0);
|
||||
|
||||
if (--DeviceObject->ReferenceCount > 0)
|
||||
{
|
||||
KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Here, DO is not referenced any longer, check if we have to unload it */
|
||||
if (UnloadIfUnused || IoGetDevObjExtension(DeviceObject)->ExtensionFlags &
|
||||
(DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | DOE_REMOVE_PENDING))
|
||||
{
|
||||
/* Unload the driver */
|
||||
IopUnloadDevice(DeviceObject);
|
||||
}
|
||||
|
||||
/* Release lock */
|
||||
KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
IopDecrementDeviceObjectHandleCount(IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
/* Just decrease reference count */
|
||||
IopDecrementDeviceObjectRef(DeviceObject, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PVPB
|
||||
NTAPI
|
||||
IopCheckVpbMounted(IN POPEN_PACKET OpenPacket,
|
||||
|
@ -100,6 +147,9 @@ IopCheckVpbMounted(IN POPEN_PACKET OpenPacket,
|
|||
return Vpb;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopCreateVpb(IN PDEVICE_OBJECT DeviceObject)
|
||||
|
@ -110,7 +160,7 @@ IopCreateVpb(IN PDEVICE_OBJECT DeviceObject)
|
|||
Vpb = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(VPB),
|
||||
TAG_VPB);
|
||||
if (!Vpb) return STATUS_UNSUCCESSFUL;
|
||||
if (!Vpb) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* Clear it so we don't waste time manually */
|
||||
RtlZeroMemory(Vpb, sizeof(VPB));
|
||||
|
@ -125,9 +175,12 @@ IopCreateVpb(IN PDEVICE_OBJECT DeviceObject)
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
IopDereferenceVpb(IN PVPB Vpb)
|
||||
IopDereferenceVpbAndFree(IN PVPB Vpb)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
|
@ -136,21 +189,30 @@ IopDereferenceVpb(IN PVPB Vpb)
|
|||
Vpb->ReferenceCount--;
|
||||
|
||||
/* Check if we're out of references */
|
||||
if (!Vpb->ReferenceCount)
|
||||
if (!Vpb->ReferenceCount && Vpb->RealDevice->Vpb == Vpb &&
|
||||
!(Vpb->Flags & VPB_PERSISTENT))
|
||||
{
|
||||
/* FIXME: IMPLEMENT CLEANUP! */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
/* Release VPB lock */
|
||||
IoReleaseVpbSpinLock(OldIrql);
|
||||
|
||||
/* Release VPB lock */
|
||||
IoReleaseVpbSpinLock(OldIrql);
|
||||
/* And free VPB */
|
||||
ExFreePoolWithTag(Vpb, TAG_VPB);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Release VPB lock */
|
||||
IoReleaseVpbSpinLock(OldIrql);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
IopReferenceVpbForVerify(IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PDEVICE_OBJECT *FileSystemObject,
|
||||
OUT PVPB *Vpb)
|
||||
IopReferenceVerifyVpb(IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PDEVICE_OBJECT *FileSystemObject,
|
||||
OUT PVPB *Vpb)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PVPB LocalVpb;
|
||||
|
@ -181,9 +243,9 @@ IopReferenceVpbForVerify(IN PDEVICE_OBJECT DeviceObject,
|
|||
|
||||
PVPB
|
||||
NTAPI
|
||||
IopInitializeVpbForMount(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PDEVICE_OBJECT AttachedDeviceObject,
|
||||
IN BOOLEAN Raw)
|
||||
IopMountInitializeVpb(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PDEVICE_OBJECT AttachedDeviceObject,
|
||||
IN BOOLEAN Raw)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PVPB Vpb;
|
||||
|
@ -212,20 +274,20 @@ IopInitializeVpbForMount(IN PDEVICE_OBJECT DeviceObject,
|
|||
return Vpb;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
FORCEINLINE
|
||||
IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN BOOLEAN DriverActive)
|
||||
{
|
||||
PFS_CHANGE_NOTIFY_ENTRY ChangeEntry;
|
||||
PLIST_ENTRY ListEntry;
|
||||
|
||||
/* Acquire the notification lock */
|
||||
KeAcquireGuardedMutex(&FsChangeNotifyListLock);
|
||||
|
||||
/* Loop the list */
|
||||
ListEntry = FsChangeNotifyListHead.Flink;
|
||||
while (ListEntry != &FsChangeNotifyListHead)
|
||||
ListEntry = IopFsNotifyChangeQueueHead.Flink;
|
||||
while (ListEntry != &IopFsNotifyChangeQueueHead)
|
||||
{
|
||||
/* Get the entry */
|
||||
ChangeEntry = CONTAINING_RECORD(ListEntry,
|
||||
|
@ -238,11 +300,47 @@ IopNotifyFileSystemChange(IN PDEVICE_OBJECT DeviceObject,
|
|||
/* Go to the next entry */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
KeReleaseGuardedMutex(&FsChangeNotifyListLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
ULONG
|
||||
FASTCALL
|
||||
IopInterlockedIncrementUlong(IN KSPIN_LOCK_QUEUE_NUMBER Queue,
|
||||
IN PULONG Ulong)
|
||||
{
|
||||
KIRQL Irql;
|
||||
ULONG OldValue;
|
||||
|
||||
Irql = KeAcquireQueuedSpinLock(Queue);
|
||||
OldValue = (*Ulong)++;
|
||||
KeReleaseQueuedSpinLock(Queue, Irql);
|
||||
|
||||
return OldValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
ULONG
|
||||
FASTCALL
|
||||
IopInterlockedDecrementUlong(IN KSPIN_LOCK_QUEUE_NUMBER Queue,
|
||||
IN PULONG Ulong)
|
||||
{
|
||||
KIRQL Irql;
|
||||
ULONG OldValue;
|
||||
|
||||
Irql = KeAcquireQueuedSpinLock(Queue);
|
||||
OldValue = (*Ulong)--;
|
||||
KeReleaseQueuedSpinLock(Queue, Irql);
|
||||
|
||||
return OldValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead)
|
||||
|
@ -254,9 +352,6 @@ IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead)
|
|||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Lock the FS List and initialize an event to wait on */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceSharedLite(&FileSystemListLock,TRUE);
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* Get the first entry and start looping */
|
||||
|
@ -268,6 +363,9 @@ IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead)
|
|||
DEVICE_OBJECT,
|
||||
Queue.ListEntry);
|
||||
|
||||
ObReferenceObject(DeviceObject);
|
||||
IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
|
||||
|
||||
/* Check if we're attached */
|
||||
if (DeviceObject->AttachedDevice)
|
||||
{
|
||||
|
@ -293,18 +391,20 @@ IopShutdownBaseFileSystems(IN PLIST_ENTRY ListHead)
|
|||
/* Reset the event */
|
||||
KeClearEvent(&Event);
|
||||
|
||||
IopDecrementDeviceObjectRef(DeviceObject, FALSE);
|
||||
ObDereferenceObject(DeviceObject);
|
||||
|
||||
/* Go to the next entry */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
ExReleaseResourceLite(&FileSystemListLock);
|
||||
KeLeaveCriticalRegion();
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
IopLoadFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
||||
IopLoadFileSystemDriver(IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PIO_STACK_LOCATION StackPtr;
|
||||
|
@ -347,8 +447,14 @@ IopLoadFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
|||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dereference DO - FsRec? */
|
||||
IopDecrementDeviceObjectRef(AttachedDeviceObject, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -366,7 +472,7 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
LIST_ENTRY LocalList;
|
||||
PDEVICE_OBJECT AttachedDeviceObject = DeviceObject;
|
||||
PDEVICE_OBJECT FileSystemDeviceObject, ParentFsDeviceObject;
|
||||
ULONG FsStackOverhead;
|
||||
ULONG FsStackOverhead, RegistrationOps;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Check if the device isn't already locked */
|
||||
|
@ -387,7 +493,7 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
|
||||
/* Acquire the FS Lock*/
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceSharedLite(&FileSystemListLock, TRUE);
|
||||
ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);
|
||||
|
||||
/* Make sure we weren't already mounted */
|
||||
if (!(DeviceObject->Vpb->Flags & (VPB_MOUNTED | VPB_REMOVE_PENDING)))
|
||||
|
@ -411,17 +517,17 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
(DeviceObject->DeviceType == FILE_DEVICE_VIRTUAL_DISK))
|
||||
{
|
||||
/* Use the disk list */
|
||||
FsList = &IopDiskFsListHead;
|
||||
FsList = &IopDiskFileSystemQueueHead;
|
||||
}
|
||||
else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM)
|
||||
{
|
||||
/* Use the CD-ROM list */
|
||||
FsList = &IopCdRomFsListHead;
|
||||
FsList = &IopCdRomFileSystemQueueHead;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's gotta be a tape... */
|
||||
FsList = &IopTapeFsListHead;
|
||||
FsList = &IopTapeFileSystemQueueHead;
|
||||
}
|
||||
|
||||
/* Now loop the fs list until one of the file systems accepts us */
|
||||
|
@ -502,6 +608,13 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
StackPtr->Parameters.MountVolume.DeviceObject =
|
||||
AttachedDeviceObject;
|
||||
|
||||
/* Save registration operations */
|
||||
RegistrationOps = IopFsRegistrationOps;
|
||||
|
||||
/* Release locks */
|
||||
IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
|
||||
/* Call the driver */
|
||||
Status = IoCallDriver(FileSystemDeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
|
@ -515,14 +628,17 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);
|
||||
IopInterlockedDecrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
|
||||
|
||||
/* Check if mounting was successful */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Mount the VPB */
|
||||
*Vpb = IopInitializeVpbForMount(DeviceObject,
|
||||
AttachedDeviceObject,
|
||||
(DeviceObject->Vpb->Flags &
|
||||
VPB_RAW_MOUNT));
|
||||
*Vpb = IopMountInitializeVpb(DeviceObject,
|
||||
AttachedDeviceObject,
|
||||
(DeviceObject->Vpb->Flags &
|
||||
VPB_RAW_MOUNT));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -534,11 +650,22 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
break;
|
||||
}
|
||||
|
||||
/* If there were registration operations in the meanwhile */
|
||||
if (RegistrationOps != IopFsRegistrationOps)
|
||||
{
|
||||
/* We need to setup a local list to pickup where we left */
|
||||
LocalList.Flink = FsList->Flink;
|
||||
ListEntry = &LocalList;
|
||||
|
||||
Status = STATUS_UNRECOGNIZED_VOLUME;
|
||||
}
|
||||
|
||||
/* Otherwise, check if we need to load the FS driver */
|
||||
if (Status == STATUS_FS_DRIVER_REQUIRED)
|
||||
{
|
||||
/* We need to release the lock */
|
||||
ExReleaseResourceLite(&FileSystemListLock);
|
||||
IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
|
||||
/* Release the device lock if we're holding it */
|
||||
if (!DeviceIsLocked)
|
||||
|
@ -546,8 +673,11 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
KeSetEvent(&DeviceObject->DeviceLock, 0, FALSE);
|
||||
}
|
||||
|
||||
/* Leave critical section */
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Load the FS */
|
||||
IopLoadFileSystem(ParentFsDeviceObject);
|
||||
IopLoadFileSystemDriver(ParentFsDeviceObject);
|
||||
|
||||
/* Check if the device isn't already locked */
|
||||
if (!DeviceIsLocked)
|
||||
|
@ -569,7 +699,8 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
}
|
||||
|
||||
/* Reacquire the lock */
|
||||
ExAcquireResourceSharedLite(&FileSystemListLock, TRUE);
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceSharedLite(&IopDatabaseResource, TRUE);
|
||||
|
||||
/* When we released the lock, make sure nobody beat us */
|
||||
if (DeviceObject->Vpb->Flags & VPB_MOUNTED)
|
||||
|
@ -620,7 +751,7 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
}
|
||||
|
||||
/* Release the FS lock */
|
||||
ExReleaseResourceLite(&FileSystemListLock);
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Release the device lock if we're holding it */
|
||||
|
@ -628,7 +759,8 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
|
||||
/* Check if we failed to mount the boot partition */
|
||||
if ((!NT_SUCCESS(Status)) &&
|
||||
(DeviceObject->Flags & DO_SYSTEM_BOOT_PARTITION))
|
||||
(DeviceObject->Flags & DO_SYSTEM_BOOT_PARTITION) &&
|
||||
ExpInitializationPhase < 2)
|
||||
{
|
||||
/* Bugcheck the system */
|
||||
KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE,
|
||||
|
@ -642,19 +774,102 @@ IopMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
IopNotifyAlreadyRegisteredFileSystems(IN PLIST_ENTRY ListHead,
|
||||
IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine,
|
||||
BOOLEAN SkipLast)
|
||||
{
|
||||
PLIST_ENTRY ListEntry;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
||||
/* Browse the whole list */
|
||||
ListEntry = ListHead->Flink;
|
||||
while (ListEntry != ListHead)
|
||||
{
|
||||
/* Check if we reached end and if we have to skip it */
|
||||
if (ListEntry->Flink == ListHead && SkipLast)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, get DO and notify */
|
||||
DeviceObject = CONTAINING_RECORD(ListEntry,
|
||||
DEVICE_OBJECT,
|
||||
Queue.ListEntry);
|
||||
|
||||
DriverNotificationRoutine(DeviceObject, TRUE);
|
||||
|
||||
/* Go to the next entry */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IoEnumerateRegisteredFiltersList(IN PDRIVER_OBJECT *DriverObjectList,
|
||||
IoEnumerateRegisteredFiltersList(OUT PDRIVER_OBJECT *DriverObjectList,
|
||||
IN ULONG DriverObjectListSize,
|
||||
OUT PULONG ActualNumberDriverObjects)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
USHORT Index = 0;
|
||||
ULONG ListSize = 0;
|
||||
PLIST_ENTRY ListEntry;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PFS_CHANGE_NOTIFY_ENTRY ChangeEntry;
|
||||
|
||||
/* Acquire the FS lock */
|
||||
ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
|
||||
|
||||
/* First of all, count number of driver objects */
|
||||
ListEntry = IopFsNotifyChangeQueueHead.Flink;
|
||||
while (ListEntry != &IopFsNotifyChangeQueueHead)
|
||||
{
|
||||
ListSize++;
|
||||
|
||||
/* Go to the next entry */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Return this size */
|
||||
*ActualNumberDriverObjects = ListSize;
|
||||
|
||||
/* Then, check if given buffer is big enough to contain list */
|
||||
if (ListSize > DriverObjectListSize / sizeof(PDRIVER_OBJECT))
|
||||
{
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Rebrowse the whole list */
|
||||
ListEntry = IopFsNotifyChangeQueueHead.Flink;
|
||||
while (ListEntry != &IopFsNotifyChangeQueueHead)
|
||||
{
|
||||
ChangeEntry = CONTAINING_RECORD(ListEntry,
|
||||
FS_CHANGE_NOTIFY_ENTRY,
|
||||
FsChangeNotifyList);
|
||||
|
||||
/* Reference the driver object */
|
||||
ObReferenceObject(ChangeEntry->DriverObject);
|
||||
/* And pass it to the caller */
|
||||
DriverObjectList[Index++] = ChangeEntry->DriverObject;
|
||||
|
||||
/* Go to the next entry */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the FS lock */
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -669,20 +884,21 @@ IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
PIO_STACK_LOCATION StackPtr;
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
NTSTATUS Status = STATUS_SUCCESS, VpbStatus;
|
||||
NTSTATUS Status, VpbStatus;
|
||||
PDEVICE_OBJECT FileSystemDeviceObject;
|
||||
PVPB Vpb, NewVpb;
|
||||
BOOLEAN WasNotMounted = TRUE;
|
||||
|
||||
/* Wait on the device lock */
|
||||
KeWaitForSingleObject(&DeviceObject->DeviceLock,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
Status = KeWaitForSingleObject(&DeviceObject->DeviceLock,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
|
||||
/* Reference the VPB */
|
||||
if (IopReferenceVpbForVerify(DeviceObject, &FileSystemDeviceObject, &Vpb))
|
||||
if (IopReferenceVerifyVpb(DeviceObject, &FileSystemDeviceObject, &Vpb))
|
||||
{
|
||||
/* Initialize the event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
@ -698,7 +914,11 @@ IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
|
||||
/* Allocate the IRP */
|
||||
Irp = IoAllocateIrp(FileSystemDeviceObject->StackSize, FALSE);
|
||||
if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
if (!Irp)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Release;
|
||||
}
|
||||
|
||||
/* Set it up */
|
||||
Irp->UserIosb = &IoStatusBlock;
|
||||
|
@ -726,28 +946,37 @@ IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
|
|||
}
|
||||
|
||||
/* Dereference the VPB */
|
||||
IopDereferenceVpb(Vpb);
|
||||
IopDereferenceVpbAndFree(Vpb);
|
||||
}
|
||||
|
||||
/* Check if we had the wrong volume or didn't mount at all */
|
||||
if ((Status == STATUS_WRONG_VOLUME) || (WasNotMounted))
|
||||
if (Status == STATUS_WRONG_VOLUME)
|
||||
{
|
||||
/* Create a VPB */
|
||||
VpbStatus = IopCreateVpb(DeviceObject);
|
||||
if (NT_SUCCESS(VpbStatus))
|
||||
{
|
||||
PoVolumeDevice(DeviceObject);
|
||||
|
||||
/* Mount it */
|
||||
VpbStatus = IopMountVolume(DeviceObject,
|
||||
AllowRawMount,
|
||||
TRUE,
|
||||
FALSE,
|
||||
&NewVpb);
|
||||
|
||||
/* If we got a new VPB, dereference it */
|
||||
if (NewVpb)
|
||||
{
|
||||
IopInterlockedDecrementUlong(LockQueueIoVpbLock, &NewVpb->ReferenceCount);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we failed, remove the verify flag */
|
||||
if (!NT_SUCCESS(VpbStatus)) DeviceObject->Flags &= ~DO_VERIFY_VOLUME;
|
||||
}
|
||||
|
||||
Release:
|
||||
/* Signal the device lock and return */
|
||||
KeSetEvent(&DeviceObject->DeviceLock, IO_NO_INCREMENT, FALSE);
|
||||
return Status;
|
||||
|
@ -764,29 +993,28 @@ IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
|||
PAGED_CODE();
|
||||
|
||||
/* Acquire the FS lock */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE);
|
||||
ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
|
||||
|
||||
/* Check what kind of FS this is */
|
||||
if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM)
|
||||
{
|
||||
/* Use the disk list */
|
||||
FsList = &IopDiskFsListHead;
|
||||
FsList = &IopDiskFileSystemQueueHead;
|
||||
}
|
||||
else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM)
|
||||
{
|
||||
/* Use the network device list */
|
||||
FsList = &IopNetworkFsListHead;
|
||||
FsList = &IopNetworkFileSystemQueueHead;
|
||||
}
|
||||
else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
|
||||
{
|
||||
/* Use the CD-ROM list */
|
||||
FsList = &IopCdRomFsListHead;
|
||||
FsList = &IopCdRomFileSystemQueueHead;
|
||||
}
|
||||
else if (DeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM)
|
||||
{
|
||||
/* Use the tape list */
|
||||
FsList = &IopTapeFsListHead;
|
||||
FsList = &IopTapeFileSystemQueueHead;
|
||||
}
|
||||
|
||||
/* Make sure that we have a valid list */
|
||||
|
@ -805,15 +1033,20 @@ IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
|||
}
|
||||
}
|
||||
|
||||
/* Update operations counter */
|
||||
IopFsRegistrationOps++;
|
||||
|
||||
/* Clear the initializing flag */
|
||||
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
/* Release the FS Lock */
|
||||
ExReleaseResourceLite(&FileSystemListLock);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Notify file systems of the addition */
|
||||
IopNotifyFileSystemChange(DeviceObject, TRUE);
|
||||
|
||||
/* Release the FS Lock */
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
|
||||
/* Ensure driver won't be unloaded */
|
||||
IopInterlockedIncrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -826,18 +1059,25 @@ IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
|||
PAGED_CODE();
|
||||
|
||||
/* Acquire the FS lock */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&FileSystemListLock, TRUE);
|
||||
ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
|
||||
|
||||
/* Simply remove the entry */
|
||||
RemoveEntryList(&DeviceObject->Queue.ListEntry);
|
||||
/* Simply remove the entry - if queued */
|
||||
if (DeviceObject->Queue.ListEntry.Flink)
|
||||
{
|
||||
RemoveEntryList(&DeviceObject->Queue.ListEntry);
|
||||
}
|
||||
|
||||
/* And notify all registered file systems */
|
||||
IopNotifyFileSystemChange(DeviceObject, FALSE);
|
||||
|
||||
/* Update operations counter */
|
||||
IopFsRegistrationOps++;
|
||||
|
||||
/* Then release the lock */
|
||||
ExReleaseResourceLite(&FileSystemListLock);
|
||||
KeLeaveCriticalRegion();
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
|
||||
/* Decrease reference count to allow unload */
|
||||
IopInterlockedDecrementUlong(LockQueueIoDatabaseLock, (PULONG)&DeviceObject->ReferenceCount);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -846,25 +1086,60 @@ IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject)
|
|||
NTSTATUS
|
||||
NTAPI
|
||||
IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDRIVER_FS_NOTIFICATION FSDNotificationProc)
|
||||
IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine)
|
||||
{
|
||||
PFS_CHANGE_NOTIFY_ENTRY Entry;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Acquire the list lock */
|
||||
ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
|
||||
|
||||
/* Check if that driver is already registered (successive calls)
|
||||
* See MSDN note: http://msdn.microsoft.com/en-us/library/ff548499%28v=vs.85%29.aspx
|
||||
*/
|
||||
if (!IsListEmpty(&IopFsNotifyChangeQueueHead))
|
||||
{
|
||||
Entry = CONTAINING_RECORD(IopFsNotifyChangeQueueHead.Blink,
|
||||
FS_CHANGE_NOTIFY_ENTRY,
|
||||
FsChangeNotifyList);
|
||||
|
||||
if (Entry->DriverObject == DriverObject &&
|
||||
Entry->FSDNotificationProc == DriverNotificationRoutine)
|
||||
{
|
||||
/* Release the lock */
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
|
||||
return STATUS_DEVICE_ALREADY_ATTACHED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a notification entry */
|
||||
Entry = ExAllocatePoolWithTag(PagedPool,
|
||||
sizeof(FS_CHANGE_NOTIFY_ENTRY),
|
||||
TAG_FS_CHANGE_NOTIFY);
|
||||
if (!Entry) return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
if (!Entry)
|
||||
{
|
||||
/* Release the lock */
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Save the driver object and notification routine */
|
||||
Entry->DriverObject = DriverObject;
|
||||
Entry->FSDNotificationProc = FSDNotificationProc;
|
||||
Entry->FSDNotificationProc = DriverNotificationRoutine;
|
||||
|
||||
/* Insert it into the notification list */
|
||||
KeAcquireGuardedMutex(&FsChangeNotifyListLock);
|
||||
InsertTailList(&FsChangeNotifyListHead, &Entry->FsChangeNotifyList);
|
||||
KeReleaseGuardedMutex(&FsChangeNotifyListLock);
|
||||
InsertTailList(&IopFsNotifyChangeQueueHead, &Entry->FsChangeNotifyList);
|
||||
|
||||
/* Start notifying all already present FS */
|
||||
IopNotifyAlreadyRegisteredFileSystems(&IopNetworkFileSystemQueueHead, DriverNotificationRoutine, FALSE);
|
||||
IopNotifyAlreadyRegisteredFileSystems(&IopCdRomFileSystemQueueHead, DriverNotificationRoutine, TRUE);
|
||||
IopNotifyAlreadyRegisteredFileSystems(&IopDiskFileSystemQueueHead, DriverNotificationRoutine, TRUE);
|
||||
IopNotifyAlreadyRegisteredFileSystems(&IopTapeFileSystemQueueHead, DriverNotificationRoutine, TRUE);
|
||||
|
||||
/* Release the lock */
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
|
||||
/* Reference the driver */
|
||||
ObReferenceObject(DriverObject);
|
||||
|
@ -884,11 +1159,11 @@ IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject,
|
|||
PAGED_CODE();
|
||||
|
||||
/* Acquire the list lock */
|
||||
KeAcquireGuardedMutex(&FsChangeNotifyListLock);
|
||||
ExAcquireResourceExclusiveLite(&IopDatabaseResource, TRUE);
|
||||
|
||||
/* Loop the list */
|
||||
NextEntry = FsChangeNotifyListHead.Flink;
|
||||
while (NextEntry != &FsChangeNotifyListHead)
|
||||
NextEntry = IopFsNotifyChangeQueueHead.Flink;
|
||||
while (NextEntry != &IopFsNotifyChangeQueueHead)
|
||||
{
|
||||
/* Get the entry */
|
||||
ChangeEntry = CONTAINING_RECORD(NextEntry,
|
||||
|
@ -910,7 +1185,7 @@ IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject,
|
|||
}
|
||||
|
||||
/* Release the lock and dereference the driver */
|
||||
KeReleaseGuardedMutex(&FsChangeNotifyListLock);
|
||||
ExReleaseResourceLite(&IopDatabaseResource);
|
||||
ObDereferenceObject(DriverObject);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue