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; +}