Reactos
at master 375 lines 13 kB view raw
1/* 2 * PROJECT: apphelp_apitest 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Tests for shim database registration 5 * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8#include <ntstatus.h> 9#define WIN32_NO_STATUS 10#include <windef.h> 11#include <ntndk.h> 12#include <atlbase.h> 13#include <strsafe.h> 14#include "wine/test.h" 15 16static const unsigned char rawDB[] = 17{ 18 /* Header: Major, Minor, 'sdbf' */ 19 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x73, 0x64, 0x62, 0x66, 20 21 /* TAG_DATABASE, Length */ 22 0x01, 0x70, 0x22, 0x00, 0x00, 0x00, 23 /* TAG_NAME, Value */ 24 0x01, 0x60, 0x06, 0x00, 0x00, 0x00, 25 26 /* TAG_DATABASE_ID, Length, Value*/ 27 0x07, 0x90, 0x10, 0x00, 0x00, 0x00, 28 /* offset 30 */ 29 0xEB, 0x75, 0xDD, 0x79, 0x98, 0xC0, 0x57, 0x47, 0x99, 0x65, 0x9E, 0x83, 0xC4, 0xCA, 0x9D, 0xA4, 30 31 /* TAG_LIBRARY, Length */ 32 0x02, 0x70, 0x00, 0x00, 0x00, 0x00, 33 34 /* TAG_STRINGTABLE, Length */ 35 0x01, 0x78, 0x0E, 0x00, 0x00, 0x00, 36 /* TAG_STRINGTABLE_ITEM, Length, Value */ 37 0x01, 0x88, 0x08, 0x00, 0x00, 0x00, 38 0x49, 0x00, 0x43, 0x00, 0x53, 0x00, 0x00, 0x00 39}; 40 41static BOOL WriteSdbFile(const WCHAR* FileName, const unsigned char* Data, DWORD Size, const GUID* CustomID) 42{ 43 BOOL Success; 44 DWORD dwWritten; 45 HANDLE Handle = CreateFileW(FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 46 47 if (Handle == INVALID_HANDLE_VALUE) 48 { 49 skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError()); 50 return FALSE; 51 } 52 Success = WriteFile(Handle, Data, Size, &dwWritten, NULL); 53 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError()); 54 ok(dwWritten == Size, "WriteFile wrote %lu bytes instead of %lu\n", dwWritten, Size); 55 if (CustomID) 56 { 57 DWORD dwGuidSize; 58 SetFilePointer(Handle, 30, NULL, FILE_BEGIN); 59 Success = WriteFile(Handle, CustomID, sizeof(*CustomID), &dwGuidSize, NULL); 60 ok(dwGuidSize == sizeof(GUID), "WriteFile wrote %lu bytes instead of 0l%u\n", dwGuidSize, sizeof(GUID)); 61 } 62 CloseHandle(Handle); 63 return Success && (dwWritten == Size); 64} 65 66 67 68static const GUID GUID_DATABASE_SHIM = { 0x11111111, 0x1111, 0x1111, { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 } }; 69static const GUID GUID_DATABASE_MSI = { 0xd8ff6d16, 0x6a3a, 0x468a, { 0x8b, 0x44, 0x01, 0x71, 0x4d, 0xdc, 0x49, 0xea } }; 70static const GUID GUID_DATABASE_DRIVERS = { 0xf9ab2228, 0x3312, 0x4a73, { 0xb6, 0xf9, 0x93, 0x6d, 0x70, 0xe1, 0x12, 0xef } }; 71static const GUID TEST_DB_GUID = { 0x79dd75eb, 0xc098, 0x4757, { 0x99, 0x65, 0x9e, 0x83, 0xc4, 0xca, 0x9d, 0xa4 } }; 72 73#define SDB_DATABASE_MAIN 0x80000000 74 75BOOL (WINAPI *pSdbRegisterDatabase)(LPCWSTR pszDatabasePath, DWORD dwDatabaseType); 76BOOL (WINAPI *pSdbRegisterDatabaseEx)(LPCWSTR pszDatabasePath, DWORD dwDatabaseType, const PULONGLONG pTimeStamp); 77BOOL (WINAPI *pSdbUnregisterDatabase)(REFGUID pguidDB); 78 79 80extern "C" 81BOOL IsUserAdmin(VOID) 82{ 83 BOOL Result; 84 SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY }; 85 PSID AdministratorsGroup; 86 87 Result = AllocateAndInitializeSid(&NtAuthority, 2, 88 SECURITY_BUILTIN_DOMAIN_RID, 89 DOMAIN_ALIAS_RID_ADMINS, 90 0, 0, 0, 0, 0, 0, 91 &AdministratorsGroup); 92 if (Result) 93 { 94 if (!CheckTokenMembership(NULL, AdministratorsGroup, &Result)) 95 Result = FALSE; 96 FreeSid(AdministratorsGroup); 97 } 98 99 return Result; 100} 101 102static DWORD g_QueryFlag = 0xffffffff; 103static DWORD QueryFlag(void) 104{ 105 if (g_QueryFlag == 0xffffffff) 106 { 107 ULONG_PTR wow64_ptr = 0; 108 NTSTATUS status = NtQueryInformationProcess(NtCurrentProcess(), ProcessWow64Information, &wow64_ptr, sizeof(wow64_ptr), NULL); 109 g_QueryFlag = (NT_SUCCESS(status) && wow64_ptr != 0) ? KEY_WOW64_64KEY : 0; 110 } 111 return g_QueryFlag; 112} 113 114static void FileTimeNow(ULARGE_INTEGER& Result) 115{ 116 FILETIME TimeBuffer; 117 118 GetSystemTimeAsFileTime(&TimeBuffer); 119 Result.HighPart = TimeBuffer.dwHighDateTime; 120 Result.LowPart = TimeBuffer.dwLowDateTime; 121} 122 123static void ok_keys_(REFGUID Guid, LPCWSTR DisplayName, LPCWSTR Path, DWORD Type, PULONGLONG TimeStamp) 124{ 125 UNICODE_STRING GuidString; 126 WCHAR StringBuffer[200]; 127 DWORD ValueBuffer; 128 ULARGE_INTEGER LargeUIntBuffer; 129 130 CRegKey key; 131 LSTATUS Status = key.Open(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\InstalledSDB", KEY_READ | QueryFlag()); 132 winetest_ok(!Status, "Unable to open InstalledSDB key\n"); 133 if (Status) 134 return; 135 136 if (!SUCCEEDED(RtlStringFromGUID(Guid, &GuidString))) 137 { 138 ok(0, "Unable to format guid\n"); 139 return; 140 } 141 142 Status = key.Open(key.m_hKey, GuidString.Buffer, KEY_READ); 143 winetest_ok(!Status, "Unable to open %s key (0x%lx)\n", wine_dbgstr_w(GuidString.Buffer), Status); 144 RtlFreeUnicodeString(&GuidString); 145 if (Status) 146 return; 147 148 ULONG nChars = _countof(StringBuffer); 149 Status = key.QueryStringValue(L"DatabaseDescription", StringBuffer, &nChars); 150 winetest_ok(!Status, "Unable to read DatabaseDescription (0x%lx)\n", Status); 151 if (!Status) 152 winetest_ok(!wcscmp(DisplayName, StringBuffer), "Expected DatabaseDescription to be %s, was %s\n", wine_dbgstr_w(DisplayName), wine_dbgstr_w(StringBuffer)); 153 154 nChars = _countof(StringBuffer); 155 Status = key.QueryStringValue(L"DatabasePath", StringBuffer, &nChars); 156 winetest_ok(!Status, "Unable to read DatabasePath (0x%lx)\n", Status); 157 if (!Status) 158 winetest_ok(!wcscmp(Path, StringBuffer), "Expected DatabasePath to be %s, was %s\n", wine_dbgstr_w(Path), wine_dbgstr_w(StringBuffer)); 159 160 Status = key.QueryDWORDValue(L"DatabaseType", ValueBuffer); 161 winetest_ok(!Status, "Unable to read DatabaseType (0x%lx)\n", Status); 162 if (!Status) 163 winetest_ok(ValueBuffer == Type, "Expected DatabaseType to be 0x%lx, was 0x%lx\n", Type, ValueBuffer); 164 165 Status = key.QueryQWORDValue(L"DatabaseInstallTimeStamp", LargeUIntBuffer.QuadPart); 166 winetest_ok(!Status, "Unable to read DatabaseInstallTimeStamp (0x%lx)\n", Status); 167 if (!Status) 168 { 169 if (TimeStamp) 170 { 171 winetest_ok(LargeUIntBuffer.QuadPart == *TimeStamp, "Expected DatabaseInstallTimeStamp to be %s, was %s\n", 172 wine_dbgstr_longlong(*TimeStamp), wine_dbgstr_longlong(LargeUIntBuffer.QuadPart)); 173 } 174 else 175 { 176 ULARGE_INTEGER CurrentTime; 177 FileTimeNow(CurrentTime); 178 ULONG DiffMS = (ULONG)((CurrentTime.QuadPart - LargeUIntBuffer.QuadPart) / 10000); 179 winetest_ok(DiffMS < 5000 , "Expected DatabaseInstallTimeStamp to be less than 5 seconds before now (was: %lu)\n", DiffMS); 180 } 181 } 182} 183 184 185#define ok_keys (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : ok_keys_ 186 187 188START_TEST(register) 189{ 190 WCHAR TempPath[MAX_PATH * 2]; 191 BOOL Success; 192 HMODULE hdll; 193 194 SetEnvironmentVariableA("SHIM_DEBUG_LEVEL", "4"); 195 SetEnvironmentVariableA("SHIMENG_DEBUG_LEVEL", "4"); 196 SetEnvironmentVariableA("DEBUGCHANNEL", "+apphelp"); 197 198 //silence_debug_output(); 199 hdll = LoadLibraryA("apphelp.dll"); 200 201 *(void**)&pSdbRegisterDatabase = (void*)GetProcAddress(hdll, "SdbRegisterDatabase"); 202 *(void**)&pSdbRegisterDatabaseEx = (void*)GetProcAddress(hdll, "SdbRegisterDatabaseEx"); 203 *(void**)&pSdbUnregisterDatabase = (void*)GetProcAddress(hdll, "SdbUnregisterDatabase"); 204 205 if (!pSdbRegisterDatabase || !pSdbRegisterDatabaseEx || !pSdbUnregisterDatabase) 206 { 207 skip("Not all functions present: %p, %p, %p\n", pSdbRegisterDatabase, pSdbRegisterDatabaseEx, pSdbUnregisterDatabase); 208 return; 209 } 210 211 /* [Err ][SdbUnregisterDatabase] Failed to open key "\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\InstalledSDB\{11111111-1111-1111-1111-111111111111}" Status 0xc0000034 */ 212 ok_int(pSdbUnregisterDatabase(GUID_DATABASE_SHIM), FALSE); 213 ok_int(pSdbUnregisterDatabase(GUID_DATABASE_MSI), FALSE); 214 ok_int(pSdbUnregisterDatabase(GUID_DATABASE_DRIVERS), FALSE); 215 216 217 if (!IsUserAdmin()) 218 { 219 skip("Not running as admin, unable to install databases!\n"); 220 return; 221 } 222 223 GetTempPathW(_countof(TempPath), TempPath); 224 StringCchCatW(TempPath, _countof(TempPath), L"\\shim_db.sdb"); 225 if (!WriteSdbFile(TempPath, rawDB, sizeof(rawDB), NULL)) 226 { 227 skip("Cannot write %s\n", wine_dbgstr_w(TempPath)); 228 return; 229 } 230 231 /* No Type */ 232 Success = pSdbRegisterDatabase(TempPath, 0); 233 ok_int(Success, TRUE); 234 if (Success) 235 { 236 ok_keys(TEST_DB_GUID, L"ICS", TempPath, 0, NULL); 237 Success = pSdbUnregisterDatabase(TEST_DB_GUID); 238 ok_int(Success, TRUE); 239 } 240 241 /* Unknown type */ 242 Success = pSdbRegisterDatabase(TempPath, 1); 243 ok_int(Success, TRUE); 244 if (Success) 245 { 246 ok_keys(TEST_DB_GUID, L"ICS", TempPath, 1, NULL); 247 Success = pSdbUnregisterDatabase(TEST_DB_GUID); 248 ok_int(Success, TRUE); 249 } 250 251 /* System type */ 252 Success = pSdbRegisterDatabase(TempPath, SDB_DATABASE_MAIN); 253 ok_int(Success, TRUE); 254 if (Success) 255 { 256 ok_keys(TEST_DB_GUID, L"ICS", TempPath, SDB_DATABASE_MAIN, NULL); 257 Success = pSdbUnregisterDatabase(TEST_DB_GUID); 258 ok_int(Success, TRUE); 259 } 260 261 /* No type, null time */ 262 Success = pSdbRegisterDatabaseEx(TempPath, 0, NULL); 263 ok_int(Success, TRUE); 264 if (Success) 265 { 266 ok_keys(TEST_DB_GUID, L"ICS", TempPath, 0, NULL); 267 Success = pSdbUnregisterDatabase(TEST_DB_GUID); 268 ok_int(Success, TRUE); 269 } 270 271 /* Unknown type, null time */ 272 Success = pSdbRegisterDatabaseEx(TempPath, 1, NULL); 273 ok_int(Success, TRUE); 274 if (Success) 275 { 276 ok_keys(TEST_DB_GUID, L"ICS", TempPath, 1, NULL); 277 Success = pSdbUnregisterDatabase(TEST_DB_GUID); 278 ok_int(Success, TRUE); 279 } 280 281 282 /* System type, null time */ 283 Success = pSdbRegisterDatabaseEx(TempPath, SDB_DATABASE_MAIN, NULL); 284 ok_int(Success, TRUE); 285 if (Success) 286 { 287 ok_keys(TEST_DB_GUID, L"ICS", TempPath, SDB_DATABASE_MAIN, NULL); 288 Success = pSdbUnregisterDatabase(TEST_DB_GUID); 289 ok_int(Success, TRUE); 290 } 291 292 ULARGE_INTEGER Time; 293 FileTimeNow(Time); 294 Time.QuadPart ^= 0xffffffffffffffffll; 295 /* No type, random time */ 296 Success = pSdbRegisterDatabaseEx(TempPath, 0, &Time.QuadPart); 297 ok_int(Success, TRUE); 298 if (Success) 299 { 300 ok_keys(TEST_DB_GUID, L"ICS", TempPath, 0, &Time.QuadPart); 301 Success = pSdbUnregisterDatabase(TEST_DB_GUID); 302 ok_int(Success, TRUE); 303 } 304 305 /* Unknown type, random time */ 306 Success = pSdbRegisterDatabaseEx(TempPath, 1, &Time.QuadPart); 307 ok_int(Success, TRUE); 308 if (Success) 309 { 310 ok_keys(TEST_DB_GUID, L"ICS", TempPath, 1, &Time.QuadPart); 311 Success = pSdbUnregisterDatabase(TEST_DB_GUID); 312 ok_int(Success, TRUE); 313 } 314 315 /* System type, random time */ 316 Success = pSdbRegisterDatabaseEx(TempPath, SDB_DATABASE_MAIN, &Time.QuadPart); 317 ok_int(Success, TRUE); 318 if (Success) 319 { 320 ok_keys(TEST_DB_GUID, L"ICS", TempPath, SDB_DATABASE_MAIN, &Time.QuadPart); 321 Success = pSdbUnregisterDatabase(TEST_DB_GUID); 322 ok_int(Success, TRUE); 323 } 324 325 /* System reserved ID's */ 326 if (!WriteSdbFile(TempPath, rawDB, sizeof(rawDB), &GUID_DATABASE_SHIM)) 327 { 328 skip("Cannot write %s\n", wine_dbgstr_w(TempPath)); 329 DeleteFileW(TempPath); 330 return; 331 } 332 333 Success = pSdbRegisterDatabase(TempPath, 0); 334 ok_int(Success, TRUE); 335 if (Success) 336 { 337 ok_keys(GUID_DATABASE_SHIM, L"ICS", TempPath, 0, NULL); 338 Success = pSdbUnregisterDatabase(GUID_DATABASE_SHIM); 339 ok_int(Success, TRUE); 340 } 341 342 if (!WriteSdbFile(TempPath, rawDB, sizeof(rawDB), &GUID_DATABASE_MSI)) 343 { 344 skip("Cannot write %s\n", wine_dbgstr_w(TempPath)); 345 DeleteFileW(TempPath); 346 return; 347 } 348 349 Success = pSdbRegisterDatabase(TempPath, 0); 350 ok_int(Success, TRUE); 351 if (Success) 352 { 353 ok_keys(GUID_DATABASE_MSI, L"ICS", TempPath, 0, NULL); 354 Success = pSdbUnregisterDatabase(GUID_DATABASE_MSI); 355 ok_int(Success, TRUE); 356 } 357 358 if (!WriteSdbFile(TempPath, rawDB, sizeof(rawDB), &GUID_DATABASE_DRIVERS)) 359 { 360 skip("Cannot write %s\n", wine_dbgstr_w(TempPath)); 361 DeleteFileW(TempPath); 362 return; 363 } 364 365 Success = pSdbRegisterDatabase(TempPath, 0); 366 ok_int(Success, TRUE); 367 if (Success) 368 { 369 ok_keys(GUID_DATABASE_DRIVERS, L"ICS", TempPath, 0, NULL); 370 Success = pSdbUnregisterDatabase(GUID_DATABASE_DRIVERS); 371 ok_int(Success, TRUE); 372 } 373 374 DeleteFileW(TempPath); 375}