[APPHELP][APPHELP_APITEST] Partially implement SdbMakeIndexKeyFromString
[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 static LONGLONG(WINAPI* pSdbMakeIndexKeyFromString)(LPCWSTR);
170
171
172 DEFINE_GUID(GUID_DATABASE_TEST,0xe39b0eb0,0x55db,0x450b,0x9b,0xd4,0xd2,0x0c,0x94,0x84,0x26,0x0f);
173
174
175 static void Write(HANDLE file, LPCVOID buffer, DWORD size)
176 {
177 DWORD dwWritten = 0;
178 WriteFile(file, buffer, size, &dwWritten, NULL);
179 }
180
181 static void test_Sdb(void)
182 {
183 static const WCHAR temp[] = {'t','e','m','p',0};
184 static const WCHAR path1[] = {'t','e','m','p','.','s','d','b',0};
185 static const WCHAR path2[] = {'t','e','m','p','2','.','b','i','n',0};
186 static const WCHAR tag_size_string[] = {'S','I','Z','E',0};
187 static const WCHAR tag_flag_lua_string[] = {'F','L','A','G','_','L','U','A',0};
188 static const TAG tags[5] = {
189 TAG_SIZE, TAG_FLAG_LUA, TAG_NAME,
190 TAG_STRINGTABLE, TAG_STRINGTABLE_ITEM
191 };
192 WCHAR buffer[6] = {0};
193 PDB pdb;
194 QWORD qword;
195 DWORD dword;
196 WORD word;
197 BOOL ret;
198 HANDLE file; /* temp file created for testing purpose */
199 TAG tag;
200 TAGID tagid, ptagid, stringref = 6;
201 LPCWSTR string;
202 PBYTE binary;
203
204 pdb = pSdbCreateDatabase(path1, DOS_PATH);
205 ok (pdb != NULL, "failed to create database\n");
206 if(pdb != NULL)
207 {
208 ret = pSdbWriteDWORDTag(pdb, tags[0], 0xDEADBEEF);
209 ok (ret, "failed to write DWORD tag\n");
210 ret = pSdbWriteQWORDTag(pdb, tags[1], 0xDEADBEEFBABE);
211 ok (ret, "failed to write QWORD tag\n");
212 ret = pSdbWriteStringRefTag(pdb, tags[2], stringref);
213 ok (ret, "failed to write stringref tag\n");
214 tagid = pSdbBeginWriteListTag(pdb, tags[3]);
215 ok (tagid != TAGID_NULL, "unexpected NULL tagid\n");
216 ret = pSdbWriteStringTag(pdb, tags[4], temp);
217 ok (ret, "failed to write string tag\n");
218 ret = pSdbWriteNULLTag(pdb, TAG_GENERAL);
219 ok (ret, "failed to write NULL tag\n");
220 ret = pSdbWriteWORDTag(pdb, TAG_MATCH_MODE, 0xACE);
221 ok (ret, "failed to write WORD tag\n");
222 ret = pSdbEndWriteListTag(pdb, tagid);
223 ok (ret, "failed to update list size\n");
224 /* [Err ][SdbCloseDatabase ] Failed to close the file. */
225 pSdbCloseDatabaseWrite(pdb);
226 }
227
228 /* [Err ][SdbGetDatabaseID ] Failed to get root tag */
229 pdb = pSdbOpenDatabase(path1, DOS_PATH);
230 ok(pdb != NULL, "unexpected NULL handle\n");
231
232 if(pdb)
233 {
234 tagid = pSdbGetFirstChild(pdb, TAGID_ROOT);
235 ok(tagid == _TAGID_ROOT, "unexpected tagid %u, expected %u\n", tagid, _TAGID_ROOT);
236
237 tag = pSdbGetTagFromTagID(pdb, tagid);
238 ok(tag == TAG_SIZE, "unexpected tag 0x%x, expected 0x%x\n", tag, TAG_SIZE);
239
240 string = pSdbTagToString(tag);
241 ok(lstrcmpW(string, tag_size_string) == 0, "unexpected string %s, expected %s\n",
242 wine_dbgstr_w(string), wine_dbgstr_w(tag_size_string));
243
244 dword = pSdbReadDWORDTag(pdb, tagid, 0);
245 ok(dword == 0xDEADBEEF, "unexpected value %u, expected 0xDEADBEEF\n", dword);
246
247 tagid = pSdbGetNextChild(pdb, TAGID_ROOT, tagid);
248 ok(tagid == _TAGID_ROOT + sizeof(TAG) + sizeof(DWORD), "unexpected tagid %u, expected %u\n",
249 tagid, _TAGID_ROOT + sizeof(TAG) + sizeof(DWORD));
250
251 tag = pSdbGetTagFromTagID(pdb, tagid);
252 ok (tag == TAG_FLAG_LUA, "unexpected tag 0x%x, expected 0x%x\n", tag, TAG_FLAG_LUA);
253
254 string = pSdbTagToString(tag);
255 ok(lstrcmpW(string, tag_flag_lua_string) == 0, "unexpected string %s, expected %s\n",
256 wine_dbgstr_w(string), wine_dbgstr_w(tag_flag_lua_string));
257
258 qword = pSdbReadQWORDTag(pdb, tagid, 0);
259 ok(qword == 0xDEADBEEFBABE, "unexpected value 0x%I64x, expected 0xDEADBEEFBABE\n", qword);
260
261 tagid = pSdbGetNextChild(pdb, TAGID_ROOT, tagid);
262 string = pSdbGetStringTagPtr(pdb, tagid);
263 ok (string && (lstrcmpW(string, temp) == 0), "unexpected string %s, expected %s\n",
264 wine_dbgstr_w(string), wine_dbgstr_w(temp));
265
266 ptagid = pSdbGetNextChild(pdb, TAGID_ROOT, tagid);
267 tagid = pSdbGetFirstChild(pdb, ptagid);
268
269 string = pSdbGetStringTagPtr(pdb, tagid);
270 ok (string && (lstrcmpW(string, temp) == 0), "unexpected string %s, expected %s\n",
271 wine_dbgstr_w(string), wine_dbgstr_w(temp));
272
273 ok (pSdbReadStringTag(pdb, tagid, buffer, 6), "failed to write string to buffer\n");
274 /* [Err ][SdbpReadTagData ] Buffer too small. Avail: 6, Need: 10. */
275 ok (!pSdbReadStringTag(pdb, tagid, buffer, 3), "string was written to buffer, but failure was expected");
276 ok (pSdbGetTagDataSize(pdb, tagid) == 5 * sizeof(WCHAR), "string has unexpected size\n");
277
278 tagid = pSdbGetNextChild(pdb, ptagid, tagid);
279 tag = pSdbGetTagFromTagID(pdb, tagid);
280 ok (tag == TAG_GENERAL, "unexpected tag 0x%x, expected 0x%x\n", tag, TAG_GENERAL);
281 ok (pSdbGetTagDataSize(pdb, tagid) == 0, "null tag with size > 0\n");
282
283 tagid = pSdbGetNextChild(pdb, ptagid, tagid);
284 word = pSdbReadWORDTag(pdb, tagid, 0);
285 ok (word == 0xACE, "unexpected value 0x%x, expected 0x%x\n", word, 0xACE);
286
287 pSdbCloseDatabase(pdb);
288 }
289 DeleteFileW(path1);
290
291 file = CreateFileW(path2, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
292 ok (file != INVALID_HANDLE_VALUE, "failed to open file\n");
293 Write(file, &qword, 8);
294 CloseHandle(file);
295
296 pdb = pSdbCreateDatabase(path1, DOS_PATH);
297 ok(pdb != NULL, "unexpected NULL handle\n");
298
299 if(pdb)
300 {
301 ret = pSdbWriteBinaryTagFromFile(pdb, TAG_DATA_BITS, path2);
302 ok(ret, "failed to write tag from binary file\n");
303 pSdbCloseDatabaseWrite(pdb); /* [Err ][SdbCloseDatabase ] Failed to close the file. */
304 DeleteFileW(path2);
305
306 pdb = pSdbOpenDatabase(path1, DOS_PATH);
307 ok(pdb != NULL, "unexpected NULL handle\n");
308 binary = pSdbGetBinaryTagData(pdb, _TAGID_ROOT);
309 ok(memcmp(binary, &qword, 8) == 0, "binary data is corrupt\n");
310 ret = pSdbReadBinaryTag(pdb, _TAGID_ROOT, (PBYTE)buffer, 12);
311 ok(ret, "failed to read binary tag\n");
312 ok(memcmp(buffer, &qword, 8) == 0, "binary data is corrupt\n");
313 pSdbCloseDatabase(pdb);
314 }
315 DeleteFileW(path1);
316 }
317
318 /*
319 - Show that a stringtable is automatically generated,
320 - Show that entries in the stringtable are re-used,
321 - validate multiple lists (for the length)
322 */
323 static void test_write_ex(void)
324 {
325 WCHAR path1[] = {'t','e','s','t','.','s','d','b',0};
326 WCHAR test1[] = {'T','E','S','T',0};
327 WCHAR test2[] = {'t','e','s','t',0};
328 PDB pdb;
329 TAGID tagdb, tagstr;
330 TAG tag;
331 DWORD size;
332 BOOL ret;
333 LPWSTR ptr;
334
335 /* Write a small database */
336 pdb = pSdbCreateDatabase(path1, DOS_PATH);
337 ok(pdb != NULL, "Expected a valid database\n");
338 if (!pdb)
339 return;
340 tagdb = pSdbBeginWriteListTag(pdb, TAG_DATABASE);
341 ok(tagdb == 12, "Expected tag to be 12, was %u\n", tagdb);
342 ret = pSdbWriteStringTag(pdb, TAG_NAME, test1);
343 ret = pSdbWriteStringTag(pdb, TAG_NAME, test2);
344 ok(ret, "Expected SdbWriteStringTag to succeed\n");
345 ret = pSdbEndWriteListTag(pdb, tagdb);
346 ok(ret, "Expected SdbEndWriteListTag to succeed\n");
347
348 tagdb = pSdbBeginWriteListTag(pdb, TAG_DATABASE);
349 ok(tagdb == 30, "Expected tag to be 24, was %u\n", tagdb);
350 ret = pSdbWriteStringTag(pdb, TAG_NAME, test1);
351 ret = pSdbWriteStringTag(pdb, TAG_NAME, test2);
352 ok(ret, "Expected SdbWriteStringTag to succeed\n");
353 ret = pSdbEndWriteListTag(pdb, tagdb);
354 ok(ret, "Expected SdbEndWriteListTag to succeed\n");
355
356 pSdbCloseDatabaseWrite(pdb);
357
358 /* Now validate it's contents */
359 pdb = pSdbOpenDatabase(path1, DOS_PATH);
360 ok(pdb != NULL, "Expected a valid database\n");
361 if (!pdb)
362 return;
363
364 tagdb = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
365 ok(tagdb == 12, "Expected tag to be 12, was %u\n", tagdb);
366 size = pSdbGetTagDataSize(pdb, tagdb);
367 ok(size == 12, "Expected size to be 12, was %u\n", size);
368
369 tagstr = pSdbFindFirstTag(pdb, tagdb, TAG_NAME);
370 ok(tagstr == 18, "Expected string tag to be 18, was %u\n", tagstr);
371 tag = pSdbGetTagFromTagID(pdb, tagstr);
372 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x\n", (DWORD)tag);
373 size = pSdbGetTagDataSize(pdb, tagstr);
374 ok(size == 4, "Expected size to be 4, was 0x%x\n", size);
375
376 tagstr = pSdbFindNextTag(pdb, tagdb, tagstr);
377 ok(tagstr == 24, "Expected string tag to be 24, was %u\n", tagstr);
378 tag = pSdbGetTagFromTagID(pdb, tagstr);
379 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x\n", (DWORD)tag);
380 size = pSdbGetTagDataSize(pdb, tagstr);
381 ok(size == 4, "Expected size to be 4, was 0x%x\n", size);
382
383 tagdb = pSdbFindNextTag(pdb, TAGID_ROOT, tagdb);
384 ok(tagdb == 30, "Expected tag to be 30, was %u\n", tagdb);
385 size = pSdbGetTagDataSize(pdb, tagdb);
386 ok(size == 12, "Expected size to be 12, was %u\n", size);
387
388 tagstr = pSdbFindFirstTag(pdb, tagdb, TAG_NAME);
389 ok(tagstr == 36, "Expected string tag to be 36, was %u\n", tagstr);
390 tag = pSdbGetTagFromTagID(pdb, tagstr);
391 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x\n", (DWORD)tag);
392 size = pSdbGetTagDataSize(pdb, tagstr);
393 ok(size == 4, "Expected size to be 4, was %u\n", size);
394
395 tagstr = pSdbFindNextTag(pdb, tagdb, tagstr);
396 ok(tagstr == 42, "Expected string tag to be 42, was %u\n", tagstr);
397 tag = pSdbGetTagFromTagID(pdb, tagstr);
398 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x\n", (DWORD)tag);
399 size = pSdbGetTagDataSize(pdb, tagstr);
400 ok(size == 4, "Expected size to be 4, was 0x%x\n", size);
401
402 tagdb = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_STRINGTABLE);
403 ok(tagdb == 48, "Expected tag to be 48, was %u\n", tagdb);
404 size = pSdbGetTagDataSize(pdb, tagdb);
405 ok(size == 32, "Expected size to be 32, was %u\n", size);
406
407 tagstr = pSdbGetFirstChild(pdb, tagdb);
408 ok(tagstr == 54, "Expected string tag to be 54, was %u\n", tagstr);
409 tag = pSdbGetTagFromTagID(pdb, tagstr);
410 ok(tag == TAG_STRINGTABLE_ITEM, "Expected tag to be TAG_STRINGTABLE_ITEM, was 0x%x\n", (DWORD)tag);
411 size = pSdbGetTagDataSize(pdb, tagstr);
412 ok(size == 10, "Expected size to be 10, was %u\n", size);
413 ptr = pSdbGetStringTagPtr(pdb, tagstr);
414 ok(ptr != NULL, "Expected a valid pointer\n");
415 if (ptr)
416 ok(!wcscmp(ptr, test1), "Expected ptr to be %s, was %s\n", wine_dbgstr_w(test1), wine_dbgstr_w(ptr));
417
418 tagstr = pSdbGetNextChild(pdb, tagdb, tagstr);
419 ok(tagstr == 70, "Expected string tag to be 70, was %u\n", tagstr);
420 tag = pSdbGetTagFromTagID(pdb, tagstr);
421 ok(tag == TAG_STRINGTABLE_ITEM, "Expected tag to be TAG_STRINGTABLE_ITEM, was 0x%x\n", (DWORD)tag);
422 size = pSdbGetTagDataSize(pdb, tagstr);
423 ok(size == 10, "Expected size to be 10, was %u\n", size);
424 ptr = pSdbGetStringTagPtr(pdb, tagstr);
425 ok(ptr != NULL, "Expected a valid pointer\n");
426 if (ptr)
427 ok(!wcscmp(ptr, test2), "Expected ptr to be %s, was %s\n", wine_dbgstr_w(test2), wine_dbgstr_w(ptr));
428
429 pSdbCloseDatabase(pdb);
430 }
431
432
433 static void write_db_strings(const WCHAR* name, const WCHAR* data[], size_t count)
434 {
435 PDB pdb;
436 size_t n;
437 BOOL ret;
438
439 pdb = pSdbCreateDatabase(name, DOS_PATH);
440 ok(pdb != NULL, "Failed to create db for case %u\n", count);
441 for (n = 0; n < count; ++n)
442 {
443 ret = pSdbWriteStringTag(pdb, TAG_NAME, data[n]);
444 ok(ret, "Failed to write string %u/%u\n", n, count);
445 }
446 pSdbCloseDatabaseWrite(pdb);
447 }
448
449 static void test_stringtable()
450 {
451 static const WCHAR path1[] = {'t','e','s','t','.','s','d','b',0};
452 static const WCHAR test1[] = {'t','e','s','t','1',0};
453 static const WCHAR test2[] = {'T','e','s','t','1',0};
454 static const WCHAR test3[] = {'T','E','s','t','1',0};
455 static const WCHAR test4[] = {'T','E','S','T','1',0};
456 static const WCHAR test5[] = {'T','E','S','T','2',0};
457 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};
458 /* Last char changed from '.' to '!' */
459 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};
460 static const WCHAR empty[] = {0};
461 static const WCHAR* all[] = { test1, test2, test3, test4, test5, lipsum, lipsum2, empty };
462 static const TAGID expected_str[] = { 0xc, 0x12, 0x18, 0x1e, 0x24, 0x2a, 0x30, 0x36 };
463 static const TAGID expected_tab[] = { 6, 0x18, 0x2a, 0x3c, 0x4e, 0x60, 0x846, 0x102c };
464 size_t n, j;
465
466 for (n = 0; n < (sizeof(all) / sizeof(all[0])); ++n)
467 {
468 PDB pdb;
469 TAGID tagstr, table, expected_table;
470
471 write_db_strings(path1, all, n+1);
472
473 pdb = pSdbOpenDatabase(path1, DOS_PATH);
474 ok(pdb != NULL, "Expected a valid database\n");
475 if (!pdb)
476 {
477 DeleteFileW(path1);
478 continue;
479 }
480 tagstr = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_NAME);
481 for (j = 0; j <= n; ++j)
482 {
483 ok(tagstr == expected_str[j], "Expected tagstr to be 0x%x, was 0x%x for %u/%u\n", expected_str[j], tagstr, j, n);
484 if (tagstr)
485 {
486 LPWSTR data;
487 DWORD size;
488 TAG tag = pSdbGetTagFromTagID(pdb, tagstr);
489 ok(tag == TAG_NAME, "Expected tag to be TAG_NAME, was 0x%x for %u/%u\n", tag, j, n);
490 size = pSdbGetTagDataSize(pdb, tagstr);
491 ok(size == 4, "Expected datasize to be 4, was %u for %u/%u\n", size, j, n);
492 data = pSdbGetStringTagPtr(pdb, tagstr);
493 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);
494 }
495 tagstr = pSdbFindNextTag(pdb, TAGID_ROOT, tagstr);
496 }
497 ok(tagstr == TAGID_NULL, "Expected to be at the end for %u\n", n);
498
499
500 table = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_STRINGTABLE);
501 expected_table = 0xc + (n+1)*6;
502 ok(table == expected_table, "Expected to find a stringtable at 0x%x instead of 0x%x for %u\n", expected_table, table, n);
503 if (table)
504 {
505 tagstr = pSdbFindFirstTag(pdb, table, TAG_STRINGTABLE_ITEM);
506 for (j = 0; j <= n; ++j)
507 {
508 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);
509 if (tagstr)
510 {
511 LPWSTR data;
512 DWORD size, expected_size;
513 TAG tag = pSdbGetTagFromTagID(pdb, tagstr);
514 ok(tag == TAG_STRINGTABLE_ITEM, "Expected tag to be TAG_NAME, was 0x%x for %u/%u\n", tag, j, n);
515 size = pSdbGetTagDataSize(pdb, tagstr);
516 expected_size = (lstrlenW(all[j])+1) * 2;
517 ok(size == expected_size, "Expected datasize to be %u, was %u for %u/%u\n", expected_size, size, j, n);
518 data = pSdbGetStringTagPtr(pdb, tagstr);
519 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);
520 }
521 tagstr = pSdbFindNextTag(pdb, TAGID_ROOT, tagstr);
522 }
523 ok(tagstr == TAGID_NULL, "Expected to be at the end for %u\n", n);
524 }
525
526 pSdbCloseDatabase(pdb);
527 DeleteFileW(path1);
528 }
529 }
530
531 static void match_str_attr_imp(PDB pdb, TAGID parent, TAG find, const char* compare)
532 {
533 TAGID attr = pSdbFindFirstTag(pdb, parent, find);
534 winetest_ok(attr != TAG_NULL, "Could not find: %x\n", find);
535 if (attr != TAG_NULL)
536 {
537 LPWSTR name = pSdbGetStringTagPtr(pdb, attr);
538 winetest_ok(name != NULL, "Could not convert attr to str.\n");
539 if (name)
540 {
541 char name_a[100];
542 WideCharToMultiByte(CP_ACP, 0, name, -1, name_a, sizeof(name_a), NULL, NULL);
543 winetest_ok(strcmp(name_a, compare) == 0, "Expected tagid %x to be %s, was %s\n", attr, compare, name_a);
544 }
545 }
546 }
547
548 static void match_dw_attr_imp(PDB pdb, TAGID parent, TAG find, DWORD compare)
549 {
550 TAGID attr = pSdbFindFirstTag(pdb, parent, find);
551 winetest_ok(attr != TAG_NULL, "Could not find: %x\n", find);
552 if (attr != TAG_NULL)
553 {
554 DWORD val = pSdbReadDWORDTag(pdb, attr, 0x1234567);
555 winetest_ok(val == compare, "Expected tagid %x to be 0x%x, was 0x%x\n", attr, compare, val);
556 }
557 }
558
559 static void match_qw_attr_imp(PDB pdb, TAGID parent, TAG find, QWORD compare)
560 {
561 TAGID attr = pSdbFindFirstTag(pdb, parent, find);
562 winetest_ok(attr != TAG_NULL, "Could not find: %x\n", find);
563 if (attr != TAG_NULL)
564 {
565 QWORD val = pSdbReadQWORDTag(pdb, attr, 0x123456789abcdef);
566 winetest_ok(val == compare, "Expected tagid %x to be 0x%I64x, was 0x%I64x\n", attr, compare, val);
567 }
568 }
569
570 static void match_guid_attr_imp(PDB pdb, TAGID parent, TAG find, const GUID* compare)
571 {
572 TAGID attr = pSdbFindFirstTag(pdb, parent, find);
573 winetest_ok(attr != TAG_NULL, "Could not find: %x\n", find);
574 if (attr != TAG_NULL)
575 {
576 GUID guid = {0};
577 BOOL result = pSdbReadBinaryTag(pdb, attr, (PBYTE)&guid, sizeof(guid));
578 winetest_ok(result, "expected pSdbReadBinaryTag not to fail.\n");
579 winetest_ok(IsEqualGUID(&guid, compare), "expected guids to be equal(%s:%s)\n", wine_dbgstr_guid(&guid), wine_dbgstr_guid(compare));
580 }
581 }
582
583 #define match_str_attr (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : match_str_attr_imp
584 #define match_dw_attr (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : match_dw_attr_imp
585 #define match_qw_attr (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : match_qw_attr_imp
586 #define match_guid_attr (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : match_guid_attr_imp
587
588
589 //The application name cannot contain any of the following characters:
590 // \ / < > : * ? | "
591
592 static void check_db_properties(PDB pdb, TAGID root)
593 {
594 TAGID iter = pSdbFindFirstTag(pdb, root, TAG_DATABASE_ID);
595 ok(iter != TAGID_NULL, "expected a result, got TAGID_NULL\n");
596 if(iter != TAGID_NULL)
597 {
598 GUID guid = {0}, guid2 = {0};
599 BOOL result = pSdbReadBinaryTag(pdb, iter, (PBYTE)&guid, sizeof(guid));
600 ok(result, "expected SdbReadBinaryTag not to fail.\n");
601 if(result)
602 {
603 WCHAR guid_wstr[50];
604 result = pSdbGUIDToString(&guid, guid_wstr, 50);
605 ok(result, "expected SdbGUIDToString not to fail.\n");
606 if(result)
607 {
608 char guid_str[50];
609 WideCharToMultiByte( CP_ACP, 0, guid_wstr, -1, guid_str, sizeof(guid_str), NULL, NULL );
610 ok_str(guid_str, "{e39b0eb0-55db-450b-9bd4-d20c9484260f}");
611 }
612 ok(pSdbGetDatabaseID(pdb, &guid2),"expected SdbGetDatabaseID not to fail.\n");
613 ok(IsEqualGUID(&guid, &guid2), "expected guids to be equal(%s:%s)\n", wine_dbgstr_guid(&guid), wine_dbgstr_guid(&guid2));
614 }
615 }
616 match_qw_attr(pdb, root, TAG_TIME, 0x1d1b91a02c0d63e);
617 match_str_attr(pdb, root, TAG_COMPILER_VERSION, "2.1.0.3");
618 match_str_attr(pdb, root, TAG_NAME, "apphelp_test1");
619 match_dw_attr(pdb, root, TAG_OS_PLATFORM, 1);
620 }
621
622 static void check_db_layer(PDB pdb, TAGID layer)
623 {
624 TAGID shimref, inexclude, is_include;
625 ok(layer != TAGID_NULL, "Expected a valid layer, got NULL\n");
626 if(!layer)
627 return;
628
629 match_str_attr(pdb, layer, TAG_NAME, "TestNewMode");
630 shimref = pSdbFindFirstTag(pdb, layer, TAG_SHIM_REF);
631 ok(shimref != TAGID_NULL, "Expected a valid shim ref, got NULL\n");
632 if(!shimref)
633 return;
634
635 match_str_attr(pdb, shimref, TAG_NAME, "VirtualRegistry");
636 match_str_attr(pdb, shimref, TAG_COMMAND_LINE, "ThemeActive");
637 inexclude = pSdbFindFirstTag(pdb, shimref, TAG_INEXCLUD);
638 ok(inexclude != TAGID_NULL, "Expected a valid in/exclude ref, got NULL\n");
639 if(!inexclude)
640 return;
641
642 is_include = pSdbFindFirstTag(pdb, inexclude, TAG_INCLUDE);
643 ok(is_include == TAGID_NULL, "Expected a NULL include ref, but got one anyway.\n");
644 match_str_attr(pdb, inexclude, TAG_MODULE, "exclude.dll");
645
646 inexclude = pSdbFindNextTag(pdb, shimref, inexclude);
647 ok(inexclude != TAGID_NULL, "Expected a valid in/exclude ref, got NULL\n");
648 if(!inexclude)
649 return;
650
651 is_include = pSdbFindFirstTag(pdb, inexclude, TAG_INCLUDE);
652 ok(is_include != TAGID_NULL, "Expected a valid include ref, got NULL\n");
653 match_str_attr(pdb, inexclude, TAG_MODULE, "include.dll");
654 }
655
656 static void check_matching_file(PDB pdb, TAGID exe, TAGID matching_file, int num)
657 {
658 ok(matching_file != TAGID_NULL, "Expected to find atleast 1 matching file.\n");
659 if(matching_file == TAGID_NULL)
660 return;
661
662 ok(num < 4, "Too many matches, expected only 4!\n");
663 if (num >= 4)
664 return;
665
666
667 match_str_attr(pdb, matching_file, TAG_NAME, "*");
668 match_str_attr(pdb, matching_file, TAG_COMPANY_NAME, "CompanyName");
669 match_str_attr(pdb, matching_file, TAG_PRODUCT_NAME, "ProductName");
670 match_str_attr(pdb, matching_file, TAG_PRODUCT_VERSION, "1.0.0.1");
671 match_str_attr(pdb, matching_file, TAG_FILE_VERSION, "1.0.0.0");
672
673 if( num == 0 || num == 3)
674 {
675 match_qw_attr(pdb, matching_file, TAG_UPTO_BIN_PRODUCT_VERSION, 0x1000000000001);
676 match_qw_attr(pdb, matching_file, TAG_UPTO_BIN_FILE_VERSION, 0x1000000000000);
677 }
678 if(num == 1 || num == 3)
679 {
680 match_dw_attr(pdb, matching_file, TAG_PE_CHECKSUM, 0xbaad);
681 }
682 if(num != 0)
683 {
684 match_qw_attr(pdb, matching_file, TAG_BIN_PRODUCT_VERSION, 0x1000000000001);
685 match_qw_attr(pdb, matching_file, TAG_BIN_FILE_VERSION, 0x1000000000000);
686 }
687 if(num == 3)
688 {
689 match_dw_attr(pdb, matching_file, TAG_SIZE, 0x800);
690 match_dw_attr(pdb, matching_file, TAG_CHECKSUM, 0x178bd629);
691 match_str_attr(pdb, matching_file, TAG_FILE_DESCRIPTION, "FileDescription");
692 match_dw_attr(pdb, matching_file, TAG_MODULE_TYPE, 3);
693 match_dw_attr(pdb, matching_file, TAG_VERFILEOS, 4);
694 match_dw_attr(pdb, matching_file, TAG_VERFILETYPE, 1);
695 match_dw_attr(pdb, matching_file, TAG_LINKER_VERSION, 0x40002);
696 match_str_attr(pdb, matching_file, TAG_ORIGINAL_FILENAME, "OriginalFilename");
697 match_str_attr(pdb, matching_file, TAG_INTERNAL_NAME, "InternalName");
698 match_str_attr(pdb, matching_file, TAG_LEGAL_COPYRIGHT, "LegalCopyright");
699 match_dw_attr(pdb, matching_file, TAG_LINK_DATE, 0x12345);
700 match_dw_attr(pdb, matching_file, TAG_UPTO_LINK_DATE, 0x12345);
701 }
702 if(num > 3)
703 {
704 ok(0, "unknown case: %d\n", num);
705 }
706 matching_file = pSdbFindNextTag(pdb, exe, matching_file);
707 if(num == 2)
708 {
709 ok(matching_file != TAGID_NULL, "Did expect a secondary match on %d\n", num);
710 match_str_attr(pdb, matching_file, TAG_NAME, "test_checkfile.txt");
711 match_dw_attr(pdb, matching_file, TAG_SIZE, 0x4);
712 match_dw_attr(pdb, matching_file, TAG_CHECKSUM, 0xb0b0b0b0);
713 }
714 else
715 {
716 ok(matching_file == TAGID_NULL, "Did not expect a secondary match on %d\n", num);
717 }
718 }
719
720 static void check_matching_apphelp(PDB pdb, TAGID apphelp, int num)
721 {
722 if(num == 0)
723 {
724 /*
725 [Window Title]
726 Program Compatibility Assistant
727
728 [Main Instruction]
729 This program has known compatibility issues
730
731 [Expanded Information]
732 Allow it!
733
734 [^] Hide details [ ] Don't show this message again [Check for solutions online] [Run program] [Cancel]
735 */
736 match_dw_attr(pdb, apphelp, TAG_FLAGS, 1);
737 match_dw_attr(pdb, apphelp, TAG_PROBLEMSEVERITY, 1);
738 match_dw_attr(pdb, apphelp, TAG_HTMLHELPID, 1);
739 match_dw_attr(pdb, apphelp, TAG_APP_NAME_RC_ID, 0x6f0072);
740 match_dw_attr(pdb, apphelp, TAG_VENDOR_NAME_RC_ID, 0x720067);
741 match_dw_attr(pdb, apphelp, TAG_SUMMARY_MSG_RC_ID, 0);
742 }
743 else
744 {
745 /*
746 [Window Title]
747 Program Compatibility Assistant
748
749 [Main Instruction]
750 This program is blocked due to compatibility issues
751
752 [Expanded Information]
753 Not allowed!
754
755 [^] Hide details [Check for solutions online] [Cancel]
756 */
757 match_dw_attr(pdb, apphelp, TAG_FLAGS, 1);
758 match_dw_attr(pdb, apphelp, TAG_PROBLEMSEVERITY, 2);
759 match_dw_attr(pdb, apphelp, TAG_HTMLHELPID, 2);
760 match_dw_attr(pdb, apphelp, TAG_APP_NAME_RC_ID, 0x320020);
761 match_dw_attr(pdb, apphelp, TAG_VENDOR_NAME_RC_ID, 0x38002e);
762 match_dw_attr(pdb, apphelp, TAG_SUMMARY_MSG_RC_ID, 0);
763 }
764 apphelp = pSdbFindNextTag(pdb, apphelp, apphelp);
765 ok(apphelp == TAGID_NULL, "Did not expect a secondary match on %d\n", num);
766 }
767
768 static void check_matching_layer(PDB pdb, TAGID layer, int num)
769 {
770 if(num == 2)
771 {
772 match_dw_attr(pdb, layer, TAG_LAYER_TAGID, 0x18e);
773 match_str_attr(pdb, layer, TAG_NAME, "TestNewMode");
774 }
775 else
776 {
777 TAGID layer_tagid = pSdbFindFirstTag(pdb, layer, TAG_LAYER_TAGID);
778 ok(layer_tagid == TAGID_NULL, "expected not to find a layer tagid, got %x\n", layer_tagid);
779 match_str_attr(pdb, layer, TAG_NAME, "WinSrv03");
780 }
781 }
782
783 static struct
784 {
785 const char* name;
786 const char* app_name;
787 const char* vendor;
788 GUID exe_id;
789 const char* extra_file;
790 DWORD dwLayerCount;
791 TAGREF atrExes_0;
792 TAGREF atrLayers_0;
793 } test_exedata[4] = {
794 {
795 "test_allow.exe",
796 "apphelp_name_allow",
797 "apphelp_vendor_allow",
798 {0x4e50c93f,0xb863,0x4dfa,{0xba,0xe2,0xd8,0x0e,0xf4,0xce,0x5c,0x89}},
799 NULL,
800 0,
801 0x1c6,
802 0,
803 },
804 {
805 "test_disallow.exe",
806 "apphelp_name_disallow",
807 "apphelp_vendor_disallow",
808 {0x156720e1,0xef98,0x4d04,{0x96,0x5a,0xd8,0x5d,0xe0,0x5e,0x6d,0x9f}},
809 NULL,
810 0,
811 0x256,
812 0,
813 },
814 {
815 "test_new.exe",
816 "fixnew_name",
817 "fixnew_vendor",
818 {0xce70ef69,0xa21d,0x408b,{0x84,0x5b,0xf9,0x9e,0xac,0x06,0x09,0xe7}},
819 "test_checkfile.txt",
820 1,
821 0x2ec,
822 0x18e,
823 },
824 {
825 "test_w2k3.exe",
826 "fix_name",
827 "fix_vendor",
828 {0xb4ead144,0xf640,0x4e4b,{0x94,0xc4,0x0c,0x7f,0xa8,0x66,0x23,0xb0}},
829 NULL,
830 0,
831 0x37c,
832 0,
833 },
834 };
835
836 static void check_db_exes(PDB pdb, TAGID root)
837 {
838 int num = 0;
839 TAGID exe = pSdbFindFirstTag(pdb, root, TAG_EXE);
840 while (exe != TAGID_NULL)
841 {
842 TAGID apphelp, layer;
843 ok(num < 4, "Too many matches, expected only 4!\n");
844 if(num >= 4)
845 break;
846 match_str_attr(pdb, exe, TAG_NAME, test_exedata[num].name);
847 match_str_attr(pdb, exe, TAG_APP_NAME, test_exedata[num].app_name);
848 match_str_attr(pdb, exe, TAG_VENDOR, test_exedata[num].vendor);
849 match_guid_attr(pdb, exe, TAG_EXE_ID, &test_exedata[num].exe_id);
850 check_matching_file(pdb, exe, pSdbFindFirstTag(pdb, exe, TAG_MATCHING_FILE), num);
851 apphelp = pSdbFindFirstTag(pdb, exe, TAG_APPHELP);
852 if(num == 0 || num == 1)
853 {
854 ok(apphelp != TAGID_NULL, "Expected to find a valid apphelp match on %d.\n", num);
855 if(apphelp)
856 check_matching_apphelp(pdb, apphelp, num);
857 }
858 else
859 {
860 ok(apphelp == TAGID_NULL, "Did not expect an apphelp match on %d\n", num);
861 }
862 layer = pSdbFindFirstTag(pdb, exe, TAG_LAYER);
863 if(num == 2 || num == 3)
864 {
865 ok(layer != TAGID_NULL, "Expected to find a valid layer match on %d.\n", num);
866 if(layer)
867 check_matching_layer(pdb, layer, num);
868 }
869 else
870 {
871 ok(layer == TAGID_NULL, "Did not expect a layer match on %d\n", num);
872 }
873 ++num;
874 exe = pSdbFindNextTag(pdb, root, exe);
875 }
876 ok(num == 4, "Expected to find 4 exe tags, found: %d\n", num);
877 }
878
879 static struct
880 {
881 DWORD htmlhelpid;
882 const char* link;
883 const char* apphelp_title;
884 const char* apphelp_details;
885 } test_layerdata[2] = {
886 {
887 2,
888 "http://reactos.org/disallow",
889 "apphelp_name_disallow",
890 "Not allowed!",
891 },
892 {
893 1,
894 "http://reactos.org/allow",
895 "apphelp_name_allow",
896 "Allow it!",
897 },
898 };
899
900 static void check_db_apphelp(PDB pdb, TAGID root)
901 {
902 int num = 0;
903 TAGID apphelp = pSdbFindFirstTag(pdb, root, TAG_APPHELP);
904 while (apphelp != TAGID_NULL)
905 {
906 TAGID link;
907 ok(num < 2, "Too many matches, expected only 4!\n");
908 if(num >= 2)
909 break;
910 match_dw_attr(pdb, apphelp, TAG_HTMLHELPID, test_layerdata[num].htmlhelpid);
911 link = pSdbFindFirstTag(pdb, apphelp, TAG_LINK);
912 ok(link != TAGID_NULL, "expected to find a link tag\n");
913 if (link != TAGID_NULL)
914 {
915 match_str_attr(pdb, link, TAG_LINK_URL, test_layerdata[num].link);
916 }
917 match_str_attr(pdb, apphelp, TAG_APPHELP_TITLE, test_layerdata[num].apphelp_title);
918 match_str_attr(pdb, apphelp, TAG_APPHELP_DETAILS, test_layerdata[num].apphelp_details);
919 apphelp = pSdbFindNextTag(pdb, root, apphelp);
920 num++;
921 }
922 ok(num == 2, "Expected to find 2 layer tags, found: %d\n", num);
923 }
924
925 static void test_CheckDatabaseManually(void)
926 {
927 static const WCHAR path[] = {'t','e','s','t','_','d','b','.','s','d','b',0};
928 TAGID root;
929 PDB pdb;
930 BOOL ret;
931 DWORD ver_hi, ver_lo;
932
933 test_create_db("test_db.sdb");
934
935 /* both ver_hi and ver_lo cannot be null, it'll crash. */
936 ver_hi = ver_lo = 0x12345678;
937 ret = pSdbGetDatabaseVersion(path, &ver_hi, &ver_lo);
938 ok(ret,"Expected SdbGetDatabaseVersion to succeed\n");
939 ok(ver_hi == 2,"Expected ver_hi to be 2, was: %d\n", ver_hi);
940 ok(ver_lo == 1,"Expected ver_lo to be 1, was: %d\n", ver_lo);
941
942 ver_hi = ver_lo = 0x12345678;
943 ret = pSdbGetDatabaseVersion(NULL, &ver_hi, &ver_lo);
944 ok(ret,"Expected SdbGetDatabaseVersion to succeed\n");
945 ok(ver_hi == 0x12345678,"Expected ver_hi to be 0x12345678, was: 0x%x\n", ver_hi);
946 ok(ver_lo == 0x12345678,"Expected ver_lo to be 0x12345678, was: 0x%x\n", ver_lo);
947
948 ver_hi = ver_lo = 0x12345678;
949 ret = pSdbGetDatabaseVersion(path + 1, &ver_hi, &ver_lo);
950 ok(ret,"Expected SdbGetDatabaseVersion to succeed\n");
951 ok(ver_hi == 0x12345678,"Expected ver_hi to be 0x12345678, was: 0x%x\n", ver_hi);
952 ok(ver_lo == 0x12345678,"Expected ver_lo to be 0x12345678, was: 0x%x\n", ver_lo);
953
954 pdb = pSdbOpenDatabase(path, DOS_PATH);
955 ok(pdb != NULL, "unexpected NULL handle\n");
956
957 root = pSdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
958 ok(root != TAGID_NULL, "expected to find a root tag\n");
959 if (root != TAGID_NULL)
960 {
961 check_db_properties(pdb, root);
962 check_db_layer(pdb, pSdbFindFirstTag(pdb, root, TAG_LAYER));
963 check_db_exes(pdb, root);
964 check_db_apphelp(pdb, root);
965 }
966
967 pSdbCloseDatabase(pdb);
968 DeleteFileA("test_db.sdb");
969 }
970
971
972 static void expect_indexA_imp(const char* text, LONGLONG expected)
973 {
974 static WCHAR wide_string[100] = { 0 };
975 LONGLONG result;
976 MultiByteToWideChar(CP_ACP, 0, text, -1, wide_string, 100);
977
978 result = pSdbMakeIndexKeyFromString(wide_string);
979 winetest_ok(result == expected, "Expected %s to result in %s, was: %s\n", text, wine_dbgstr_longlong(expected), wine_dbgstr_longlong(result));
980 }
981
982 #define expect_indexA (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_indexA_imp
983
984 static void test_IndexKeyFromString(void)
985 {
986 static WCHAR tmp [] = { 0xabba, 0xbcde, 0x2020, 0x20, 0x4444, 0};
987 static WCHAR tmp2 [] = { 0xabba, 0xbcde, 0x20, 0x4444, 0};
988 static WCHAR tmp3 [] = { 0x20, 0xbcde, 0x4041, 0x4444, 0};
989 static WCHAR tmp4 [] = { 0x20, 0xbcde, 0x4041, 0x4444, 0x4444, 0};
990 static WCHAR tmp5 [] = { 0x2020, 0xbcde, 0x4041, 0x4444, 0x4444, 0};
991 static WCHAR tmp6 [] = { 0x20, 0xbcde, 0x4041, 0x4444, 0x4444, 0x4444, 0};
992 static WCHAR tmp7 [] = { 0xbcde, 0x4041, 0x4444, 0x4444, 0x4444, 0x4444, 0x4444, 0x4444, 0x4444, 0};
993 static WCHAR tmp8 [] = { 0xbc00, 0x4041, 0x4444, 0x4444, 0x4444, 0x4444, 0x4444, 0x4444, 0x4444, 0};
994 LONGLONG result;
995
996 #if 0
997 /* This crashes. */
998 pSdbMakeIndexKeyFromString(NULL);
999 #endif
1000
1001 expect_indexA("", 0x0000000000000000);
1002 expect_indexA("a", 0x4100000000000000);
1003 expect_indexA("aa", 0x4141000000000000);
1004 expect_indexA("aaa", 0x4141410000000000);
1005 expect_indexA("aaaa", 0x4141414100000000);
1006 expect_indexA("aaaaa", 0x4141414141000000);
1007 expect_indexA("aaaaaa", 0x4141414141410000);
1008 expect_indexA("aaaaaaa", 0x4141414141414100);
1009 expect_indexA("aaaaaaaa", 0x4141414141414141);
1010 expect_indexA("aaa aaaaa", 0x4141412041414141);
1011 /* Does not change */
1012 expect_indexA("aaaaaaaaa", 0x4141414141414141);
1013 expect_indexA("aaaaaaaab", 0x4141414141414141);
1014 expect_indexA("aaaaaaaac", 0x4141414141414141);
1015 expect_indexA("aaaaaaaaF", 0x4141414141414141);
1016 /* Upcase */
1017 expect_indexA("AAAAAAAA", 0x4141414141414141);
1018 expect_indexA("ABABABAB", 0x4142414241424142);
1019 expect_indexA("ABABABABZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", 0x4142414241424142);
1020
1021 result = pSdbMakeIndexKeyFromString(tmp);
1022 ok(result == 0xbaabdebc20200000, "Expected %s to result in %s, was: %s\n", wine_dbgstr_w(tmp),
1023 wine_dbgstr_longlong(0xbaabdebc20200000), wine_dbgstr_longlong(result));
1024
1025 result = pSdbMakeIndexKeyFromString(tmp2);
1026 ok(result == 0xbaabdebc00000000, "Expected %s to result in %s, was: %s\n", wine_dbgstr_w(tmp2),
1027 wine_dbgstr_longlong(0xbaabdebc00000000), wine_dbgstr_longlong(result));
1028
1029 result = pSdbMakeIndexKeyFromString(tmp3);
1030 ok(result == 0x20debc4140000000, "Expected %s to result in %s, was: %s\n", wine_dbgstr_w(tmp3),
1031 wine_dbgstr_longlong(0x20debc4140000000), wine_dbgstr_longlong(result));
1032
1033 result = pSdbMakeIndexKeyFromString(tmp4);
1034 ok(result == 0x20debc4140000000, "Expected %s to result in %s, was: %s\n", wine_dbgstr_w(tmp4),
1035 wine_dbgstr_longlong(0x20debc4140000000), wine_dbgstr_longlong(result));
1036
1037 result = pSdbMakeIndexKeyFromString(tmp5);
1038 ok(result == 0x2020debc41400000, "Expected %s to result in %s, was: %s\n", wine_dbgstr_w(tmp5),
1039 wine_dbgstr_longlong(0x2020debc41400000), wine_dbgstr_longlong(result));
1040
1041 result = pSdbMakeIndexKeyFromString(tmp6);
1042 ok(result == 0x20debc4140444400, "Expected %s to result in %s, was: %s\n", wine_dbgstr_w(tmp6),
1043 wine_dbgstr_longlong(0x20debc4140444400), wine_dbgstr_longlong(result));
1044
1045 result = pSdbMakeIndexKeyFromString(tmp7);
1046 ok(result == 0xdebc414044444444, "Expected %s to result in %s, was: %s\n", wine_dbgstr_w(tmp7),
1047 wine_dbgstr_longlong(0xdebc414044444444), wine_dbgstr_longlong(result));
1048
1049 result = pSdbMakeIndexKeyFromString(tmp8);
1050 ok(result == 0xbc414044444444, "Expected %s to result in %s, was: %s\n", wine_dbgstr_w(tmp8),
1051 wine_dbgstr_longlong(0xbc414044444444), wine_dbgstr_longlong(result));
1052 }
1053
1054
1055 START_TEST(db)
1056 {
1057 //SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "4");
1058 //SetEnvironmentVariable("DEBUGCHANNEL", "+apphelp");
1059 hdll = LoadLibraryA("apphelp.dll");
1060 pSdbTagToString = (void *) GetProcAddress(hdll, "SdbTagToString");
1061 pSdbOpenDatabase = (void *) GetProcAddress(hdll, "SdbOpenDatabase");
1062 pSdbCreateDatabase = (void *) GetProcAddress(hdll, "SdbCreateDatabase");
1063 pSdbGetDatabaseVersion = (void *) GetProcAddress(hdll, "SdbGetDatabaseVersion");
1064 pSdbCloseDatabase = (void *) GetProcAddress(hdll, "SdbCloseDatabase");
1065 pSdbCloseDatabaseWrite = (void *) GetProcAddress(hdll, "SdbCloseDatabaseWrite");
1066 pSdbGetTagFromTagID = (void *) GetProcAddress(hdll, "SdbGetTagFromTagID");
1067 pSdbWriteNULLTag = (void *) GetProcAddress(hdll, "SdbWriteNULLTag");
1068 pSdbWriteWORDTag = (void *) GetProcAddress(hdll, "SdbWriteWORDTag");
1069 pSdbWriteDWORDTag = (void *) GetProcAddress(hdll, "SdbWriteDWORDTag");
1070 pSdbWriteQWORDTag = (void *) GetProcAddress(hdll, "SdbWriteQWORDTag");
1071 pSdbWriteBinaryTagFromFile = (void *) GetProcAddress(hdll, "SdbWriteBinaryTagFromFile");
1072 pSdbWriteStringTag = (void *) GetProcAddress(hdll, "SdbWriteStringTag");
1073 pSdbWriteStringRefTag = (void *) GetProcAddress(hdll, "SdbWriteStringRefTag");
1074 pSdbBeginWriteListTag = (void *)GetProcAddress(hdll, "SdbBeginWriteListTag");
1075 pSdbEndWriteListTag = (void *) GetProcAddress(hdll, "SdbEndWriteListTag");
1076 pSdbFindFirstTag = (void *) GetProcAddress(hdll, "SdbFindFirstTag");
1077 pSdbFindNextTag = (void *) GetProcAddress(hdll, "SdbFindNextTag");
1078 pSdbReadWORDTag = (void *) GetProcAddress(hdll, "SdbReadWORDTag");
1079 pSdbReadDWORDTag = (void *) GetProcAddress(hdll, "SdbReadDWORDTag");
1080 pSdbReadQWORDTag = (void *) GetProcAddress(hdll, "SdbReadQWORDTag");
1081 pSdbReadBinaryTag = (void *) GetProcAddress(hdll, "SdbReadBinaryTag");
1082 pSdbReadStringTag = (void *) GetProcAddress(hdll, "SdbReadStringTag");
1083 pSdbGetTagDataSize = (void *) GetProcAddress(hdll, "SdbGetTagDataSize");
1084 pSdbGetBinaryTagData = (void *) GetProcAddress(hdll, "SdbGetBinaryTagData");
1085 pSdbGetStringTagPtr = (void *) GetProcAddress(hdll, "SdbGetStringTagPtr");
1086 pSdbGetFirstChild = (void *) GetProcAddress(hdll, "SdbGetFirstChild");
1087 pSdbGetNextChild = (void *) GetProcAddress(hdll, "SdbGetNextChild");
1088 pSdbGetDatabaseID = (void *) GetProcAddress(hdll, "SdbGetDatabaseID");
1089 pSdbGUIDToString = (void *) GetProcAddress(hdll, "SdbGUIDToString");
1090 pSdbMakeIndexKeyFromString = (void*) GetProcAddress(hdll, "SdbMakeIndexKeyFromString");
1091
1092 test_Sdb();
1093 test_write_ex();
1094 test_stringtable();
1095 test_CheckDatabaseManually();
1096 test_IndexKeyFromString();
1097 }