From f386a6ec410eb778deb7f999fc5805092cc139f8 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Sun, 25 Nov 2018 19:52:20 +0100 Subject: [PATCH] [SFC_APITEST] Initial test for SfcIsFileProtected and SfcGetFiles --- modules/rostests/apitests/CMakeLists.txt | 1 + modules/rostests/apitests/sfc/CMakeLists.txt | 10 ++ modules/rostests/apitests/sfc/SfcGetFiles.c | 83 +++++++++++++ .../apitests/sfc/SfcIsFileProtected.c | 116 ++++++++++++++++++ modules/rostests/apitests/sfc/testlist.c | 12 ++ 5 files changed, 222 insertions(+) create mode 100644 modules/rostests/apitests/sfc/CMakeLists.txt create mode 100644 modules/rostests/apitests/sfc/SfcGetFiles.c create mode 100644 modules/rostests/apitests/sfc/SfcIsFileProtected.c create mode 100644 modules/rostests/apitests/sfc/testlist.c diff --git a/modules/rostests/apitests/CMakeLists.txt b/modules/rostests/apitests/CMakeLists.txt index 5312b2838f4..ec5048551e5 100644 --- a/modules/rostests/apitests/CMakeLists.txt +++ b/modules/rostests/apitests/CMakeLists.txt @@ -29,6 +29,7 @@ add_subdirectory(pefile) add_subdirectory(powrprof) add_subdirectory(sdk) add_subdirectory(setupapi) +add_subdirectory(sfc) add_subdirectory(shell32) add_subdirectory(shlwapi) add_subdirectory(spoolss) diff --git a/modules/rostests/apitests/sfc/CMakeLists.txt b/modules/rostests/apitests/sfc/CMakeLists.txt new file mode 100644 index 00000000000..1d51f0b6a12 --- /dev/null +++ b/modules/rostests/apitests/sfc/CMakeLists.txt @@ -0,0 +1,10 @@ + +list(APPEND SOURCE + SfcGetFiles.c + SfcIsFileProtected.c + testlist.c) + +add_executable(sfc_apitest ${SOURCE}) +set_module_type(sfc_apitest win32cui) +add_importlibs(sfc_apitest msvcrt user32 kernel32 ntdll) +add_rostests_file(TARGET sfc_apitest) diff --git a/modules/rostests/apitests/sfc/SfcGetFiles.c b/modules/rostests/apitests/sfc/SfcGetFiles.c new file mode 100644 index 00000000000..edcf3cb7e08 --- /dev/null +++ b/modules/rostests/apitests/sfc/SfcGetFiles.c @@ -0,0 +1,83 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Test for SfcGetFiles + * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org) + */ + +#include +#include +#include + +typedef struct _PROTECT_FILE_ENTRY { + PWSTR SourceFileName; + PWSTR FileName; + PWSTR InfName; +} PROTECT_FILE_ENTRY, *PPROTECT_FILE_ENTRY; + +NTSTATUS (WINAPI *SfcGetFiles)(PPROTECT_FILE_ENTRY* ProtFileData, PULONG FileCount); + +PCWSTR wszEnvVars[] = +{ + L"%systemroot%", + L"%commonprogramfiles%", + L"%ProgramFiles%", + L"%systemdrive%" +}; + +static void Test_GetFiles() +{ + PPROTECT_FILE_ENTRY FileData; + PCWSTR Ptr; + ULONG FileCount, n, j; + NTSTATUS Status; + + Status = SfcGetFiles(&FileData, &FileCount); + ok(NT_SUCCESS(Status), "SfcGetFiles failed: 0x%lx\n", Status); + + if (!NT_SUCCESS(Status)) + return; + + for (n = 0; n < FileCount; ++n) + { + PPROTECT_FILE_ENTRY Entry = FileData + n; + + ok(Entry->FileName != NULL, "Entry %lu without FileName!", n); + if (Entry->FileName) + { + Ptr = NULL; + for (j = 0; j < _countof(wszEnvVars); ++j) + { + Ptr = wcsstr(Entry->FileName, wszEnvVars[j]); + if (Ptr) + break; + } + ok(Ptr != NULL, "Expected to find one match from wszEnvVars in %s\n", wine_dbgstr_w(Entry->FileName)); + } + if (Entry->InfName) + { + Ptr = wcsstr(Entry->InfName, L".inf"); + ok(Ptr == (Entry->InfName + wcslen(Entry->InfName) - 4), + ".inf not found in %s\n", wine_dbgstr_w(Entry->InfName)); + } + } +} + +START_TEST(SfcGetFiles) +{ + HMODULE mod; + + mod = LoadLibraryA("sfcfiles.dll"); + if (!mod) + { + skip("sfcfiles.dll not found\n"); + return; + } + + SfcGetFiles = (void*)GetProcAddress(mod, "SfcGetFiles"); + ok(SfcGetFiles != NULL, "Function not exported!\n"); + if (!SfcGetFiles) + return; + + Test_GetFiles(); +} diff --git a/modules/rostests/apitests/sfc/SfcIsFileProtected.c b/modules/rostests/apitests/sfc/SfcIsFileProtected.c new file mode 100644 index 00000000000..6bcf7e904d5 --- /dev/null +++ b/modules/rostests/apitests/sfc/SfcIsFileProtected.c @@ -0,0 +1,116 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Test for SfcIsFileProtected + * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org) + */ + +#include +#include +#include +#include + +BOOL (WINAPI *SfcIsFileProtected)(HANDLE RpcHandle,LPCWSTR ProtFileName); +static DWORD g_WinVersion; + +typedef struct _osrange +{ + DWORD Min; + DWORD Max; +} osrange; + +typedef struct _testdata +{ + PCWSTR Path; + BOOL Expand; + osrange Success; +} testdata; + + +#define _WIN32_WINNT_MINVER 0x0001 + +#define MAKERANGE(from, to) \ + { _WIN32_WINNT_ ## from, _WIN32_WINNT_ ## to } + +#define PASS(from, to) \ + MAKERANGE(from, to) + +static testdata tests[] = +{ + { L"%systemroot%\\system32\\kernel32.dll", TRUE, PASS(MINVER, WIN10) }, + { L"%SYSTEMROOT%\\SYSTEM32\\KERNEL32.DLL", TRUE, PASS(MINVER, WIN10) }, + /* Paths are normalized on newer windows */ + { L"%systemroot%//system32\\kernel32.dll", TRUE, PASS(VISTA, WIN10) }, + { L"%systemroot%\\system32\\..\\system32\\kernel32.dll", TRUE, PASS(VISTA, WIN10) }, + + /* These are rejected as-is */ + { L"kernel32.dll", FALSE, PASS(MINVER, MINVER) }, + { L"%systemroot%//system32\\kernel32.dll", FALSE, PASS(MINVER, MINVER) }, + /* Environment strings are expanded on older windows */ + { L"%systemroot%\\system32\\kernel32.dll", FALSE, PASS(MINVER, WS03) }, + { L"%SYSTEMROOT%\\SYSTEM32\\KERNEL32.DLL", FALSE, PASS(MINVER, WS03) }, + + /* Show some files under SFC protection */ + { L"%systemroot%\\system32\\user32.dll", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\system32\\shell32.dll", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\system32\\browseui.dll", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\system32\\apphelp.dll", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\system32\\sfc.dll", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\system32\\sfc_os.dll", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\system32\\sdbinst.exe", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\AppPatch\\sysmain.sdb", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\fonts\\tahoma.ttf", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\fonts\\tahomabd.ttf", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\system32\\ntoskrnl.exe", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\system32\\c_1252.nls", TRUE, PASS(MINVER, WIN10) }, + { L"%systemroot%\\NOTEPAD.EXE", TRUE, PASS(MINVER, WIN10) }, +}; + + +static void Test_ProtectedFiles() +{ + ULONG n; + BOOL Protected; + WCHAR Buffer[MAX_PATH * 3]; + + for (n = 0; n < _countof(tests); ++n) + { + if (tests[n].Expand) + ExpandEnvironmentStringsW(tests[n].Path, Buffer, _countof(Buffer)); + else + StringCchCopyW(Buffer, _countof(Buffer), tests[n].Path); + + Protected = SfcIsFileProtected(NULL, Buffer); + + if (g_WinVersion >= tests[n].Success.Min && g_WinVersion <= tests[n].Success.Max) + { + ok(Protected, "[%lu,0x%04lx]: Failed: %S\n", n, g_WinVersion, Buffer); + } + else + { + ok(!Protected, "[%lu,0x%04lx]: Succeeded: %S\n", n, g_WinVersion, Buffer); + } + } +} + + +START_TEST(SfcIsFileProtected) +{ + RTL_OSVERSIONINFOW rtlinfo = { sizeof(rtlinfo) }; + HMODULE mod; + + mod = LoadLibraryA("sfc_os.dll"); + ok(mod != NULL, "Unable to load sfc_os: 0x%lu\n", GetLastError()); + if (!mod) + return; + + SfcIsFileProtected = (void*)GetProcAddress(mod, "SfcIsFileProtected"); + ok(SfcIsFileProtected != NULL, "Unable to resolve SfcIsFileProtected: 0x%lu\n", GetLastError()); + if (!SfcIsFileProtected) + return; + + RtlGetVersion(&rtlinfo); + g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion; + + Test_ProtectedFiles(); +} diff --git a/modules/rostests/apitests/sfc/testlist.c b/modules/rostests/apitests/sfc/testlist.c new file mode 100644 index 00000000000..d75f8114584 --- /dev/null +++ b/modules/rostests/apitests/sfc/testlist.c @@ -0,0 +1,12 @@ +#define STANDALONE +#include + +extern void func_SfcGetFiles(void); +extern void func_SfcIsFileProtected(void); + +const struct test winetest_testlist[] = +{ + { "SfcGetFiles", func_SfcGetFiles }, + { "SfcIsFileProtected", func_SfcIsFileProtected }, + { 0, 0 } +};