diff --git a/build/VStudio/winfsp_sys.vcxproj b/build/VStudio/winfsp_sys.vcxproj
index 62a6f886..03b7bcb6 100644
--- a/build/VStudio/winfsp_sys.vcxproj
+++ b/build/VStudio/winfsp_sys.vcxproj
@@ -260,6 +260,7 @@
+
diff --git a/build/VStudio/winfsp_sys.vcxproj.filters b/build/VStudio/winfsp_sys.vcxproj.filters
index fabab43a..96b12918 100644
--- a/build/VStudio/winfsp_sys.vcxproj.filters
+++ b/build/VStudio/winfsp_sys.vcxproj.filters
@@ -134,6 +134,9 @@
Source\shared\ku
+
+ Source
+
diff --git a/src/dll/sxs.c b/src/dll/sxs.c
index 58332826..76d01044 100644
--- a/src/dll/sxs.c
+++ b/src/dll/sxs.c
@@ -93,7 +93,7 @@ static BOOL WINAPI FspSxsIdentInitialize(
if (0 == Size)
goto exit;
- FspSxsIdentBuf[0] = L'-';
+ FspSxsIdentBuf[0] = L'+';
memcpy(FspSxsIdentBuf + 1, WBuffer, Size * sizeof(WCHAR));
FspSxsIdentBuf[1 + Size] = L'\0';
diff --git a/src/sys/driver.c b/src/sys/driver.c
index c0f615d8..1763f9b7 100644
--- a/src/sys/driver.c
+++ b/src/sys/driver.c
@@ -21,13 +21,24 @@
#include
+/*
+ * Define the following macro to include FspUnload and make the driver unloadable.
+ */
+#define FSP_UNLOAD
+
DRIVER_INITIALIZE DriverEntry;
+#if defined(FSP_UNLOAD)
+DRIVER_UNLOAD FspUnload;
+#endif
static VOID FspDriverMultiVersionInitialize(VOID);
static NTSTATUS FspDriverInitializeDevices(VOID);
static VOID FspDriverFinalizeDevices(VOID);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
+#if defined(FSP_UNLOAD)
+#pragma alloc_text(PAGE, FspUnload)
+#endif
#pragma alloc_text(INIT, FspDriverMultiVersionInitialize)
#pragma alloc_text(PAGE, FspDriverInitializeDevices)
#pragma alloc_text(PAGE, FspDriverFinalizeDevices)
@@ -40,7 +51,12 @@ NTSTATUS DriverEntry(
FSP_TRACE_INIT();
+ FspSxsIdentInitialize(&DriverObject->DriverName);
+
/* setup the driver object */
+#if defined(FSP_UNLOAD)
+ DriverObject->DriverUnload = FspUnload;
+#endif
DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose;
DriverObject->MajorFunction[IRP_MJ_READ] = FspRead;
@@ -172,6 +188,26 @@ exit:
&DriverObject->DriverName, RegistryPath);
}
+#if defined(FSP_UNLOAD)
+VOID FspUnload(
+ PDRIVER_OBJECT DriverObject)
+{
+ FSP_ENTER_VOID(PAGED_CODE());
+
+ 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);
+}
+#endif
+
static VOID FspDriverMultiVersionInitialize(VOID)
{
FspProcessorCount = KeQueryActiveProcessorCount(0);
@@ -202,6 +238,8 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
FSP_SILO_GLOBALS *Globals;
UNICODE_STRING DeviceSddl;
UNICODE_STRING DeviceName;
+ WCHAR DeviceNameBuf[128];
+ UNICODE_STRING SymlinkName;
GUID Guid;
NTSTATUS Result;
@@ -210,20 +248,46 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
/* create the file system control device objects */
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
- RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
+ 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;
- RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
+ 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);
@@ -257,8 +321,9 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
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 :
- L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ 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]);
@@ -293,11 +358,23 @@ exit:
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);
@@ -315,6 +392,7 @@ static VOID FspDriverFinalizeDevices(VOID)
PAGED_CODE();
FSP_SILO_GLOBALS *Globals;
+ UNICODE_STRING SymlinkName;
FspSiloGetGlobals(&Globals);
ASSERT(0 != Globals);
@@ -331,11 +409,23 @@ static VOID FspDriverFinalizeDevices(VOID)
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);
diff --git a/src/sys/driver.h b/src/sys/driver.h
index c0e56e26..07888662 100644
--- a/src/sys/driver.h
+++ b/src/sys/driver.h
@@ -739,6 +739,11 @@ LONG FspCompareUnicodeString(
PCUNICODE_STRING String2,
BOOLEAN CaseInsensitive);
+/* SxS */
+VOID FspSxsIdentInitialize(PUNICODE_STRING DriverName);
+PUNICODE_STRING FspSxsIdent(VOID);
+PUNICODE_STRING FspSxsSuffix(VOID);
+
/* silos */
typedef struct
{
@@ -746,7 +751,8 @@ typedef struct
PDEVICE_OBJECT FsctlNetDeviceObject;
PDEVICE_OBJECT FsmupDeviceObject;
HANDLE MupHandle;
- WCHAR FsmupDeviceNameBuf[64];
+ WCHAR FsmupDeviceNameBuf[128];
+ UINT32 InitDoneSymlinkDisk:1, InitDoneSymlinkNet:1;
} FSP_SILO_GLOBALS;
typedef NTSTATUS (*FSP_SILO_INIT_CALLBACK)(VOID);
typedef VOID (*FSP_SILO_FINI_CALLBACK)(VOID);
diff --git a/src/sys/sxs.c b/src/sys/sxs.c
new file mode 100644
index 00000000..084e6d65
--- /dev/null
+++ b/src/sys/sxs.c
@@ -0,0 +1,71 @@
+/**
+ * @file sys/sxs.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
+
+VOID FspSxsIdentInitialize(PUNICODE_STRING DriverName);
+PUNICODE_STRING FspSxsIdent(VOID);
+PUNICODE_STRING FspSxsSuffix(VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, FspSxsIdentInitialize)
+#endif
+
+static WCHAR FspSxsIdentBuf[32 + 1] = L"";
+static UNICODE_STRING FspSxsIdentStr = { 0, sizeof FspSxsIdentBuf - 1, FspSxsIdentBuf + 1 };
+static UNICODE_STRING FspSxsSuffixStr = { 0, sizeof FspSxsIdentBuf, FspSxsIdentBuf };
+
+VOID FspSxsIdentInitialize(PUNICODE_STRING DriverName)
+{
+ PWCHAR Ident = 0;
+ USHORT Length;
+
+ for (PWCHAR P = DriverName->Buffer + DriverName->Length / sizeof(WCHAR) - 1; DriverName->Buffer <= P; P--)
+ {
+ if (L'\\' == *P)
+ break;
+ if (L'+' == *P)
+ {
+ Ident = P;
+ break;
+ }
+ }
+ if (0 == Ident)
+ return;
+
+ Length = (USHORT)(((PUINT8)DriverName->Buffer + DriverName->Length) - (PUINT8)Ident);
+ if (Length > sizeof FspSxsIdentBuf)
+ Length = sizeof FspSxsIdentBuf;
+
+ RtlCopyMemory(FspSxsIdentBuf, Ident, Length);
+ FspSxsIdentStr.Length = Length - sizeof(WCHAR);
+ FspSxsSuffixStr.Length = Length;
+}
+
+PUNICODE_STRING FspSxsIdent(VOID)
+{
+ return &FspSxsIdentStr;
+}
+
+PUNICODE_STRING FspSxsSuffix(VOID)
+{
+ return &FspSxsSuffixStr;
+}