From c01fa8e9c13de66f4b167e024fe4837a02cb5a67 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Mon, 11 Feb 2019 22:45:48 +0100 Subject: [PATCH] [APPHELP] Implement SdbRegisterDatabase[Ex] CORE-11301 --- dll/appcompat/apphelp/apphelp.c | 195 ++++++++++++++++++++++++++++---- dll/appcompat/apphelp/layer.c | 6 +- 2 files changed, 174 insertions(+), 27 deletions(-) diff --git a/dll/appcompat/apphelp/apphelp.c b/dll/appcompat/apphelp/apphelp.c index ceb71a8e166..e05c1fd9ebe 100644 --- a/dll/appcompat/apphelp/apphelp.c +++ b/dll/appcompat/apphelp/apphelp.c @@ -10,21 +10,29 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" -#include "winver.h" +#include "winreg.h" #include "strsafe.h" #include "apphelp.h" -#include "ndk/rtlfuncs.h" -#include "ndk/kdtypes.h" +#include +#include +#include +#include +ACCESS_MASK Wow64QueryFlag(void); + +const UNICODE_STRING InstalledSDBKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\InstalledSDB"); + /* from dpfilter.h */ #define DPFLTR_APPCOMPAT_ID 123 +#define MAX_GUID_STRING_LEN sizeof("{12345678-1234-1234-0123-456789abcdef}") + #ifndef NT_SUCCESS #define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode) >= 0) #endif -ULONG g_ShimDebugLevel = 0xffffffff; +ULONG g_ShimDebugLevel = ~0; HMODULE g_hInstance; void ApphelppInitDebugLevel(void) @@ -52,14 +60,14 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) { switch (reason) { - case DLL_PROCESS_ATTACH: - g_hInstance = hinst; - DisableThreadLibraryCalls( hinst ); - SdbpHeapInit(); - break; - case DLL_PROCESS_DETACH: - SdbpHeapDeinit(); - break; + case DLL_PROCESS_ATTACH: + g_hInstance = hinst; + DisableThreadLibraryCalls(hinst); + SdbpHeapInit(); + break; + case DLL_PROCESS_DETACH: + SdbpHeapDeinit(); + break; } return TRUE; } @@ -73,8 +81,8 @@ BOOL WINAPI ApphelpCheckInstallShieldPackage(void* ptr, LPCWSTR path) BOOL WINAPI ApphelpCheckShellObject(REFCLSID ObjectCLSID, BOOL bShimIfNecessary, ULONGLONG *pullFlags) { - WCHAR GuidString[100]; - if (!ObjectCLSID || !SdbGUIDToString(ObjectCLSID, GuidString, 100)) + WCHAR GuidString[MAX_GUID_STRING_LEN]; + if (!ObjectCLSID || !SdbGUIDToString(ObjectCLSID, GuidString, RTL_NUMBER_OF(GuidString))) GuidString[0] = L'\0'; SHIM_WARN("stub: ObjectCLSID='%S', bShimIfNecessary=%d, pullFlags=%p)\n", GuidString, bShimIfNecessary, pullFlags); @@ -103,7 +111,7 @@ BOOL WINAPIV ShimDbgPrint(SHIM_LOG_LEVEL Level, PCSTR FunctionName, PCSTR Format const char* LevelStr; size_t Length = sizeof(Buffer); - if (g_ShimDebugLevel == 0xffffffff) + if (g_ShimDebugLevel == ~0) ApphelppInitDebugLevel(); if (Level > g_ShimDebugLevel) @@ -251,14 +259,124 @@ ApphelpCheckRunAppEx( * @return TRUE on success, or FALSE on failure. */ BOOL WINAPI SdbRegisterDatabaseEx( - _In_ LPCTSTR pszDatabasePath, + _In_ LPCWSTR pszDatabasePath, _In_ DWORD dwDatabaseType, - _In_opt_ PULONGLONG pTimeStamp) + _In_opt_ const PULONGLONG pTimeStamp) { - SHIM_ERR("UNIMPLEMENTED, pszDatabasePath=%ws, dwDatabaseType=0x%x, pTimeStamp=%p\n", - pszDatabasePath, dwDatabaseType, pTimeStamp); + PDB pdb; + DB_INFORMATION Information; + WCHAR GuidBuffer[MAX_GUID_STRING_LEN]; + UNICODE_STRING KeyName; + ACCESS_MASK KeyAccess; + OBJECT_ATTRIBUTES ObjectKey = RTL_INIT_OBJECT_ATTRIBUTES(&KeyName, OBJ_CASE_INSENSITIVE); + NTSTATUS Status; + HANDLE InstalledSDBKey; - return FALSE; + pdb = SdbOpenDatabase(pszDatabasePath, DOS_PATH); + if (!pdb) + { + SHIM_ERR("Unable to open DB %S\n", pszDatabasePath); + return FALSE; + } + + if (!SdbGetDatabaseInformation(pdb, &Information) || + !(Information.dwFlags & DB_INFO_FLAGS_VALID_GUID)) + { + SHIM_ERR("Unable to retrieve DB info\n"); + SdbCloseDatabase(pdb); + return FALSE; + } + + if (!SdbGUIDToString(&Information.Id, GuidBuffer, RTL_NUMBER_OF(GuidBuffer))) + { + SHIM_ERR("Unable to Convert GUID to string\n"); + SdbFreeDatabaseInformation(&Information); + SdbCloseDatabase(pdb); + return FALSE; + } + + KeyName = InstalledSDBKeyName; + KeyAccess = Wow64QueryFlag() | KEY_WRITE | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS; + Status = NtCreateKey(&InstalledSDBKey, KeyAccess, &ObjectKey, 0, NULL, 0, NULL); + if (NT_SUCCESS(Status)) + { + HANDLE DbKey; + + RtlInitUnicodeString(&KeyName, GuidBuffer); + ObjectKey.RootDirectory = InstalledSDBKey; + + Status = NtCreateKey(&DbKey, KeyAccess, &ObjectKey, 0, NULL, 0, NULL); + if (NT_SUCCESS(Status)) + { + UNICODE_STRING DatabasePathKey = RTL_CONSTANT_STRING(L"DatabasePath"); + UNICODE_STRING DatabaseInstallTimeStampKey = RTL_CONSTANT_STRING(L"DatabaseInstallTimeStamp"); + UNICODE_STRING DatabaseTypeKey = RTL_CONSTANT_STRING(L"DatabaseType"); + UNICODE_STRING DatabaseDescriptionKey = RTL_CONSTANT_STRING(L"DatabaseDescription"); + + Status = NtSetValueKey(DbKey, &DatabasePathKey, 0, REG_SZ, + (PVOID)pszDatabasePath, (wcslen(pszDatabasePath) + 1) * sizeof(WCHAR)); + if (!NT_SUCCESS(Status)) + SHIM_ERR("Unable to write %wZ\n", &DatabasePathKey); + + if (NT_SUCCESS(Status)) + { + ULARGE_INTEGER ulTimeStamp; + if (pTimeStamp) + { + ulTimeStamp.QuadPart = *pTimeStamp; + } + else + { + FILETIME fi; + GetSystemTimeAsFileTime(&fi); + ulTimeStamp.LowPart = fi.dwLowDateTime; + ulTimeStamp.HighPart = fi.dwHighDateTime; + } + Status = NtSetValueKey(DbKey, &DatabaseInstallTimeStampKey, 0, REG_QWORD, + &ulTimeStamp.QuadPart, sizeof(ulTimeStamp)); + if (!NT_SUCCESS(Status)) + SHIM_ERR("Unable to write %wZ\n", &DatabaseInstallTimeStampKey); + } + + if (NT_SUCCESS(Status)) + { + Status = NtSetValueKey(DbKey, &DatabaseTypeKey, 0, REG_DWORD, + &dwDatabaseType, sizeof(dwDatabaseType)); + if (!NT_SUCCESS(Status)) + SHIM_ERR("Unable to write %wZ\n", &DatabaseTypeKey); + } + + if (NT_SUCCESS(Status) && Information.Description) + { + Status = NtSetValueKey(DbKey, &DatabaseDescriptionKey, 0, REG_SZ, + (PVOID)Information.Description, (wcslen(Information.Description) + 1) * sizeof(WCHAR)); + if (!NT_SUCCESS(Status)) + SHIM_ERR("Unable to write %wZ\n", &DatabaseDescriptionKey); + } + + NtClose(DbKey); + + if (NT_SUCCESS(Status)) + { + SHIM_INFO("Installed %wS as %wZ\n", pszDatabasePath, &KeyName); + } + } + else + { + SHIM_ERR("Unable to create key %wZ\n", &KeyName); + } + + NtClose(InstalledSDBKey); + } + else + { + SHIM_ERR("Unable to create key %wZ\n", &KeyName); + } + + SdbFreeDatabaseInformation(&Information); + SdbCloseDatabase(pdb); + + return NT_SUCCESS(Status); } @@ -271,7 +389,7 @@ BOOL WINAPI SdbRegisterDatabaseEx( * @return TRUE on success, or FALSE on failure. */ BOOL WINAPI SdbRegisterDatabase( - _In_ LPCTSTR pszDatabasePath, + _In_ LPCWSTR pszDatabasePath, _In_ DWORD dwDatabaseType) { return SdbRegisterDatabaseEx(pszDatabasePath, dwDatabaseType, NULL); @@ -285,11 +403,40 @@ BOOL WINAPI SdbRegisterDatabase( * @param pguidDB * @return */ -BOOL WINAPI SdbUnregisterDatabase(_In_ GUID *pguidDB) +BOOL WINAPI SdbUnregisterDatabase(_In_ const GUID *pguidDB) { - SHIM_ERR("UNIMPLEMENTED, pguidDB = %p\n", pguidDB); + WCHAR KeyBuffer[MAX_PATH], GuidBuffer[50]; + UNICODE_STRING KeyName; + ACCESS_MASK KeyAccess; + OBJECT_ATTRIBUTES ObjectKey = RTL_INIT_OBJECT_ATTRIBUTES(&KeyName, OBJ_CASE_INSENSITIVE); + NTSTATUS Status; + HANDLE DbKey; - return FALSE; + if (!SdbGUIDToString(pguidDB, GuidBuffer, RTL_NUMBER_OF(GuidBuffer))) + { + SHIM_ERR("Unable to Convert GUID to string\n"); + return FALSE; + } + + RtlInitEmptyUnicodeString(&KeyName, KeyBuffer, sizeof(KeyBuffer)); + RtlAppendUnicodeStringToString(&KeyName, &InstalledSDBKeyName); + RtlAppendUnicodeToString(&KeyName, L"\\"); + RtlAppendUnicodeToString(&KeyName, GuidBuffer); + + KeyAccess = Wow64QueryFlag() | DELETE; + Status = NtCreateKey(&DbKey, KeyAccess, &ObjectKey, 0, NULL, 0, NULL); + if (!NT_SUCCESS(Status)) + { + SHIM_ERR("Unable to open %wZ\n", &KeyName); + return FALSE; + } + + Status = NtDeleteKey(DbKey); + if (!NT_SUCCESS(Status)) + SHIM_ERR("Unable to delete %wZ\n", &KeyName); + + NtClose(DbKey); + return NT_SUCCESS(Status); } diff --git a/dll/appcompat/apphelp/layer.c b/dll/appcompat/apphelp/layer.c index 36f9e86ae8a..9c35c3f19fa 100644 --- a/dll/appcompat/apphelp/layer.c +++ b/dll/appcompat/apphelp/layer.c @@ -2,7 +2,7 @@ * PROJECT: ReactOS Application compatibility module * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: Registry layer manipulation functions - * COPYRIGHT: Copyright 2015-2017 Mark Jansen (mark.jansen@reactos.org) + * COPYRIGHT: Copyright 2015-2019 Mark Jansen (mark.jansen@reactos.org) */ #define WIN32_NO_STATUS @@ -176,7 +176,7 @@ BOOL SdbpResolvePath(PSDB_TMP_STR LongPath, PCWSTR wszPath) } static ACCESS_MASK g_QueryFlag = 0xffffffff; -ACCESS_MASK QueryFlag(void) +ACCESS_MASK Wow64QueryFlag(void) { if (g_QueryFlag == 0xffffffff) { @@ -216,7 +216,7 @@ NTSTATUS SdbpOpenKey(PUNICODE_STRING FullPath, BOOL bMachine, ACCESS_MASK Access RtlFreeUnicodeString(&BasePath); RtlAppendUnicodeToString(FullPath, LayersKey); - Status = NtOpenKey(KeyHandle, Access | QueryFlag(), &ObjectLayer); + Status = NtOpenKey(KeyHandle, Access | Wow64QueryFlag(), &ObjectLayer); if (!NT_SUCCESS(Status)) { SHIM_ERR("Unable to open Key \"%wZ\" Status 0x%lx\n", FullPath, Status);