sys: silo support

This commit is contained in:
Bill Zissimopoulos 2020-06-05 15:47:19 -07:00
parent 899cd5595d
commit aa3beba928
No known key found for this signature in database
GPG Key ID: 3D4F95D52C7B3EA3
7 changed files with 554 additions and 119 deletions

View File

@ -185,6 +185,7 @@
<ClCompile Include="..\..\src\sys\read.c" /> <ClCompile Include="..\..\src\sys\read.c" />
<ClCompile Include="..\..\src\sys\security.c" /> <ClCompile Include="..\..\src\sys\security.c" />
<ClCompile Include="..\..\src\sys\shutdown.c" /> <ClCompile Include="..\..\src\sys\shutdown.c" />
<ClCompile Include="..\..\src\sys\silo.c" />
<ClCompile Include="..\..\src\sys\statistics.c" /> <ClCompile Include="..\..\src\sys\statistics.c" />
<ClCompile Include="..\..\src\sys\util.c" /> <ClCompile Include="..\..\src\sys\util.c" />
<ClCompile Include="..\..\src\sys\volinfo.c" /> <ClCompile Include="..\..\src\sys\volinfo.c" />

View File

@ -122,6 +122,9 @@
<ClCompile Include="..\..\src\shared\ku\uuid5.c"> <ClCompile Include="..\..\src\shared\ku\uuid5.c">
<Filter>Source\shared\ku</Filter> <Filter>Source\shared\ku</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\sys\silo.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\sys\driver.h"> <ClInclude Include="..\..\src\sys\driver.h">

View File

