From 47aa53c70aa43fa140863717a9142f840a02fa32 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 27 May 2022 18:31:36 +0100 Subject: [PATCH] dll: FspFsctlServiceVersion During file system volume creation FspFsctlCreateVolume calls FspFsctlServiceVersion which examines the version of the driver in use and initializes the variables FspFsctlTransactCode and FspFsctlTransactBatchCode with either the new FSP_IOCTL_TRANSACT* codes or the old FSP_FSCTL_TRANSACT* codes. --- src/dll/fsctl.c | 92 +++++++++++++++++++++++++++++++++++++++++++++-- src/dll/library.h | 1 + src/dll/util.c | 33 +++++++++++++++++ 3 files changed, 124 insertions(+), 2 deletions(-) diff --git a/src/dll/fsctl.c b/src/dll/fsctl.c index 2cb8930e..956c3840 100644 --- a/src/dll/fsctl.c +++ b/src/dll/fsctl.c @@ -26,6 +26,12 @@ #define PREFIXW L"" FSP_FSCTL_VOLUME_PARAMS_PREFIX #define PREFIXW_SIZE (sizeof PREFIXW - sizeof(WCHAR)) +static INIT_ONCE FspFsctlServiceVersionInitOnce = INIT_ONCE_STATIC_INIT; +static ULONG FspFsctlServiceVersionValue; +static DWORD FspFsctlTransactCode = FSP_FSCTL_TRANSACT; +static DWORD FspFsctlTransactBatchCode = FSP_FSCTL_TRANSACT_BATCH; + +static VOID FspFsctlServiceVersion(PUINT32 PVersion); static NTSTATUS FspFsctlStartService(VOID); FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath, @@ -76,6 +82,9 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath, if (!NT_SUCCESS(Result)) return Result; + /* initialize FspFsctlTransactCode */ + FspFsctlServiceVersion(0); + VolumeHandle = CreateFileW(DevicePathBuf, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (INVALID_HANDLE_VALUE == VolumeHandle) @@ -136,9 +145,15 @@ FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle, *PRequestBufSize = 0; } + /* + * During file system volume creation FspFsctlCreateVolume called FspFsctlServiceVersion + * which examined the version of the driver in use and initialized the variables + * FspFsctlTransactCode and FspFsctlTransactBatchCode with either the new + * FSP_IOCTL_TRANSACT* codes or the old FSP_FSCTL_TRANSACT* codes. + */ ControlCode = Batch ? - (DEBUGTEST(50) ? FSP_IOCTL_TRANSACT_BATCH : FSP_FSCTL_TRANSACT_BATCH) : - (DEBUGTEST(50) ? FSP_IOCTL_TRANSACT : FSP_FSCTL_TRANSACT); + (DEBUGTEST(50) ? FspFsctlTransactBatchCode : FSP_FSCTL_TRANSACT_BATCH) : + (DEBUGTEST(50) ? FspFsctlTransactCode : FSP_FSCTL_TRANSACT); if (!DeviceIoControl(VolumeHandle, ControlCode, @@ -267,6 +282,79 @@ FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath) return STATUS_SUCCESS; } +static BOOL WINAPI FspFsctlServiceVersionInitialize( + PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) +{ + PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME; + PWSTR ModuleFileName; + SC_HANDLE ScmHandle = 0; + SC_HANDLE SvcHandle = 0; + QUERY_SERVICE_CONFIGW *ServiceConfig = 0; + DWORD Size; + + ScmHandle = OpenSCManagerW(0, 0, 0); + if (0 == ScmHandle) + goto exit; + + SvcHandle = OpenServiceW(ScmHandle, DriverName, SERVICE_QUERY_CONFIG); + if (0 == SvcHandle) + goto exit; + + if (QueryServiceConfig(SvcHandle, 0, 0, &Size) || + ERROR_INSUFFICIENT_BUFFER != GetLastError()) + goto exit; + + ServiceConfig = MemAlloc(Size); + if (0 == ServiceConfig) + goto exit; + + if (!QueryServiceConfig(SvcHandle, ServiceConfig, Size, &Size)) + goto exit; + + ModuleFileName = ServiceConfig->lpBinaryPathName; + if (L'\\' == ModuleFileName[0] && + L'?' == ModuleFileName[1] && + L'?' == ModuleFileName[2] && + L'\\' == ModuleFileName[3]) + { + if (L'U' == ModuleFileName[4] && + L'N' == ModuleFileName[5] && + L'C' == ModuleFileName[6] && + L'\\' == ModuleFileName[7]) + { + ModuleFileName[6] = L'\\'; + ModuleFileName = ModuleFileName + 6; + } + else + ModuleFileName = ModuleFileName + 4; + } + + FspGetModuleVersion(ModuleFileName, &FspFsctlServiceVersionValue); + + if (0x0001000b /*v1.11*/ <= FspFsctlServiceVersionValue) + { + FspFsctlTransactCode = FSP_IOCTL_TRANSACT; + FspFsctlTransactBatchCode = FSP_IOCTL_TRANSACT_BATCH; + } + +exit: + MemFree(ServiceConfig); + if (0 != SvcHandle) + CloseServiceHandle(SvcHandle); + if (0 != ScmHandle) + CloseServiceHandle(ScmHandle); + + return TRUE; +} + +static VOID FspFsctlServiceVersion(PUINT32 PVersion) +{ + InitOnceExecuteOnce(&FspFsctlServiceVersionInitOnce, FspFsctlServiceVersionInitialize, 0, 0); + + if (0 != PVersion) + *PVersion = FspFsctlServiceVersionValue; +} + static NTSTATUS FspFsctlStartService(VOID) { static SRWLOCK Lock = SRWLOCK_INIT; diff --git a/src/dll/library.h b/src/dll/library.h index 38df10b6..0485e32e 100644 --- a/src/dll/library.h +++ b/src/dll/library.h @@ -81,6 +81,7 @@ ULONG FspLdapGetDefaultNamingContext(PVOID Ldap, PWSTR *PValue); ULONG FspLdapGetTrustPosixOffset(PVOID Ldap, PWSTR Context, PWSTR Domain, PWSTR *PValue); PWSTR FspDiagIdent(VOID); +NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion); #define FspFileSystemDirectoryBufferEntryInvalid ((ULONG)-1) VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer, diff --git a/src/dll/util.c b/src/dll/util.c index 395d488b..b08ce50e 100644 --- a/src/dll/util.c +++ b/src/dll/util.c @@ -215,3 +215,36 @@ FSP_API NTSTATUS FspVersion(PUINT32 PVersion) return STATUS_SUCCESS; } + +NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion) +{ + /* internal only: get version of any module */ + + PVOID VersionInfo; + DWORD Size; + VS_FIXEDFILEINFO *FixedFileInfo = 0; + UINT32 Version; + + *PVersion = 0; + + Size = GetFileVersionInfoSizeW(ModuleFileName, &Size/*dummy*/); + if (0 < Size) + { + VersionInfo = MemAlloc(Size); + if (0 != VersionInfo && + GetFileVersionInfoW(ModuleFileName, 0, Size, VersionInfo) && + VerQueryValueW(VersionInfo, L"\\", &FixedFileInfo, &Size)) + { + Version = FixedFileInfo->dwFileVersionMS; + } + + MemFree(VersionInfo); + } + + if (0 == FixedFileInfo) + return STATUS_UNSUCCESSFUL; + + *PVersion = Version; + + return STATUS_SUCCESS; +}