6dfe8dbf32c2c2c3ea0b29e4efaa238e56ebf91b
[reactos.git] / rostests / apitests / apphelp / db.c
1 /*
2 * Copyright 2012 Detlef Riekenberg
3 * Copyright 2013 Mislav Blažević
4 * Copyright 2015,2016 Mark Jansen
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21
22 #include <ntstatus.h>
23 #define WIN32_NO_STATUS
24 #include <windows.h>
25 #include <shlwapi.h>
26 #include <winnt.h>
27 #ifdef __REACTOS__
28 #include <ntndk.h>
29 #else
30 #include <winternl.h>
31 #endif
32
33 #include <winerror.h>
34 #include <stdio.h>
35 #include <initguid.h>
36
37 #include "wine/test.h"
38
39 /* data.c */
40 void test_create_db_imp(const char* name);
41
42 #define test_create_db (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_create_db_imp
43
44 typedef WORD TAG;
45 typedef DWORD TAGID;
46 typedef DWORD TAGREF;
47 typedef UINT64 QWORD;
48 typedef VOID* PDB;
49 typedef INT PATH_TYPE;
50 #define DOS_PATH 0
51
52 #define TAGID_NULL 0x0
53 #define TAGID_ROOT 0x0
54 #define _TAGID_ROOT 12
55
56
57 #define TAG_TYPE_MASK 0xF000
58
59 #define TAG_TYPE_NULL 0x1000
60 #define TAG_TYPE_BYTE 0x2000
61 #define TAG_TYPE_WORD 0x3000
62 #define TAG_TYPE_DWORD 0x4000
63 #define TAG_TYPE_QWORD 0x5000
64 #define TAG_TYPE_STRINGREF 0x6000
65 #define TAG_TYPE_LIST 0x7000
66 #define TAG_TYPE_STRING 0x8000
67 #define TAG_TYPE_BINARY 0x9000
68 #define TAG_NULL 0x0
69
70 #define TAG_INCLUDE (0x1 | TAG_TYPE_NULL)
71
72 #define TAG_MATCH_MODE (0x1 | TAG_TYPE_WORD)
73
74 #define TAG_SIZE (0x1 | TAG_TYPE_DWORD)
75 #define TAG_CHECKSUM (0x3 | TAG_TYPE_DWORD)
76 #define TAG_MODULE_TYPE (0x6 | TAG_TYPE_DWORD)
77 #define TAG_VERFILEOS (0x9 | TAG_TYPE_DWORD)
78 #define TAG_VERFILETYPE (0xA | TAG_TYPE_DWORD)
79 #define TAG_PE_CHECKSUM (0xB | TAG_TYPE_DWORD)
80 #define TAG_PROBLEMSEVERITY (0x10 | TAG_TYPE_DWORD)
81 #define TAG_HTMLHELPID (0x15 | TAG_TYPE_DWORD)
82 #define TAG_FLAGS (0x17 | TAG_TYPE_DWORD)
83 #define TAG_LAYER_TAGID (0x1A | TAG_TYPE_DWORD)
84 #define TAG_LINKER_VERSION (0x1C | TAG_TYPE_DWORD)
85 #define TAG_LINK_DATE (0x1D | TAG_TYPE_DWORD)
86 #define TAG_UPTO_LINK_DATE (0x1E | TAG_TYPE_DWORD)
87 #define TAG_APP_NAME_RC_ID (0x24 | TAG_TYPE_DWORD)
88 #define TAG_VENDOR_NAME_RC_ID (0x25 | TAG_TYPE_DWORD)
89 #define TAG_SUMMARY_MSG_RC_ID (0x26 | TAG_TYPE_DWORD)
90 #define TAG_OS_PLATFORM (0x23 | TAG_TYPE_DWORD)
91
92 #define TAG_TIME (0x1 | TAG_TYPE_QWORD)
93 #define TAG_BIN_FILE_VERSION (0x2 | TAG_TYPE_QWORD)
94 #define TAG_BIN_PRODUCT_VERSION (0x3 | TAG_TYPE_QWORD)
95 #define TAG_UPTO_BIN_PRODUCT_VERSION (0x6 | TAG_TYPE_QWORD)
96 #define TAG_UPTO_BIN_FILE_VERSION (0xD | TAG_TYPE_QWORD)
97 #define TAG_FLAG_LUA (0x10 | TAG_TYPE_QWORD)
98
99 #define TAG_DATABASE (0x1 | TAG_TYPE_LIST)
100 #define TAG_INEXCLUD (0x3 | TAG_TYPE_LIST)
101 #define TAG_EXE (0x7 | TAG_TYPE_LIST)
102 #define TAG_MATCHING_FILE (0x8 | TAG_TYPE_LIST)
103 #define TAG_SHIM_REF (0x9| TAG_TYPE_LIST)
104 #define TAG_LAYER (0xB | TAG_TYPE_LIST)
105 #define TAG_APPHELP (0xD | TAG_TYPE_LIST)
106 #define TAG_LINK (0xE | TAG_TYPE_LIST)
107 #define TAG_STRINGTABLE (0x801 | TAG_TYPE_LIST)
108
109 #define TAG_STRINGTABLE_ITEM (0x801 | TAG_TYPE_STRING)
110
111 #define TAG_NAME (0x1 | TAG_TYPE_STRINGREF)
112 #define TAG_MODULE (0x3 | TAG_TYPE_STRINGREF)
113 #define TAG_VENDOR (0x5 | TAG_TYPE_STRINGREF)
114 #define TAG_APP_NAME (0x6 | TAG_TYPE_STRINGREF)
115 #define TAG_COMMAND_LINE (0x8 | TAG_TYPE_STRINGREF)
116 #define TAG_COMPANY_NAME (0x9 | TAG_TYPE_STRINGREF)
117 #define TAG_PRODUCT_NAME (0x10 | TAG_TYPE_STRINGREF)
118 #define TAG_PRODUCT_VERSION (0x11 | TAG_TYPE_STRINGREF)
119 #define TAG_FILE_DESCRIPTION (0x12 | TAG_TYPE_STRINGREF)
120 #define TAG_FILE_VERSION (0x13 | TAG_TYPE_STRINGREF)
121 #define TAG_ORIGINAL_FILENAME (0x14 | TAG_TYPE_STRINGREF)
122 #define TAG_INTERNAL_NAME (0x15 | TAG_TYPE_STRINGREF)
123 #define TAG_LEGAL_COPYRIGHT (0x16 | TAG_TYPE_STRINGREF)
124 #define TAG_APPHELP_DETAILS (0x18 | TAG_TYPE_STRINGREF)
125 #define TAG_LINK_URL (0x19 | TAG_TYPE_STRINGREF)
126 #define TAG_APPHELP_TITLE (0x1B | TAG_TYPE_STRINGREF)
127
128 #define TAG_COMPILER_VERSION (0x22 | TAG_TYPE_STRINGREF)
129
130 #define TAG_GENERAL (0x2 | TAG_TYPE_NULL)
131
132 #define TAG_EXE_ID (0x4 | TAG_TYPE_BINARY)
133 #define TAG_DATA_BITS (0x5 | TAG_TYPE_BINARY)
134 #define TAG_DATABASE_ID (0x7 | TAG_TYPE_BINARY)
135
136
137
138 static HMODULE hdll;
139 static LPCWSTR (WINAPI *pSdbTagToString)(TAG);
140 static PDB (WINAPI *pSdbOpenDatabase)(LPCWSTR, PATH_TYPE);
141 static PDB (WINAPI *pSdbCreateDatabase)(LPCWSTR, PATH_TYPE);
142 static BOOL (WINAPI *pSdbGetDatabaseVersion)(LPCWSTR, PDWORD, PDWORD);
143 static void (WINAPI *pSdbCloseDatabase)(PDB);
144 static void (WINAPI *pSdbCloseDatabaseWrite)(PDB);
145 static TAG (WINAPI *pSdbGetTagFromTagID)(PDB, TAGID);
146 static BOOL (WINAPI *pSdbWriteNULLTag)(PDB, TAG);
147 static BOOL (WINAPI *pSdbWriteWORDTag)(PDB, TAG, WORD);
148 static BOOL (WINAPI *pSdbWriteDWORDTag)(PDB, TAG, DWORD);
149 static BOOL (WINAPI *pSdbWriteQWORDTag)(PDB, TAG, QWORD);
150 static BOOL (WINAPI *pSdbWriteBinaryTagFromFile)(PDB, TAG, LPCWSTR);
151 static BOOL (WINAPI *pSdbWriteStringTag)(PDB, TAG, LPCWSTR);
152 static BOOL (WINAPI *pSdbWriteStringRefTag)(PDB, TAG, TAGID);
153 static TAGID (WINAPI *pSdbBeginWriteListTag)(PDB, TAG);
154 static BOOL (WINAPI *pSdbEndWriteListTag)(PDB, TAGID);
155 static TAGID (WINAPI *pSdbFindFirstTag)(PDB, TAGID, TAG);
156 static TAGID (WINAPI *pSdbFindNextTag)(PDB, TAGID, TAGID);
157 static WORD (WINAPI *pSdbReadWORDTag)(PDB, TAGID, WORD);
158 static DWORD (WINAPI *pSdbReadDWORDTag)(PDB, TAGID, DWORD);
159 static QWORD (WINAPI *pSdbReadQWORDTag)(PDB, TAGID, QWORD);
160 static BOOL (WINAPI *pSdbReadBinaryTag)(PDB, TAGID, PBYTE, DWORD);
161 static BOOL (WINAPI *pSdbReadStringTag)(PDB, TAGID, LPWSTR, DWORD);
162 static DWORD (WINAPI *pSdbGetTagDataSize)(PDB, TAGID);
163 static PVOID (WINAPI *pSdbGetBinaryTagData)(PDB, TAGID);
164 static LPWSTR (WINAPI *pSdbGetStringTagPtr)(PDB, TAGID);
165 static TAGID (WINAPI *pSdbGetFirstChild)(PDB, TAGID);
166 static TAGID (WINAPI *pSdbGetNextChild)(PDB, TAGID, TAGID);
167 static BOOL (WINAPI *pSdbGetDatabaseID)(PDB, GUID*);
168 static BOOL (WINAPI *pSdbGUIDToString)(CONST GUID *, PCWSTR, SIZE_T);
169
170 DEFINE_GUID(GUID_DATABASE_TEST,0xe39b0eb0,0x55db,0x450b,0x9b,0xd4,0xd2,0x0c,0x94,0x84,0x26,0x0f);
171
172
173 static void Write(HANDLE file, LPCVOID buffer, DWORD size)
174 {
175 DWORD dwWritten = 0;
176 WriteFile(file, buffer, size, &dwWritten, NULL);
177 }
178
179 static void test_Sdb(void)
180 {
181 static const WCHAR temp[] = {'t','e','m','p',0};
182 static const WCHAR path1[] = {'t','e','m','p','.','s','d','b',0};
183 static const WCHAR path2[] = {'t','e','m','p','2','.','b','i','n',0};
184 static const WCHAR tag_size_string[] = {'S','I','Z','E',0};
185 static const WCHAR tag_flag_lua_string[] = {'F','L','A','G','_','L','U','A',0};
186 static const TAG tags[5] = {
187 TAG_SIZE, TAG_FLAG_LUA, TAG_NAME,
188 TAG_STRINGTABLE, TAG_STRINGTABLE_ITEM
189 };
190 WCHAR buffer[6] = {0};
191 PDB pdb;
192 QWORD qword;
193 DWORD dword;
194 WORD word;
195 BOOL ret;
196 HANDLE file; /* temp file created for testing purpose */
197 TAG tag;
198 TAGID tagid, ptagid, stringref = 6;
199 LPCWSTR string;
200 PBYTE binary;
201
202 pdb = pSdbCreateDatabase(path1, DOS_PATH);
203 ok (pdb != NULL, "failed to create database\n");
204 if(pdb != NULL)
205 {
206 ret = pSdbWriteDWORDTag(pdb, tags[0], 0xDEADBEEF);
207 ok (ret, "failed to write DWORD tag\n");
208 ret = pSdbWriteQWORDTag(pdb, tags[1], 0xDEADBEEFBABE);
209 ok (ret, "failed to write QWORD tag\n");
210 ret = pSdbWriteStringRefTag(pdb, tags[2], stringref);
211 ok (ret, "failed to write stringref tag\n");
212 tagid = pSdbBeginWriteListTag(pdb, tags[3]);
213 ok (tagid != TAGID_NULL, "unexpected NULL tagid\n");
214 ret = pSdbWriteStringTag(pdb, tags[4], temp);
215 ok (ret, "failed to write string tag\n");
216 ret = pSdbWriteNULLTag(pdb, TAG_GENERAL);
217 ok (ret, "failed to write NULL tag\n");
218 ret = pSdbWriteWORDTag(pdb, TAG_MATCH_MODE, 0xACE);
219 ok (ret, "failed to write WORD tag\n");
220 ret = pSdbEndWriteListTag(pdb, tagid);
221 ok (ret, "failed to update list size\n");
222 /* [Err ][SdbCloseDatabase ] Failed to close the file. */
223 pSdbCloseDatabaseWrite(pdb);
224 }
225
226 /* [Err ][SdbGetDatabaseID ] Failed to get root tag */
227 pdb = pSdbOpenDatabase(path1, DOS_PATH);
228 ok(pdb != NULL, "unexpected NULL handle\n");
229
230 if(pdb)
231 {
232 tagid = pSdbGetFirstChild(pdb, TAGID_ROOT);
233 ok(tagid == _TAGID_ROOT, "unexpected tagid %u, expected %u\n", tagid, _TAGID_ROOT);
234
235 tag = pSdbGetTagFromTagID(pdb, tagid);
236 ok(tag == TAG_SIZE, "unexpected tag 0x%x, expected 0x%x\n", tag, TAG_SIZE);
237
238 string = pSdbTagToString(tag);
239 ok(lstrcmpW(string, tag_size_string) == 0, "unexpected string %s, expected %s\n",
240 wine_dbgstr_w(string), wine_dbgstr_w(tag_size_string));
241
242 dword = pSdbReadDWORDTag(pdb, tagid, 0);
243 ok(dword == 0xDEADBEEF, "unexpected value %u, expected 0xDEADBEEF\n", dword);
244
245 tagid = pSdbGetNextChild(pdb, TAGID_ROOT, tagid);
246 ok(tagid == _TAGID_ROOT + sizeof(TAG) + sizeof(DWORD), "unexpected tagid %u, expected %u\n",
247 tagid, _TAGID_ROOT + sizeof(TAG) + sizeof(DWORD));
248
249 tag = pSdbGetTagFromTagID(pdb, tagid);
250 ok (tag == TAG_FLAG_LUA, "unexpected tag 0x%x, expected 0x%x\n", tag, TAG_FLAG_LUA);
251
252 string = pSdbTagToString(tag);
253 ok(lstrcmpW(string, tag_flag_lua_string) == 0, "unexpected string %s, expected %s\n",
254 wine_dbgstr_w(string), wine_dbgstr_w(tag_flag_lua_string));
255
256 qword = pSdbReadQWORDTag(pdb, tagid, 0);
257 ok(qword == 0xDEADBEEFBABE, "unexpected value 0x%I64x, expected 0xDEADBEEFBABE\n", qword);
258
259 tagid = pSdbGetNextChild(pdb, TAGID_ROOT, tagid);
260 string = pSdbGetStringTagPtr(pdb, tagid);
261 ok (string && (lstrcmpW(string, temp) == 0), "unexpected string %s, expected %s\n",
262 wine_dbgstr_w(string), wine_dbgstr_w(temp));
263
264 ptagid = pSdbGetNextChild(pdb, TAGID_ROOT, tagid);
265 tagid = pSdbGetFirstChild(pdb, ptagid);
266
267 string = pSdbGetStringTagPtr(pdb, tagid);
268 ok (string && (lstrcmpW(string, temp) == 0), "unexpected string %s, expected %s\n",
269 wine_dbgstr_w(string), wine_dbgstr_w(temp));
270
271 ok (pSdbReadStringTag(pdb, tagid, buffer, 6), "failed to write string to buffer\n");
272 /* [Err ][SdbpReadTagData ] Buffer too small. Avail: 6, Need: 10. */
273 ok (!pSdbReadStringTag(pdb, tagid, buffer, 3), "string was written to buffer, but failure was expected");
274 ok (pSdbGetTagDataSize(pdb, tagid) == 5 * sizeof(WCHAR), "string has unexpected size\n");
275
276 tagid = pSdbGetNextChild(pdb, ptagid, tagid);
277 tag = pSdbGetTagFromTagID(pdb, tagid);
278 ok (tag == TAG_GENERAL, "unexpected tag 0x%x, expected 0x%x\n", tag, TAG_GENERAL);
279 ok (pSdbGetTagDataSize(pdb, tagid) == 0, "null tag with size > 0\n");
280
281 tagid = pSdbGetNextChild(pdb, ptagid, tagid);
282 word = pSdbReadWORDTag(pdb, tagid, 0);
283 ok (word == 0xACE, "unexpected value 0x%x, expected 0x%x\n", word, 0xACE);
284
285 pSdbCloseDatabase(pdb);
286 }
287 DeleteFileW(path1);
288
289 file = CreateFileW(path2, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
290 ok (file != INVALID_HANDLE_VALUE, "failed to open file\n");
291 Write(file, &qword, 8);
292 CloseHandle(file);
293
294 pdb = pSdbCreateDatabase(path1, DOS_PATH);
295 ok(pdb != NULL, "unexpected NULL handle\n");
296
297 if(pdb)
298 {
299 ret = pSdbWriteBinaryTagFromFile(pdb, TAG_DATA_BITS, path2);
300 ok(ret, "failed to write tag from binary file\n");
301 pSdbCloseDatabaseWrite(pdb); /* [Err ][SdbCloseDatabase ] Failed to close the file. */
302 DeleteFileW(path2);
303
304 pdb = pSdbOpenDatabase(path1, DOS_PATH);
305 ok(pdb != NULL, "unexpected NULL handle\n");
306 binary = pSdbGetBinaryTagData(pdb, _TAGID_ROOT);
307 ok(memcmp(binary, &qword, 8) == 0, "binary data is corrupt\n");
308 ret = pSdbReadBinaryTag(pdb, _TAGID_ROOT, (PBYTE)buffer, 12);
309 ok(ret, "failed to read binary tag\n");
310 ok(memcmp(buffer, &qword, 8) == 0, "binary data is corrupt\n");
311 pSdbCloseDatabase(pdb);
312 }
313 DeleteFileW(path1);
314 }
315
316 /*
317 - Show that a stringtable is automatically generated,
318 - Show that entries in the stringtable are re-used,
319 - validate multiple lists (for the length)
320 */
321 static void test_write_ex(void)
322 {
323 WCHAR path1[] = {'t','e','s','t','.','s','d','b',0};
324 WCHAR test1[] = {'T','E','S','T',0};
325 WCHAR test2[] = {'t','e','s','t',0};
326 PDB pdb;
327 TAGID tagdb, tagstr;
328 TAG tag;
329 DWORD size;
330 BOOL ret;
331 LPWSTR ptr;
332
333 /* Write a small database */
334 pdb = pSdbCreateDatabase(path1, DOS_PATH);
335 ok(pdb != NULL, "Expected a valid database\n");
336 if (!pdb)
337 return;
338 tagdb = pSdbBeginWriteListTag(pdb, TAG_DATABASE);
339 ok(tagdb == 12, "Expected tag to be 12, was %u\n", tagdb);
340 ret = pSdbWriteStringTag(pdb, TAG_NAME, test1);
341 ret = pSdbWriteStringTag(pdb, TAG_NAME, test2);
342 ok(ret, "Expected SdbWriteStringTag to succeed\n");
343 ret = pSdbEndWriteListTag(pdb, tagdb);
344 ok(ret, "Expected SdbEndWriteListTag to succeed\n");
345
346 tagdb = pSdbBeginWriteListTag(pdb, TAG_DATABASE);
347 ok(tagdb == 30, "Expected tag to be 24, was %u\n", tagdb);
348 ret = pSdbWriteStringTag(pdb, TAG_NAME, test1);
349 ret = pSdbWriteStringTag(pdb, TAG_NAME, test2);
350 ok(ret, "Expected SdbWriteStringTag to succeed\n");
351 ret = pSdbEndWriteListTag(pdb, tagdb);
352 ok(ret, "Expected SdbEndWriteListTag to succeed\n");
353
354 pSdbCloseDatabaseWrite(pdb);
355
356 /* Now validate it's contents */
357 pdb = pSdbOpenDatabase(path1, DOS_PATH);
358 ok(pdb != NULL, "Expected a valid database\n");
359 if (!pdb)
360 return;
361
362 tagdb = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
363 ok(tagdb == 12, "Expected tag to be 12, was %u\n", tagdb);
364 size = pSdbGetTagDataSize(pdb, tagdb);
365 ok(size == 12, "Expected size to be 12, was %u\n", size);
366
367 tagstr = pSdbFindFirstTag(pdb, tagdb, TAG_NAME);
368 ok(tagstr == 18, "Expected string tag to be 18, was %u\n", tagstr);
369 tag = pSdbGetTagFromTagID(pdb, tagstr);
370 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x\n", (DWORD)tag);
371 size = pSdbGetTagDataSize(pdb, tagstr);
372 ok(size == 4, "Expected size to be 4, was 0x%x\n", size);
373
374 tagstr = pSdbFindNextTag(pdb, tagdb, tagstr);
375 ok(tagstr == 24, "Expected string tag to be 24, was %u\n", tagstr);
376 tag = pSdbGetTagFromTagID(pdb, tagstr);
377 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x\n", (DWORD)tag);
378 size = pSdbGetTagDataSize(pdb, tagstr);
379 ok(size == 4, "Expected size to be 4, was 0x%x\n", size);
380
381 tagdb = pSdbFindNextTag(pdb, TAGID_ROOT, tagdb);
382 ok(tagdb == 30, "Expected tag to be 30, was %u\n", tagdb);
383 size = pSdbGetTagDataSize(pdb, tagdb);
384 ok(size == 12, "Expected size to be 12, was %u\n", size);
385
386 tagstr = pSdbFindFirstTag(pdb, tagdb, TAG_NAME);
387 ok(tagstr == 36, "Expected string tag to be 36, was %u\n", tagstr);
388 tag = pSdbGetTagFromTagID(pdb, tagstr);
389 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x\n", (DWORD)tag);
390 size = pSdbGetTagDataSize(pdb, tagstr);
391 ok(size == 4, "Expected size to be 4, was %u\n", size);
392
393 tagstr = pSdbFindNextTag(pdb, tagdb, tagstr);
394 ok(tagstr == 42, "Expected string tag to be 42, was %u\n", tagstr);
395 tag = pSdbGetTagFromTagID(pdb, tagstr);
396 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x\n", (DWORD)tag);
397 size = pSdbGetTagDataSize(pdb, tagstr);
398 ok(size == 4, "Expected size to be 4, was 0x%x\n", size);
399
400 tagdb = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_STRINGTABLE);
401 ok(tagdb == 48, "Expected tag to be 48, was %u\n", tagdb);
402 size = pSdbGetTagDataSize(pdb, tagdb);
403 ok(size == 32, "Expected size to be 32, was %u\n", size);
404
405 tagstr = pSdbGetFirstChild(pdb, tagdb);
406 ok(tagstr == 54, "Expected string tag to be 54, was %u\n", tagstr);
407 tag = pSdbGetTagFromTagID(pdb, tagstr);
408 ok(tag == TAG_STRINGTABLE_ITEM, "Expected tag to be TAG_STRINGTABLE_ITEM, was 0x%x\n", (DWORD)tag);
409 size = pSdbGetTagDataSize(pdb, tagstr);
410 ok(size == 10, "Expected size to be 10, was %u\n", size);
411 ptr = pSdbGetStringTagPtr(pdb, tagstr);
412 ok(ptr != NULL, "Expected a valid pointer\n");
413 if (ptr)
414 ok(!wcscmp(ptr, test1), "Expected ptr to be %s, was %s\n", wine_dbgstr_w(test1), wine_dbgstr_w(ptr));
415
416 tagstr = pSdbGetNextChild(pdb, tagdb, tagstr);
417 ok(tagstr == 70, "Expected string tag to be 70, was %u\n", tagstr);
418 tag = pSdbGetTagFromTagID(pdb, tagstr);
419 ok(tag == TAG_STRINGTABLE_ITEM, "Expected tag to be TAG_STRINGTABLE_ITEM, was 0x%x\n", (DWORD)tag);
420 size = pSdbGetTagDataSize(pdb, tagstr);
421 ok(size == 10, "Expected size to be 10, was %u\n", size);
422 ptr = pSdbGetStringTagPtr(pdb, tagstr);
423 ok(ptr != NULL, "Expected a valid pointer\n");
424 if (ptr)
425 ok(!wcscmp(ptr, test2), "Expected ptr to be %s, was %s\n", wine_dbgstr_w(test2), wine_dbgstr_w(ptr));
426
427 pSdbCloseDatabase(pdb);
428 }
429
430
431 static void write_db_strings(const WCHAR* name, const WCHAR* data[], size_t count)
432 {
433 PDB pdb;
434 size_t n;
435 BOOL ret;
436
437 pdb = pSdbCreateDatabase(name, DOS_PATH);
438 ok(pdb != NULL, "Failed to create db for case %u\n", count);
439 for (n = 0; n < count; ++n)
440 {
441 ret = pSdbWriteStringTag(pdb, TAG_NAME, data[n]);
442 ok(ret, "Failed to write string %u/%u\n", n, count);
443 }
444 pSdbCloseDatabaseWrite(pdb);
445 }
446
447 static void test_stringtable()
448 {
449 static const WCHAR path1[] = {'t','e','s','t','.','s','d','b',0};
450 static const WCHAR test1[] = {'t','e','s','t','1',0};
451 static const WCHAR test2[] = {'T','e','s','t','1',0};
452 static const WCHAR test3[] = {'T','E','s','t','1',0};
453 static const WCHAR test4[] = {'T','E','S','T','1',0};
454 static const WCHAR test5[] = {'T','E','S','T','2',0};
455 static const WCHAR lipsum[] = {'L','o','r','e','m',' ','i','p','s','u','m',' ','d','o','l','o','r',' ','s','i','t',' ','a','m','e','t',',',' ','c','o','n','s','e','c','t','e','t','u','r',' ','a','d','i','p','i','s','c','i','n','g',' ','e','l','i','t','.',' ','N','u','l','l','a',' ','a','n','t','e',' ','r','i','s','u','s',',',' ','m','a','l','e','s','u','a','d','a',' ','s','e','d',' ','i','a','c','u','l','i','s',' ','l','u','c','t','u','s',',',' ','o','r','n','a','r','e',' ','p','u','l','v','i','n','a','r',' ','v','e','l','i','t','.',' ','L','o','r','e','m',' ','i','p','s','u','m',' ','d','o','l','o','r',' ','s','i','t',' ','a','m','e','t',',',' ','c','o','n','s','e','c','t','e','t','u','r',' ','a','d','i','p','i','s','c','i','n','g',' ','e','l','i','t','.',' ','I','n','t','e','g','e','r',' ','q','u','i','s',' ','f','e','l','i','s',' ','u','t',' ','l','e','o',' ','e','l','e','i','f','e','n','d',' ','u','l','t','r','i','c','e','s',' ','f','i','n','i','b','u','s',' ','e','u',' ','d','o','l','o','r','.',' ','I','n',' ','b','i','b','e','n','d','u','m',',',' ','e','r','o','s',' ','e','u',' ','f','a','u','c','i','b','u','s',' ','c','o','n','s','e','q','u','a','t',',',' ','n','i','s','i',' ','m','a','g','n','a',' ','v','e','n','e','n','a','t','i','s',' ','j','u','s','t','o',',',' ','a','t',' ','t','r','i','s','t','i','q','u','e',' ','m','e','t','u','s',' ','d','o','l','o','r',' ','u','t',' ','r','i','s','u','s','.',' ','N','u','n','c',' ','e','u',' ','o','d','i','o',' ','d','i','g','n','i','s','s','i','m',',',' ','o','r','n','a','r','e',' ','a','n','t','e',' ','g','r','a','v','i','d','a',',',' ','l','o','b','o','r','t','i','s',' ','e','r','o','s','.',' ','C','r','a','s',' ','s','e','m',' ','e','x',',',' ','c','o','n','s','e','c','t','e','t','u','r',' ','p','u','l','v','i','n','a','r',' ','t','i','n','c','i','d','u','n','t',' ','e','u',',',' ','c','o','n','g','u','e',' ','a',' ','e','r','o','s','.',' ','C','u','r','a','b','i','t','u','r',' ','e','r','o','s',' ','e','r','a','t',',',' ','p','e','l','l','e','n','t','e','s','q','u','e',' ','e','t',' ','n','i','b','h',' ','q','u','i','s',',',' ','i','n','t','e','r','d','u','m',' ','t','e','m','p','o','r',' ','o','d','i','o','.',' ','E','t','i','a','m',' ','s','a','p','i','e','n',' ','s','a','p','i','e','n',',',' ','a','l','i','q','u','a','m',' ','u','t',' ','a','l','i','q','u','a','m',' ','a','t',',',' ','s','a','g','i','t','t','i','s',' ','e','u',' ','m','a','g','n','a','.',' ','M','a','e','c','e','n','a','s',' ','m','a','g','n','a',' ','m','a','g','n','a',',',' ','s','u','s','c','i','p','i','t',' ','u','t',' ','l','o','r','e','m',' ','u','t',',',' ','v','a','r','i','u','s',' ','p','r','e','t','i','u','m',' ','f','e','l','i','s','.',' ','I','n','t','e','g','e','r',' ','t','i','n','c','i','d','u','n','t',',',' ','m','e','t','u','s',' ','v','e','l',' ','s','o','l','l','i','c','i','t','u','d','i','n',' ','f','i','n','i','b','u','s',',',' ','f','e','l','i','s',' ','e','r','a','t',' ','m','o','l','e','s','t','i','e',' ','u','r','n','a',',',' ','a',' ','c','o','n','d','i','m','e','n','t','u','m',' ','a','u','g','u','e',' ','a','r','c','u',' ','v','i','t','a','e',' ','r','i','s','u','s','.',' ','E','t','i','a','m',' ','i','d',' ','s','a','g','i','t','t','i','s',' ','q','u','a','m','.',' ','M','o','r','b','i',' ','a',' ','u','l','t','r','i','c','i','e','s',' ','n','u','n','c','.',' ','P','h','a','s','e','l','l','u','s',' ','e','r','o','s',' ','r','i','s','u','s',',',' ','c','u','r','s','u','s',' ','u','l','l','a','m','c','o','r','p','e','r',' ','m','a','s','s','a',' ','s','e','d',',',' ','d','i','g','n','i','s','s','i','m',' ','c','o','n','s','e','q','u','a','t',' ','l','i','g','u','l','a','.',' ','A','l','i','q','u','a','m',' ','t','u','r','p','i','s',' ','a','r','c','u',',',' ','a','c','c','u','m','s','a','n',' ','q','u','i','s',' ','s','a','p','i','e','n',' ','v','i','t','a','e',',',' ','l','a','c','i','n','i','a',' ','e','u','i','s','m','o','d',' ','n','i','s','l','.',' ','M','a','u','r','i','s',' ','i','d',' ','f','e','l','i','s',' ','s','e','m','.',0};
456 /* Last char changed from '.' to '!' */
457 static const WCHAR lipsum2[] = {'L','o','r','e','m',' ','i','p','s','u','m',' ','d','o','l','o','r',' ','s','i','t',' ','a','m','e','t',',',' ','c','o','n','s','e','c','t','e','t','u','r',' ','a','d','i','p','i','s','c','i','n','g',' ','e','l','i','t','.',' ','N','u','l','l','a',' ','a','n','t','e',' ','r','i','s','u','s',',',' ','m','a','l','e','s','u','a','d','a',' ','s','e','d',' ','i','a','c','u','l','i','s',' ','l','u','c','t','u','s',',',' ','o','r','n','a','r','e',' ','p','u','l','v','i','n','a','r',' ','v','e','l','i','t','.',' ','L','o','r','e','m',' ','i','p','s','u','m',' ','d','o','l','o','r',' ','s','i','t',' ','a','m','e','t',',',' ','c','o','n','s','e','c','t','e','t','u','r',' ','a','d','i','p','i','s','c','i','n','g',' ','e','l','i','t','.',' ','I','n','t','e','g','e','r',' ','q','u','i','s',' ','f','e','l','i','s',' ','u','t',' ','l','e','o',' ','e','l','e','i','f','e','n','d',' ','u','l','t','r','i','c','e','s',' ','f','i','n','i','b','u','s',' ','e','u',' ','d','o','l','o','r','.',' ','I','n',' ','b','i','b','e','n','d','u','m',',',' ','e','r','o','s',' ','e','u',' ','f','a','u','c','i','b','u','s',' ','c','o','n','s','e','q','u','a','t',',',' ','n','i','s','i',' ','m','a','g','n','a',' ','v','e','n','e','n','a','t','i','s',' ','j','u','s','t','o',',',' ','a','t',' ','t','r','i','s','t','i','q','u','e',' ','m','e','t','u','s',' ','d','o','l','o','r',' ','u','t',' ','r','i','s','u','s','.',' ','N','u','n','c',' ','e','u',' ','o','d','i','o',' ','d','i','g','n','i','s','s','i','m',',',' ','o','r','n','a','r','e',' ','a','n','t','e',' ','g','r','a','v','i','d','a',',',' ','l','o','b','o','r','t','i','s',' ','e','r','o','s','.',' ','C','r','a','s',' ','s','e','m',' ','e','x',',',' ','c','o','n','s','e','c','t','e','t','u','r',' ','p','u','l','v','i','n','a','r',' ','t','i','n','c','i','d','u','n','t',' ','e','u',',',' ','c','o','n','g','u','e',' ','a',' ','e','r','o','s','.',' ','C','u','r','a','b','i','t','u','r',' ','e','r','o','s',' ','e','r','a','t',',',' ','p','e','l','l','e','n','t','e','s','q','u','e',' ','e','t',' ','n','i','b','h',' ','q','u','i','s',',',' ','i','n','t','e','r','d','u','m',' ','t','e','m','p','o','r',' ','o','d','i','o','.',' ','E','t','i','a','m',' ','s','a','p','i','e','n',' ','s','a','p','i','e','n',',',' ','a','l','i','q','u','a','m',' ','u','t',' ','a','l','i','q','u','a','m',' ','a','t',',',' ','s','a','g','i','t','t','i','s',' ','e','u',' ','m','a','g','n','a','.',' ','M','a','e','c','e','n','a','s',' ','m','a','g','n','a',' ','m','a','g','n','a',',',' ','s','u','s','c','i','p','i','t',' ','u','t',' ','l','o','r','e','m',' ','u','t',',',' ','v','a','r','i','u','s',' ','p','r','e','t','i','u','m',' ','f','e','l','i','s','.',' ','I','n','t','e','g','e','r',' ','t','i','n','c','i','d','u','n','t',',',' ','m','e','t','u','s',' ','v','e','l',' ','s','o','l','l','i','c','i','t','u','d','i','n',' ','f','i','n','i','b','u','s',',',' ','f','e','l','i','s',' ','e','r','a','t',' ','m','o','l','e','s','t','i','e',' ','u','r','n','a',',',' ','a',' ','c','o','n','d','i','m','e','n','t','u','m',' ','a','u','g','u','e',' ','a','r','c','u',' ','v','i','t','a','e',' ','r','i','s','u','s','.',' ','E','t','i','a','m',' ','i','d',' ','s','a','g','i','t','t','i','s',' ','q','u','a','m','.',' ','M','o','r','b','i',' ','a',' ','u','l','t','r','i','c','i','e','s',' ','n','u','n','c','.',' ','P','h','a','s','e','l','l','u','s',' ','e','r','o','s',' ','r','i','s','u','s',',',' ','c','u','r','s','u','s',' ','u','l','l','a','m','c','o','r','p','e','r',' ','m','a','s','s','a',' ','s','e','d',',',' ','d','i','g','n','i','s','s','i','m',' ','c','o','n','s','e','q','u','a','t',' ','l','i','g','u','l','a','.',' ','A','l','i','q','u','a','m',' ','t','u','r','p','i','s',' ','a','r','c','u',',',' ','a','c','c','u','m','s','a','n',' ','q','u','i','s',' ','s','a','p','i','e','n',' ','v','i','t','a','e',',',' ','l','a','c','i','n','i','a',' ','e','u','i','s','m','o','d',' ','n','i','s','l','.',' ','M','a','u','r','i','s',' ','i','d',' ','f','e','l','i','s',' ','s','e','m','!',0};
458 static const WCHAR empty[] = {0};
459 static const WCHAR* all[] = { test1, test2, test3, test4, test5, lipsum, lipsum2, empty };
460 static const TAGID expected_str[] = { 0xc, 0x12, 0x18, 0x1e, 0x24, 0x2a, 0x30, 0x36 };
461 static const TAGID expected_tab[] = { 6, 0x18, 0x2a, 0x3c, 0x4e, 0x60, 0x846, 0x102c };
462 size_t n, j;
463
464 for (n = 0; n < (sizeof(all) / sizeof(all[0])); ++n)
465 {
466 PDB pdb;
467 TAGID tagstr, table, expected_table;
468
469 write_db_strings(path1, all, n+1);
470
471 pdb = pSdbOpenDatabase(path1, DOS_PATH);
472 ok(pdb != NULL, "Expected a valid database\n");
473 if (!pdb)
474 {
475 DeleteFileW(path1);
476 continue;
477 }
478 tagstr = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_NAME);
479 for (j = 0; j <= n; ++j)
480 {
481 ok(tagstr == expected_str[j], "Expected tagstr to be 0x%x, was 0x%x for %u/%u\n", expected_str[j], tagstr, j, n);
482 if (tagstr)
483 {
484 LPWSTR data;
485 DWORD size;
486 TAG tag = pSdbGetTagFromTagID(pdb, tagstr);
487 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x for %u/%u\n", tag, j, n);
488 size = pSdbGetTagDataSize(pdb, tagstr);
489 ok(size == 4, "Expected datasize to be 4, was %u for %u/%u\n", size, j, n);
490 data = pSdbGetStringTagPtr(pdb, tagstr);
491 ok(data && !wcsicmp(data, all[j]), "Expected data to be %s was %s for %u/%u\n", wine_dbgstr_w(all[j]), wine_dbgstr_w(data), j, n);
492 }
493 tagstr = pSdbFindNextTag(pdb, TAGID_ROOT, tagstr);
494 }
495 ok(tagstr == TAGID_NULL, "Expected to be at the end for %u\n", n);
496
497
498 table = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_STRINGTABLE);
499 expected_table = 0xc + (n+1)*6;
500 ok(table == expected_table, "Expected to find a stringtable at 0x%x instead of 0x%x for %u\n", expected_table, table, n);
501 if (table)
502 {
503 tagstr = pSdbFindFirstTag(pdb, table, TAG_STRINGTABLE_ITEM);
504 for (j = 0; j <= n; ++j)
505 {
506 ok(tagstr == (expected_tab[j] + expected_table), "Expected tagstr to be 0x%x, was 0x%x for %u/%u\n", (expected_tab[j] + expected_table), tagstr, j, n);
507 if (tagstr)
508 {
509 LPWSTR data;
510 DWORD size, expected_size;
511 TAG tag = pSdbGetTagFromTagID(pdb, tagstr);
512 ok(tag == TAG_STRINGTABLE_ITEM, "Expected tag to be TAG_NAME, was 0x%x for %u/%u\n", tag, j, n);
513 size = pSdbGetTagDataSize(pdb, tagstr);
514 expected_size = (lstrlenW(all[j])+1) * 2;
515 ok(size == expected_size, "Expected datasize to be %u, was %u for %u/%u\n", expected_size, size, j, n);
516 data = pSdbGetStringTagPtr(pdb, tagstr);
517 ok(data && !wcsicmp(data, all[j]), "Expected data to be %s was %s for %u/%u\n", wine_dbgstr_w(all[j]), wine_dbgstr_w(data), j, n);
518 }
519 tagstr = pSdbFindNextTag(pdb, TAGID_ROOT, tagstr);
520 }
521 ok(tagstr == TAGID_NULL, "Expected to be at the end for %u\n", n);
522 }
523
524 pSdbCloseDatabase(pdb);
525 DeleteFileW(path1);
526 }
527 }
528
529 static void match_str_attr_imp(PDB pdb, TAGID parent, TAG find, const char* compare)
530 {
531 TAGID attr = pSdbFindFirstTag(pdb, parent, find);
532 winetest_ok(attr != TAG_NULL, "Could not find: %x\n", find);
533 if (attr != TAG_NULL)
534 {
535 LPWSTR name = pSdbGetStringTagPtr(pdb, attr);
536 winetest_ok(name != NULL, "Could not convert attr to str.\n");
537 if (name)
538 {
539 char name_a[100];
540 WideCharToMultiByte(CP_ACP, 0, name, -1, name_a, sizeof(name_a), NULL, NULL);
541 winetest_ok(strcmp(name_a, compare) == 0, "Expected tagid %x to be %s, was %s\n", attr, compare, name_a);
542 }
543 }
544 }
545
546 static void match_dw_attr_imp(PDB pdb, TAGID parent, TAG find, DWORD compare)
547 {
548 TAGID attr = pSdbFindFirstTag(pdb, parent, find);
549 winetest_ok(attr != TAG_NULL, "Could not find: %x\n", find);
550 if (attr != TAG_NULL)
551 {
552 DWORD val = pSdbReadDWORDTag(pdb, attr, 0x1234567);
553 winetest_ok(val == compare, "Expected tagid %x to be 0x%x, was 0x%x\n", attr, compare, val);
554 }
555 }
556
557 static void match_qw_attr_imp(PDB pdb, TAGID parent, TAG find, QWORD compare)
558 {
559 TAGID attr = pSdbFindFirstTag(pdb, parent, find);
560 winetest_ok(attr != TAG_NULL, "Could not find: %x\n", find);
561 if (attr != TAG_NULL)
562 {
563 QWORD val = pSdbReadQWORDTag(pdb, attr, 0x123456789abcdef);
564 winetest_ok(val == compare, "Expected tagid %x to be 0x%I64x, was 0x%I64x\n", attr, compare, val);
565 }
566 }
567
568 static void match_guid_attr_imp(PDB pdb, TAGID parent, TAG find, const GUID* compare)
569 {
570 TAGID attr = pSdbFindFirstTag(pdb, parent, find);
571 winetest_ok(attr != TAG_NULL, "Could not find: %x\n", find);
572 if (attr != TAG_NULL)
573 {
574 GUID guid = {0};
575 BOOL result = pSdbReadBinaryTag(pdb, attr, (PBYTE)&guid, sizeof(guid));
576 winetest_ok(result, "expected pSdbReadBinaryTag not to fail.\n");
577 winetest_ok(IsEqualGUID(&guid, compare), "expected guids to be equal(%s:%s)\n", wine_dbgstr_guid(&guid), wine_dbgstr_guid(compare));
578 }
579 }
580
581 #define match_str_attr (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : match_str_attr_imp
582 #define match_dw_attr (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : match_dw_attr_imp
583 #define match_qw_attr (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : match_qw_attr_imp
584 #define match_guid_attr (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : match_guid_attr_imp
585
586
587 //The application name cannot contain any of the following characters:
588 // \ / < > : * ? | "
589
590 static void check_db_properties(PDB pdb, TAGID root)
591 {
592 TAGID iter = pSdbFindFirstTag(pdb, root, TAG_DATABASE_ID);
593 ok(iter != TAGID_NULL, "expected a result, got TAGID_NULL\n");
594 if(iter != TAGID_NULL)
595 {
596 GUID guid = {0}, guid2 = {0};
597 BOOL result = pSdbReadBinaryTag(pdb, iter, (PBYTE)&guid, sizeof(guid));
598 ok(result, "expected SdbReadBinaryTag not to fail.\n");
599 if(result)
600 {
601 WCHAR guid_wstr[50];
602 result = pSdbGUIDToString(&guid, guid_wstr, 50);
603 ok(result, "expected SdbGUIDToString not to fail.\n");
604 if(result)
605 {
606 char guid_str[50];
607 WideCharToMultiByte( CP_ACP, 0, guid_wstr, -1, guid_str, sizeof(guid_str), NULL, NULL );
608 ok_str(guid_str, "{e39b0eb0-55db-450b-9bd4-d20c9484260f}");
609 }
610 ok(pSdbGetDatabaseID(pdb, &guid2),"expected SdbGetDatabaseID not to fail.\n");
611 ok(IsEqualGUID(&guid, &guid2), "expected guids to be equal(%s:%s)\n", wine_dbgstr_guid(&guid), wine_dbgstr_guid(&guid2));
612 }
613 }
614 match_qw_attr(pdb, root, TAG_TIME, 0x1d1b91a02c0d63e);
615 match_str_attr(pdb, root, TAG_COMPILER_VERSION, "2.1.0.3");
616 match_str_attr(pdb, root, TAG_NAME, "apphelp_test1");
617 match_dw_attr(pdb, root, TAG_OS_PLATFORM, 1);
618 }
619
620 static void check_db_layer(PDB pdb, TAGID layer)
621 {
622 TAGID shimref, inexclude, is_include;
623 ok(layer != TAGID_NULL, "Expected a valid layer, got NULL\n");
624 if(!layer)
625 return;
626
627 match_str_attr(pdb, layer, TAG_NAME, "TestNewMode");
628 shimref = pSdbFindFirstTag(pdb, layer, TAG_SHIM_REF);
629 ok(shimref != TAGID_NULL, "Expected a valid shim ref, got NULL\n");
630 if(!shimref)
631 return;
632
633 match_str_attr(pdb, shimref, TAG_NAME, "VirtualRegistry");
634 match_str_attr(pdb, shimref, TAG_COMMAND_LINE, "ThemeActive");
635 inexclude = pSdbFindFirstTag(pdb, shimref, TAG_INEXCLUD);
636 ok(inexclude != TAGID_NULL, "Expected a valid in/exclude ref, got NULL\n");
637 if(!inexclude)
638 return;
639
640 is_include = pSdbFindFirstTag(pdb, inexclude, TAG_INCLUDE);
641 ok(is_include == TAGID_NULL, "Expected a NULL include ref, but got one anyway.\n");
642 match_str_attr(pdb, inexclude, TAG_MODULE, "exclude.dll");
643
644 inexclude = pSdbFindNextTag(pdb, shimref, inexclude);
645 ok(inexclude != TAGID_NULL, "Expected a valid in/exclude ref, got NULL\n");
646 if(!inexclude)
647 return;
648
649 is_include = pSdbFindFirstTag(pdb, inexclude, TAG_INCLUDE);
650 ok(is_include != TAGID_NULL, "Expected a valid include ref, got NULL\n");
651 match_str_attr(pdb, inexclude, TAG_MODULE, "include.dll");
652 }
653
654 static void check_matching_file(PDB pdb, TAGID exe, TAGID matching_file, int num)
655 {
656 ok(matching_file != TAGID_NULL, "Expected to find atleast 1 matching file.\n");
657 if(matching_file == TAGID_NULL)
658 return;
659
660 ok(num < 4, "Too many matches, expected only 4!\n");
661 if (num >= 4)
662 return;
663
664
665 match_str_attr(pdb, matching_file, TAG_NAME, "*");
666 match_str_attr(pdb, matching_file, TAG_COMPANY_NAME, "CompanyName");
667 match_str_attr(pdb, matching_file, TAG_PRODUCT_NAME, "ProductName");
668 match_str_attr(pdb, matching_file, TAG_PRODUCT_VERSION, "1.0.0.1");
669 match_str_attr(pdb, matching_file, TAG_FILE_VERSION, "1.0.0.0");
670
671 if( num == 0 || num == 3)
672 {
673 match_qw_attr(pdb, matching_file, TAG_UPTO_BIN_PRODUCT_VERSION, 0x1000000000001);
674 match_qw_attr(pdb, matching_file, TAG_UPTO_BIN_FILE_VERSION, 0x1000000000000);
675 }
676 if(num == 1 || num == 3)
677 {
678 match_dw_attr(pdb, matching_file, TAG_PE_CHECKSUM, 0xbaad);
679 }
680 if(num != 0)
681 {
682 match_qw_attr(pdb, matching_file, TAG_BIN_PRODUCT_VERSION, 0x1000000000001);
683 match_qw_attr(pdb, matching_file, TAG_BIN_FILE_VERSION, 0x1000000000000);
684 }
685 if(num == 3)
686 {
687 match_dw_attr(pdb, matching_file, TAG_SIZE, 0x800);
688 match_dw_attr(pdb, matching_file, TAG_CHECKSUM, 0x178bd629);
689 match_str_attr(pdb, matching_file, TAG_FILE_DESCRIPTION, "FileDescription");
690 match_dw_attr(pdb, matching_file, TAG_MODULE_TYPE, 3);
691 match_dw_attr(pdb, matching_file, TAG_VERFILEOS, 4);
692 match_dw_attr(pdb, matching_file, TAG_VERFILETYPE, 1);
693 match_dw_attr(pdb, matching_file, TAG_LINKER_VERSION, 0x40002);
694 match_str_attr(pdb, matching_file, TAG_ORIGINAL_FILENAME, "OriginalFilename");
695 match_str_attr(pdb, matching_file, TAG_INTERNAL_NAME, "InternalName");
696 match_str_attr(pdb, matching_file, TAG_LEGAL_COPYRIGHT, "LegalCopyright");
697 match_dw_attr(pdb, matching_file, TAG_LINK_DATE, 0x12345);
698 match_dw_attr(pdb, matching_file, TAG_UPTO_LINK_DATE, 0x12345);
699 }
700 if(num > 3)
701 {
702 ok(0, "unknown case: %d\n", num);
703 }
704 matching_file = pSdbFindNextTag(pdb, exe, matching_file);
705 if(num == 2)
706 {
707 ok(matching_file != TAGID_NULL, "Did expect a secondary match on %d\n", num);
708 match_str_attr(pdb, matching_file, TAG_NAME, "test_checkfile.txt");
709 match_dw_attr(pdb, matching_file, TAG_SIZE, 0x4);
710 match_dw_attr(pdb, matching_file, TAG_CHECKSUM, 0xb0b0b0b0);
711 }
712 else
713 {
714 ok(matching_file == TAGID_NULL, "Did not expect a secondary match on %d\n", num);
715 }
716 }
717
718 static void check_matching_apphelp(PDB pdb, TAGID apphelp, int num)
719 {
720 if(num == 0)
721 {
722 /*
723 [Window Title]
724 Program Compatibility Assistant
725
726 [Main Instruction]
727 This program has known compatibility issues
728
729 [Expanded Information]
730 Allow it!
731
732 [^] Hide details [ ] Don't show this message again [Check for solutions online] [Run program] [Cancel]
733 */
734 match_dw_attr(pdb, apphelp, TAG_FLAGS, 1);
735 match_dw_attr(pdb, apphelp, TAG_PROBLEMSEVERITY, 1);
736 match_dw_attr(pdb, apphelp, TAG_HTMLHELPID, 1);
737 match_dw_attr(pdb, apphelp, TAG_APP_NAME_RC_ID, 0x6f0072);
738 match_dw_attr(pdb, apphelp, TAG_VENDOR_NAME_RC_ID, 0x720067);
739 match_dw_attr(pdb, apphelp, TAG_SUMMARY_MSG_RC_ID, 0);
740 }
741 else
742 {
743 /*
744 [Window Title]
745 Program Compatibility Assistant
746
747 [Main Instruction]
748 This program is blocked due to compatibility issues
749
750 [Expanded Information]
751 Not allowed!
752
753 [^] Hide details [Check for solutions online] [Cancel]
754 */
755 match_dw_attr(pdb, apphelp, TAG_FLAGS, 1);
756 match_dw_attr(pdb, apphelp, TAG_PROBLEMSEVERITY, 2);
757 match_dw_attr(pdb, apphelp, TAG_HTMLHELPID, 2);
758 match_dw_attr(pdb, apphelp, TAG_APP_NAME_RC_ID, 0x320020);
759 match_dw_attr(pdb, apphelp, TAG_VENDOR_NAME_RC_ID, 0x38002e);
760 match_dw_attr(pdb, apphelp, TAG_SUMMARY_MSG_RC_ID, 0);
761 }
762 apphelp = pSdbFindNextTag(pdb, apphelp, apphelp);
763 ok(apphelp == TAGID_NULL, "Did not expect a secondary match on %d\n", num);
764 }
765
766 static void check_matching_layer(PDB pdb, TAGID layer, int num)
767 {
768 if(num == 2)
769 {
770 match_dw_attr(pdb, layer, TAG_LAYER_TAGID, 0x18e);
771 match_str_attr(pdb, layer, TAG_NAME, "TestNewMode");
772 }
773 else
774 {
775 TAGID layer_tagid = pSdbFindFirstTag(pdb, layer, TAG_LAYER_TAGID);
776 ok(layer_tagid == TAGID_NULL, "expected not to find a layer tagid, got %x\n", layer_tagid);
777 match_str_attr(pdb, layer, TAG_NAME, "WinSrv03");
778 }
779 }
780
781 static struct
782 {
783 const char* name;
784 const char* app_name;
785 const char* vendor;
786 GUID exe_id;
787 const char* extra_file;
788 DWORD dwLayerCount;
789 TAGREF atrExes_0;
790 TAGREF atrLayers_0;
791 } test_exedata[4] = {
792 {
793 "test_allow.exe",
794 "apphelp_name_allow",
795 "apphelp_vendor_allow",
796 {0x4e50c93f,0xb863,0x4dfa,{0xba,0xe2,0xd8,0x0e,0xf4,0xce,0x5c,0x89}},
797 NULL,
798 0,
799 0x1c6,
800 0,
801 },
802 {
803 "test_disallow.exe",
804 "apphelp_name_disallow",
805 "apphelp_vendor_disallow",
806 {0x156720e1,0xef98,0x4d04,{0x96,0x5a,0xd8,0x5d,0xe0,0x5e,0x6d,0x9f}},
807 NULL,
808 0,
809 0x256,
810 0,
811 },
812 {
813 "test_new.exe",
814 "fixnew_name",
815 "fixnew_vendor",
816 {0xce70ef69,0xa21d,0x408b,{0x84,0x5b,0xf9,0x9e,0xac,0x06,0x09,0xe7}},
817 "test_checkfile.txt",
818 1,
819 0x2ec,
820 0x18e,
821 },
822 {
823 "test_w2k3.exe",
824 "fix_name",
825 "fix_vendor",
826 {0xb4ead144,0xf640,0x4e4b,{0x94,0xc4,0x0c,0x7f,0xa8,0x66,0x23,0xb0}},
827 NULL,
828 0,
829 0x37c,
830 0,
831 },
832 };
833
834 static void check_db_exes(PDB pdb, TAGID root)
835 {
836 int num = 0;
837 TAGID exe = pSdbFindFirstTag(pdb, root, TAG_EXE);
838 while (exe != TAGID_NULL)
839 {
840 TAGID apphelp, layer;
841 ok(num < 4, "Too many matches, expected only 4!\n");
842 if(num >= 4)
843 break;
844 match_str_attr(pdb, exe, TAG_NAME, test_exedata[num].name);
845 match_str_attr(pdb, exe, TAG_APP_NAME, test_exedata[num].app_name);
846 match_str_attr(pdb, exe, TAG_VENDOR, test_exedata[num].vendor);
847 match_guid_attr(pdb, exe, TAG_EXE_ID, &test_exedata[num].exe_id);
848 check_matching_file(pdb, exe, pSdbFindFirstTag(pdb, exe, TAG_MATCHING_FILE), num);
849 apphelp = pSdbFindFirstTag(pdb, exe, TAG_APPHELP);
850 if(num == 0 || num == 1)
851 {
852 ok(apphelp != TAGID_NULL, "Expected to find a valid apphelp match on %d.\n", num);
853 if(apphelp)
854 check_matching_apphelp(pdb, apphelp, num);
855 }
856 else
857 {
858 ok(apphelp == TAGID_NULL, "Did not expect an apphelp match on %d\n", num);
859 }
860 layer = pSdbFindFirstTag(pdb, exe, TAG_LAYER);
861 if(num == 2 || num == 3)
862 {
863 ok(layer != TAGID_NULL, "Expected to find a valid layer match on %d.\n", num);
864 if(layer)
865 check_matching_layer(pdb, layer, num);
866 }
867 else
868 {
869 ok(layer == TAGID_NULL, "Did not expect a layer match on %d\n", num);
870 }
871 ++num;
872 exe = pSdbFindNextTag(pdb, root, exe);
873 }
874 ok(num == 4, "Expected to find 4 exe tags, found: %d\n", num);
875 }
876
877 static struct
878 {
879 DWORD htmlhelpid;
880 const char* link;
881 const char* apphelp_title;
882 const char* apphelp_details;
883 } test_layerdata[2] = {
884 {
885 2,
886 "http://reactos.org/disallow",
887 "apphelp_name_disallow",
888 "Not allowed!",
889 },
890 {
891 1,
892 "http://reactos.org/allow",
893 "apphelp_name_allow",
894 "Allow it!",
895 },
896 };
897
898 static void check_db_apphelp(PDB pdb, TAGID root)
899 {
900 int num = 0;
901 TAGID apphelp = pSdbFindFirstTag(pdb, root, TAG_APPHELP);
902 while (apphelp != TAGID_NULL)
903 {
904 TAGID link;
905 ok(num < 2, "Too many matches, expected only 4!\n");
906 if(num >= 2)
907 break;
908 match_dw_attr(pdb, apphelp, TAG_HTMLHELPID, test_layerdata[num].htmlhelpid);
909 link = pSdbFindFirstTag(pdb, apphelp, TAG_LINK);
910 ok(link != TAGID_NULL, "expected to find a link tag\n");
911 if (link != TAGID_NULL)
912 {
913 match_str_attr(pdb, link, TAG_LINK_URL, test_layerdata[num].link);
914 }
915 match_str_attr(pdb, apphelp, TAG_APPHELP_TITLE, test_layerdata[num].apphelp_title);
916 match_str_attr(pdb, apphelp, TAG_APPHELP_DETAILS, test_layerdata[num].apphelp_details);
917 apphelp = pSdbFindNextTag(pdb, root, apphelp);
918 num++;
919 }
920 ok(num == 2, "Expected to find 2 layer tags, found: %d\n", num);
921 }
922
923 static void test_CheckDatabaseManually(void)
924 {
925 static const WCHAR path[] = {'t','e','s','t','_','d','b','.','s','d','b',0};
926 TAGID root;
927 PDB pdb;
928 BOOL ret;
929 DWORD ver_hi, ver_lo;
930
931 test_create_db("test_db.sdb");
932
933 /* both ver_hi and ver_lo cannot be null, it'll crash. */
934 ver_hi = ver_lo = 0x12345678;
935 ret = pSdbGetDatabaseVersion(path, &ver_hi, &ver_lo);
936 ok(ret,"Expected SdbGetDatabaseVersion to succeed\n");
937 ok(ver_hi == 2,"Expected ver_hi to be 2, was: %d\n", ver_hi);
938 ok(ver_lo == 1,"Expected ver_lo to be 1, was: %d\n", ver_lo);
939
940 ver_hi = ver_lo = 0x12345678;
941 ret = pSdbGetDatabaseVersion(NULL, &ver_hi, &ver_lo);
942 ok(ret,"Expected SdbGetDatabaseVersion to succeed\n");
943 ok(ver_hi == 0x12345678,"Expected ver_hi to be 0x12345678, was: 0x%x\n", ver_hi);
944 ok(ver_lo == 0x12345678,"Expected ver_lo to be 0x12345678, was: 0x%x\n", ver_lo);
945
946 ver_hi = ver_lo = 0x12345678;
947 ret = pSdbGetDatabaseVersion(path + 1, &ver_hi, &ver_lo);
948 ok(ret,"Expected SdbGetDatabaseVersion to succeed\n");
949 ok(ver_hi == 0x12345678,"Expected ver_hi to be 0x12345678, was: 0x%x\n", ver_hi);
950 ok(ver_lo == 0x12345678,"Expected ver_lo to be 0x12345678, was: 0x%x\n", ver_lo);
951
952 pdb = pSdbOpenDatabase(path, DOS_PATH);
953 ok(pdb != NULL, "unexpected NULL handle\n");
954
955 root = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
956 ok(root != TAGID_NULL, "expected to find a root tag\n");
957 if (root != TAGID_NULL)
958 {
959 check_db_properties(pdb, root);
960 check_db_layer(pdb, pSdbFindFirstTag(pdb, root, TAG_LAYER));
961 check_db_exes(pdb, root);
962 check_db_apphelp(pdb, root);
963 }
964
965 pSdbCloseDatabase(pdb);
966 DeleteFileA("test_db.sdb");
967 }
968
969 START_TEST(db)
970 {
971 //SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "4");
972 //SetEnvironmentVariable("DEBUGCHANNEL", "+apphelp");
973 hdll = LoadLibraryA("apphelp.dll");
974 pSdbTagToString = (void *) GetProcAddress(hdll, "SdbTagToString");
975 pSdbOpenDatabase = (void *) GetProcAddress(hdll, "SdbOpenDatabase");
976 pSdbCreateDatabase = (void *) GetProcAddress(hdll, "SdbCreateDatabase");
977 pSdbGetDatabaseVersion = (void *) GetProcAddress(hdll, "SdbGetDatabaseVersion");
978 pSdbCloseDatabase = (void *) GetProcAddress(hdll, "SdbCloseDatabase");
979 pSdbCloseDatabaseWrite = (void *) GetProcAddress(hdll, "SdbCloseDatabaseWrite");
980 pSdbGetTagFromTagID = (void *) GetProcAddress(hdll, "SdbGetTagFromTagID");
981 pSdbWriteNULLTag = (void *) GetProcAddress(hdll, "SdbWriteNULLTag");
982 pSdbWriteWORDTag = (void *) GetProcAddress(hdll, "SdbWriteWORDTag");
983 pSdbWriteDWORDTag = (void *) GetProcAddress(hdll, "SdbWriteDWORDTag");
984 pSdbWriteQWORDTag = (void *) GetProcAddress(hdll, "SdbWriteQWORDTag");
985 pSdbWriteBinaryTagFromFile = (void *) GetProcAddress(hdll, "SdbWriteBinaryTagFromFile");
986 pSdbWriteStringTag = (void *) GetProcAddress(hdll, "SdbWriteStringTag");
987 pSdbWriteStringRefTag = (void *) GetProcAddress(hdll, "SdbWriteStringRefTag");
988 pSdbBeginWriteListTag = (void *)GetProcAddress(hdll, "SdbBeginWriteListTag");
989 pSdbEndWriteListTag = (void *) GetProcAddress(hdll, "SdbEndWriteListTag");
990 pSdbFindFirstTag = (void *) GetProcAddress(hdll, "SdbFindFirstTag");
991 pSdbFindNextTag = (void *) GetProcAddress(hdll, "SdbFindNextTag");
992 pSdbReadWORDTag = (void *) GetProcAddress(hdll, "SdbReadWORDTag");
993 pSdbReadDWORDTag = (void *) GetProcAddress(hdll, "SdbReadDWORDTag");
994 pSdbReadQWORDTag = (void *) GetProcAddress(hdll, "SdbReadQWORDTag");
995 pSdbReadBinaryTag = (void *) GetProcAddress(hdll, "SdbReadBinaryTag");
996 pSdbReadStringTag = (void *) GetProcAddress(hdll, "SdbReadStringTag");
997 pSdbGetTagDataSize = (void *) GetProcAddress(hdll, "SdbGetTagDataSize");
998 pSdbGetBinaryTagData = (void *) GetProcAddress(hdll, "SdbGetBinaryTagData");
999 pSdbGetStringTagPtr = (void *) GetProcAddress(hdll, "SdbGetStringTagPtr");
1000 pSdbGetFirstChild = (void *) GetProcAddress(hdll, "SdbGetFirstChild");
1001 pSdbGetNextChild = (void *) GetProcAddress(hdll, "SdbGetNextChild");
1002 pSdbGetDatabaseID = (void *) GetProcAddress(hdll, "SdbGetDatabaseID");
1003 pSdbGUIDToString = (void *) GetProcAddress(hdll, "SdbGUIDToString");
1004
1005 test_Sdb();
1006 test_write_ex();
1007 test_stringtable();
1008 test_CheckDatabaseManually();
1009 }