dll: FspFileSystemStopServiceIfNecessary

This commit is contained in:
Bill Zissimopoulos
2023-02-01 17:42:11 +00:00
parent da3a8aa229
commit 3aadaee511
10 changed files with 196 additions and 3 deletions

View File

@ -1883,3 +1883,12 @@ FSP_API BOOLEAN FspFileSystemAddNotifyInfo(FSP_FSCTL_NOTIFY_INFO *NotifyInfo,
{
return FspFileSystemAddXxxInfo(NotifyInfo, Buffer, Length, PBytesTransferred);
}
FSP_API VOID FspFileSystemStopServiceIfNecessary(FSP_FILE_SYSTEM *FileSystem,
BOOLEAN Normally)
{
/* NOTE: .NET calls us with a zero FileSystem pointer! */
if (Normally)
return;
FspServiceStopLoop();
}

View File

@ -2635,6 +2635,17 @@ static NTSTATUS fsp_fuse_intf_SetEa(FSP_FILE_SYSTEM *FileSystem,
&Uid, &Gid, &Mode, FileInfo);
}
static VOID fsp_fuse_intf_DispatcherStopped(FSP_FILE_SYSTEM *FileSystem,
BOOLEAN Normally)
{
if (Normally)
return;
struct fuse *f = FileSystem->UserContext;
fsp_fuse_exit(f->env, f);
}
FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
{
fsp_fuse_intf_GetVolumeInfo,
@ -2668,6 +2679,8 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
fsp_fuse_intf_Overwrite,
fsp_fuse_intf_GetEa,
fsp_fuse_intf_SetEa,
0,
fsp_fuse_intf_DispatcherStopped,
};
/*

View File

@ -110,6 +110,7 @@ NTSTATUS FspGetModuleFileName(
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
PUINT8 *PBuffer, PULONG *PIndex, PULONG PCount);
VOID FspServiceStopLoop(VOID);
BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType);
static inline ULONG FspPathSuffixIndex(PWSTR FileName)

View File

@ -40,6 +40,8 @@ enum
GetStatus_WaitHint = 0x4000,
};
static SRWLOCK FspServiceLoopLock = SRWLOCK_INIT;
static SRWLOCK FspServiceTableLock = SRWLOCK_INIT;
static SERVICE_TABLE_ENTRYW *FspServiceTable;
static HANDLE FspServiceConsoleModeEvent;
static UINT32 FspServiceConsoleCtrlHandlerDisabled;
@ -220,6 +222,14 @@ FSP_API ULONG FspServiceGetExitCode(FSP_SERVICE *Service)
FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
{
/*
* FspServiceLoop can only be called once per process, because of StartServiceCtrlDispatcherW
* (which returns ERROR_SERVICE_ALREADY_RUNNING if called more than once). Unfortunately this
* limitation was never documented and there may be users of FspServiceLoop out there that call
* it more than once per process.
*/
AcquireSRWLockExclusive(&FspServiceLoopLock);
NTSTATUS Result;
SERVICE_TABLE_ENTRYW ServiceTable[2];
@ -236,7 +246,9 @@ FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
ServiceTable[0].lpServiceProc = FspServiceEntry;
ServiceTable[1].lpServiceName = 0;
ServiceTable[1].lpServiceProc = 0;
AcquireSRWLockExclusive(&FspServiceTableLock);
FspServiceTable = ServiceTable;
ReleaseSRWLockExclusive(&FspServiceTableLock);
if (!StartServiceCtrlDispatcherW(ServiceTable))
{
@ -331,11 +343,42 @@ FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
Result = STATUS_SUCCESS;
exit:
AcquireSRWLockExclusive(&FspServiceTableLock);
FspServiceTable = 0;
ReleaseSRWLockExclusive(&FspServiceTableLock);
ReleaseSRWLockExclusive(&FspServiceLoopLock);
return Result;
}
static DWORD WINAPI FspServiceStopLoopThread(PVOID Context);
VOID FspServiceStopLoop(VOID)
{
BOOLEAN HasService;
HANDLE Thread;
AcquireSRWLockShared(&FspServiceTableLock);
HasService = 0 != FspServiceFromTable();
ReleaseSRWLockShared(&FspServiceTableLock);
if (HasService)
{
Thread = CreateThread(0, 0, FspServiceStopLoopThread, 0, 0, 0);
if (0 != Thread)
CloseHandle(Thread);
}
}
static DWORD WINAPI FspServiceStopLoopThread(PVOID Context)
{
AcquireSRWLockShared(&FspServiceTableLock);
FSP_SERVICE *Service = FspServiceFromTable();
if (0 != Service)
FspServiceStop(Service);
ReleaseSRWLockShared(&FspServiceTableLock);
return 0;
}
FSP_API VOID FspServiceStop(FSP_SERVICE *Service)
{
SERVICE_STATUS ServiceStatus;
@ -393,6 +436,7 @@ static VOID WINAPI FspServiceEntry(DWORD Argc, PWSTR *Argv)
FSP_SERVICE *Service;
Service = FspServiceFromTable();
/* we are subordinate to FspServiceLoop; no need to protect this access with FspServiceTableLock */
if (0 == Service)
{
FspServiceLog(EVENTLOG_ERROR_TYPE,
@ -501,6 +545,7 @@ static DWORD WINAPI FspServiceConsoleModeThread(PVOID Context)
;
Service = FspServiceFromTable();
/* we are subordinate to FspServiceLoop; no need to protect this access with FspServiceTableLock */
if (0 == Service)
FspServiceLog(EVENTLOG_ERROR_TYPE,
L"" __FUNCTION__ ": internal error: FspServiceFromTable = 0");