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