diff --git a/build/VStudio/winfsp_sys.vcxproj b/build/VStudio/winfsp_sys.vcxproj
index b9c9b249..8843ec77 100644
--- a/build/VStudio/winfsp_sys.vcxproj
+++ b/build/VStudio/winfsp_sys.vcxproj
@@ -185,6 +185,7 @@
+
diff --git a/build/VStudio/winfsp_sys.vcxproj.filters b/build/VStudio/winfsp_sys.vcxproj.filters
index f8e5bfe7..7ee41c66 100644
--- a/build/VStudio/winfsp_sys.vcxproj.filters
+++ b/build/VStudio/winfsp_sys.vcxproj.filters
@@ -122,6 +122,9 @@
Source\shared\ku
+
+ Source
+
diff --git a/src/dll/fsctl.c b/src/dll/fsctl.c
index 4a64899d..c5023815 100644
--- a/src/dll/fsctl.c
+++ b/src/dll/fsctl.c
@@ -242,6 +242,22 @@ static NTSTATUS FspFsctlStartService(VOID)
DWORD LastError;
NTSTATUS Result;
+ /* Determine if we are running inside container.
+ *
+ * See https://github.com/microsoft/perfview/blob/V1.9.65/src/TraceEvent/TraceEventSession.cs#L525
+ * See https://stackoverflow.com/a/50748300
+ */
+ LastError = RegGetValueW(
+ HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control",
+ L"ContainerType",
+ RRF_RT_REG_DWORD, 0,
+ 0, 0);
+ if (ERROR_SUCCESS == LastError)
+ {
+ Result = STATUS_SUCCESS;
+ goto exit;
+ }
+
ScmHandle = OpenSCManagerW(0, 0, 0);
if (0 == ScmHandle)
{
diff --git a/src/sys/driver.c b/src/sys/driver.c
index f430deb8..a03c385a 100644
--- a/src/sys/driver.c
+++ b/src/sys/driver.c
@@ -21,26 +21,16 @@
#include
-/*
- * Define the following macro to include FspUnload.
- *
- * Note that this driver is no longer unloadable.
- * See the comments in DriverEntry as to why!
- */
-//#define FSP_UNLOAD
-
DRIVER_INITIALIZE DriverEntry;
static VOID FspDriverMultiVersionInitialize(VOID);
-#if defined(FSP_UNLOAD)
-DRIVER_UNLOAD FspUnload;
-#endif
+static NTSTATUS FspDriverInitializeDevices(VOID);
+static VOID FspDriverFinalizeDevices(VOID);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(INIT, FspDriverMultiVersionInitialize)
-#if defined(FSP_UNLOAD)
-#pragma alloc_text(PAGE, FspUnload)
-#endif
+#pragma alloc_text(PAGE, FspDriverInitializeDevices)
+#pragma alloc_text(PAGE, FspDriverFinalizeDevices)
#endif
NTSTATUS DriverEntry(
@@ -49,9 +39,6 @@ NTSTATUS DriverEntry(
FSP_ENTER_DRV();
/* 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;
@@ -133,94 +120,41 @@ NTSTATUS DriverEntry(
#pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch")
DriverObject->FastIoDispatch = &FspFastIoDispatch;
- BOOLEAN InitDoneGRes = FALSE, InitDonePsBuf = FALSE;
- UNICODE_STRING DeviceSddl;
- UNICODE_STRING DeviceName;
+ BOOLEAN InitDoneGRes = FALSE, InitDoneSilo = FALSE, InitDonePsBuf = FALSE,
+ InitDoneDevices = FALSE;
FspDriverObject = DriverObject;
+ FspDriverMultiVersionInitialize();
+
ExInitializeResourceLite(&FspDeviceGlobalResource);
InitDoneGRes = TRUE;
- FspDriverMultiVersionInitialize();
+ Result = FspSiloInitialize(FspDriverInitializeDevices, FspDriverFinalizeDevices);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+ InitDoneSilo = TRUE;
Result = FspProcessBufferInitialize();
if (!NT_SUCCESS(Result))
goto exit;
InitDonePsBuf = TRUE;
- /* create the file system control device objects */
- RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
- RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
- Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
- &DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
- &DeviceSddl, &FspFsctlDeviceClassGuid,
- &FspFsctlDiskDeviceObject);
+ Result = FspDriverInitializeDevices();
if (!NT_SUCCESS(Result))
goto exit;
- RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
- Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
- &DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
- &DeviceSddl, &FspFsctlDeviceClassGuid,
- &FspFsctlNetDeviceObject);
- if (!NT_SUCCESS(Result))
- goto exit;
- Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0,
- FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE,
- &FspFsmupDeviceObject);
- 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(FspFsctlDiskDeviceObject->Flags, DO_LOW_PRIORITY_FILESYSTEM);
-#endif
-
- Result = FspDeviceInitialize(FspFsctlDiskDeviceObject);
- ASSERT(STATUS_SUCCESS == Result);
- Result = FspDeviceInitialize(FspFsctlNetDeviceObject);
- ASSERT(STATUS_SUCCESS == Result);
- Result = FspDeviceInitialize(FspFsmupDeviceObject);
- ASSERT(STATUS_SUCCESS == Result);
-
- RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
- Result = FsRtlRegisterUncProviderEx(&FspMupHandle,
- &DeviceName, FspFsmupDeviceObject, 0);
- if (!NT_SUCCESS(Result))
- 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.
- *
- * Please note that the call below makes our driver unloadable. In fact the driver
- * remains unloadable even if we issue an IoUnregisterFileSystem() call immediately
- * after our IoRegisterFileSystem() call! Some system component appears to keep an
- * extra reference to our device somewhere.
- */
- IoRegisterFileSystem(FspFsctlDiskDeviceObject);
+ InitDoneDevices = TRUE;
Result = STATUS_SUCCESS;
exit:
if (!NT_SUCCESS(Result))
{
- if (0 != FspFsmupDeviceObject)
- FspDeviceDelete(FspFsmupDeviceObject);
- if (0 != FspFsctlNetDeviceObject)
- FspDeviceDelete(FspFsctlNetDeviceObject);
- if (0 != FspFsctlDiskDeviceObject)
- FspDeviceDelete(FspFsctlDiskDeviceObject);
+ if (InitDoneDevices)
+ FspDriverFinalizeDevices();
if (InitDonePsBuf)
FspProcessBufferFinalize();
+ if (InitDoneSilo)
+ FspSiloFinalize();
if (InitDoneGRes)
ExDeleteResourceLite(&FspDeviceGlobalResource);
}
@@ -253,35 +187,157 @@ static VOID FspDriverMultiVersionInitialize(VOID)
FspHasReparsePointCaseSensitivityFix = TRUE;
}
-#if defined(FSP_UNLOAD)
-VOID FspUnload(
- PDRIVER_OBJECT DriverObject)
+static NTSTATUS FspDriverInitializeDevices(VOID)
{
- FSP_ENTER_VOID(PAGED_CODE());
+ PAGED_CODE();
- FsRtlDeregisterUncProvider(FspMupHandle);
+ FSP_SILO_GLOBALS *Globals;
+ UNICODE_STRING DeviceSddl;
+ UNICODE_STRING DeviceName;
+ GUID Guid;
+ NTSTATUS Result;
- FspFsctlDiskDeviceObject = 0;
- FspFsctlNetDeviceObject = 0;
- FspFsmupDeviceObject = 0;
- //FspDeviceDeleteAll();
+ FspSiloGetGlobals(&Globals);
+ ASSERT(0 != Globals);
- ExDeleteResourceLite(&FspDeviceGlobalResource);
- FspDriverObject = 0;
+ /* create the file system control device objects */
+ RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
+ RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
+ 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);
+ Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
+ &DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
+ &DeviceSddl, &FspFsctlDeviceClassGuid,
+ &Globals->FsctlNetDeviceObject);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+ Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0,
+ FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE,
+ &Globals->FsmupDeviceObject);
+ if (!NT_SUCCESS(Result))
+ goto exit;
- FspProcessBufferFinalize();
-
-#pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName")
- FSP_LEAVE_VOID("DriverName=\"%wZ\"",
- &DriverObject->DriverName);
-}
+#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 :
+ L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ 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);
+
+ Result = STATUS_SUCCESS;
+
+exit:
+ if (!NT_SUCCESS(Result))
+ {
+ if (0 != Globals->MupHandle)
+ {
+ FsRtlDeregisterUncProvider(Globals->MupHandle);
+ Globals->MupHandle = 0;
+ }
+ if (0 != Globals->FsmupDeviceObject)
+ {
+ FspDeviceDelete(Globals->FsmupDeviceObject);
+ Globals->FsmupDeviceObject = 0;
+ }
+ if (0 != Globals->FsctlNetDeviceObject)
+ {
+ FspDeviceDelete(Globals->FsctlNetDeviceObject);
+ Globals->FsctlNetDeviceObject = 0;
+ }
+ if (0 != Globals->FsctlDiskDeviceObject)
+ {
+ FspDeviceDelete(Globals->FsctlDiskDeviceObject);
+ Globals->FsctlDiskDeviceObject = 0;
+ }
+ }
+
+ FspSiloDereferenceGlobals(Globals);
+
+ return Result;
+}
+
+static VOID FspDriverFinalizeDevices(VOID)
+{
+ PAGED_CODE();
+
+ FSP_SILO_GLOBALS *Globals;
+
+ FspSiloGetGlobals(&Globals);
+ ASSERT(0 != Globals);
+
+ IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
+
+ if (0 != Globals->MupHandle)
+ {
+ FsRtlDeregisterUncProvider(Globals->MupHandle);
+ Globals->MupHandle = 0;
+ }
+ if (0 != Globals->FsmupDeviceObject)
+ {
+ FspDeviceDelete(Globals->FsmupDeviceObject);
+ Globals->FsmupDeviceObject = 0;
+ }
+ if (0 != Globals->FsctlNetDeviceObject)
+ {
+ FspDeviceDelete(Globals->FsctlNetDeviceObject);
+ Globals->FsctlNetDeviceObject = 0;
+ }
+ if (0 != Globals->FsctlDiskDeviceObject)
+ {
+ FspDeviceDelete(Globals->FsctlDiskDeviceObject);
+ Globals->FsctlDiskDeviceObject = 0;
+ }
+
+ FspSiloDereferenceGlobals(Globals);
+}
+
PDRIVER_OBJECT FspDriverObject;
-PDEVICE_OBJECT FspFsctlDiskDeviceObject;
-PDEVICE_OBJECT FspFsctlNetDeviceObject;
-PDEVICE_OBJECT FspFsmupDeviceObject;
-HANDLE FspMupHandle;
FAST_IO_DISPATCH FspFastIoDispatch;
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
diff --git a/src/sys/driver.h b/src/sys/driver.h
index 2eaee33f..9391541a 100644
--- a/src/sys/driver.h
+++ b/src/sys/driver.h
@@ -652,6 +652,23 @@ VOID FspIrpHookReset(PIRP Irp);
PVOID FspIrpHookContext(PVOID Context);
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
+/* silos */
+typedef struct
+{
+ PDEVICE_OBJECT FsctlDiskDeviceObject;
+ PDEVICE_OBJECT FsctlNetDeviceObject;
+ PDEVICE_OBJECT FsmupDeviceObject;
+ HANDLE MupHandle;
+ WCHAR FsmupDeviceNameBuf[64];
+} FSP_SILO_GLOBALS;
+typedef NTSTATUS (*FSP_SILO_INIT_CALLBACK)(VOID);
+typedef VOID (*FSP_SILO_FINI_CALLBACK)(VOID);
+NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals);
+VOID FspSiloDereferenceGlobals(FSP_SILO_GLOBALS *Globals);
+VOID FspSiloGetContainerId(GUID *ContainerId);
+NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
+VOID FspSiloFinalize(VOID);
+
/* process buffers */
#define FspProcessBufferSizeMax (64 * 1024)
NTSTATUS FspProcessBufferInitialize(VOID);
@@ -1069,6 +1086,7 @@ typedef struct
KSPIN_LOCK SpinLock;
LONG RefCount;
UINT32 Kind;
+ GUID SiloContainerId;
} FSP_DEVICE_EXTENSION;
typedef struct
{
@@ -1695,10 +1713,6 @@ FSP_MV_CcCoherencyFlushAndPurgeCache(
/* extern */
extern PDRIVER_OBJECT FspDriverObject;
-extern PDEVICE_OBJECT FspFsctlDiskDeviceObject;
-extern PDEVICE_OBJECT FspFsctlNetDeviceObject;
-extern PDEVICE_OBJECT FspFsmupDeviceObject;
-extern HANDLE FspMupHandle;
extern FAST_IO_DISPATCH FspFastIoDispatch;
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
diff --git a/src/sys/silo.c b/src/sys/silo.c
new file mode 100644
index 00000000..d266aa60
--- /dev/null
+++ b/src/sys/silo.c
@@ -0,0 +1,325 @@
+/**
+ * @file sys/silo.c
+ *
+ * @copyright 2015-2020 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
+
+NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, FspSiloInitialize)
+#endif
+
+typedef PEJOB FSP_PESILO;
+typedef PVOID FSP_PSILO_MONITOR;
+
+typedef NTSTATUS (NTAPI *FSP_SILO_MONITOR_CREATE_CALLBACK)(FSP_PESILO Silo);
+typedef VOID (NTAPI *FSP_SILO_MONITOR_TERMINATE_CALLBACK)(FSP_PESILO Silo);
+typedef VOID (NTAPI *FSP_SILO_CONTEXT_CLEANUP_CALLBACK)(PVOID SiloContext);
+
+#pragma warning(push)
+#pragma warning(disable:4201) /* nameless struct/union */
+typedef struct _FSP_SILO_MONITOR_REGISTRATION
+{
+ UCHAR Version;
+ BOOLEAN MonitorHost;
+ BOOLEAN MonitorExistingSilos;
+ UCHAR Reserved[5];
+ union
+ {
+ PUNICODE_STRING DriverObjectName;
+ PUNICODE_STRING ComponentName;
+ };
+ FSP_SILO_MONITOR_CREATE_CALLBACK CreateCallback;
+ FSP_SILO_MONITOR_TERMINATE_CALLBACK TerminateCallback;
+} FSP_SILO_MONITOR_REGISTRATION;
+#pragma warning(pop)
+
+typedef NTSTATUS FSP_SILO_PsRegisterSiloMonitor(
+ FSP_SILO_MONITOR_REGISTRATION *Registration,
+ FSP_PSILO_MONITOR *ReturnedMonitor);
+typedef NTSTATUS FSP_SILO_PsStartSiloMonitor(
+ FSP_PSILO_MONITOR Monitor);
+typedef VOID FSP_SILO_PsUnregisterSiloMonitor(
+ FSP_PSILO_MONITOR Monitor);
+typedef ULONG FSP_SILO_PsGetSiloMonitorContextSlot(
+ FSP_PSILO_MONITOR Monitor);
+typedef NTSTATUS FSP_SILO_PsCreateSiloContext(
+ FSP_PESILO Silo,
+ ULONG Size,
+ POOL_TYPE PoolType,
+ FSP_SILO_CONTEXT_CLEANUP_CALLBACK ContextCleanupCallback,
+ PVOID *ReturnedSiloContext);
+typedef VOID FSP_SILO_PsDereferenceSiloContext(
+ PVOID SiloContext);
+typedef NTSTATUS FSP_SILO_PsInsertSiloContext(
+ FSP_PESILO Silo,
+ ULONG ContextSlot,
+ PVOID SiloContext);
+typedef NTSTATUS FSP_SILO_PsRemoveSiloContext(
+ FSP_PESILO Silo,
+ ULONG ContextSlot,
+ PVOID *RemovedSiloContext);
+typedef NTSTATUS FSP_SILO_PsGetSiloContext(
+ FSP_PESILO Silo,
+ ULONG ContextSlot,
+ PVOID *ReturnedSiloContext);
+typedef FSP_PESILO FSP_SILO_PsAttachSiloToCurrentThread(
+ FSP_PESILO Silo);
+typedef VOID FSP_SILO_PsDetachSiloFromCurrentThread(
+ FSP_PESILO PreviousSilo);
+typedef FSP_PESILO FSP_SILO_PsGetCurrentServerSilo(
+ VOID);
+typedef GUID* FSP_SILO_PsGetSiloContainerId(
+ FSP_PESILO Silo);
+
+static FSP_SILO_PsRegisterSiloMonitor *FspSiloPsRegisterSiloMonitor;
+static FSP_SILO_PsStartSiloMonitor *FspSiloPsStartSiloMonitor;
+static FSP_SILO_PsUnregisterSiloMonitor *FspSiloPsUnregisterSiloMonitor;
+static FSP_SILO_PsGetSiloMonitorContextSlot *FspSiloPsGetSiloMonitorContextSlot;
+static FSP_SILO_PsCreateSiloContext *FspSiloPsCreateSiloContext;
+static FSP_SILO_PsDereferenceSiloContext *FspSiloPsDereferenceSiloContext;
+static FSP_SILO_PsInsertSiloContext *FspSiloPsInsertSiloContext;
+static FSP_SILO_PsRemoveSiloContext *FspSiloPsRemoveSiloContext;
+static FSP_SILO_PsGetSiloContext *FspSiloPsGetSiloContext;
+static FSP_SILO_PsAttachSiloToCurrentThread *FspSiloPsAttachSiloToCurrentThread;
+static FSP_SILO_PsDetachSiloFromCurrentThread *FspSiloPsDetachSiloFromCurrentThread;
+static FSP_SILO_PsGetCurrentServerSilo *FspSiloPsGetCurrentServerSilo;
+static FSP_SILO_PsGetSiloContainerId *FspSiloPsGetSiloContainerId;
+static FSP_PSILO_MONITOR FspSiloMonitor;
+static FSP_SILO_INIT_CALLBACK FspSiloInitCallback;
+static FSP_SILO_FINI_CALLBACK FspSiloFiniCallback;
+static BOOLEAN FspSiloInitDone = FALSE;
+
+static FSP_SILO_GLOBALS FspSiloHostGlobals;
+
+#define FSP_SILO_MONITOR_REGISTRATION_VERSION 1
+
+#define LOAD(n) \
+ { \
+ UNICODE_STRING Name; \
+ RtlInitUnicodeString(&Name, L"" #n);\
+ FspSilo ## n = \
+ (FSP_SILO_ ## n *)(UINT_PTR)MmGetSystemRoutineAddress(&Name);\
+ if (0 == FspSilo ## n) \
+ Fail++; \
+ }
+#define CALL(n) (FspSilo ## n)
+
+NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals)
+{
+ FSP_PESILO Silo;
+ ULONG ContextSlot;
+ FSP_SILO_GLOBALS *Globals;
+ NTSTATUS Result;
+
+ if (!FspSiloInitDone ||
+ 0 == (Silo = CALL(PsGetCurrentServerSilo)()))
+ {
+ *PGlobals = &FspSiloHostGlobals;
+ return STATUS_SUCCESS;
+ }
+
+ ContextSlot = CALL(PsGetSiloMonitorContextSlot)(FspSiloMonitor);
+
+ Result = CALL(PsGetSiloContext)(Silo, ContextSlot, &Globals);
+ if (!NT_SUCCESS(Result))
+ {
+ *PGlobals = 0;
+ return Result;
+ }
+
+ *PGlobals = Globals;
+ return STATUS_SUCCESS;
+}
+
+VOID FspSiloDereferenceGlobals(FSP_SILO_GLOBALS *Globals)
+{
+ if (&FspSiloHostGlobals == Globals)
+ return;
+
+ CALL(PsDereferenceSiloContext)(Globals);
+}
+
+VOID FspSiloGetContainerId(GUID *ContainerId)
+{
+ FSP_PESILO Silo;
+ GUID *Guid;
+
+ if (!FspSiloInitDone ||
+ 0 == (Silo = CALL(PsGetCurrentServerSilo)()) ||
+ 0 == (Guid = CALL(PsGetSiloContainerId)(Silo)))
+ {
+ RtlZeroMemory(ContainerId, sizeof *ContainerId);
+ return;
+ }
+
+ RtlCopyMemory(ContainerId, Guid, sizeof *ContainerId);
+}
+
+static NTSTATUS NTAPI FspSiloMonitorCreateCallback(FSP_PESILO Silo)
+{
+ ULONG ContextSlot;
+ FSP_SILO_GLOBALS *Globals = 0;
+ BOOLEAN Inserted = FALSE;
+ NTSTATUS Result;
+
+ ASSERT(0 != Silo);
+
+ ContextSlot = CALL(PsGetSiloMonitorContextSlot)(FspSiloMonitor);
+
+ Result = CALL(PsCreateSiloContext)(Silo, sizeof(FSP_SILO_GLOBALS), NonPagedPoolNx, 0, &Globals);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+ RtlZeroMemory(Globals, sizeof(FSP_SILO_GLOBALS));
+
+ /* PsInsertSiloContext adds reference to Globals */
+ Result = CALL(PsInsertSiloContext)(Silo, ContextSlot, Globals);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+ Inserted = TRUE;
+
+ if (0 != FspSiloInitCallback)
+ {
+ FSP_PESILO PreviousSilo = CALL(PsAttachSiloToCurrentThread)(Silo);
+ Result = FspSiloInitCallback();
+ CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
+ }
+
+exit:
+ if (!NT_SUCCESS(Result))
+ {
+ if (Inserted)
+ CALL(PsRemoveSiloContext)(Silo, ContextSlot, 0);
+ }
+
+ if (0 != Globals)
+ CALL(PsDereferenceSiloContext)(Globals);
+
+ /*
+ * Ignore errors and return success. There are two reasons for this:
+ *
+ * - Returning an error will disallow container creation.
+ * - In some cases returning an error will crash Windows with an
+ * unexpected page fault in wcifs.sys.
+ */
+ return STATUS_SUCCESS;
+}
+
+static VOID NTAPI FspSiloMonitorTerminateCallback(FSP_PESILO Silo)
+{
+ ULONG ContextSlot;
+ FSP_SILO_GLOBALS *Globals;
+ NTSTATUS Result;
+
+ ASSERT(0 != Silo);
+
+ ContextSlot = CALL(PsGetSiloMonitorContextSlot)(FspSiloMonitor);
+
+ /* if we cannot get the Globals, it must mean that we failed in Create callback */
+ Result = CALL(PsGetSiloContext)(Silo, ContextSlot, &Globals);
+ if (!NT_SUCCESS(Result))
+ return;
+ CALL(PsDereferenceSiloContext)(Globals);
+ Globals = 0;
+
+ if (0 != FspSiloFiniCallback)
+ {
+ FSP_PESILO PreviousSilo = CALL(PsAttachSiloToCurrentThread)(Silo);
+ FspSiloFiniCallback();
+ CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
+ }
+
+ /* PsRemoveSiloContext removes reference to Globals (possibly freeing it) */
+ CALL(PsRemoveSiloContext)(Silo, ContextSlot, 0);
+}
+
+NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini)
+{
+ NTSTATUS Result = STATUS_SUCCESS;
+
+ if (FspIsNtDdiVersionAvailable(NTDDI_WIN10_RS5))
+ {
+ ULONG Fail = 0;
+
+ LOAD(PsRegisterSiloMonitor);
+ LOAD(PsStartSiloMonitor);
+ LOAD(PsUnregisterSiloMonitor);
+ LOAD(PsGetSiloMonitorContextSlot);
+ LOAD(PsCreateSiloContext);
+ LOAD(PsDereferenceSiloContext);
+ LOAD(PsInsertSiloContext);
+ LOAD(PsRemoveSiloContext);
+ LOAD(PsGetSiloContext);
+ LOAD(PsAttachSiloToCurrentThread);
+ LOAD(PsDetachSiloFromCurrentThread);
+ LOAD(PsGetCurrentServerSilo);
+ LOAD(PsGetSiloContainerId);
+
+ if (0 == Fail)
+ {
+ FSP_SILO_MONITOR_REGISTRATION Registration =
+ {
+ .Version = FSP_SILO_MONITOR_REGISTRATION_VERSION,
+ .MonitorHost = FALSE,
+ .MonitorExistingSilos = TRUE,
+ .DriverObjectName = 0,
+ .CreateCallback = FspSiloMonitorCreateCallback,
+ .TerminateCallback = FspSiloMonitorTerminateCallback,
+ };
+ FSP_PSILO_MONITOR Monitor = 0;
+ UNICODE_STRING DriverName;
+
+ RtlInitUnicodeString(&DriverName, L"" DRIVER_NAME);
+ Registration.DriverObjectName = &DriverName;
+ Result = CALL(PsRegisterSiloMonitor)(&Registration, &Monitor);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ Result = CALL(PsStartSiloMonitor)(Monitor);
+ if (!NT_SUCCESS(Result))
+ goto exit;
+
+ FspSiloMonitor = Monitor;
+ FspSiloInitCallback = Init;
+ FspSiloFiniCallback = Fini;
+
+ FspSiloInitDone = TRUE;
+ Result = STATUS_SUCCESS;
+
+ exit:
+ if (!NT_SUCCESS(Result))
+ {
+ if (0 != Monitor)
+ CALL(PsUnregisterSiloMonitor)(Monitor);
+ }
+ }
+ }
+
+ return Result;
+}
+
+VOID FspSiloFinalize(VOID)
+{
+ if (!FspSiloInitDone)
+ return;
+
+ CALL(PsUnregisterSiloMonitor)(FspSiloMonitor);
+}
diff --git a/src/sys/volume.c b/src/sys/volume.c
index 06784a4b..2017432e 100644
--- a/src/sys/volume.c
+++ b/src/sys/volume.c
@@ -24,11 +24,13 @@
NTSTATUS FspVolumeCreate(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspVolumeCreateNoLock(
- PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+ PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
+ FSP_SILO_GLOBALS *Globals);
VOID FspVolumeDelete(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static VOID FspVolumeDeleteNoLock(
- PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
+ PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
+ FSP_SILO_GLOBALS *Globals);
static WORKER_THREAD_ROUTINE FspVolumeDeleteDelayed;
NTSTATUS FspVolumeMount(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
@@ -77,15 +79,25 @@ NTSTATUS FspVolumeCreate(
{
PAGED_CODE();
+ FSP_SILO_GLOBALS *Globals;
NTSTATUS Result;
+
+ FspSiloGetGlobals(&Globals);
+ ASSERT(0 != Globals);
+
FspDeviceGlobalLock();
- Result = FspVolumeCreateNoLock(FsctlDeviceObject, Irp, IrpSp);
+ Result = FspVolumeCreateNoLock(FsctlDeviceObject, Irp, IrpSp,
+ Globals);
FspDeviceGlobalUnlock();
+
+ FspSiloDereferenceGlobals(Globals);
+
return Result;
}
static NTSTATUS FspVolumeCreateNoLock(
- PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+ PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
+ FSP_SILO_GLOBALS *Globals)
{
PAGED_CODE();
@@ -302,18 +314,18 @@ static NTSTATUS FspVolumeCreateNoLock(
/* do we need to register with fsmup? */
if (0 == FsvrtDeviceObject)
{
- Result = FspMupRegister(FspFsmupDeviceObject, FsvolDeviceObject);
+ Result = FspMupRegister(Globals->FsmupDeviceObject, FsvolDeviceObject);
if (!NT_SUCCESS(Result))
{
FspDeviceDereference(FsvolDeviceObject);
return Result;
}
- RtlInitUnicodeString(&FsmupDeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME);
+ RtlInitUnicodeString(&FsmupDeviceName, Globals->FsmupDeviceNameBuf);
Result = IoCreateSymbolicLink(&FsvolDeviceExtension->VolumeName, &FsmupDeviceName);
if (!NT_SUCCESS(Result))
{
- FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject);
+ FspMupUnregister(Globals->FsmupDeviceObject, FsvolDeviceObject);
FspDeviceDereference(FsvolDeviceObject);
return Result;
}
@@ -331,6 +343,7 @@ VOID FspVolumeDelete(
{
// !PAGED_CODE();
+ FSP_SILO_GLOBALS *Globals;
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
@@ -350,10 +363,16 @@ VOID FspVolumeDelete(
FspDeviceReference(FsvolDeviceObject);
+ FspSiloGetGlobals(&Globals);
+ ASSERT(0 != Globals);
+
FspDeviceGlobalLock();
- FspVolumeDeleteNoLock(FsctlDeviceObject, Irp, IrpSp);
+ FspVolumeDeleteNoLock(FsctlDeviceObject, Irp, IrpSp,
+ Globals);
FspDeviceGlobalUnlock();
+ FspSiloDereferenceGlobals(Globals);
+
/*
* Call MmForceSectionClosed on active files to ensure that Mm removes them from Standby List.
*/
@@ -370,7 +389,8 @@ VOID FspVolumeDelete(
}
static VOID FspVolumeDeleteNoLock(
- PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
+ PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
+ FSP_SILO_GLOBALS *Globals)
{
// !PAGED_CODE();
@@ -445,7 +465,7 @@ static VOID FspVolumeDeleteNoLock(
else
{
IoDeleteSymbolicLink(&FsvolDeviceExtension->VolumeName);
- FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject);
+ FspMupUnregister(Globals->FsmupDeviceObject, FsvolDeviceObject);
}
/* release the volume device object */