From cc58668ce53244bc56f6a1f759d57d28d1360c7d Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 9 Jan 2018 22:17:07 -0800 Subject: [PATCH] dll: FspLaunchReg*: testing --- build/VStudio/testing/winfsp-tests.vcxproj | 1 + .../testing/winfsp-tests.vcxproj.filters | 3 + src/dll/launch.c | 104 +++++++---- tst/winfsp-tests/launch-test.c | 166 ++++++++++++++++++ tst/winfsp-tests/winfsp-tests.c | 1 + 5 files changed, 242 insertions(+), 33 deletions(-) create mode 100644 tst/winfsp-tests/launch-test.c diff --git a/build/VStudio/testing/winfsp-tests.vcxproj b/build/VStudio/testing/winfsp-tests.vcxproj index 5ddf40fd..74c4edc5 100644 --- a/build/VStudio/testing/winfsp-tests.vcxproj +++ b/build/VStudio/testing/winfsp-tests.vcxproj @@ -190,6 +190,7 @@ + diff --git a/build/VStudio/testing/winfsp-tests.vcxproj.filters b/build/VStudio/testing/winfsp-tests.vcxproj.filters index 9afe1684..0d3b22f1 100644 --- a/build/VStudio/testing/winfsp-tests.vcxproj.filters +++ b/build/VStudio/testing/winfsp-tests.vcxproj.filters @@ -85,6 +85,9 @@ Source + + Source + diff --git a/src/dll/launch.c b/src/dll/launch.c index 287e4136..d74b1442 100644 --- a/src/dll/launch.c +++ b/src/dll/launch.c @@ -218,8 +218,7 @@ FSP_API NTSTATUS FspLaunchRegSetRecord( } ClassNameLen = lstrlenW(ClassName); - if (sizeof RegPath - sizeof L"" FSP_LAUNCH_REGKEY <= - (1/*backslash*/ + ClassNameLen) * sizeof(WCHAR)) + if (sizeof RegPath - sizeof L"" FSP_LAUNCH_REGKEY <= (ClassNameLen + 1) * sizeof(WCHAR)) { Result = STATUS_INVALID_PARAMETER; goto exit; @@ -227,12 +226,13 @@ FSP_API NTSTATUS FspLaunchRegSetRecord( memcpy(RegPath, L"" FSP_LAUNCH_REGKEY, sizeof L"" FSP_LAUNCH_REGKEY - sizeof(WCHAR)); RegPath[sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR) - 1] = L'\\'; - memcpy(RegPath + sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR), ClassName, ClassNameLen); + memcpy(RegPath + sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR), + ClassName, (ClassNameLen + 1) * sizeof(WCHAR)); if (0 != Record) { RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, RegPath, - 0, 0, 0, FSP_LAUNCH_REGKEY_WOW64 | KEY_ALL_ACCESS, 0, &RegKey, 0); + 0, 0, 0, FSP_LAUNCH_REGKEY_WOW64 | KEY_SET_VALUE, 0, &RegKey, 0); if (ERROR_SUCCESS != RegResult) { Result = FspNtStatusFromWin32(RegResult); @@ -245,7 +245,7 @@ FSP_API NTSTATUS FspLaunchRegSetRecord( SETFIELD(WorkDirectory); SETFIELD(RunAs); SETFIELD(Security); - SETFIELDI(JobControl, 1); + SETFIELDI(JobControl, ~0); /* JobControl default is 1; but we treat as without default */ SETFIELDI(Credentials, 0); } else @@ -259,6 +259,8 @@ FSP_API NTSTATUS FspLaunchRegSetRecord( } } + Result = STATUS_SUCCESS; + exit: if (0 != RegKey) RegCloseKey(RegKey); @@ -277,58 +279,87 @@ FSP_API NTSTATUS FspLaunchRegGetRecord( do \ { \ RegSize = sizeof RegBuf - RegMark;\ - RegResult = RegGetValueW(RegKey,\ - ClassName, L"" #FieldName, RRF_RT_REG_SZ, 0,\ - RegBuf + RegMark, &RegSize);\ - if (ERROR_SUCCESS == RegResult) \ + RegResult = RegQueryValueEx(RegKey,\ + L"" #FieldName, 0, &RegType,\ + (PVOID)(RegBuf + RegMark), &RegSize);\ + if (ERROR_SUCCESS != RegResult) \ { \ - Record->FieldName = (PVOID)(RegBuf + RegMark);\ - RegMark += RegSize; \ + if (ERROR_FILE_NOT_FOUND != RegResult)\ + { \ + Result = FspNtStatusFromWin32(RegResult);\ + goto exit; \ + } \ } \ - else if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)\ + else if (REG_SZ != RegType || \ + sizeof(WCHAR) > RegSize || \ + L'\0' != *(PWSTR)(RegBuf + RegMark + RegSize - sizeof(WCHAR)))\ { \ - Result = FspNtStatusFromWin32(RegResult);\ + Result = STATUS_OBJECT_NAME_NOT_FOUND;\ goto exit; \ } \ + else \ + { \ + Record->FieldName = (PWSTR)(RegBuf + RegMark);\ + RegMark += RegSize; \ + } \ } while (0,0) #define GETFIELDI(FieldName) \ do \ { \ - RegSize = sizeof RegDword;\ - RegResult = RegGetValueW(RegKey,\ - ClassName, L"" #FieldName, RRF_RT_DWORD, 0,\ - &RegDword, &RegSize);\ - if (ERROR_SUCCESS == RegResult) \ + RegSize = sizeof RegDword; \ + RegResult = RegQueryValueEx(RegKey,\ + L"" #FieldName, 0, &RegType,\ + (PVOID)&RegDword, &RegSize);\ + if (ERROR_SUCCESS != RegResult) \ { \ - Record->FieldName = RegDword;\ - RegMark += RegSize; \ + if (ERROR_FILE_NOT_FOUND != RegResult)\ + { \ + Result = FspNtStatusFromWin32(RegResult);\ + goto exit; \ + } \ } \ - else if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)\ + else if (REG_DWORD != RegType) \ { \ - Result = FspNtStatusFromWin32(RegResult);\ + Result = STATUS_OBJECT_NAME_NOT_FOUND;\ goto exit; \ } \ + else \ + Record->FieldName = RegDword;\ } while (0,0) NTSTATUS Result; + ULONG ClassNameLen; + WCHAR RegPath[MAX_PATH]; FSP_LAUNCH_REG_RECORD RecordBuf, *Record = &RecordBuf; HKEY RegKey = 0; - DWORD RegResult, RegDword, RegSize, RegMark; - UINT8 RegBuf[3 * 1024]; + DWORD RegResult, RegDword, RegType, RegSize, RegMark; + UINT8 RegBuf[2 * 1024]; PWSTR P, Part; BOOLEAN FoundAgent; *PRecord = 0; - RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" FSP_LAUNCH_REGKEY, - 0, FSP_LAUNCH_REGKEY_WOW64 | KEY_READ, &RegKey); + ClassNameLen = lstrlenW(ClassName); + if (sizeof RegPath - sizeof L"" FSP_LAUNCH_REGKEY <= (ClassNameLen + 1) * sizeof(WCHAR)) + { + Result = STATUS_INVALID_PARAMETER; + goto exit; + } + + memcpy(RegPath, L"" FSP_LAUNCH_REGKEY, sizeof L"" FSP_LAUNCH_REGKEY - sizeof(WCHAR)); + RegPath[sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR) - 1] = L'\\'; + memcpy(RegPath + sizeof L"" FSP_LAUNCH_REGKEY / sizeof(WCHAR), + ClassName, (ClassNameLen + 1) * sizeof(WCHAR)); + + RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, RegPath, + 0, FSP_LAUNCH_REGKEY_WOW64 | KEY_QUERY_VALUE, &RegKey); if (ERROR_SUCCESS != RegResult) { Result = FspNtStatusFromWin32(RegResult); goto exit; } - memset(&Record, 0, sizeof Record); + memset(Record, 0, sizeof *Record); Record->JobControl = 1; /* default is YES! */ RegMark = 0; @@ -380,13 +411,20 @@ FSP_API NTSTATUS FspLaunchRegGetRecord( goto exit; } + memset(Record, 0, sizeof *Record); memcpy(Record->Buffer, RegBuf, RegMark); - Record->Agent = (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Agent - RegBuf)); - Record->Executable = (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Executable - RegBuf)); - Record->CommandLine = (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.CommandLine - RegBuf)); - Record->WorkDirectory = (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.WorkDirectory - RegBuf)); - Record->RunAs = (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.RunAs - RegBuf)); - Record->Security = (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Security - RegBuf)); + Record->Agent = 0 != RecordBuf.Agent ? + (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Agent - RegBuf)) : 0; + Record->Executable = 0 != RecordBuf.Executable ? + (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Executable - RegBuf)) : 0; + Record->CommandLine = 0 != RecordBuf.CommandLine ? + (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.CommandLine - RegBuf)) : 0; + Record->WorkDirectory = 0 != RecordBuf.WorkDirectory ? + (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.WorkDirectory - RegBuf)) : 0; + Record->RunAs = 0 != RecordBuf.RunAs ? + (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.RunAs - RegBuf)) : 0; + Record->Security = 0 != RecordBuf.Security ? + (PVOID)(Record->Buffer + ((PUINT8)RecordBuf.Security - RegBuf)) : 0; Record->JobControl = RecordBuf.JobControl; Record->Credentials = RecordBuf.Credentials; diff --git a/tst/winfsp-tests/launch-test.c b/tst/winfsp-tests/launch-test.c new file mode 100644 index 00000000..4e90f217 --- /dev/null +++ b/tst/winfsp-tests/launch-test.c @@ -0,0 +1,166 @@ +/** + * @file launch-test.c + * + * @copyright 2015-2018 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 file in + * accordance with the commercial license agreement provided with the + * software. + */ + +#include +#include + +#include "winfsp-tests.h" + +static void launch_reg_test(void) +{ + NTSTATUS Result; + PWSTR ClassName = L"winfsp-tests-launch-reg-test"; + FSP_LAUNCH_REG_RECORD RecordBuf = { 0 }, *Record; + + Result = FspLaunchRegGetRecord(ClassName, 0, &Record); + ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result); + ASSERT(0 == Record); + + RecordBuf.Executable = 0; + Result = FspLaunchRegSetRecord(ClassName, &RecordBuf); + ASSERT(STATUS_INVALID_PARAMETER == Result); + + RecordBuf.Executable = L"Executable"; + RecordBuf.CommandLine = L"CommandLine"; + RecordBuf.WorkDirectory = L"WorkDirectory"; + RecordBuf.RunAs = L"RunAs"; + RecordBuf.Security = L"Security"; + RecordBuf.JobControl = 1; + RecordBuf.Credentials = 42; + Result = FspLaunchRegSetRecord(ClassName, &RecordBuf); + if (STATUS_ACCESS_DENIED == Result) + { + FspDebugLog(__FUNCTION__ ": need Administrator\n"); + return; + } + ASSERT(NT_SUCCESS(Result)); + + Result = FspLaunchRegGetRecord(ClassName, 0, &Record); + ASSERT(NT_SUCCESS(Result)); + ASSERT(0 != Record); + ASSERT(0 == Record->Agent); + ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable)); + ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine)); + ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory)); + ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs)); + ASSERT(0 == wcscmp(RecordBuf.Security, Record->Security)); + ASSERT(RecordBuf.JobControl == Record->JobControl); + ASSERT(RecordBuf.Credentials == Record->Credentials); + FspLaunchRegFreeRecord(Record); + + Result = FspLaunchRegSetRecord(ClassName, &RecordBuf); + ASSERT(NT_SUCCESS(Result)); + + Result = FspLaunchRegGetRecord(ClassName, 0, &Record); + ASSERT(NT_SUCCESS(Result)); + ASSERT(0 != Record); + ASSERT(0 == Record->Agent); + ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable)); + ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine)); + ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory)); + ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs)); + ASSERT(0 == wcscmp(RecordBuf.Security, Record->Security)); + ASSERT(RecordBuf.JobControl == Record->JobControl); + ASSERT(RecordBuf.Credentials == Record->Credentials); + FspLaunchRegFreeRecord(Record); + + RecordBuf.Security = 0; + RecordBuf.Credentials = 0; + Result = FspLaunchRegSetRecord(ClassName, &RecordBuf); + ASSERT(NT_SUCCESS(Result)); + + Result = FspLaunchRegGetRecord(ClassName, 0, &Record); + ASSERT(NT_SUCCESS(Result)); + ASSERT(0 != Record); + ASSERT(0 == Record->Agent); + ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable)); + ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine)); + ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory)); + ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs)); + ASSERT(0 == Record->Security); + ASSERT(RecordBuf.JobControl == Record->JobControl); + ASSERT(RecordBuf.Credentials == Record->Credentials); + FspLaunchRegFreeRecord(Record); + + Result = FspLaunchRegSetRecord(ClassName, 0); + ASSERT(NT_SUCCESS(Result)); + + Result = FspLaunchRegGetRecord(ClassName, 0, &Record); + ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result); + ASSERT(0 == Record); + + Result = FspLaunchRegSetRecord(ClassName, 0); + ASSERT(NT_SUCCESS(Result)); + + Result = FspLaunchRegGetRecord(ClassName, 0, &Record); + ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result); + ASSERT(0 == Record); + + RecordBuf.Agent = L"Agent1,Agent2"; + Result = FspLaunchRegSetRecord(ClassName, &RecordBuf); + ASSERT(NT_SUCCESS(Result)); + + Result = FspLaunchRegGetRecord(ClassName, L"Agent", &Record); + ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result); + ASSERT(0 == Record); + + Result = FspLaunchRegGetRecord(ClassName, L"Agent1", &Record); + ASSERT(NT_SUCCESS(Result)); + ASSERT(0 != Record); + ASSERT(0 == wcscmp(RecordBuf.Agent, Record->Agent)); + ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable)); + ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine)); + ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory)); + ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs)); + ASSERT(0 == Record->Security); + ASSERT(RecordBuf.JobControl == Record->JobControl); + ASSERT(RecordBuf.Credentials == Record->Credentials); + FspLaunchRegFreeRecord(Record); + + Result = FspLaunchRegGetRecord(ClassName, 0, &Record); + ASSERT(NT_SUCCESS(Result)); + ASSERT(0 != Record); + ASSERT(0 == wcscmp(RecordBuf.Agent, Record->Agent)); + ASSERT(0 == wcscmp(RecordBuf.Executable, Record->Executable)); + ASSERT(0 == wcscmp(RecordBuf.CommandLine, Record->CommandLine)); + ASSERT(0 == wcscmp(RecordBuf.WorkDirectory, Record->WorkDirectory)); + ASSERT(0 == wcscmp(RecordBuf.RunAs, Record->RunAs)); + ASSERT(0 == Record->Security); + ASSERT(RecordBuf.JobControl == Record->JobControl); + ASSERT(RecordBuf.Credentials == Record->Credentials); + FspLaunchRegFreeRecord(Record); + + Result = FspLaunchRegSetRecord(ClassName, 0); + ASSERT(NT_SUCCESS(Result)); + + Result = FspLaunchRegGetRecord(ClassName, 0, &Record); + ASSERT(STATUS_OBJECT_NAME_NOT_FOUND == Result); + ASSERT(0 == Record); +} + +static void launch_test(void) +{ +} + +void launch_tests(void) +{ + if (OptExternal) + return; + + TEST(launch_reg_test); + TEST(launch_test); +} diff --git a/tst/winfsp-tests/winfsp-tests.c b/tst/winfsp-tests/winfsp-tests.c index a96b44df..87bd24f5 100644 --- a/tst/winfsp-tests/winfsp-tests.c +++ b/tst/winfsp-tests/winfsp-tests.c @@ -186,6 +186,7 @@ int main(int argc, char *argv[]) TESTSUITE(path_tests); TESTSUITE(dirbuf_tests); TESTSUITE(version_tests); + TESTSUITE(launch_tests); TESTSUITE(mount_tests); TESTSUITE(timeout_tests); TESTSUITE(memfs_tests);