@ -242,6 +242,22 @@ static NTSTATUS FspFsctlStartService(VOID)
DWORD LastError; DWORD LastError;
NTSTATUS Result; 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); ScmHandle = OpenSCManagerW(0, 0, 0);
if (0 == ScmHandle) if (0 == ScmHandle)
{ {

View File

@ -21,26 +21,16 @@
#include <sys/driver.h> #include <sys/driver.h>
/*
* 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; DRIVER_INITIALIZE DriverEntry;
static VOID FspDriverMultiVersionInitialize(VOID); static VOID FspDriverMultiVersionInitialize(VOID);
#if defined(FSP_UNLOAD) static NTSTATUS FspDriverInitializeDevices(VOID);
DRIVER_UNLOAD FspUnload; static VOID FspDriverFinalizeDevices(VOID);
#endif
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry) #pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(INIT, FspDriverMultiVersionInitialize) #pragma alloc_text(INIT, FspDriverMultiVersionInitialize)
#if defined(FSP_UNLOAD) #pragma alloc_text(PAGE, FspDriverInitializeDevices)
#pragma alloc_text(PAGE, FspUnload) #pragma alloc_text(PAGE, FspDriverFinalizeDevices)
#endif
#endif #endif
NTSTATUS DriverEntry( NTSTATUS DriverEntry(
@ -49,9 +39,6 @@ NTSTATUS DriverEntry(
FSP_ENTER_DRV(); FSP_ENTER_DRV();
/* setup the driver object */ /* setup the driver object */
#if defined(FSP_UNLOAD)
DriverObject->DriverUnload = FspUnload;
#endif
DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate; DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose;
DriverObject->MajorFunction[IRP_MJ_READ] = FspRead; DriverObject->MajorFunction[IRP_MJ_READ] = FspRead;
@ -133,94 +120,41 @@ NTSTATUS DriverEntry(
#pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch") #pragma prefast(suppress:28175, "We are a filesystem: ok to access FastIoDispatch")
DriverObject->FastIoDispatch = &FspFastIoDispatch; DriverObject->FastIoDispatch = &FspFastIoDispatch;
BOOLEAN InitDoneGRes = FALSE, InitDonePsBuf = FALSE; BOOLEAN InitDoneGRes = FALSE, InitDoneSilo = FALSE, InitDonePsBuf = FALSE,
UNICODE_STRING DeviceSddl; InitDoneDevices = FALSE;
UNICODE_STRING DeviceName;
FspDriverObject = DriverObject; FspDriverObject = DriverObject;
FspDriverMultiVersionInitialize();
ExInitializeResourceLite(&FspDeviceGlobalResource); ExInitializeResourceLite(&FspDeviceGlobalResource);
InitDoneGRes = TRUE; InitDoneGRes = TRUE;
FspDriverMultiVersionInitialize(); Result = FspSiloInitialize(FspDriverInitializeDevices, FspDriverFinalizeDevices);
if (!NT_SUCCESS(Result))
goto exit;
InitDoneSilo = TRUE;
Result = FspProcessBufferInitialize(); Result = FspProcessBufferInitialize();
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
goto exit; goto exit;
InitDonePsBuf = TRUE; InitDonePsBuf = TRUE;
/* create the file system control device objects */ Result = FspDriverInitializeDevices();
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);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
goto exit; goto exit;
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME); InitDoneDevices = TRUE;
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);
Result = STATUS_SUCCESS; Result = STATUS_SUCCESS;
exit: exit:
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
if (0 != FspFsmupDeviceObject) if (InitDoneDevices)
FspDeviceDelete(FspFsmupDeviceObject); FspDriverFinalizeDevices();
if (0 != FspFsctlNetDeviceObject)
FspDeviceDelete(FspFsctlNetDeviceObject);
if (0 != FspFsctlDiskDeviceObject)
FspDeviceDelete(FspFsctlDiskDeviceObject);
if (InitDonePsBuf) if (InitDonePsBuf)
FspProcessBufferFinalize(); FspProcessBufferFinalize();
if (InitDoneSilo)
FspSiloFinalize();
if (InitDoneGRes) if (InitDoneGRes)
ExDeleteResourceLite(&FspDeviceGlobalResource); ExDeleteResourceLite(&FspDeviceGlobalResource);
} }
@ -253,35 +187,157 @@ static VOID FspDriverMultiVersionInitialize(VOID)
FspHasReparsePointCaseSensitivityFix = TRUE; FspHasReparsePointCaseSensitivityFix = TRUE;
} }
#if defined(FSP_UNLOAD) static NTSTATUS FspDriverInitializeDevices(VOID)
VOID FspUnload(
PDRIVER_OBJECT DriverObject)
{ {
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; FspSiloGetGlobals(&Globals);
FspFsctlNetDeviceObject = 0; ASSERT(0 != Globals);
FspFsmupDeviceObject = 0;
//FspDeviceDeleteAll();
ExDeleteResourceLite(&FspDeviceGlobalResource); /* create the file system control device objects */
FspDriverObject = 0; 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(); #if DBG
/*
#pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName") * Fix GitHub issue #177. All credit for the investigation of this issue
FSP_LEAVE_VOID("DriverName=\"%wZ\"", * and the suggested steps to reproduce and work around the problem goes
&DriverObject->DriverName); * 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 #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; PDRIVER_OBJECT FspDriverObject;
PDEVICE_OBJECT FspFsctlDiskDeviceObject;
PDEVICE_OBJECT FspFsctlNetDeviceObject;
PDEVICE_OBJECT FspFsmupDeviceObject;
HANDLE FspMupHandle;
FAST_IO_DISPATCH FspFastIoDispatch; FAST_IO_DISPATCH FspFastIoDispatch;
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks; CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;

View File

@ -652,6 +652,23 @@ VOID FspIrpHookReset(PIRP Irp);
PVOID FspIrpHookContext(PVOID Context); PVOID FspIrpHookContext(PVOID Context);
NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, 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 */ /* process buffers */
#define FspProcessBufferSizeMax (64 * 1024) #define FspProcessBufferSizeMax (64 * 1024)
NTSTATUS FspProcessBufferInitialize(VOID); NTSTATUS FspProcessBufferInitialize(VOID);
@ -1069,6 +1086,7 @@ typedef struct
KSPIN_LOCK SpinLock; KSPIN_LOCK SpinLock;
LONG RefCount; LONG RefCount;
UINT32 Kind; UINT32 Kind;
GUID SiloContainerId;
} FSP_DEVICE_EXTENSION; } FSP_DEVICE_EXTENSION;
typedef struct typedef struct
{ {
@ -1695,10 +1713,6 @@ FSP_MV_CcCoherencyFlushAndPurgeCache(
/* extern */ /* extern */
extern PDRIVER_OBJECT FspDriverObject; 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 FAST_IO_DISPATCH FspFastIoDispatch;
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks; extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[]; extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];

325
src/sys/silo.c Normal file
View File

@ -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 <sys/driver.h>
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);
}

