https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a9bd3da29907983285388…
commit a9bd3da299079832853884be595fa9b7e08ee95b
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Fri Jun 23 21:47:36 2017 +0200
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Mon Feb 25 20:00:34 2019 +0100
[APPHELP_APITEST] Add a test for shim database registration
CORE-11301
---
modules/rostests/apitests/apphelp/CMakeLists.txt | 7 +-
modules/rostests/apitests/apphelp/register.cpp | 374 +++++++++++++++++++++++
modules/rostests/apitests/apphelp/testlist.c | 2 +
3 files changed, 381 insertions(+), 2 deletions(-)
diff --git a/modules/rostests/apitests/apphelp/CMakeLists.txt
b/modules/rostests/apitests/apphelp/CMakeLists.txt
index 06ca2ba83a..40da34c905 100644
--- a/modules/rostests/apitests/apphelp/CMakeLists.txt
+++ b/modules/rostests/apitests/apphelp/CMakeLists.txt
@@ -1,7 +1,9 @@
project(appcompat)
-add_definitions(-D__ROS_LONG64__ -DWINETEST_USE_DBGSTR_LONGLONG)
+add_definitions(-D__ROS_LONG64__ -DWINETEST_USE_DBGSTR_LONGLONG -DUNICODE -D_UNICODE)
+set_cpp(WITH_RUNTIME)
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
+include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/atl
+ ${CMAKE_CURRENT_BINARY_DIR})
list(APPEND SOURCE
apphelp.c
@@ -9,6 +11,7 @@ list(APPEND SOURCE
db.cpp
env.c
layerapi.c
+ register.cpp
testlist.c
testdata.rc
testdb.xml)
diff --git a/modules/rostests/apitests/apphelp/register.cpp
b/modules/rostests/apitests/apphelp/register.cpp
new file mode 100644
index 0000000000..fb093cc594
--- /dev/null
+++ b/modules/rostests/apitests/apphelp/register.cpp
@@ -0,0 +1,374 @@
+/*
+ * PROJECT: apphelp_apitest
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Tests for shim database registration
+ * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen(a)reactos.org)
+ */
+
+#include <ntstatus.h>
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <ntndk.h>
+#include <atlbase.h>
+#include <strsafe.h>
+#include "wine/test.h"
+
+static const unsigned char rawDB[] =
+{
+ /* Header: Major, Minor, 'sdbf' */
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x64, 0x62, 0x66,
+
+ /* TAG_DATABASE, Length */
+ 0x01, 0x70, 0x22, 0x00, 0x00, 0x00,
+ /* TAG_NAME, Value */
+ 0x01, 0x60, 0x06, 0x00, 0x00, 0x00,
+
+ /* TAG_DATABASE_ID, Length, Value*/
+ 0x07, 0x90, 0x10, 0x00, 0x00, 0x00,
+ /* offset 30 */
+ 0xEB, 0x75, 0xDD, 0x79, 0x98, 0xC0, 0x57, 0x47, 0x99, 0x65, 0x9E,
0x83, 0xC4, 0xCA, 0x9D, 0xA4,
+
+ /* TAG_LIBRARY, Length */
+ 0x02, 0x70, 0x00, 0x00, 0x00, 0x00,
+
+ /* TAG_STRINGTABLE, Length */
+ 0x01, 0x78, 0x0E, 0x00, 0x00, 0x00,
+ /* TAG_STRINGTABLE_ITEM, Length, Value */
+ 0x01, 0x88, 0x08, 0x00, 0x00, 0x00,
+ 0x49, 0x00, 0x43, 0x00, 0x53, 0x00, 0x00, 0x00
+};
+
+static BOOL WriteSdbFile(const WCHAR* FileName, const unsigned char* Data, DWORD Size,
const GUID* CustomID)
+{
+ BOOL Success;
+ DWORD dwWritten;
+ HANDLE Handle = CreateFileW(FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (Handle == INVALID_HANDLE_VALUE)
+ {
+ skip("Failed to create temp file %ls, error %u\n", FileName,
GetLastError());
+ return FALSE;
+ }
+ Success = WriteFile(Handle, Data, Size, &dwWritten, NULL);
+ ok(Success == TRUE, "WriteFile failed with %u\n", GetLastError());
+ ok(dwWritten == Size, "WriteFile wrote %u bytes instead of %u\n",
dwWritten, Size);
+ if (CustomID)
+ {
+ DWORD dwGuidSize;
+ SetFilePointer(Handle, 30, NULL, FILE_BEGIN);
+ Success = WriteFile(Handle, CustomID, sizeof(*CustomID), &dwGuidSize, NULL);
+ ok(dwGuidSize == sizeof(GUID), "WriteFile wrote %u bytes instead of
%u\n", dwGuidSize, sizeof(GUID));
+ }
+ CloseHandle(Handle);
+ return Success && (dwWritten == Size);
+}
+
+
+
+static const GUID GUID_DATABASE_SHIM = { 0x11111111, 0x1111, 0x1111, { 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11 } };
+static const GUID GUID_DATABASE_MSI = { 0xd8ff6d16, 0x6a3a, 0x468a, { 0x8b, 0x44,
0x01, 0x71, 0x4d, 0xdc, 0x49, 0xea } };
+static const GUID GUID_DATABASE_DRIVERS = { 0xf9ab2228, 0x3312, 0x4a73, { 0xb6, 0xf9,
0x93, 0x6d, 0x70, 0xe1, 0x12, 0xef } };
+static const GUID TEST_DB_GUID = { 0x79dd75eb, 0xc098, 0x4757, { 0x99, 0x65,
0x9e, 0x83, 0xc4, 0xca, 0x9d, 0xa4 } };
+
+#define SDB_DATABASE_MAIN 0x80000000
+
+BOOL (WINAPI *pSdbRegisterDatabase)(LPCWSTR pszDatabasePath, DWORD dwDatabaseType);
+BOOL (WINAPI *pSdbRegisterDatabaseEx)(LPCWSTR pszDatabasePath, DWORD dwDatabaseType,
const PULONGLONG pTimeStamp);
+BOOL (WINAPI *pSdbUnregisterDatabase)(REFGUID pguidDB);
+
+
+BOOL IsUserAdmin()
+{
+ BOOL Result;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
+ PSID AdministratorsGroup;
+
+ Result = AllocateAndInitializeSid(&NtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &AdministratorsGroup);
+ if (Result)
+ {
+ if (!CheckTokenMembership( NULL, AdministratorsGroup, &Result))
+ Result = FALSE;
+ FreeSid(AdministratorsGroup);
+ }
+
+ return Result;
+}
+
+static DWORD g_QueryFlag = 0xffffffff;
+static DWORD QueryFlag(void)
+{
+ if (g_QueryFlag == 0xffffffff)
+ {
+ ULONG_PTR wow64_ptr = 0;
+ NTSTATUS status = NtQueryInformationProcess(NtCurrentProcess(),
ProcessWow64Information, &wow64_ptr, sizeof(wow64_ptr), NULL);
+ g_QueryFlag = (NT_SUCCESS(status) && wow64_ptr != 0) ? KEY_WOW64_64KEY :
0;
+ }
+ return g_QueryFlag;
+}
+
+static void FileTimeNow(ULARGE_INTEGER& Result)
+{
+ FILETIME TimeBuffer;
+
+ GetSystemTimeAsFileTime(&TimeBuffer);
+ Result.HighPart = TimeBuffer.dwHighDateTime;
+ Result.LowPart = TimeBuffer.dwLowDateTime;
+}
+
+static void ok_keys_(REFGUID Guid, LPCWSTR DisplayName, LPCWSTR Path, DWORD Type,
PULONGLONG TimeStamp)
+{
+ UNICODE_STRING GuidString;
+ WCHAR StringBuffer[200];
+ DWORD ValueBuffer;
+ ULARGE_INTEGER LargeUIntBuffer;
+
+ CRegKey key;
+ LSTATUS Status = key.Open(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows
NT\\CurrentVersion\\AppCompatFlags\\InstalledSDB", KEY_READ | QueryFlag());
+ winetest_ok(!Status, "Unable to open InstalledSDB key\n");
+ if (Status)
+ return;
+
+ if (!SUCCEEDED(RtlStringFromGUID(Guid, &GuidString)))
+ {
+ ok(0, "Unable to format guid\n");
+ return;
+ }
+
+ Status = key.Open(key.m_hKey, GuidString.Buffer, KEY_READ);
+ winetest_ok(!Status, "Unable to open %s key (0x%x)\n",
wine_dbgstr_w(GuidString.Buffer), Status);
+ RtlFreeUnicodeString(&GuidString);
+ if (Status)
+ return;
+
+ ULONG nChars = _countof(StringBuffer);
+ Status = key.QueryStringValue(L"DatabaseDescription", StringBuffer,
&nChars);
+ winetest_ok(!Status, "Unable to read DatabaseDescription (0x%x)\n",
Status);
+ if (!Status)
+ winetest_ok(!wcscmp(DisplayName, StringBuffer), "Expected
DatabaseDescription to be %s, was %s\n", wine_dbgstr_w(DisplayName),
wine_dbgstr_w(StringBuffer));
+
+ nChars = _countof(StringBuffer);
+ Status = key.QueryStringValue(L"DatabasePath", StringBuffer, &nChars);
+ winetest_ok(!Status, "Unable to read DatabasePath (0x%x)\n", Status);
+ if (!Status)
+ winetest_ok(!wcscmp(Path, StringBuffer), "Expected DatabasePath to be %s,
was %s\n", wine_dbgstr_w(Path), wine_dbgstr_w(StringBuffer));
+
+ Status = key.QueryDWORDValue(L"DatabaseType", ValueBuffer);
+ winetest_ok(!Status, "Unable to read DatabaseType (0x%x)\n", Status);
+ if (!Status)
+ winetest_ok(ValueBuffer == Type, "Expected DatabaseType to be 0x%x, was
0x%x\n", Type, ValueBuffer);
+
+ Status = key.QueryQWORDValue(L"DatabaseInstallTimeStamp",
LargeUIntBuffer.QuadPart);
+ winetest_ok(!Status, "Unable to read DatabaseInstallTimeStamp (0x%x)\n",
Status);
+ if (!Status)
+ {
+ if (TimeStamp)
+ {
+ winetest_ok(LargeUIntBuffer.QuadPart == *TimeStamp, "Expected
DatabaseInstallTimeStamp to be %s, was %s\n",
+ wine_dbgstr_longlong(*TimeStamp),
wine_dbgstr_longlong(LargeUIntBuffer.QuadPart));
+ }
+ else
+ {
+ ULARGE_INTEGER CurrentTime;
+ FileTimeNow(CurrentTime);
+ ULONG DiffMS = (ULONG)((CurrentTime.QuadPart - LargeUIntBuffer.QuadPart) /
10000);
+ winetest_ok(DiffMS < 5000 , "Expected DatabaseInstallTimeStamp to be
less than 5 seconds before now (was: %u)\n", DiffMS);
+ }
+ }
+}
+
+
+#define ok_keys (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 :
ok_keys_
+
+
+START_TEST(register)
+{
+ WCHAR TempPath[MAX_PATH * 2];
+ BOOL Success;
+ HMODULE hdll;
+
+ SetEnvironmentVariableA("SHIM_DEBUG_LEVEL", "4");
+ SetEnvironmentVariableA("SHIMENG_DEBUG_LEVEL", "4");
+ SetEnvironmentVariableA("DEBUGCHANNEL", "+apphelp");
+
+ //silence_debug_output();
+ hdll = LoadLibraryA("apphelp.dll");
+
+ *(void**)&pSdbRegisterDatabase = (void*)GetProcAddress(hdll,
"SdbRegisterDatabase");
+ *(void**)&pSdbRegisterDatabaseEx = (void*)GetProcAddress(hdll,
"SdbRegisterDatabaseEx");
+ *(void**)&pSdbUnregisterDatabase = (void*)GetProcAddress(hdll,
"SdbUnregisterDatabase");
+
+ if (!pSdbRegisterDatabase || !pSdbRegisterDatabaseEx || !pSdbUnregisterDatabase)
+ {
+ skip("Not all functions present: %p, %p, %p\n", pSdbRegisterDatabase,
pSdbRegisterDatabaseEx, pSdbUnregisterDatabase);
+ return;
+ }
+
+ /* [Err ][SdbUnregisterDatabase] Failed to open key
"\Registry\Machine\Software\Microsoft\Windows
NT\CurrentVersion\AppCompatFlags\InstalledSDB\{11111111-1111-1111-1111-111111111111}"
Status 0xc0000034 */
+ ok_int(pSdbUnregisterDatabase(GUID_DATABASE_SHIM), FALSE);
+ ok_int(pSdbUnregisterDatabase(GUID_DATABASE_MSI), FALSE);
+ ok_int(pSdbUnregisterDatabase(GUID_DATABASE_DRIVERS), FALSE);
+
+
+ if (!IsUserAdmin())
+ {
+ skip("Not running as admin, unable to install databases!\n");
+ return;
+ }
+
+ GetTempPathW(_countof(TempPath), TempPath);
+ StringCchCatW(TempPath, _countof(TempPath), L"\\shim_db.sdb");
+ if (!WriteSdbFile(TempPath, rawDB, sizeof(rawDB), NULL))
+ {
+ skip("Cannot write %s\n", wine_dbgstr_w(TempPath));
+ return;
+ }
+
+ /* No Type */
+ Success = pSdbRegisterDatabase(TempPath, 0);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(TEST_DB_GUID, L"ICS", TempPath, 0, NULL);
+ Success = pSdbUnregisterDatabase(TEST_DB_GUID);
+ ok_int(Success, TRUE);
+ }
+
+ /* Unknown type */
+ Success = pSdbRegisterDatabase(TempPath, 1);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(TEST_DB_GUID, L"ICS", TempPath, 1, NULL);
+ Success = pSdbUnregisterDatabase(TEST_DB_GUID);
+ ok_int(Success, TRUE);
+ }
+
+ /* System type */
+ Success = pSdbRegisterDatabase(TempPath, SDB_DATABASE_MAIN);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(TEST_DB_GUID, L"ICS", TempPath, SDB_DATABASE_MAIN, NULL);
+ Success = pSdbUnregisterDatabase(TEST_DB_GUID);
+ ok_int(Success, TRUE);
+ }
+
+ /* No type, null time */
+ Success = pSdbRegisterDatabaseEx(TempPath, 0, NULL);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(TEST_DB_GUID, L"ICS", TempPath, 0, NULL);
+ Success = pSdbUnregisterDatabase(TEST_DB_GUID);
+ ok_int(Success, TRUE);
+ }
+
+ /* Unknown type, null time */
+ Success = pSdbRegisterDatabaseEx(TempPath, 1, NULL);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(TEST_DB_GUID, L"ICS", TempPath, 1, NULL);
+ Success = pSdbUnregisterDatabase(TEST_DB_GUID);
+ ok_int(Success, TRUE);
+ }
+
+
+ /* System type, null time */
+ Success = pSdbRegisterDatabaseEx(TempPath, SDB_DATABASE_MAIN, NULL);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(TEST_DB_GUID, L"ICS", TempPath, SDB_DATABASE_MAIN, NULL);
+ Success = pSdbUnregisterDatabase(TEST_DB_GUID);
+ ok_int(Success, TRUE);
+ }
+
+ ULARGE_INTEGER Time;
+ FileTimeNow(Time);
+ Time.QuadPart ^= 0xffffffffffffffffll;
+ /* No type, random time */
+ Success = pSdbRegisterDatabaseEx(TempPath, 0, &Time.QuadPart);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(TEST_DB_GUID, L"ICS", TempPath, 0, &Time.QuadPart);
+ Success = pSdbUnregisterDatabase(TEST_DB_GUID);
+ ok_int(Success, TRUE);
+ }
+
+ /* Unknown type, random time */
+ Success = pSdbRegisterDatabaseEx(TempPath, 1, &Time.QuadPart);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(TEST_DB_GUID, L"ICS", TempPath, 1, &Time.QuadPart);
+ Success = pSdbUnregisterDatabase(TEST_DB_GUID);
+ ok_int(Success, TRUE);
+ }
+
+ /* System type, random time */
+ Success = pSdbRegisterDatabaseEx(TempPath, SDB_DATABASE_MAIN, &Time.QuadPart);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(TEST_DB_GUID, L"ICS", TempPath, SDB_DATABASE_MAIN,
&Time.QuadPart);
+ Success = pSdbUnregisterDatabase(TEST_DB_GUID);
+ ok_int(Success, TRUE);
+ }
+
+ /* System reserved ID's */
+ if (!WriteSdbFile(TempPath, rawDB, sizeof(rawDB), &GUID_DATABASE_SHIM))
+ {
+ skip("Cannot write %s\n", wine_dbgstr_w(TempPath));
+ DeleteFileW(TempPath);
+ return;
+ }
+
+ Success = pSdbRegisterDatabase(TempPath, 0);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(GUID_DATABASE_SHIM, L"ICS", TempPath, 0, NULL);
+ Success = pSdbUnregisterDatabase(GUID_DATABASE_SHIM);
+ ok_int(Success, TRUE);
+ }
+
+ if (!WriteSdbFile(TempPath, rawDB, sizeof(rawDB), &GUID_DATABASE_MSI))
+ {
+ skip("Cannot write %s\n", wine_dbgstr_w(TempPath));
+ DeleteFileW(TempPath);
+ return;
+ }
+
+ Success = pSdbRegisterDatabase(TempPath, 0);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(GUID_DATABASE_MSI, L"ICS", TempPath, 0, NULL);
+ Success = pSdbUnregisterDatabase(GUID_DATABASE_MSI);
+ ok_int(Success, TRUE);
+ }
+
+ if (!WriteSdbFile(TempPath, rawDB, sizeof(rawDB), &GUID_DATABASE_DRIVERS))
+ {
+ skip("Cannot write %s\n", wine_dbgstr_w(TempPath));
+ DeleteFileW(TempPath);
+ return;
+ }
+
+ Success = pSdbRegisterDatabase(TempPath, 0);
+ ok_int(Success, TRUE);
+ if (Success)
+ {
+ ok_keys(GUID_DATABASE_DRIVERS, L"ICS", TempPath, 0, NULL);
+ Success = pSdbUnregisterDatabase(GUID_DATABASE_DRIVERS);
+ ok_int(Success, TRUE);
+ }
+
+ DeleteFileW(TempPath);
+}
diff --git a/modules/rostests/apitests/apphelp/testlist.c
b/modules/rostests/apitests/apphelp/testlist.c
index a90da5fba5..c27d4e4821 100644
--- a/modules/rostests/apitests/apphelp/testlist.c
+++ b/modules/rostests/apitests/apphelp/testlist.c
@@ -7,6 +7,7 @@ extern void func_apphelp(void);
extern void func_db(void);
extern void func_env(void);
extern void func_layerapi(void);
+extern void func_register(void);
const struct test winetest_testlist[] =
{
@@ -14,5 +15,6 @@ const struct test winetest_testlist[] =
{ "db", func_db },
{ "env", func_env },
{ "layerapi", func_layerapi },
+ { "register", func_register },
{ 0, 0 }
};