mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-24 17:32:29 -05:00
544 lines
20 KiB
C
544 lines
20 KiB
C
/**
|
|
* @file sys/driver.c
|
|
*
|
|
* @copyright 2015-2022 Bill Zissimopoulos
|
|
*/
|
|
/*
|
|
* This file is part of WinFsp.
|
|
*
|
|
* You can redistribute it and/or modify it under the terms of the GNU
|
|
* General Public License version 3 as published by the Free Software
|
|
* Foundation.
|
|
*
|
|
* Licensees holding a valid commercial license may use this software
|
|
* in accordance with the commercial license agreement provided in
|
|
* conjunction with the software. The terms and conditions of any such
|
|
* commercial license agreement shall govern, supersede, and render
|
|
* ineffective any application of the GPLv3 license to this software,
|
|
* notwithstanding of any reference thereto in the software or
|
|
* associated repository.
|
|
*/
|
|
|
|
#include <sys/driver.h>
|
|
|
|
DRIVER_INITIALIZE DriverEntry;
|
|
static DRIVER_UNLOAD DriverUnload;
|
|
static VOID FspDriverMultiVersionInitialize(VOID);
|
|
static NTSTATUS FspDriverInitializeDevices(VOID);
|
|
static VOID FspDriverFinalizeDevices(VOID);
|
|
static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices);
|
|
NTSTATUS FspDriverUnload(
|
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT, DriverEntry)
|
|
#pragma alloc_text(PAGE, DriverUnload)
|
|
#pragma alloc_text(INIT, FspDriverMultiVersionInitialize)
|
|
#pragma alloc_text(PAGE, FspDriverInitializeDevices)
|
|
#pragma alloc_text(PAGE, FspDriverFinalizeDevices)
|
|
#pragma alloc_text(PAGE, FspDriverFinalizeDevicesEx)
|
|
#pragma alloc_text(PAGE, FspDriverUnload)
|
|
#endif
|
|
|
|
NTSTATUS DriverEntry(
|
|
PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|
{
|
|
FSP_ENTER_DRV();
|
|
|
|
FSP_TRACE_INIT();
|
|
|
|
FspSxsIdentInitialize(&DriverObject->DriverName);
|
|
|
|
/* setup the driver object */
|
|
DriverObject->DriverUnload = DriverUnload;
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose;
|
|
DriverObject->MajorFunction[IRP_MJ_READ] = FspRead;
|
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = FspWrite;
|
|
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = FspQueryInformation;
|
|
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = FspSetInformation;
|
|
DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = FspQueryEa;
|
|
DriverObject->MajorFunction[IRP_MJ_SET_EA] = FspSetEa;
|
|
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = FspFlushBuffers;
|
|
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FspQueryVolumeInformation;
|
|
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FspSetVolumeInformation;
|
|
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FspDirectoryControl;
|
|
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFileSystemControl;
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FspDeviceControl;
|
|
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FspShutdown;
|
|
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FspLockControl;
|
|
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FspCleanup;
|
|
DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = FspQuerySecurity;
|
|
DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = FspSetSecurity;
|
|
|
|
/* setup the I/O prepare/complete functions */
|
|
FspIopPrepareFunction[IRP_MJ_CREATE] = FspFsvolCreatePrepare;
|
|
FspIopCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateComplete;
|
|
FspIopCompleteFunction[IRP_MJ_CLOSE] = FspFsvolCloseComplete;
|
|
FspIopPrepareFunction[IRP_MJ_READ] = FspFsvolReadPrepare;
|
|
FspIopCompleteFunction[IRP_MJ_READ] = FspFsvolReadComplete;
|
|
FspIopPrepareFunction[IRP_MJ_WRITE] = FspFsvolWritePrepare;
|
|
FspIopCompleteFunction[IRP_MJ_WRITE] = FspFsvolWriteComplete;
|
|
FspIopCompleteFunction[IRP_MJ_QUERY_INFORMATION] = FspFsvolQueryInformationComplete;
|
|
FspIopPrepareFunction[IRP_MJ_SET_INFORMATION] = FspFsvolSetInformationPrepare;
|
|
FspIopCompleteFunction[IRP_MJ_SET_INFORMATION] = FspFsvolSetInformationComplete;
|
|
FspIopCompleteFunction[IRP_MJ_QUERY_EA] = FspFsvolQueryEaComplete;
|
|
FspIopCompleteFunction[IRP_MJ_SET_EA] = FspFsvolSetEaComplete;
|
|
FspIopCompleteFunction[IRP_MJ_FLUSH_BUFFERS] = FspFsvolFlushBuffersComplete;
|
|
FspIopCompleteFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FspFsvolQueryVolumeInformationComplete;
|
|
FspIopCompleteFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FspFsvolSetVolumeInformationComplete;
|
|
FspIopPrepareFunction[IRP_MJ_DIRECTORY_CONTROL] = FspFsvolDirectoryControlPrepare;
|
|
FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspFsvolDirectoryControlComplete;
|
|
FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFsvolFileSystemControlComplete;
|
|
FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspFsvolDeviceControlComplete;
|
|
FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspFsvolLockControlComplete;
|
|
FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspFsvolCleanupComplete;
|
|
FspIopCompleteFunction[IRP_MJ_QUERY_SECURITY] = FspFsvolQuerySecurityComplete;
|
|
FspIopCompleteFunction[IRP_MJ_SET_SECURITY] = FspFsvolSetSecurityComplete;
|
|
|
|
/* setup fast I/O and resource acquisition */
|
|
FspFastIoDispatch.SizeOfFastIoDispatch = sizeof FspFastIoDispatch;
|
|
FspFastIoDispatch.FastIoCheckIfPossible = FspFastIoCheckIfPossible;
|
|
FspFastIoDispatch.FastIoRead = FspFastIoRead;
|
|
FspFastIoDispatch.FastIoWrite = FspFastIoWrite;
|
|
FspFastIoDispatch.FastIoQueryBasicInfo = FspFastIoQueryBasicInfo;
|
|
FspFastIoDispatch.FastIoQueryStandardInfo = FspFastIoQueryStandardInfo;
|
|
//FspFastIoDispatch.FastIoLock = 0;
|
|
//FspFastIoDispatch.FastIoUnlockSingle = 0;
|
|
//FspFastIoDispatch.FastIoUnlockAll = 0;
|
|
//FspFastIoDispatch.FastIoUnlockAllByKey = 0;
|
|
FspFastIoDispatch.FastIoDeviceControl = FspFastIoDeviceControl;
|
|
FspFastIoDispatch.AcquireFileForNtCreateSection = FspAcquireFileForNtCreateSection;
|
|
FspFastIoDispatch.ReleaseFileForNtCreateSection = FspReleaseFileForNtCreateSection;
|
|
//FspFastIoDispatch.FastIoDetachDevice = 0;
|
|
FspFastIoDispatch.FastIoQueryNetworkOpenInfo = FspFastIoQueryNetworkOpenInfo;
|
|
FspFastIoDispatch.AcquireForModWrite = FspAcquireForModWrite;
|
|
//FspFastIoDispatch.MdlRead = 0;
|
|
//FspFastIoDispatch.MdlReadComplete = 0;
|
|
//FspFastIoDispatch.PrepareMdlWrite = 0;
|
|
//FspFastIoDispatch.MdlWriteComplete = 0;
|
|
//FspFastIoDispatch.FastIoReadCompressed = 0;
|
|
//FspFastIoDispatch.FastIoWriteCompressed = 0;
|
|
//FspFastIoDispatch.MdlReadCompleteCompressed = 0;
|
|
//FspFastIoDispatch.MdlWriteCompleteCompressed = 0;
|
|
FspFastIoDispatch.FastIoQueryOpen = FspFastIoQueryOpen;
|
|
FspFastIoDispatch.ReleaseForModWrite = FspReleaseForModWrite;
|
|
FspFastIoDispatch.AcquireForCcFlush = FspAcquireForCcFlush;
|
|
FspFastIoDispatch.ReleaseForCcFlush = FspReleaseForCcFlush;
|
|
FspCacheManagerCallbacks.AcquireForLazyWrite = FspAcquireForLazyWrite;
|
|
FspCacheManagerCallbacks.ReleaseFromLazyWrite = FspReleaseFromLazyWrite;
|
|
FspCacheManagerCallbacks.AcquireForReadAhead = FspAcquireForReadAhead;
|
|
FspCacheManagerCallbacks.ReleaseFromReadAhead = FspReleaseFromReadAhead;
|
|
#pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch")
|
|
DriverObject->FastIoDispatch = &FspFastIoDispatch;
|
|
|
|
BOOLEAN InitDoneSilo = FALSE, InitDonePsBuf = FALSE,
|
|
InitDoneTimers = FALSE, InitDoneDevices = FALSE;
|
|
|
|
FspDriverObject = DriverObject;
|
|
FspDriverMultiVersionInitialize();
|
|
|
|
ExInitializeFastMutex(&FspDriverUnloadMutex);
|
|
ExInitializeFastMutex(&FspDeviceGlobalMutex);
|
|
|
|
Result = FspSiloInitialize(FspDriverInitializeDevices, FspDriverFinalizeDevices);
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
InitDoneSilo = TRUE;
|
|
|
|
Result = FspProcessBufferInitialize();
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
InitDonePsBuf = TRUE;
|
|
|
|
Result = FspDeviceInitializeAllTimers();
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
InitDoneTimers = TRUE;
|
|
|
|
Result = FspDriverInitializeDevices();
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
InitDoneDevices = TRUE;
|
|
|
|
Result = STATUS_SUCCESS;
|
|
|
|
exit:
|
|
if (!NT_SUCCESS(Result))
|
|
{
|
|
if (InitDoneDevices)
|
|
FspDriverFinalizeDevices();
|
|
if (InitDoneTimers)
|
|
FspDeviceFinalizeAllTimers();
|
|
if (InitDonePsBuf)
|
|
FspProcessBufferFinalize();
|
|
if (InitDoneSilo)
|
|
FspSiloFinalize();
|
|
|
|
FSP_TRACE_FINI();
|
|
}
|
|
|
|
#pragma prefast(suppress:28175, "We are in DriverEntry: ok to access DriverName")
|
|
FSP_LEAVE_DRV("DriverName=\"%wZ\", RegistryPath=\"%wZ\"",
|
|
&DriverObject->DriverName, RegistryPath);
|
|
}
|
|
|
|
VOID DriverUnload(
|
|
PDRIVER_OBJECT DriverObject)
|
|
{
|
|
FSP_ENTER_VOID(PAGED_CODE());
|
|
|
|
FspDriverFinalizeDevices();
|
|
|
|
FspDeviceFinalizeAllTimers();
|
|
|
|
FspProcessBufferFinalize();
|
|
|
|
FspSiloFinalize();
|
|
|
|
FSP_TRACE_FINI();
|
|
|
|
#pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName")
|
|
FSP_LEAVE_VOID("DriverName=\"%wZ\"",
|
|
&DriverObject->DriverName);
|
|
}
|
|
|
|
static VOID FspDriverMultiVersionInitialize(VOID)
|
|
{
|
|
FspProcessorCount = KeQueryActiveProcessorCount(0);
|
|
|
|
#pragma prefast(suppress:30035, "FspDriverMultiVersionInitialize is called from DriverEntry")
|
|
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
|
|
|
|
if (FspIsNtDdiVersionAvailable(NTDDI_WIN7))
|
|
{
|
|
UNICODE_STRING Name;
|
|
|
|
RtlInitUnicodeString(&Name, L"CcCoherencyFlushAndPurgeCache");
|
|
FspMvCcCoherencyFlushAndPurgeCache =
|
|
(FSP_MV_CcCoherencyFlushAndPurgeCache *)(UINT_PTR)MmGetSystemRoutineAddress(&Name);
|
|
}
|
|
|
|
if (FspIsNtDdiVersionAvailable(NTDDI_WIN8))
|
|
FspMvMdlMappingNoWrite = MdlMappingNoWrite;
|
|
|
|
if (FspIsNtDdiVersionAvailable(NTDDI_WIN10_RS4))
|
|
FspHasReparsePointCaseSensitivityFix = TRUE;
|
|
}
|
|
|
|
static NTSTATUS FspDriverInitializeDevices(VOID)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
FSP_SILO_GLOBALS *Globals;
|
|
UNICODE_STRING DeviceSddl;
|
|
UNICODE_STRING DeviceName;
|
|
WCHAR DeviceNameBuf[128];
|
|
UNICODE_STRING SymlinkName;
|
|
GUID Guid;
|
|
NTSTATUS Result;
|
|
|
|
FspSiloGetGlobals(&Globals);
|
|
ASSERT(0 != Globals);
|
|
|
|
/* create the file system control device objects */
|
|
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
|
RtlInitEmptyUnicodeString(&DeviceName, DeviceNameBuf, sizeof DeviceNameBuf);
|
|
Result = RtlUnicodeStringPrintf(&DeviceName,
|
|
L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME "%wZ",
|
|
FspSxsSuffix());
|
|
ASSERT(NT_SUCCESS(Result));
|
|
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
|
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
|
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
|
&Globals->FsctlDiskDeviceObject);
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
if (0 != FspSxsIdent()->Length)
|
|
{
|
|
/* \Device\WinFsp.Disk SxS symlink */
|
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
|
Result = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
Globals->InitDoneSymlinkDisk = 1;
|
|
}
|
|
RtlInitEmptyUnicodeString(&DeviceName, DeviceNameBuf, sizeof DeviceNameBuf);
|
|
Result = RtlUnicodeStringPrintf(&DeviceName,
|
|
L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME "%wZ",
|
|
FspSxsSuffix());
|
|
ASSERT(NT_SUCCESS(Result));
|
|
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
|
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
|
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
|
&Globals->FsctlNetDeviceObject);
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
if (0 != FspSxsIdent()->Length)
|
|
{
|
|
/* \Device\WinFsp.Net SxS symlink */
|
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
|
Result = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
Globals->InitDoneSymlinkNet = 1;
|
|
}
|
|
Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0,
|
|
FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE,
|
|
&Globals->FsmupDeviceObject);
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
|
|
#if DBG
|
|
/*
|
|
* Fix GitHub issue #177. All credit for the investigation of this issue
|
|
* and the suggested steps to reproduce and work around the problem goes
|
|
* to GitHub user @thinkport.
|
|
*
|
|
* On debug builds set DO_LOW_PRIORITY_FILESYSTEM to place the file system
|
|
* at the end of the file system list during IoRegisterFileSystem below.
|
|
* This allows us to test the behavior of our Fsvrt devices when foreign
|
|
* file systems attempt to use them for mounting.
|
|
*/
|
|
SetFlag(Globals->FsctlDiskDeviceObject->Flags, DO_LOW_PRIORITY_FILESYSTEM);
|
|
#endif
|
|
|
|
Result = FspDeviceInitialize(Globals->FsctlDiskDeviceObject);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
Result = FspDeviceInitialize(Globals->FsctlNetDeviceObject);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
Result = FspDeviceInitialize(Globals->FsmupDeviceObject);
|
|
ASSERT(STATUS_SUCCESS == Result);
|
|
|
|
FspSiloGetContainerId(&Guid);
|
|
RtlInitEmptyUnicodeString(&DeviceName,
|
|
Globals->FsmupDeviceNameBuf, sizeof Globals->FsmupDeviceNameBuf);
|
|
Result = RtlUnicodeStringPrintf(&DeviceName,
|
|
0 == ((PULONG)&Guid)[0] && 0 == ((PULONG)&Guid)[1] &&
|
|
0 == ((PULONG)&Guid)[2] && 0 == ((PULONG)&Guid)[3] ?
|
|
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "%wZ":
|
|
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "%wZ{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
|
FspSxsSuffix(),
|
|
Guid.Data1, Guid.Data2, Guid.Data3,
|
|
Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
|
|
Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
|
|
ASSERT(NT_SUCCESS(Result));
|
|
DeviceName.MaximumLength = DeviceName.Length;
|
|
Result = FsRtlRegisterUncProviderEx(&Globals->MupHandle,
|
|
&DeviceName, Globals->FsmupDeviceObject, 0);
|
|
if (!NT_SUCCESS(Result))
|
|
{
|
|
Globals->MupHandle = 0;
|
|
goto exit;
|
|
}
|
|
|
|
/*
|
|
* Register our "disk" device as a file system. We do not register our "net" device
|
|
* as a file system; we register with the MUP instead.
|
|
*/
|
|
IoRegisterFileSystem(Globals->FsctlDiskDeviceObject);
|
|
Globals->InitDoneRegisterDisk = 1;
|
|
|
|
/*
|
|
* Reference primary device objects to allow for IoDeleteDevice during FspDriverUnload.
|
|
*/
|
|
ObReferenceObject(Globals->FsctlDiskDeviceObject);
|
|
ObReferenceObject(Globals->FsctlNetDeviceObject);
|
|
ObReferenceObject(Globals->FsmupDeviceObject);
|
|
|
|
Result = STATUS_SUCCESS;
|
|
|
|
exit:
|
|
if (!NT_SUCCESS(Result))
|
|
{
|
|
if (Globals->InitDoneRegisterDisk)
|
|
{
|
|
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
|
|
Globals->InitDoneRegisterDisk = 0;
|
|
}
|
|
if (0 != Globals->MupHandle)
|
|
{
|
|
FsRtlDeregisterUncProvider(Globals->MupHandle);
|
|
Globals->MupHandle = 0;
|
|
}
|
|
if (0 != Globals->FsmupDeviceObject)
|
|
{
|
|
FspDeviceDelete(Globals->FsmupDeviceObject);
|
|
Globals->FsmupDeviceObject = 0;
|
|
}
|
|
if (Globals->InitDoneSymlinkNet)
|
|
{
|
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
|
IoDeleteSymbolicLink(&SymlinkName);
|
|
Globals->InitDoneSymlinkNet = 0;
|
|
}
|
|
if (0 != Globals->FsctlNetDeviceObject)
|
|
{
|
|
FspDeviceDelete(Globals->FsctlNetDeviceObject);
|
|
Globals->FsctlNetDeviceObject = 0;
|
|
}
|
|
if (Globals->InitDoneSymlinkDisk)
|
|
{
|
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
|
IoDeleteSymbolicLink(&SymlinkName);
|
|
Globals->InitDoneSymlinkDisk = 0;
|
|
}
|
|
if (0 != Globals->FsctlDiskDeviceObject)
|
|
{
|
|
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
|
|
Globals->FsctlDiskDeviceObject = 0;
|
|
}
|
|
}
|
|
|
|
FspSiloDereferenceGlobals(Globals);
|
|
|
|
return Result;
|
|
}
|
|
|
|
static VOID FspDriverFinalizeDevices(VOID)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
FspDriverFinalizeDevicesEx(TRUE);
|
|
}
|
|
|
|
static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
FSP_SILO_GLOBALS *Globals;
|
|
UNICODE_STRING SymlinkName;
|
|
|
|
FspSiloGetGlobals(&Globals);
|
|
ASSERT(0 != Globals);
|
|
|
|
if (Globals->InitDoneRegisterDisk)
|
|
{
|
|
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
|
|
Globals->InitDoneRegisterDisk = 0;
|
|
}
|
|
if (0 != Globals->MupHandle)
|
|
{
|
|
FsRtlDeregisterUncProvider(Globals->MupHandle);
|
|
Globals->MupHandle = 0;
|
|
}
|
|
if (0 != Globals->FsmupDeviceObject)
|
|
{
|
|
if (DeleteDevices)
|
|
{
|
|
FspDeviceDelete(Globals->FsmupDeviceObject);
|
|
ObDereferenceObject(Globals->FsmupDeviceObject);
|
|
Globals->FsmupDeviceObject = 0;
|
|
}
|
|
else
|
|
FspDeviceDoIoDeleteDevice(Globals->FsmupDeviceObject);
|
|
}
|
|
if (Globals->InitDoneSymlinkNet)
|
|
{
|
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
|
IoDeleteSymbolicLink(&SymlinkName);
|
|
Globals->InitDoneSymlinkNet = 0;
|
|
}
|
|
if (0 != Globals->FsctlNetDeviceObject)
|
|
{
|
|
if (DeleteDevices)
|
|
{
|
|
FspDeviceDelete(Globals->FsctlNetDeviceObject);
|
|
ObDereferenceObject(Globals->FsctlNetDeviceObject);
|
|
Globals->FsctlNetDeviceObject = 0;
|
|
}
|
|
else
|
|
FspDeviceDoIoDeleteDevice(Globals->FsctlNetDeviceObject);
|
|
}
|
|
if (Globals->InitDoneSymlinkDisk)
|
|
{
|
|
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
|
IoDeleteSymbolicLink(&SymlinkName);
|
|
Globals->InitDoneSymlinkDisk = 0;
|
|
}
|
|
if (0 != Globals->FsctlDiskDeviceObject)
|
|
{
|
|
if (DeleteDevices)
|
|
{
|
|
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
|
|
ObDereferenceObject(Globals->FsctlDiskDeviceObject);
|
|
Globals->FsctlDiskDeviceObject = 0;
|
|
}
|
|
else
|
|
FspDeviceDoIoDeleteDevice(Globals->FsctlDiskDeviceObject);
|
|
}
|
|
|
|
FspSiloDereferenceGlobals(Globals);
|
|
}
|
|
|
|
NTSTATUS FspDriverUnload(
|
|
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
|
|
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
|
ASSERT(FSP_FSCTL_UNLOAD == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
|
|
|
NTSTATUS Result;
|
|
UNICODE_STRING DriverServiceName, DriverName, Remain;
|
|
WCHAR DriverServiceNameBuf[64 + 256];
|
|
PDEVICE_OBJECT *DeviceObjects = 0;
|
|
ULONG DeviceObjectCount = 0;
|
|
|
|
if (!FspSiloIsHost())
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_LOAD_DRIVER_PRIVILEGE), UserMode))
|
|
return STATUS_PRIVILEGE_NOT_HELD;
|
|
|
|
ExAcquireFastMutexUnsafe(&FspDriverUnloadMutex);
|
|
|
|
if (!FspDriverUnloadDone)
|
|
{
|
|
FspFileNameSuffix(&FspDriverObject->DriverName, &Remain, &DriverName);
|
|
RtlInitEmptyUnicodeString(&DriverServiceName, DriverServiceNameBuf, sizeof DriverServiceNameBuf);
|
|
Result = RtlUnicodeStringPrintf(&DriverServiceName,
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%wZ", &DriverName);
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
Result = ZwUnloadDriver(&DriverServiceName);
|
|
if (!NT_SUCCESS(Result))
|
|
goto exit;
|
|
|
|
FspDriverFinalizeDevicesEx(FALSE);
|
|
|
|
Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
|
|
if (NT_SUCCESS(Result))
|
|
{
|
|
for (ULONG I = 0; DeviceObjectCount > I; I++)
|
|
{
|
|
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObjects[I]);
|
|
if (FspFsvolDeviceExtensionKind == DeviceExtension->Kind)
|
|
FspIoqStop(((FSP_FSVOL_DEVICE_EXTENSION *)DeviceExtension)->Ioq, FALSE);
|
|
}
|
|
FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
|
|
}
|
|
|
|
FspDriverUnloadDone = TRUE;
|
|
}
|
|
|
|
Result = STATUS_SUCCESS;
|
|
|
|
exit:
|
|
ExReleaseFastMutexUnsafe(&FspDriverUnloadMutex);
|
|
|
|
return Result;
|
|
}
|
|
|
|
PDRIVER_OBJECT FspDriverObject;
|
|
FAST_IO_DISPATCH FspFastIoDispatch;
|
|
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
|
FAST_MUTEX FspDriverUnloadMutex;
|
|
BOOLEAN FspDriverUnloadDone;
|
|
|
|
ULONG FspProcessorCount;
|
|
FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
|
|
ULONG FspMvMdlMappingNoWrite = 0;
|
|
BOOLEAN FspHasReparsePointCaseSensitivityFix = FALSE;
|