View File

@ -24,11 +24,13 @@
NTSTATUS FspVolumeCreate( NTSTATUS FspVolumeCreate(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspVolumeCreateNoLock( 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( VOID FspVolumeDelete(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static VOID FspVolumeDeleteNoLock( 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; static WORKER_THREAD_ROUTINE FspVolumeDeleteDelayed;
NTSTATUS FspVolumeMount( NTSTATUS FspVolumeMount(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
@ -77,15 +79,25 @@ NTSTATUS FspVolumeCreate(
{ {
PAGED_CODE(); PAGED_CODE();
FSP_SILO_GLOBALS *Globals;
NTSTATUS Result; NTSTATUS Result;
FspSiloGetGlobals(&Globals);
ASSERT(0 != Globals);
FspDeviceGlobalLock(); FspDeviceGlobalLock();
Result = FspVolumeCreateNoLock(FsctlDeviceObject, Irp, IrpSp); Result = FspVolumeCreateNoLock(FsctlDeviceObject, Irp, IrpSp,
Globals);
FspDeviceGlobalUnlock(); FspDeviceGlobalUnlock();
FspSiloDereferenceGlobals(Globals);
return Result; return Result;
} }
static NTSTATUS FspVolumeCreateNoLock( 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(); PAGED_CODE();
@ -302,18 +314,18 @@ static NTSTATUS FspVolumeCreateNoLock(
/* do we need to register with fsmup? */ /* do we need to register with fsmup? */
if (0 == FsvrtDeviceObject) if (0 == FsvrtDeviceObject)
{ {
Result = FspMupRegister(FspFsmupDeviceObject, FsvolDeviceObject); Result = FspMupRegister(Globals->FsmupDeviceObject, FsvolDeviceObject);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
FspDeviceDereference(FsvolDeviceObject); FspDeviceDereference(FsvolDeviceObject);
return Result; return Result;
} }
RtlInitUnicodeString(&FsmupDeviceName, L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME); RtlInitUnicodeString(&FsmupDeviceName, Globals->FsmupDeviceNameBuf);
Result = IoCreateSymbolicLink(&FsvolDeviceExtension->VolumeName, &FsmupDeviceName); Result = IoCreateSymbolicLink(&FsvolDeviceExtension->VolumeName, &FsmupDeviceName);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject); FspMupUnregister(Globals->FsmupDeviceObject, FsvolDeviceObject);
FspDeviceDereference(FsvolDeviceObject); FspDeviceDereference(FsvolDeviceObject);
return Result; return Result;
} }
@ -331,6 +343,7 @@ VOID FspVolumeDelete(
{ {
// !PAGED_CODE(); // !PAGED_CODE();
FSP_SILO_GLOBALS *Globals;
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2; PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject; PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
@ -350,10 +363,16 @@ VOID FspVolumeDelete(
FspDeviceReference(FsvolDeviceObject); FspDeviceReference(FsvolDeviceObject);
FspSiloGetGlobals(&Globals);
ASSERT(0 != Globals);
FspDeviceGlobalLock(); FspDeviceGlobalLock();
FspVolumeDeleteNoLock(FsctlDeviceObject, Irp, IrpSp); FspVolumeDeleteNoLock(FsctlDeviceObject, Irp, IrpSp,
Globals);
FspDeviceGlobalUnlock(); FspDeviceGlobalUnlock();
FspSiloDereferenceGlobals(Globals);
/* /*
* Call MmForceSectionClosed on active files to ensure that Mm removes them from Standby List. * Call MmForceSectionClosed on active files to ensure that Mm removes them from Standby List.
*/ */
@ -370,7 +389,8 @@ VOID FspVolumeDelete(
} }
static VOID FspVolumeDeleteNoLock( 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(); // !PAGED_CODE();
@ -445,7 +465,7 @@ static VOID FspVolumeDeleteNoLock(
else else
{ {
IoDeleteSymbolicLink(&FsvolDeviceExtension->VolumeName); IoDeleteSymbolicLink(&FsvolDeviceExtension->VolumeName);
FspMupUnregister(FspFsmupDeviceObject, FsvolDeviceObject); FspMupUnregister(Globals->FsmupDeviceObject, FsvolDeviceObject);
} }
/* release the volume device object */ /* release the volume device object */