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\security.c" />
<ClCompile Include="..\..\src\sys\shutdown.c" />
<ClCompile Include="..\..\src\sys\silo.c" />
<ClCompile Include="..\..\src\sys\statistics.c" />
<ClCompile Include="..\..\src\sys\util.c" />
<ClCompile Include="..\..\src\sys\volinfo.c" />

View File

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

View File

@ -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)
{

View File

@ -21,26 +21,16 @@
#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;
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;

View File

@ -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[];

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(
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 */