diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj
index cf77883c..19bd2de1 100644
--- a/build/VStudio/winfsp_dll.vcxproj
+++ b/build/VStudio/winfsp_dll.vcxproj
@@ -75,6 +75,7 @@
+
diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters
index 6299aaca..13c62356 100644
--- a/build/VStudio/winfsp_dll.vcxproj.filters
+++ b/build/VStudio/winfsp_dll.vcxproj.filters
@@ -175,6 +175,9 @@
Source
+
+ Source\shared\ku
+
diff --git a/build/VStudio/winfsp_sys.vcxproj b/build/VStudio/winfsp_sys.vcxproj
index 3092efa0..62a6f886 100644
--- a/build/VStudio/winfsp_sys.vcxproj
+++ b/build/VStudio/winfsp_sys.vcxproj
@@ -228,6 +228,7 @@
+
diff --git a/build/VStudio/winfsp_sys.vcxproj.filters b/build/VStudio/winfsp_sys.vcxproj.filters
index a23ea4f0..fabab43a 100644
--- a/build/VStudio/winfsp_sys.vcxproj.filters
+++ b/build/VStudio/winfsp_sys.vcxproj.filters
@@ -131,6 +131,9 @@
Source
+
+ Source\shared\ku
+
diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h
index ef970587..f5d7293a 100644
--- a/inc/winfsp/fsctl.h
+++ b/inc/winfsp/fsctl.h
@@ -91,6 +91,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
/* fsctl device codes */
#define FSP_FSCTL_MOUNTDEV \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'M', METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define FSP_FSCTL_MOUNTMGR \
+ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'm', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_NAME \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_LIST \
@@ -679,6 +681,8 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
PHANDLE PVolumeHandle);
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
BOOLEAN Persistent, GUID *UniqueId);
+FSP_API NTSTATUS FspFsctlUseMountmgr(HANDLE VolumeHandle,
+ PWSTR MountPoint);
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
PVOID ResponseBuf, SIZE_T ResponseBufSize,
PVOID RequestBuf, SIZE_T *PRequestBufSize,
diff --git a/src/dll/fsctl.c b/src/dll/fsctl.c
index 956c3840..81dbf823 100644
--- a/src/dll/fsctl.c
+++ b/src/dll/fsctl.c
@@ -130,6 +130,22 @@ FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
return STATUS_SUCCESS;
}
+FSP_API NTSTATUS FspFsctlUseMountmgr(HANDLE VolumeHandle,
+ PWSTR MountPoint)
+{
+ DWORD Bytes;
+
+ Bytes = 0 != MountPoint ? lstrlenW(MountPoint) * sizeof(WCHAR) : 0;
+
+ if (!DeviceIoControl(VolumeHandle,
+ FSP_FSCTL_MOUNTMGR,
+ MountPoint, Bytes, 0, 0,
+ &Bytes, 0))
+ return FspNtStatusFromWin32(GetLastError());
+
+ return STATUS_SUCCESS;
+}
+
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
PVOID ResponseBuf, SIZE_T ResponseBufSize,
PVOID RequestBuf, SIZE_T *PRequestBufSize,
diff --git a/src/dll/library.h b/src/dll/library.h
index f1a2e908..fa982ab2 100644
--- a/src/dll/library.h
+++ b/src/dll/library.h
@@ -73,6 +73,15 @@ NTSTATUS FspEventLogUnregister(VOID);
PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult);
PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType);
+NTSTATUS FspMountmgrCreateDrive(
+ PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
+NTSTATUS FspMountmgrDeleteDrive(
+ PUNICODE_STRING MountPoint);
+NTSTATUS FspMountmgrNotifyCreateDirectory(
+ PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
+NTSTATUS FspMountmgrNotifyDeleteDirectory(
+ PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
+
ULONG FspLdapConnect(PWSTR HostName, PVOID *PLdap);
VOID FspLdapClose(PVOID Ldap);
ULONG FspLdapGetValue(PVOID Ldap, PWSTR Base, ULONG Scope, PWSTR Filter, PWSTR Attribute,
diff --git a/src/dll/mount.c b/src/dll/mount.c
index 3f912ee7..ff745365 100644
--- a/src/dll/mount.c
+++ b/src/dll/mount.c
@@ -31,6 +31,7 @@ static NTSTATUS (NTAPI *FspNtClose)(
HANDLE Handle);
static BOOLEAN FspMountDoNotUseLauncherValue;
static BOOLEAN FspMountBroadcastDriveChangeValue;
+static BOOLEAN FspMountUseMountmgrFromFSDValue;
static VOID FspMountInitializeFromRegistry(VOID)
{
@@ -53,6 +54,14 @@ static VOID FspMountInitializeFromRegistry(VOID)
RRF_RT_REG_DWORD, 0, &Value, &Size);
if (ERROR_SUCCESS == Result)
FspMountBroadcastDriveChangeValue = !!Value;
+
+ Value = 0;
+ Size = sizeof Value;
+ Result = RegGetValueW(HKEY_LOCAL_MACHINE, L"" FSP_FSCTL_PRODUCT_FULL_REGKEY,
+ L"MountUseMountmgrFromFSD",
+ RRF_RT_REG_DWORD, 0, &Value, &Size);
+ if (ERROR_SUCCESS == Result)
+ FspMountUseMountmgrFromFSDValue = !!Value;
}
static BOOL WINAPI FspMountInitialize(
@@ -80,301 +89,40 @@ static BOOL WINAPI FspMountInitialize(
return TRUE;
}
-static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
- PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
-{
- HANDLE MgrHandle = INVALID_HANDLE_VALUE;
- DWORD Bytes = 0;
- NTSTATUS Result;
-
- if (0 == POutputBufferLength)
- POutputBufferLength = &Bytes;
-
- MgrHandle = CreateFileW(L"\\\\.\\MountPointManager",
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- 0,
- OPEN_EXISTING,
- 0,
- 0);
- if (INVALID_HANDLE_VALUE == MgrHandle)
- {
- Result = FspNtStatusFromWin32(GetLastError());
- goto exit;
- }
-
- if (!DeviceIoControl(MgrHandle,
- IoControlCode,
- InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength,
- &Bytes, 0))
- {
- Result = FspNtStatusFromWin32(GetLastError());
- goto exit;
- }
-
- *POutputBufferLength = Bytes;
- Result = STATUS_SUCCESS;
-
-exit:
- if (INVALID_HANDLE_VALUE != MgrHandle)
- CloseHandle(MgrHandle);
-
- return Result;
-}
-
-static NTSTATUS FspMountmgrMakeMountdev(HANDLE VolumeHandle, PWSTR VolumeName, GUID *UniqueId)
-{
- /* mountmgr.h */
- typedef enum
- {
- Disabled = 0,
- Enabled,
- } MOUNTMGR_AUTO_MOUNT_STATE;
- typedef struct
- {
- MOUNTMGR_AUTO_MOUNT_STATE CurrentState;
- } MOUNTMGR_QUERY_AUTO_MOUNT;
- typedef struct
- {
- MOUNTMGR_AUTO_MOUNT_STATE NewState;
- } MOUNTMGR_SET_AUTO_MOUNT;
- typedef struct
- {
- USHORT DeviceNameLength;
- WCHAR DeviceName[1];
- } MOUNTMGR_TARGET_NAME;
-
- MOUNTMGR_QUERY_AUTO_MOUNT QueryAutoMount;
- MOUNTMGR_SET_AUTO_MOUNT SetAutoMount;
- MOUNTMGR_TARGET_NAME *TargetName = 0;
- ULONG VolumeNameSize, QueryAutoMountSize, TargetNameSize;
- NTSTATUS Result;
-
- /* transform our volume into one that can be used by the MountManager */
- Result = FspFsctlMakeMountdev(VolumeHandle, FALSE, UniqueId);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- VolumeNameSize = lstrlenW(VolumeName) * sizeof(WCHAR);
- QueryAutoMountSize = sizeof QueryAutoMount;
- TargetNameSize = FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + VolumeNameSize;
-
- TargetName = MemAlloc(TargetNameSize);
- if (0 == TargetName)
- {
- Result = STATUS_INSUFFICIENT_RESOURCES;
- goto exit;
- }
-
- /* query the current AutoMount value and save it */
- Result = FspMountmgrControl(
- CTL_CODE('m', 15, METHOD_BUFFERED, FILE_ANY_ACCESS),
- /* IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT */
- 0, 0, &QueryAutoMount, &QueryAutoMountSize);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- /* disable AutoMount */
- SetAutoMount.NewState = 0;
- Result = FspMountmgrControl(
- CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
- /* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
- &SetAutoMount, sizeof SetAutoMount, 0, 0);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- /* announce volume arrival */
- memset(TargetName, 0, sizeof *TargetName);
- TargetName->DeviceNameLength = (USHORT)VolumeNameSize;
- memcpy(TargetName->DeviceName,
- VolumeName, TargetName->DeviceNameLength);
- Result = FspMountmgrControl(
- CTL_CODE('m', 11, METHOD_BUFFERED, FILE_READ_ACCESS),
- /* IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION */
- TargetName, TargetNameSize, 0, 0);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- /* reset the AutoMount value to the saved one */
- SetAutoMount.NewState = QueryAutoMount.CurrentState;
- FspMountmgrControl(
- CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
- /* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
- &SetAutoMount, sizeof SetAutoMount, 0, 0);
-
- Result = STATUS_SUCCESS;
-
-exit:
- MemFree(TargetName);
-
- return Result;
-}
-
-static NTSTATUS FspMountmgrNotify(PWSTR VolumeName, PWSTR MountPoint, BOOLEAN Created)
-{
- /* mountmgr.h */
- typedef struct
- {
- USHORT SourceVolumeNameOffset;
- USHORT SourceVolumeNameLength;
- USHORT TargetVolumeNameOffset;
- USHORT TargetVolumeNameLength;
- } MOUNTMGR_VOLUME_MOUNT_POINT;
-
- MOUNTMGR_VOLUME_MOUNT_POINT *VolumeMountPoint = 0;
- ULONG VolumeNameSize, MountPointSize, VolumeMountPointSize;
- NTSTATUS Result;
-
- VolumeNameSize = lstrlenW(VolumeName) * sizeof(WCHAR);
- MountPointSize = lstrlenW(MountPoint) * sizeof(WCHAR);
- VolumeMountPointSize = sizeof *VolumeMountPoint +
- sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPointSize + VolumeNameSize;
-
- VolumeMountPoint = MemAlloc(VolumeMountPointSize);
- if (0 == VolumeMountPoint)
- {
- Result = STATUS_INSUFFICIENT_RESOURCES;
- goto exit;
- }
-
- /* notify volume mount point created/deleted */
- memset(VolumeMountPoint, 0, sizeof *VolumeMountPoint);
- VolumeMountPoint->SourceVolumeNameOffset = sizeof *VolumeMountPoint;
- VolumeMountPoint->SourceVolumeNameLength = (USHORT)(
- sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPointSize);
- VolumeMountPoint->TargetVolumeNameOffset =
- VolumeMountPoint->SourceVolumeNameOffset + VolumeMountPoint->SourceVolumeNameLength;
- VolumeMountPoint->TargetVolumeNameLength = (USHORT)VolumeNameSize;
- memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset,
- L"\\DosDevices\\", sizeof L"\\DosDevices\\" - sizeof(WCHAR));
- memcpy((PUINT8)VolumeMountPoint +
- VolumeMountPoint->SourceVolumeNameOffset + (sizeof L"\\DosDevices\\" - sizeof(WCHAR)),
- MountPoint, MountPointSize);
- memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset,
- VolumeName, VolumeNameSize);
- Result = FspMountmgrControl(
- Created ?
- CTL_CODE('m', 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) :
- /* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED */
- CTL_CODE('m', 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
- /* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED */
- VolumeMountPoint, VolumeMountPointSize, 0, 0);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- Result = STATUS_SUCCESS;
-
-exit:
- MemFree(VolumeMountPoint);
-
- return Result;
-}
-
-static VOID FspMountmgrDeleteRegistry(GUID *UniqueId)
-{
- HKEY RegKey;
- LONG RegResult;
- WCHAR RegValueName[MAX_PATH];
- UINT8 RegValueData[sizeof *UniqueId];
- DWORD RegValueNameSize, RegValueDataSize;
- DWORD RegType;
-
- /* HACK: delete the MountManager registry entries */
- RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\MountedDevices",
- 0, KEY_READ | KEY_WRITE, &RegKey);
- if (ERROR_SUCCESS == RegResult)
- {
- for (DWORD I = 0;; I++)
- {
- RegValueNameSize = MAX_PATH;
- RegValueDataSize = sizeof RegValueData;
- RegResult = RegEnumValueW(RegKey,
- I, RegValueName, &RegValueNameSize, 0, &RegType, RegValueData, &RegValueDataSize);
- if (ERROR_NO_MORE_ITEMS == RegResult)
- break;
- else if (ERROR_SUCCESS != RegResult)
- continue;
-
- if (REG_BINARY == RegType &&
- sizeof RegValueData == RegValueDataSize &&
- InlineIsEqualGUID((GUID *)&RegValueData, UniqueId))
- {
- RegResult = RegDeleteValueW(RegKey, RegValueName);
- if (ERROR_SUCCESS == RegResult)
- /* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
- I = -1;
- }
- }
-
- RegCloseKey(RegKey);
- }
-}
-
-static NTSTATUS FspMountSet_MountmgrDrive(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint)
-{
- /* mountmgr.h */
- typedef struct
- {
- USHORT SymbolicLinkNameOffset;
- USHORT SymbolicLinkNameLength;
- USHORT DeviceNameOffset;
- USHORT DeviceNameLength;
- } MOUNTMGR_CREATE_POINT_INPUT;
-
- GUID UniqueId;
- MOUNTMGR_CREATE_POINT_INPUT *CreatePointInput = 0;
- ULONG VolumeNameSize, CreatePointInputSize;
- NTSTATUS Result;
-
- Result = FspMountmgrMakeMountdev(VolumeHandle, VolumeName, &UniqueId);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- VolumeNameSize = lstrlenW(VolumeName) * sizeof(WCHAR);
- CreatePointInputSize = sizeof *CreatePointInput +
- sizeof L"\\DosDevices\\X:" - sizeof(WCHAR) + VolumeNameSize;
-
- CreatePointInput = MemAlloc(CreatePointInputSize);
- if (0 == CreatePointInput)
- {
- Result = STATUS_INSUFFICIENT_RESOURCES;
- goto exit;
- }
-
- /* create mount point */
- memset(CreatePointInput, 0, sizeof *CreatePointInput);
- CreatePointInput->SymbolicLinkNameOffset = sizeof *CreatePointInput;
- CreatePointInput->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
- CreatePointInput->DeviceNameOffset =
- CreatePointInput->SymbolicLinkNameOffset + CreatePointInput->SymbolicLinkNameLength;
- CreatePointInput->DeviceNameLength = (USHORT)VolumeNameSize;
- memcpy((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset,
- L"\\DosDevices\\X:", CreatePointInput->SymbolicLinkNameLength);
- ((PWCHAR)((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset))[12] =
- MountPoint[4] & ~0x20;
- /* convert to uppercase */
- memcpy((PUINT8)CreatePointInput + CreatePointInput->DeviceNameOffset,
- VolumeName, CreatePointInput->DeviceNameLength);
- Result = FspMountmgrControl(
- CTL_CODE('m', 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
- /* IOCTL_MOUNTMGR_CREATE_POINT */
- CreatePointInput, CreatePointInputSize, 0, 0);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- FspMountmgrDeleteRegistry(&UniqueId);
-
- Result = STATUS_SUCCESS;
-
-exit:
- MemFree(CreatePointInput);
-
- return Result;
-}
-
static NTSTATUS FspMountSet_Directory(PWSTR VolumeName, PWSTR MountPoint,
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle);
static NTSTATUS FspMountRemove_Directory(HANDLE MountHandle);
+
+static NTSTATUS FspMountSet_MountmgrDrive(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint)
+{
+ if (FspMountUseMountmgrFromFSDValue)
+ /* use MountManager from FSD and exit */
+ return FspFsctlUseMountmgr(VolumeHandle, MountPoint + 4);
+
+ GUID UniqueId;
+ NTSTATUS Result;
+
+ /* transform our volume into one that can be used by the MountManager */
+ Result = FspFsctlMakeMountdev(VolumeHandle, FALSE, &UniqueId);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* use the MountManager to create the drive */
+ UNICODE_STRING UVolumeName, UMountPoint;
+ UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
+ UVolumeName.Buffer = VolumeName;
+ UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
+ UMountPoint.Buffer = MountPoint + 4;
+ Result = FspMountmgrCreateDrive(&UVolumeName, &UniqueId, &UMountPoint);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ return Result;
+}
+
static NTSTATUS FspMountSet_MountmgrDirectory(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint,
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle)
{
@@ -384,20 +132,33 @@ static NTSTATUS FspMountSet_MountmgrDirectory(HANDLE VolumeHandle, PWSTR VolumeN
*PMountHandle = 0;
+ /* create the directory mount point */
Result = FspMountSet_Directory(VolumeName, MountPoint + 4, SecurityDescriptor, &MountHandle);
if (!NT_SUCCESS(Result))
goto exit;
- Result = FspMountmgrMakeMountdev(VolumeHandle, VolumeName, &UniqueId);
+ if (FspMountUseMountmgrFromFSDValue)
+ {
+ /* use MountManager from FSD and exit */
+ Result = FspFsctlUseMountmgr(VolumeHandle, MountPoint + 4);
+ goto exit;
+ }
+
+ /* transform our volume into one that can be used by the MountManager */
+ Result = FspFsctlMakeMountdev(VolumeHandle, FALSE, &UniqueId);
if (!NT_SUCCESS(Result))
goto exit;
- Result = FspMountmgrNotify(VolumeName, MountPoint + 4, TRUE);
+ /* notify the MountManager about the created directory mount point */
+ UNICODE_STRING UVolumeName, UMountPoint;
+ UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
+ UVolumeName.Buffer = VolumeName;
+ UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
+ UMountPoint.Buffer = MountPoint + 4;
+ Result = FspMountmgrNotifyCreateDirectory(&UVolumeName, &UniqueId, &UMountPoint);
if (!NT_SUCCESS(Result))
goto exit;
- FspMountmgrDeleteRegistry(&UniqueId);
-
*PMountHandle = MountHandle;
Result = STATUS_SUCCESS;
@@ -409,79 +170,39 @@ exit:
return Result;
}
-static NTSTATUS FspMountRemove_MountmgrDrive(PWSTR MountPoint)
+static NTSTATUS FspMountRemove_MountmgrDrive(HANDLE VolumeHandle, PWSTR MountPoint)
{
- /* mountmgr.h */
- typedef struct
- {
- ULONG SymbolicLinkNameOffset;
- USHORT SymbolicLinkNameLength;
- USHORT Reserved1;
- ULONG UniqueIdOffset;
- USHORT UniqueIdLength;
- USHORT Reserved2;
- ULONG DeviceNameOffset;
- USHORT DeviceNameLength;
- USHORT Reserved3;
- } MOUNTMGR_MOUNT_POINT;
- typedef struct
- {
- ULONG Size;
- ULONG NumberOfMountPoints;
- MOUNTMGR_MOUNT_POINT MountPoints[1];
- } MOUNTMGR_MOUNT_POINTS;
+ if (FspMountUseMountmgrFromFSDValue)
+ /* use MountManager from FSD and exit */
+ return FspFsctlUseMountmgr(VolumeHandle, 0);
- MOUNTMGR_MOUNT_POINT *Input = 0;
- MOUNTMGR_MOUNT_POINTS *Output = 0;
- ULONG InputSize, OutputSize;
- NTSTATUS Result;
-
- InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
- OutputSize = 4096;
-
- Input = MemAlloc(InputSize);
- if (0 == Input)
- {
- Result = STATUS_INSUFFICIENT_RESOURCES;
- goto exit;
- }
-
- Output = MemAlloc(OutputSize);
- if (0 == Output)
- {
- Result = STATUS_INSUFFICIENT_RESOURCES;
- goto exit;
- }
-
- memset(Input, 0, sizeof *Input);
- Input->SymbolicLinkNameOffset = sizeof *Input;
- Input->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
- memcpy((PUINT8)Input + Input->SymbolicLinkNameOffset,
- L"\\DosDevices\\X:", Input->SymbolicLinkNameLength);
- ((PWCHAR)((PUINT8)Input + Input->SymbolicLinkNameOffset))[12] = MountPoint[4] & ~0x20;
- /* convert to uppercase */
- Result = FspMountmgrControl(
- CTL_CODE('m', 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
- /* IOCTL_MOUNTMGR_DELETE_POINTS */
- Input, InputSize, Output, &OutputSize);
- if (!NT_SUCCESS(Result))
- goto exit;
-
- Result = STATUS_SUCCESS;
-
-exit:
- MemFree(Output);
- MemFree(Input);
-
- return Result;
+ /* use the MountManager to delete the drive */
+ UNICODE_STRING UMountPoint;
+ UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
+ UMountPoint.Buffer = MountPoint + 4;
+ return FspMountmgrDeleteDrive(&UMountPoint);
}
-static NTSTATUS FspMountRemove_MountmgrDirectory(PWSTR VolumeName, PWSTR MountPoint, HANDLE MountHandle)
+static NTSTATUS FspMountRemove_MountmgrDirectory(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint,
+ HANDLE MountHandle)
{
NTSTATUS Result;
- FspMountmgrNotify(VolumeName, MountPoint + 4, FALSE);
+ if (FspMountUseMountmgrFromFSDValue)
+ /* use MountManager from FSD, but do not exit; additional processing is required below */
+ FspFsctlUseMountmgr(VolumeHandle, 0);
+ else
+ {
+ /* notify the MountManager about the deleted directory mount point */
+ UNICODE_STRING UVolumeName, UMountPoint;
+ UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
+ UVolumeName.Buffer = VolumeName;
+ UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
+ UMountPoint.Buffer = MountPoint + 4;
+ FspMountmgrNotifyDeleteDirectory(&UVolumeName, &UMountPoint);
+ }
+ /* delete the directory mount point */
Result = FspMountRemove_Directory(MountHandle);
if (!NT_SUCCESS(Result))
goto exit;
@@ -889,9 +610,10 @@ FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc)
InitOnceExecuteOnce(&FspMountInitOnce, FspMountInitialize, 0, 0);
if (FspPathIsMountmgrDrive(Desc->MountPoint))
- return FspMountRemove_MountmgrDrive(Desc->MountPoint);
+ return FspMountRemove_MountmgrDrive(Desc->VolumeHandle, Desc->MountPoint);
else if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
- return FspMountRemove_MountmgrDirectory(Desc->VolumeName, Desc->MountPoint, Desc->MountHandle);
+ return FspMountRemove_MountmgrDirectory(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint,
+ Desc->MountHandle);
else if (FspPathIsDrive(Desc->MountPoint))
return FspMountRemove_Drive(Desc->VolumeName, Desc->MountPoint, Desc->MountHandle);
else
diff --git a/src/shared/ku/mountmgr.c b/src/shared/ku/mountmgr.c
new file mode 100644
index 00000000..3437cc5f
--- /dev/null
+++ b/src/shared/ku/mountmgr.c
@@ -0,0 +1,599 @@
+/**
+ * @file shared/ku/mountmgr.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
+
+#pragma warning(push)
+#pragma warning(disable:4459) /* declaration of 'identifier' hides global declaration */
+
+static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
+ PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength);
+static NTSTATUS FspMountmgrNotifyVolumeArrival(
+ PUNICODE_STRING VolumeName, GUID *UniqueId);
+static NTSTATUS FspMountmgrNotifyMountPoint(
+ PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint, BOOLEAN Created);
+static NTSTATUS FspMountmgrCreateMountPoint(
+ PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
+static NTSTATUS FspMountmgrDeleteMountPoint(
+ PUNICODE_STRING MountPoint);
+static VOID FspMountmgrDeleteRegistry(
+ GUID *UniqueId);
+NTSTATUS FspMountmgrCreateDrive(
+ PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
+NTSTATUS FspMountmgrDeleteDrive(
+ PUNICODE_STRING MountPoint);
+NTSTATUS FspMountmgrNotifyCreateDirectory(
+ PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
+NTSTATUS FspMountmgrNotifyDeleteDirectory(
+ PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
+
+#if defined(_KERNEL_MODE)
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, FspMountmgrControl)
+#pragma alloc_text(PAGE, FspMountmgrNotifyVolumeArrival)
+#pragma alloc_text(PAGE, FspMountmgrNotifyMountPoint)
+#pragma alloc_text(PAGE, FspMountmgrCreateMountPoint)
+#pragma alloc_text(PAGE, FspMountmgrDeleteMountPoint)
+#pragma alloc_text(PAGE, FspMountmgrCreateDrive)
+#pragma alloc_text(PAGE, FspMountmgrDeleteDrive)
+#pragma alloc_text(PAGE, FspMountmgrNotifyCreateDirectory)
+#pragma alloc_text(PAGE, FspMountmgrNotifyDeleteDirectory)
+#endif
+#endif
+
+static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
+ PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
+{
+#if defined(_KERNEL_MODE)
+ FSP_KU_CODE;
+
+ UNICODE_STRING DeviceName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatus;
+ HANDLE MgrHandle = 0;
+ ULONG Bytes = 0;
+
+ if (0 == POutputBufferLength)
+ POutputBufferLength = &Bytes;
+
+ RtlInitUnicodeString(&DeviceName, L"\\Device\\MountPointManager");
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &DeviceName,
+ OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
+ 0/*RootDirectory*/,
+ 0);
+
+ IoStatus.Status = ZwOpenFile(
+ &MgrHandle,
+ GENERIC_READ | GENERIC_WRITE,
+ &ObjectAttributes,
+ &IoStatus,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(IoStatus.Status))
+ goto exit;
+
+ IoStatus.Status = ZwDeviceIoControlFile(
+ MgrHandle,
+ 0, 0, 0,
+ &IoStatus,
+ IoControlCode,
+ InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength);
+ if (!NT_SUCCESS(IoStatus.Status))
+ goto exit;
+
+ *POutputBufferLength = (ULONG)IoStatus.Information;
+ IoStatus.Status = STATUS_SUCCESS;
+
+exit:
+ if (0 != MgrHandle)
+ ZwClose(MgrHandle);
+
+ return IoStatus.Status;
+#else
+ HANDLE MgrHandle = INVALID_HANDLE_VALUE;
+ DWORD Bytes = 0;
+ NTSTATUS Result;
+
+ if (0 == POutputBufferLength)
+ POutputBufferLength = &Bytes;
+
+ MgrHandle = CreateFileW(L"\\\\.\\MountPointManager",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ 0,
+ OPEN_EXISTING,
+ 0,
+ 0);
+ if (INVALID_HANDLE_VALUE == MgrHandle)
+ {
+ Result = FspNtStatusFromWin32(GetLastError());
+ goto exit;
+ }
+
+ if (!DeviceIoControl(MgrHandle,
+ IoControlCode,
+ InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength,
+ &Bytes, 0))
+ {
+ Result = FspNtStatusFromWin32(GetLastError());
+ goto exit;
+ }
+
+ *POutputBufferLength = Bytes;
+ Result = STATUS_SUCCESS;
+
+exit:
+ if (INVALID_HANDLE_VALUE != MgrHandle)
+ CloseHandle(MgrHandle);
+
+ return Result;
+#endif
+}
+
+static NTSTATUS FspMountmgrNotifyVolumeArrival(
+ PUNICODE_STRING VolumeName, GUID *UniqueId)
+{
+ FSP_KU_CODE;
+
+ /* mountmgr.h */
+ typedef enum
+ {
+ Disabled = 0,
+ Enabled,
+ } MOUNTMGR_AUTO_MOUNT_STATE;
+ typedef struct
+ {
+ MOUNTMGR_AUTO_MOUNT_STATE CurrentState;
+ } MOUNTMGR_QUERY_AUTO_MOUNT;
+ typedef struct
+ {
+ MOUNTMGR_AUTO_MOUNT_STATE NewState;
+ } MOUNTMGR_SET_AUTO_MOUNT;
+ typedef struct
+ {
+ USHORT DeviceNameLength;
+ WCHAR DeviceName[1];
+ } MOUNTMGR_TARGET_NAME;
+
+ MOUNTMGR_QUERY_AUTO_MOUNT QueryAutoMount;
+ MOUNTMGR_SET_AUTO_MOUNT SetAutoMount;
+ MOUNTMGR_TARGET_NAME *TargetName = 0;
+ ULONG QueryAutoMountSize, TargetNameSize;
+ NTSTATUS Result;
+
+ QueryAutoMountSize = sizeof QueryAutoMount;
+ TargetNameSize = FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + VolumeName->Length;
+
+ TargetName = MemAlloc(TargetNameSize);
+ if (0 == TargetName)
+ {
+ Result = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+
+ /* query the current AutoMount value and save it */
+ Result = FspMountmgrControl(
+ CTL_CODE('m', 15, METHOD_BUFFERED, FILE_ANY_ACCESS),
+ /* IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT */
+ 0, 0, &QueryAutoMount, &QueryAutoMountSize);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* disable AutoMount */
+ SetAutoMount.NewState = 0;
+ Result = FspMountmgrControl(
+ CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
+ /* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
+ &SetAutoMount, sizeof SetAutoMount, 0, 0);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* announce volume arrival */
+ memset(TargetName, 0, sizeof *TargetName);
+ TargetName->DeviceNameLength = VolumeName->Length;
+ memcpy(TargetName->DeviceName, VolumeName->Buffer, VolumeName->Length);
+ Result = FspMountmgrControl(
+ CTL_CODE('m', 11, METHOD_BUFFERED, FILE_READ_ACCESS),
+ /* IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION */
+ TargetName, TargetNameSize, 0, 0);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* reset the AutoMount value to the saved one */
+ SetAutoMount.NewState = QueryAutoMount.CurrentState;
+ FspMountmgrControl(
+ CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
+ /* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
+ &SetAutoMount, sizeof SetAutoMount, 0, 0);
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ MemFree(TargetName);
+
+ return Result;
+}
+
+static NTSTATUS FspMountmgrNotifyMountPoint(
+ PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint, BOOLEAN Created)
+{
+ FSP_KU_CODE;
+
+ /* mountmgr.h */
+ typedef struct
+ {
+ USHORT SourceVolumeNameOffset;
+ USHORT SourceVolumeNameLength;
+ USHORT TargetVolumeNameOffset;
+ USHORT TargetVolumeNameLength;
+ } MOUNTMGR_VOLUME_MOUNT_POINT;
+
+ MOUNTMGR_VOLUME_MOUNT_POINT *VolumeMountPoint = 0;
+ ULONG VolumeMountPointSize;
+ NTSTATUS Result;
+
+ VolumeMountPointSize = sizeof *VolumeMountPoint +
+ sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPoint->Length + VolumeName->Length;
+
+ VolumeMountPoint = MemAlloc(VolumeMountPointSize);
+ if (0 == VolumeMountPoint)
+ {
+ Result = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+
+ /* notify volume mount point created/deleted */
+ memset(VolumeMountPoint, 0, sizeof *VolumeMountPoint);
+ VolumeMountPoint->SourceVolumeNameOffset = sizeof *VolumeMountPoint;
+ VolumeMountPoint->SourceVolumeNameLength = (USHORT)(
+ sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPoint->Length);
+ VolumeMountPoint->TargetVolumeNameOffset =
+ VolumeMountPoint->SourceVolumeNameOffset + VolumeMountPoint->SourceVolumeNameLength;
+ VolumeMountPoint->TargetVolumeNameLength = VolumeName->Length;
+ memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset,
+ L"\\DosDevices\\", sizeof L"\\DosDevices\\" - sizeof(WCHAR));
+ memcpy((PUINT8)VolumeMountPoint +
+ VolumeMountPoint->SourceVolumeNameOffset + (sizeof L"\\DosDevices\\" - sizeof(WCHAR)),
+ MountPoint->Buffer, MountPoint->Length);
+ memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset,
+ VolumeName->Buffer, VolumeName->Length);
+ Result = FspMountmgrControl(
+ Created ?
+ CTL_CODE('m', 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) :
+ /* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED */
+ CTL_CODE('m', 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
+ /* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED */
+ VolumeMountPoint, VolumeMountPointSize, 0, 0);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ MemFree(VolumeMountPoint);
+
+ return Result;
+}
+
+static NTSTATUS FspMountmgrCreateMountPoint(
+ PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint)
+{
+ FSP_KU_CODE;
+
+ /* mountmgr.h */
+ typedef struct
+ {
+ USHORT SymbolicLinkNameOffset;
+ USHORT SymbolicLinkNameLength;
+ USHORT DeviceNameOffset;
+ USHORT DeviceNameLength;
+ } MOUNTMGR_CREATE_POINT_INPUT;
+
+ MOUNTMGR_CREATE_POINT_INPUT *CreatePointInput = 0;
+ ULONG CreatePointInputSize;
+ NTSTATUS Result;
+
+ CreatePointInputSize = sizeof *CreatePointInput +
+ sizeof L"\\DosDevices\\X:" - sizeof(WCHAR) + VolumeName->Length;
+
+ CreatePointInput = MemAlloc(CreatePointInputSize);
+ if (0 == CreatePointInput)
+ {
+ Result = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+
+ /* create mount point */
+ memset(CreatePointInput, 0, sizeof *CreatePointInput);
+ CreatePointInput->SymbolicLinkNameOffset = sizeof *CreatePointInput;
+ CreatePointInput->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
+ CreatePointInput->DeviceNameOffset =
+ CreatePointInput->SymbolicLinkNameOffset + CreatePointInput->SymbolicLinkNameLength;
+ CreatePointInput->DeviceNameLength = VolumeName->Length;
+ memcpy((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset,
+ L"\\DosDevices\\X:", CreatePointInput->SymbolicLinkNameLength);
+ ((PWCHAR)((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset))[12] =
+ MountPoint->Buffer[0] & ~0x20;
+ /* convert to uppercase */
+ memcpy((PUINT8)CreatePointInput + CreatePointInput->DeviceNameOffset,
+ VolumeName->Buffer, VolumeName->Length);
+ Result = FspMountmgrControl(
+ CTL_CODE('m', 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
+ /* IOCTL_MOUNTMGR_CREATE_POINT */
+ CreatePointInput, CreatePointInputSize, 0, 0);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ MemFree(CreatePointInput);
+
+ return Result;
+}
+
+static NTSTATUS FspMountmgrDeleteMountPoint(
+ PUNICODE_STRING MountPoint)
+{
+ FSP_KU_CODE;
+
+ /* mountmgr.h */
+ typedef struct
+ {
+ ULONG SymbolicLinkNameOffset;
+ USHORT SymbolicLinkNameLength;
+ USHORT Reserved1;
+ ULONG UniqueIdOffset;
+ USHORT UniqueIdLength;
+ USHORT Reserved2;
+ ULONG DeviceNameOffset;
+ USHORT DeviceNameLength;
+ USHORT Reserved3;
+ } MOUNTMGR_MOUNT_POINT;
+ typedef struct
+ {
+ ULONG Size;
+ ULONG NumberOfMountPoints;
+ MOUNTMGR_MOUNT_POINT MountPoints[1];
+ } MOUNTMGR_MOUNT_POINTS;
+
+ MOUNTMGR_MOUNT_POINT *Input = 0;
+ MOUNTMGR_MOUNT_POINTS *Output = 0;
+ ULONG InputSize, OutputSize;
+ NTSTATUS Result;
+
+ InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
+ OutputSize = 4096;
+
+ Input = MemAlloc(InputSize);
+ if (0 == Input)
+ {
+ Result = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+
+ Output = MemAlloc(OutputSize);
+ if (0 == Output)
+ {
+ Result = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+
+ /* delete mount point */
+ memset(Input, 0, sizeof *Input);
+ Input->SymbolicLinkNameOffset = sizeof *Input;
+ Input->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
+ memcpy((PUINT8)Input + Input->SymbolicLinkNameOffset,
+ L"\\DosDevices\\X:", Input->SymbolicLinkNameLength);
+ ((PWCHAR)((PUINT8)Input + Input->SymbolicLinkNameOffset))[12] =
+ MountPoint->Buffer[0] & ~0x20;
+ /* convert to uppercase */
+ Result = FspMountmgrControl(
+ CTL_CODE('m', 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
+ /* IOCTL_MOUNTMGR_DELETE_POINTS */
+ Input, InputSize, Output, &OutputSize);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ MemFree(Output);
+ MemFree(Input);
+
+ return Result;
+}
+
+static VOID FspMountmgrDeleteRegistry(GUID *UniqueId)
+{
+#if defined(_KERNEL_MODE)
+ FSP_KU_CODE;
+
+ UNICODE_STRING Path;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE Handle = 0;
+ union
+ {
+ KEY_VALUE_FULL_INFORMATION V;
+ UINT8 B[FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) + 255 + sizeof *UniqueId];
+ } FullInformation;
+ ULONG FullInformationLength;
+ UNICODE_STRING ValueName;
+ NTSTATUS Result;
+
+ RtlInitUnicodeString(&Path, L"\\Registry\\Machine\\System\\MountedDevices");
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &Path,
+ OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
+ 0/*RootDirectory*/,
+ 0);
+
+ Result = ZwOpenKey(&Handle, KEY_QUERY_VALUE, &ObjectAttributes);
+ if (NT_SUCCESS(Result))
+ {
+ for (ULONG I = 0;; I++)
+ {
+ Result = ZwEnumerateValueKey(Handle,
+ I, KeyValueFullInformation, &FullInformation,
+ sizeof FullInformation, &FullInformationLength);
+ if (STATUS_NO_MORE_ENTRIES == Result)
+ break;
+ else if (!NT_SUCCESS(Result))
+ continue;
+
+ if (REG_BINARY == FullInformation.V.Type &&
+ sizeof *UniqueId == FullInformation.V.DataLength &&
+ InlineIsEqualGUID((GUID *)((PUINT8)&FullInformation.V + FullInformation.V.DataOffset),
+ UniqueId))
+ {
+ ValueName.Length = ValueName.MaximumLength = (USHORT)FullInformation.V.NameLength;
+ ValueName.Buffer = FullInformation.V.Name;
+ Result = ZwDeleteValueKey(Handle, &ValueName);
+ if (NT_SUCCESS(Result))
+ /* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
+ I = (ULONG)-1;
+ }
+ }
+
+ ZwClose(Handle);
+ }
+#else
+ HKEY RegKey;
+ LONG RegResult;
+ WCHAR RegValueName[MAX_PATH];
+ UINT8 RegValueData[sizeof *UniqueId];
+ DWORD RegValueNameSize, RegValueDataSize;
+ DWORD RegType;
+
+ RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\MountedDevices",
+ 0, KEY_READ | KEY_WRITE, &RegKey);
+ if (ERROR_SUCCESS == RegResult)
+ {
+ for (DWORD I = 0;; I++)
+ {
+ RegValueNameSize = MAX_PATH;
+ RegValueDataSize = sizeof RegValueData;
+ RegResult = RegEnumValueW(RegKey,
+ I, RegValueName, &RegValueNameSize, 0, &RegType, RegValueData, &RegValueDataSize);
+ if (ERROR_NO_MORE_ITEMS == RegResult)
+ break;
+ else if (ERROR_SUCCESS != RegResult)
+ continue;
+
+ if (REG_BINARY == RegType &&
+ sizeof RegValueData == RegValueDataSize &&
+ InlineIsEqualGUID((GUID *)&RegValueData, UniqueId))
+ {
+ RegResult = RegDeleteValueW(RegKey, RegValueName);
+ if (ERROR_SUCCESS == RegResult)
+ /* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
+ I = -1;
+ }
+ }
+
+ RegCloseKey(RegKey);
+ }
+#endif
+}
+
+NTSTATUS FspMountmgrCreateDrive(
+ PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint)
+{
+ FSP_KU_CODE;
+
+ NTSTATUS Result;
+
+ /* notify the MountManager about the new volume */
+ Result = FspMountmgrNotifyVolumeArrival(VolumeName, UniqueId);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* use the MountManager to create the drive */
+ Result = FspMountmgrCreateMountPoint(VolumeName, MountPoint);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* HACK: delete the MountManager registry entries */
+ FspMountmgrDeleteRegistry(UniqueId);
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ return Result;
+}
+
+NTSTATUS FspMountmgrDeleteDrive(
+ PUNICODE_STRING MountPoint)
+{
+ FSP_KU_CODE;
+
+ NTSTATUS Result;
+
+ /* use the MountManager to delete the drive */
+ Result = FspMountmgrDeleteMountPoint(MountPoint);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ return Result;
+}
+
+NTSTATUS FspMountmgrNotifyCreateDirectory(
+ PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint)
+{
+ FSP_KU_CODE;
+
+ NTSTATUS Result;
+
+ /* notify the MountManager about the new volume */
+ Result = FspMountmgrNotifyVolumeArrival(VolumeName, UniqueId);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* notify the MountManager about the created directory mount point */
+ Result = FspMountmgrNotifyMountPoint(VolumeName, MountPoint, TRUE);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ /* HACK: delete the MountManager registry entries */
+ FspMountmgrDeleteRegistry(UniqueId);
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ return Result;
+}
+
+NTSTATUS FspMountmgrNotifyDeleteDirectory(
+ PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint)
+{
+ FSP_KU_CODE;
+
+ /* notify the MountManager about the deleted directory mount point */
+ return FspMountmgrNotifyMountPoint(VolumeName, MountPoint, FALSE);
+}
+
+#pragma warning(pop)
diff --git a/src/sys/device.c b/src/sys/device.c
index 15cb89a3..9f0c5138 100644
--- a/src/sys/device.c
+++ b/src/sys/device.c
@@ -59,6 +59,8 @@ VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_I
BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject);
+static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject);
+static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject);
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject);
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject);
NTSTATUS FspDeviceCopyList(
@@ -84,6 +86,8 @@ VOID FspDeviceDeleteAll(VOID);
#pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName)
#pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName)
#pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName)
+#pragma alloc_text(PAGE, FspFsvrtDeviceInit)
+#pragma alloc_text(PAGE, FspFsvrtDeviceFini)
#pragma alloc_text(PAGE, FspFsmupDeviceInit)
#pragma alloc_text(PAGE, FspFsmupDeviceFini)
#pragma alloc_text(PAGE, FspDeviceCopyList)
@@ -171,7 +175,7 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject)
Result = FspFsvolDeviceInit(DeviceObject);
break;
case FspFsvrtDeviceExtensionKind:
- Result = STATUS_SUCCESS;
+ Result = FspFsvrtDeviceInit(DeviceObject);
break;
case FspFsmupDeviceExtensionKind:
Result = FspFsmupDeviceInit(DeviceObject);
@@ -202,6 +206,7 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
FspFsvolDeviceFini(DeviceObject);
break;
case FspFsvrtDeviceExtensionKind:
+ FspFsvrtDeviceFini(DeviceObject);
break;
case FspFsmupDeviceExtensionKind:
FspFsmupDeviceFini(DeviceObject);
@@ -848,6 +853,27 @@ VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject)
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
}
+static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject)
+{
+ PAGED_CODE();
+
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
+
+ ExInitializeFastMutex(&FsvrtDeviceExtension->MountMutex);
+
+ return STATUS_SUCCESS;
+}
+
+static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject)
+{
+ PAGED_CODE();
+
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
+
+ if (0 != FsvrtDeviceExtension->MountPoint.Buffer)
+ FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
+}
+
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject)
{
PAGED_CODE();
diff --git a/src/sys/driver.h b/src/sys/driver.h
index 19701468..c0e56e26 100644
--- a/src/sys/driver.h
+++ b/src/sys/driver.h
@@ -1232,13 +1232,18 @@ typedef struct
} FSP_FSVOL_DEVICE_EXTENSION;
typedef struct
{
+ /* read-only after creation (and insertion in the ContextTable) */
FSP_DEVICE_EXTENSION Base;
UINT16 SectorSize;
- LONG IsMountdev;
- BOOLEAN Persistent;
- GUID UniqueId;
UNICODE_STRING VolumeName;
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
+ FAST_MUTEX MountMutex;
+ /* interlocked access */
+ LONG IsMountdev;
+ /* protected under MountMutex */
+ BOOLEAN Persistent;
+ GUID UniqueId;
+ UNICODE_STRING MountPoint;
} FSP_FSVRT_DEVICE_EXTENSION;
typedef struct
{
@@ -1435,6 +1440,18 @@ BOOLEAN FspFsvolDeviceVolumePrefixInString(PDEVICE_OBJECT DeviceObject, PUNICODE
TRUE);
}
static inline
+VOID FspFsvrtDeviceLockMount(PDEVICE_OBJECT DeviceObject)
+{
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
+ ExAcquireFastMutexUnsafe(&FsvrtDeviceExtension->MountMutex);
+}
+static inline
+VOID FspFsvrtDeviceUnlockMount(PDEVICE_OBJECT DeviceObject)
+{
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
+ ExReleaseFastMutexUnsafe(&FsvrtDeviceExtension->MountMutex);
+}
+static inline
VOID FspFsmupDeviceLockPrefixTable(PDEVICE_OBJECT DeviceObject)
{
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
@@ -1524,6 +1541,16 @@ NTSTATUS FspMountdevMake(
VOID FspMountdevFini(
PDEVICE_OBJECT FsvrtDeviceObject);
+/* mountmgr */
+NTSTATUS FspMountmgrCreateDrive(
+ PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
+NTSTATUS FspMountmgrDeleteDrive(
+ PUNICODE_STRING MountPoint);
+NTSTATUS FspMountmgrNotifyCreateDirectory(
+ PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
+NTSTATUS FspMountmgrNotifyDeleteDirectory(
+ PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
+
/* fsmup */
NTSTATUS FspMupRegister(
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
@@ -1543,6 +1570,8 @@ NTSTATUS FspVolumeMount(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeMakeMountdev(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+NTSTATUS FspVolumeUseMountmgr(
+ PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetName(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetNameList(
diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c
index fcef99fc..cc526512 100644
--- a/src/sys/fsctl.c
+++ b/src/sys/fsctl.c
@@ -81,6 +81,10 @@ static NTSTATUS FspFsctlFileSystemControl(
if (0 != IrpSp->FileObject->FsContext2)
Result = FspVolumeMakeMountdev(FsctlDeviceObject, Irp, IrpSp);
break;
+ case FSP_FSCTL_MOUNTMGR:
+ if (0 != IrpSp->FileObject->FsContext2)
+ Result = FspVolumeUseMountmgr(FsctlDeviceObject, Irp, IrpSp);
+ break;
case FSP_FSCTL_VOLUME_NAME:
if (0 != IrpSp->FileObject->FsContext2)
Result = FspVolumeGetName(FsctlDeviceObject, Irp, IrpSp);
diff --git a/src/sys/mountdev.c b/src/sys/mountdev.c
index 4db3feb2..50fb967c 100644
--- a/src/sys/mountdev.c
+++ b/src/sys/mountdev.c
@@ -138,7 +138,7 @@ NTSTATUS FspMountdevMake(
* be mounted using the MountManager.
*
* This function requires protection against concurrency. In general this
- * is achieved by acquiring the GlobalDeviceLock.
+ * is achieved by the caller acquiring the MountMutex.
*/
PAGED_CODE();
@@ -178,11 +178,6 @@ NTSTATUS FspMountdevMake(
/* initialize the fsvrt device extension */
RtlCopyMemory(&FsvrtDeviceExtension->UniqueId, &Guid, sizeof Guid);
- RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
- FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
- RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
-
- /* mark the fsvrt device as initialized */
InterlockedIncrement(&FspFsvrtDeviceExtension(FsvrtDeviceObject)->IsMountdev);
Result = STATUS_SUCCESS;
diff --git a/src/sys/volume.c b/src/sys/volume.c
index de0f8668..f5a177fb 100644
--- a/src/sys/volume.c
+++ b/src/sys/volume.c
@@ -38,6 +38,8 @@ static NTSTATUS FspVolumeMountNoLock(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeMakeMountdev(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+NTSTATUS FspVolumeUseMountmgr(
+ PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetName(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetNameList(
@@ -76,6 +78,7 @@ NTSTATUS FspVolumeWork(
// ! #pragma alloc_text(PAGE, FspVolumeMount)
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
#pragma alloc_text(PAGE, FspVolumeMakeMountdev)
+#pragma alloc_text(PAGE, FspVolumeUseMountmgr)
#pragma alloc_text(PAGE, FspVolumeGetName)
#pragma alloc_text(PAGE, FspVolumeGetNameList)
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
@@ -316,8 +319,12 @@ static NTSTATUS FspVolumeCreateNoLock(
{
if (0 != FsvrtDeviceObject)
{
- FspFsvrtDeviceExtension(FsvrtDeviceObject)->SectorSize =
- FsvolDeviceExtension->VolumeParams.SectorSize;
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
+ FsvrtDeviceExtension->SectorSize = FsvolDeviceExtension->VolumeParams.SectorSize;
+ RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
+ FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
+ RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
+
Result = FspDeviceInitialize(FsvrtDeviceObject);
}
}
@@ -638,7 +645,7 @@ NTSTATUS FspVolumeMakeMountdev(
if (sizeof(GUID) > OutputBufferLength)
return STATUS_INVALID_PARAMETER;
- FspDeviceGlobalLock();
+ FspFsvrtDeviceLockMount(FsvrtDeviceObject);
Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
if (!NT_SUCCESS(Result))
@@ -654,7 +661,147 @@ NTSTATUS FspVolumeMakeMountdev(
Result = STATUS_SUCCESS;
exit:
- FspDeviceGlobalUnlock();
+ FspFsvrtDeviceUnlockMount(FsvrtDeviceObject);
+
+ return Result;
+}
+
+NTSTATUS FspVolumeUseMountmgr(
+ 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_MOUNTMGR == IrpSp->Parameters.FileSystemControl.FsControlCode);
+ ASSERT(0 != IrpSp->FileObject->FsContext2);
+
+ PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
+ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
+ PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
+ ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
+ NTSTATUS Result;
+
+ if (0 == FsvrtDeviceObject)
+ return STATUS_INVALID_PARAMETER; /* cannot only use fsvrt with mount manager */
+ if (1024 * sizeof(WCHAR) < InputBufferLength)
+ return STATUS_INVALID_PARAMETER; /* disallow very long paths */
+
+ FspFsvrtDeviceLockMount(FsvrtDeviceObject);
+
+ if (0 < InputBufferLength)
+ {
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
+ PWCHAR MountPointBuf = Irp->AssociatedIrp.SystemBuffer;
+ UNICODE_STRING RegPath;
+ UNICODE_STRING RegName;
+ union
+ {
+ KEY_VALUE_PARTIAL_INFORMATION V;
+ UINT8 B[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(ULONG)];
+ } RegValue;
+ ULONG RegLength;
+ BOOLEAN Persistent = FALSE;
+
+ if (!(
+ 2 * sizeof(WCHAR) <= InputBufferLength &&
+ (
+ (L'A' <= MountPointBuf[0] && MountPointBuf[0] <= L'Z') ||
+ (L'a' <= MountPointBuf[0] && MountPointBuf[0] <= L'z')
+ ) &&
+ L':' == MountPointBuf[1]
+ ))
+ {
+ Result = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (0 != FsvrtDeviceExtension->MountPoint.Buffer)
+ {
+ Result = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ RtlInitUnicodeString(&RegPath, L"" FSP_REGKEY);
+ RtlInitUnicodeString(&RegName, L"MountUseMountmgrFromFSD");
+ RegLength = sizeof RegValue;
+ Result = FspRegistryGetValue(&RegPath, &RegName, &RegValue.V, &RegLength);
+ if (!NT_SUCCESS(Result) || REG_DWORD != RegValue.V.Type || 1 != *(PULONG)&RegValue.V.Data)
+ {
+ Result = STATUS_ACCESS_DENIED;
+ goto exit;
+ }
+
+ Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
+ if (!NT_SUCCESS(Result))
+ {
+ if (STATUS_TOO_LATE != Result)
+ goto exit;
+ }
+
+ FsvrtDeviceExtension->MountPoint.Buffer = FspAllocNonPaged(InputBufferLength);
+ if (0 == FsvrtDeviceExtension->MountPoint.Buffer)
+ {
+ Result = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+ FsvrtDeviceExtension->MountPoint.Length =
+ FsvrtDeviceExtension->MountPoint.MaximumLength = (USHORT)InputBufferLength;
+ RtlCopyMemory(FsvrtDeviceExtension->MountPoint.Buffer, MountPointBuf, InputBufferLength);
+
+ if (2 * sizeof(WCHAR) == FsvrtDeviceExtension->MountPoint.Length)
+ Result = FspMountmgrCreateDrive(
+ &FsvrtDeviceExtension->VolumeName,
+ &FsvrtDeviceExtension->UniqueId,
+ &FsvrtDeviceExtension->MountPoint);
+ else
+ Result = FspMountmgrNotifyCreateDirectory(
+ &FsvrtDeviceExtension->VolumeName,
+ &FsvrtDeviceExtension->UniqueId,
+ &FsvrtDeviceExtension->MountPoint);
+ if (!NT_SUCCESS(Result))
+ {
+ FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
+ FsvrtDeviceExtension->MountPoint.Buffer = 0;
+ FsvrtDeviceExtension->MountPoint.Length =
+ FsvrtDeviceExtension->MountPoint.MaximumLength = 0;
+ goto exit;
+ }
+
+ Irp->IoStatus.Information = 0;
+ Result = STATUS_SUCCESS;
+
+ }
+ else
+ {
+ FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
+
+ if (0 == FsvrtDeviceExtension->MountPoint.Buffer)
+ {
+ Result = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ if (2 * sizeof(WCHAR) == FsvrtDeviceExtension->MountPoint.Length)
+ Result = FspMountmgrDeleteDrive(
+ &FsvrtDeviceExtension->MountPoint);
+ else
+ Result = FspMountmgrNotifyDeleteDirectory(
+ &FsvrtDeviceExtension->VolumeName,
+ &FsvrtDeviceExtension->MountPoint);
+ /* ignore Result */
+
+ FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
+ FsvrtDeviceExtension->MountPoint.Buffer = 0;
+ FsvrtDeviceExtension->MountPoint.Length =
+ FsvrtDeviceExtension->MountPoint.MaximumLength = 0;
+
+ Irp->IoStatus.Information = 0;
+ Result = STATUS_SUCCESS;
+ }
+
+exit:
+ FspFsvrtDeviceUnlockMount(FsvrtDeviceObject);
return Result;
}