1 /*
2 * DLL for testing type 1 custom actions
3 *
4 * Copyright 2017 Zebediah Figura
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 #if 0
22 #pragma makedep testdll
23 #endif
24
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include <windef.h>
29 #include <winbase.h>
30 #include <winsvc.h>
31 #include <odbcinst.h>
32 #define COBJMACROS
33 #include <shlobj.h>
34 #include <msxml.h>
35 #include <msi.h>
36 #include <msiquery.h>
37 #include <msidefs.h>
38
39 #ifdef __MINGW32__
40 #define __WINE_PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args)))
41 #else
42 #define __WINE_PRINTF_ATTR(fmt,args)
43 #endif
44
45 static int todo_level, todo_do_loop;
46
ok_(MSIHANDLE hinst,int todo,const char * file,int line,int condition,const char * msg,...)47 static void WINAPIV __WINE_PRINTF_ATTR(6,7) ok_(MSIHANDLE hinst, int todo, const char *file, int line, int condition, const char *msg, ...)
48 {
49 static char buffer[2000];
50 MSIHANDLE record;
51 va_list valist;
52
53 va_start(valist, msg);
54 vsprintf(buffer, msg, valist);
55 va_end(valist);
56
57 record = MsiCreateRecord(5);
58 MsiRecordSetInteger(record, 1, todo);
59 MsiRecordSetStringA(record, 2, file);
60 MsiRecordSetInteger(record, 3, line);
61 MsiRecordSetInteger(record, 4, condition);
62 MsiRecordSetStringA(record, 5, buffer);
63 MsiProcessMessage(hinst, INSTALLMESSAGE_USER, record);
64 MsiCloseHandle(record);
65 }
66
winetest_start_todo(int is_todo)67 static void winetest_start_todo( int is_todo )
68 {
69 todo_level = (todo_level << 1) | (is_todo != 0);
70 todo_do_loop=1;
71 }
72
winetest_loop_todo(void)73 static int winetest_loop_todo(void)
74 {
75 int do_loop=todo_do_loop;
76 todo_do_loop=0;
77 return do_loop;
78 }
79
winetest_end_todo(void)80 static void winetest_end_todo(void)
81 {
82 todo_level >>= 1;
83 }
84
85 #define ok(hinst, condition, ...) ok_(hinst, todo_level, __FILE__, __LINE__, condition, __VA_ARGS__)
86 #define todo_wine_if(is_todo) for (winetest_start_todo(is_todo); \
87 winetest_loop_todo(); \
88 winetest_end_todo())
89 #define todo_wine todo_wine_if(1)
90
dbgstr_w(WCHAR * str)91 static const char *dbgstr_w(WCHAR *str)
92 {
93 static char buffer[300], *p;
94
95 if (!str) return "(null)";
96
97 p = buffer;
98 *p++ = 'L';
99 *p++ = '"';
100 while ((*p++ = *str++));
101 *p++ = '"';
102 *p++ = 0;
103
104 return buffer;
105 }
106
check_prop(MSIHANDLE hinst,const char * prop,const char * expect)107 static void check_prop(MSIHANDLE hinst, const char *prop, const char *expect)
108 {
109 char buffer[10] = "x";
110 DWORD sz = sizeof(buffer);
111 UINT r = MsiGetPropertyA(hinst, prop, buffer, &sz);
112 ok(hinst, !r, "'%s': got %u\n", prop, r);
113 ok(hinst, sz == strlen(buffer), "'%s': expected %Iu, got %lu\n", prop, strlen(buffer), sz);
114 ok(hinst, !strcmp(buffer, expect), "expected '%s', got '%s'\n", expect, buffer);
115 }
116
test_props(MSIHANDLE hinst)117 static void test_props(MSIHANDLE hinst)
118 {
119 char buffer[10];
120 WCHAR bufferW[10];
121 DWORD sz;
122 UINT r;
123
124 /* test invalid values */
125 r = MsiGetPropertyA(hinst, NULL, NULL, NULL);
126 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
127
128 r = MsiGetPropertyA(hinst, "boo", NULL, NULL);
129 ok(hinst, !r, "got %u\n", r);
130
131 r = MsiGetPropertyA(hinst, "boo", buffer, NULL );
132 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
133
134 sz = 0;
135 r = MsiGetPropertyA(hinst, "boo", NULL, &sz);
136 ok(hinst, !r, "got %u\n", r);
137 ok(hinst, sz == 0, "got size %lu\n", sz);
138
139 sz = 0;
140 strcpy(buffer,"x");
141 r = MsiGetPropertyA(hinst, "boo", buffer, &sz);
142 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
143 ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n", buffer);
144 ok(hinst, sz == 0, "got size %lu\n", sz);
145
146 sz = 1;
147 strcpy(buffer,"x");
148 r = MsiGetPropertyA(hinst, "boo", buffer, &sz);
149 ok(hinst, !r, "got %u\n", r);
150 ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
151 ok(hinst, sz == 0, "got size %lu\n", sz);
152
153 /* set the property to something */
154 r = MsiSetPropertyA(hinst, NULL, NULL);
155 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
156
157 r = MsiSetPropertyA(hinst, "", NULL);
158 ok(hinst, !r, "got %u\n", r);
159
160 r = MsiSetPropertyA(hinst, "", "asdf");
161 ok(hinst, r == ERROR_FUNCTION_FAILED, "got %u\n", r);
162
163 r = MsiSetPropertyA(hinst, "=", "asdf");
164 ok(hinst, !r, "got %u\n", r);
165 check_prop(hinst, "=", "asdf");
166
167 r = MsiSetPropertyA(hinst, " ", "asdf");
168 ok(hinst, !r, "got %u\n", r);
169 check_prop(hinst, " ", "asdf");
170
171 r = MsiSetPropertyA(hinst, "'", "asdf");
172 ok(hinst, !r, "got %u\n", r);
173 check_prop(hinst, "'", "asdf");
174
175 r = MsiSetPropertyA(hinst, "boo", NULL);
176 ok(hinst, !r, "got %u\n", r);
177 check_prop(hinst, "boo", "");
178
179 r = MsiSetPropertyA(hinst, "boo", "");
180 ok(hinst, !r, "got %u\n", r);
181 check_prop(hinst, "boo", "");
182
183 r = MsiSetPropertyA(hinst, "boo", "xyz");
184 ok(hinst, !r, "got %u\n", r);
185 check_prop(hinst, "boo", "xyz");
186
187 r = MsiGetPropertyA(hinst, "boo", NULL, NULL);
188 ok(hinst, !r, "got %u\n", r);
189
190 r = MsiGetPropertyA(hinst, "boo", buffer, NULL );
191 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
192
193 /* Returned size is in bytes, not chars, but only for custom actions.
194 * Seems to be a casualty of RPC... */
195
196 sz = 0;
197 r = MsiGetPropertyA(hinst, "boo", NULL, &sz);
198 ok(hinst, !r, "got %u\n", r);
199 ok(hinst, sz == 6, "got size %lu\n", sz);
200
201 sz = 0;
202 strcpy(buffer,"q");
203 r = MsiGetPropertyA(hinst, "boo", buffer, &sz);
204 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
205 ok(hinst, !strcmp(buffer, "q"), "got \"%s\"\n", buffer);
206 ok(hinst, sz == 6, "got size %lu\n", sz);
207
208 sz = 1;
209 strcpy(buffer,"x");
210 r = MsiGetPropertyA(hinst, "boo", buffer, &sz);
211 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
212 ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
213 ok(hinst, sz == 6, "got size %lu\n", sz);
214
215 sz = 3;
216 strcpy(buffer,"x");
217 r = MsiGetPropertyA(hinst, "boo", buffer, &sz);
218 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
219 ok(hinst, !strcmp(buffer, "xy"), "got \"%s\"\n", buffer);
220 ok(hinst, sz == 6, "got size %lu\n", sz);
221
222 sz = 4;
223 strcpy(buffer,"x");
224 r = MsiGetPropertyA(hinst, "boo", buffer, &sz);
225 ok(hinst, !r, "got %u\n", r);
226 ok(hinst, !strcmp(buffer, "xyz"), "got \"%s\"\n", buffer);
227 ok(hinst, sz == 3, "got size %lu\n", sz);
228
229 r = MsiGetPropertyW(hinst, L"boo", NULL, NULL);
230 ok(hinst, !r, "got %u\n", r);
231
232 r = MsiGetPropertyW(hinst, L"boo", bufferW, NULL );
233 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
234
235 sz = 0;
236 r = MsiGetPropertyW(hinst, L"boo", NULL, &sz);
237 ok(hinst, !r, "got %u\n", r);
238 ok(hinst, sz == 3, "got size %lu\n", sz);
239
240 sz = 0;
241 lstrcpyW(bufferW, L"boo");
242 r = MsiGetPropertyW(hinst, L"boo", bufferW, &sz);
243 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
244 ok(hinst, !lstrcmpW(bufferW, L"boo"), "got %s\n", dbgstr_w(bufferW));
245 ok(hinst, sz == 3, "got size %lu\n", sz);
246
247 sz = 1;
248 lstrcpyW(bufferW, L"boo");
249 r = MsiGetPropertyW(hinst, L"boo", bufferW, &sz);
250 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
251 ok(hinst, !bufferW[0], "got %s\n", dbgstr_w(bufferW));
252 ok(hinst, sz == 3, "got size %lu\n", sz);
253
254 sz = 3;
255 lstrcpyW(bufferW, L"boo");
256 r = MsiGetPropertyW(hinst, L"boo", bufferW, &sz);
257 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
258 ok(hinst, !lstrcmpW(bufferW, L"xy"), "got %s\n", dbgstr_w(bufferW));
259 ok(hinst, sz == 3, "got size %lu\n", sz);
260
261 sz = 4;
262 lstrcpyW(bufferW, L"boo");
263 r = MsiGetPropertyW(hinst, L"boo", bufferW, &sz);
264 ok(hinst, !r, "got %u\n", r);
265 ok(hinst, !lstrcmpW(bufferW, L"xyz"), "got %s\n", dbgstr_w(bufferW));
266 ok(hinst, sz == 3, "got size %lu\n", sz);
267
268 r = MsiSetPropertyA(hinst, "boo", NULL);
269 ok(hinst, !r, "got %u\n", r);
270 check_prop(hinst, "boo", "");
271
272 sz = 0;
273 r = MsiGetPropertyA(hinst, "embednullprop", NULL, &sz);
274 ok(hinst, !r, "got %u\n", r);
275 ok(hinst, sz == 6, "got size %lu\n", sz);
276
277 sz = 4;
278 memset(buffer, 0xcc, sizeof(buffer));
279 r = MsiGetPropertyA(hinst, "embednullprop", buffer, &sz);
280 ok(hinst, !r, "got %u\n", r);
281 ok(hinst, sz == 3, "got size %lu\n", sz);
282 ok(hinst, !memcmp(buffer, "a\0\0\0\xcc", 5), "wrong data\n");
283 }
284
test_db(MSIHANDLE hinst)285 static void test_db(MSIHANDLE hinst)
286 {
287 static const UINT prop_type[20] = { VT_EMPTY, VT_EMPTY, VT_LPSTR, VT_EMPTY, VT_EMPTY,
288 VT_EMPTY, VT_EMPTY, VT_LPSTR, VT_EMPTY, VT_LPSTR,
289 VT_EMPTY, VT_EMPTY, VT_EMPTY, VT_EMPTY, VT_I4,
290 VT_I4, VT_EMPTY, VT_EMPTY, VT_EMPTY, VT_EMPTY };
291 MSIHANDLE hdb, hdb2, view, rec, rec2, suminfo;
292 char buffer[10];
293 DWORD sz;
294 UINT r, count, type, i;
295 INT int_value;
296 FILETIME ft;
297
298 hdb = MsiGetActiveDatabase(hinst);
299 ok(hinst, hdb, "MsiGetActiveDatabase failed\n");
300
301 r = MsiDatabaseIsTablePersistentA(hdb, "Test");
302 ok(hinst, r == MSICONDITION_TRUE, "got %u\n", r);
303
304 r = MsiDatabaseOpenViewA(hdb, NULL, &view);
305 ok(hinst, r == ERROR_BAD_QUERY_SYNTAX, "got %u\n", r);
306
307 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `Test`", NULL);
308 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
309
310 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `Test`", &view);
311 ok(hinst, !r, "got %u\n", r);
312
313 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec2);
314 ok(hinst, !r, "got %u\n", r);
315
316 sz = sizeof(buffer);
317 r = MsiRecordGetStringA(rec2, 1, buffer, &sz);
318 ok(hinst, !r, "got %u\n", r);
319 ok(hinst, sz == strlen(buffer), "got size %lu\n", sz);
320 ok(hinst, !strcmp(buffer, "Name"), "got '%s'\n", buffer);
321
322 /* Test MsiGetActiveDatabase + MsiDatabaseIsTablePersistent once again */
323 hdb2 = MsiGetActiveDatabase(hinst);
324 ok(hinst, hdb2, "MsiGetActiveDatabase failed\n");
325 ok(hinst, hdb2 != hdb, "db handles should be different\n");
326
327 r = MsiDatabaseIsTablePersistentA(hdb2, "Test");
328 ok(hinst, r == MSICONDITION_TRUE, "got %u\n", r);
329
330 r = MsiCloseHandle(hdb2);
331 ok(hinst, !r, "got %u\n", r);
332
333 r = MsiCloseHandle(rec2);
334 ok(hinst, !r, "got %u\n", r);
335
336 r = MsiViewExecute(view, 0);
337 ok(hinst, !r, "got %u\n", r);
338
339 r = MsiViewFetch(view, &rec2);
340 ok(hinst, !r, "got %u\n", r);
341
342 r = MsiRecordGetFieldCount(rec2);
343 ok(hinst, r == 3, "got %u\n", r);
344
345 sz = sizeof(buffer);
346 r = MsiRecordGetStringA(rec2, 1, buffer, &sz);
347 ok(hinst, !r, "got %u\n", r);
348 ok(hinst, sz == strlen(buffer), "got size %lu\n", sz);
349 ok(hinst, !strcmp(buffer, "one"), "got '%s'\n", buffer);
350
351 r = MsiRecordGetInteger(rec2, 2);
352 ok(hinst, r == 1, "got %u\n", r);
353
354 sz = sizeof(buffer);
355 r = MsiRecordReadStream(rec2, 3, buffer, &sz);
356 ok(hinst, !r, "got %u\n", r);
357 ok(hinst, !memcmp(buffer, "unus", 4), "wrong data\n");
358
359 r = MsiCloseHandle(rec2);
360 ok(hinst, !r, "got %u\n", r);
361
362 r = MsiViewFetch(view, &rec2);
363 ok(hinst, !r, "got %u\n", r);
364
365 r = MsiRecordGetFieldCount(rec2);
366 ok(hinst, r == 3, "got %u\n", r);
367
368 sz = sizeof(buffer);
369 r = MsiRecordGetStringA(rec2, 1, buffer, &sz);
370 ok(hinst, !r, "got %u\n", r);
371 ok(hinst, sz == strlen(buffer), "got size %lu\n", sz);
372 ok(hinst, !strcmp(buffer, "two"), "got '%s'\n", buffer);
373
374 r = MsiRecordGetInteger(rec2, 2);
375 ok(hinst, r == 2, "got %u\n", r);
376
377 sz = sizeof(buffer);
378 r = MsiRecordReadStream(rec2, 3, buffer, &sz);
379 ok(hinst, !r, "got %u\n", r);
380 ok(hinst, !memcmp(buffer, "duo", 3), "wrong data\n");
381
382 r = MsiViewModify(view, MSIMODIFY_REFRESH, 0);
383 ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
384
385 r = MsiRecordSetStringA(rec2, 1, "three");
386 ok(hinst, !r, "got %u\n", r);
387
388 r = MsiRecordSetInteger(rec2, 2, 3);
389 ok(hinst, !r, "got %u\n", r);
390
391 r = MsiRecordSetInteger(rec2, 3, 3);
392 ok(hinst, !r, "got %u\n", r);
393
394 r = MsiViewModify(view, MSIMODIFY_REFRESH, rec2);
395 ok(hinst, !r, "got %u\n", r);
396
397 sz = sizeof(buffer);
398 r = MsiRecordGetStringA(rec2, 1, buffer, &sz);
399 ok(hinst, !r, "got %u\n", r);
400 ok(hinst, sz == strlen(buffer), "got size %lu\n", sz);
401 ok(hinst, !strcmp(buffer, "two"), "got '%s'\n", buffer);
402
403 r = MsiRecordGetInteger(rec2, 2);
404 ok(hinst, r == 2, "got %u\n", r);
405
406 sz = sizeof(buffer);
407 r = MsiRecordReadStream(rec2, 3, buffer, &sz);
408 ok(hinst, !r, "got %u\n", r);
409 ok(hinst, !memcmp(buffer, "duo", 3), "wrong data\n");
410
411 r = MsiCloseHandle(rec2);
412 ok(hinst, !r, "got %u\n", r);
413
414 r = MsiViewFetch(view, &rec2);
415 ok(hinst, r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
416 ok(hinst, !rec2, "got %lu\n", rec2);
417
418 r = MsiViewClose(view);
419 ok(hinst, !r, "got %u\n", r);
420
421 r = MsiCloseHandle(view);
422 ok(hinst, !r, "got %u\n", r);
423
424 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `Test` WHERE `Name` = ?", &view);
425 ok(hinst, !r, "got %u\n", r);
426
427 rec = MsiCreateRecord(1);
428 MsiRecordSetStringA(rec, 1, "one");
429
430 r = MsiViewExecute(view, rec);
431 ok(hinst, !r, "got %u\n", r);
432
433 r = MsiViewFetch(view, &rec2);
434 ok(hinst, !r, "got %u\n", r);
435
436 r = MsiRecordGetInteger(rec2, 2);
437 ok(hinst, r == 1, "got %u\n", r);
438
439 r = MsiCloseHandle(rec2);
440 ok(hinst, !r, "got %u\n", r);
441
442 r = MsiViewFetch(view, &rec2);
443 ok(hinst, r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
444 ok(hinst, !rec2, "got %lu\n", rec2);
445
446 r = MsiCloseHandle(rec);
447 ok(hinst, !r, "got %u\n", r);
448
449 r = MsiCloseHandle(view);
450 ok(hinst, !r, "got %u\n", r);
451
452 /* test MsiDatabaseGetPrimaryKeys() */
453 r = MsiDatabaseGetPrimaryKeysA(hdb, "Test", &rec);
454 ok(hinst, !r, "got %u\n", r);
455
456 r = MsiRecordGetFieldCount(rec);
457 ok(hinst, r == 1, "got %u\n", r);
458
459 sz = sizeof(buffer);
460 r = MsiRecordGetStringA(rec, 0, buffer, &sz);
461 ok(hinst, !r, "got %u\n", r);
462 ok(hinst, sz == strlen(buffer), "got size %lu\n", sz);
463 ok(hinst, !strcmp(buffer, "Test"), "got '%s'\n", buffer);
464
465 sz = sizeof(buffer);
466 r = MsiRecordGetStringA(rec, 1, buffer, &sz);
467 ok(hinst, !r, "got %u\n", r);
468 ok(hinst, sz == strlen(buffer), "got size %lu\n", sz);
469 ok(hinst, !strcmp(buffer, "Name"), "got '%s'\n", buffer);
470
471 r = MsiCloseHandle(rec);
472 ok(hinst, !r, "got %u\n", r);
473
474 r = MsiGetSummaryInformationA(hdb, NULL, 1, NULL);
475 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
476
477 r = MsiGetSummaryInformationA(hdb, NULL, 1, &suminfo);
478 ok(hinst, !r, "got %u\n", r);
479
480 r = MsiSummaryInfoGetPropertyCount(suminfo, NULL);
481 ok(hinst, r == RPC_X_NULL_REF_POINTER, "got %u\n", r);
482
483 count = 0xdeadbeef;
484 r = MsiSummaryInfoGetPropertyCount(suminfo, &count);
485 ok(hinst, !r, "got %u\n", r);
486 ok(hinst, count == 5, "got %u\n", count);
487
488 r = MsiSummaryInfoGetPropertyA(suminfo, 0, NULL, NULL, NULL, NULL, NULL);
489 ok(hinst, r == RPC_X_NULL_REF_POINTER, "got %u\n", r);
490
491 for (i = 0; i < 20; i++)
492 {
493 /* for some reason query for PID_TITLE leads to install failure under Windows */
494 if (i == PID_TITLE) continue;
495
496 type = 0xdeadbeef;
497 int_value = 0xdeadbeef;
498 *buffer = 0;
499 sz = sizeof(buffer);
500 r = MsiSummaryInfoGetPropertyA(suminfo, i, &type, &int_value, &ft, buffer, &sz);
501 if (sz == sizeof(buffer) || i == PID_TEMPLATE)
502 ok(hinst, !r, "%u: got %u\n", i, r);
503 else
504 ok(hinst, r == ERROR_MORE_DATA, "%u: got %u\n", i, r);
505 ok(hinst, type == prop_type[i], "%u: expected %u, got %u\n", i, prop_type[i], type);
506 if (i == PID_PAGECOUNT)
507 ok(hinst, int_value == 100, "%u: got %u\n", i, int_value);
508 else
509 ok(hinst, int_value == 0, "%u: got %u\n", i, int_value);
510 if (i == PID_TEMPLATE)
511 {
512 ok(hinst, sz == 5, "%u: got %lu\n", i, sz);
513 ok(hinst, !lstrcmpA(buffer, ";1033"), "%u: got %s\n", i, buffer);
514 }
515 else if (i == PID_REVNUMBER)
516 {
517 ok(hinst, sz == 76, "%u: got %lu\n", i, sz);
518 ok(hinst, !lstrcmpA(buffer, "{004757CA"), "%u: got %s\n", i, buffer);
519 }
520 else
521 {
522 ok(hinst, sz == sizeof(buffer), "%u: got %lu\n", i, sz);
523 ok(hinst, !*buffer, "%u: got %s\n", i, buffer);
524 }
525 }
526
527 GetSystemTimeAsFileTime(&ft);
528
529 for (i = 0; i < 20; i++)
530 {
531 r = MsiSummaryInfoSetPropertyA(suminfo, i, prop_type[i], 1252, &ft, "");
532 ok(hinst, r == ERROR_FUNCTION_FAILED, "%u: got %u\n", i, r);
533
534 r = MsiSummaryInfoSetPropertyW(suminfo, i, prop_type[i], 1252, &ft, L"");
535 ok(hinst, r == ERROR_FUNCTION_FAILED, "%u: got %u\n", i, r);
536 }
537
538 r = MsiCloseHandle(suminfo);
539 ok(hinst, !r, "got %u\n", r);
540
541 r = MsiCloseHandle(hdb);
542 ok(hinst, !r, "got %u\n", r);
543 }
544
test_doaction(MSIHANDLE hinst)545 static void test_doaction(MSIHANDLE hinst)
546 {
547 UINT r;
548
549 r = MsiDoActionA(hinst, "nested51");
550 ok(hinst, !r, "got %u\n", r);
551 check_prop(hinst, "nested", "1");
552
553 r = MsiDoActionA(hinst, "nested1");
554 ok(hinst, !r, "got %u\n", r);
555 check_prop(hinst, "nested", "2");
556
557 r = MsiSequenceA(hinst, NULL, 0);
558 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
559
560 r = MsiSequenceA(hinst, "TestSequence", 0);
561 ok(hinst, !r, "got %u\n", r);
562 check_prop(hinst, "nested", "1");
563 }
564
nested(MSIHANDLE hinst)565 UINT WINAPI nested(MSIHANDLE hinst)
566 {
567 MsiSetPropertyA(hinst, "nested", "2");
568
569 return ERROR_SUCCESS;
570 }
571
test_targetpath(MSIHANDLE hinst)572 static void test_targetpath(MSIHANDLE hinst)
573 {
574 WCHAR bufferW[100];
575 char buffer[100];
576 DWORD sz, srcsz;
577 UINT r;
578
579 /* test invalid values */
580 r = MsiGetTargetPathA(hinst, NULL, NULL, NULL);
581 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
582
583 r = MsiGetTargetPathA(hinst, "TARGETDIR", NULL, NULL );
584 ok(hinst, !r, "got %u\n", r);
585
586 r = MsiGetTargetPathA(hinst, "TARGETDIR", buffer, NULL );
587 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
588
589 /* Returned size is in bytes, not chars, but only for custom actions.
590 * Seems to be a casualty of RPC... */
591
592 sz = 0;
593 r = MsiGetTargetPathA(hinst, "TARGETDIR", NULL, &sz);
594 ok(hinst, !r, "got %u\n", r);
595 ok(hinst, sz == 6, "got size %lu\n", sz);
596
597 sz = 0;
598 strcpy(buffer,"q");
599 r = MsiGetTargetPathA(hinst, "TARGETDIR", buffer, &sz);
600 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
601 ok(hinst, !strcmp(buffer, "q"), "got \"%s\"\n", buffer);
602 ok(hinst, sz == 6, "got size %lu\n", sz);
603
604 sz = 1;
605 strcpy(buffer,"x");
606 r = MsiGetTargetPathA(hinst, "TARGETDIR", buffer, &sz);
607 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
608 ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
609 ok(hinst, sz == 6, "got size %lu\n", sz);
610
611 sz = 3;
612 strcpy(buffer,"x");
613 r = MsiGetTargetPathA(hinst, "TARGETDIR", buffer, &sz);
614 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
615 ok(hinst, !strcmp(buffer, "C:"), "got \"%s\"\n", buffer);
616 ok(hinst, sz == 6, "got size %lu\n", sz);
617
618 sz = 4;
619 strcpy(buffer,"x");
620 r = MsiGetTargetPathA(hinst, "TARGETDIR", buffer, &sz);
621 ok(hinst, !r, "got %u\n", r);
622 ok(hinst, !strcmp(buffer, "C:\\"), "got \"%s\"\n", buffer);
623 ok(hinst, sz == 3, "got size %lu\n", sz);
624
625 sz = 0;
626 r = MsiGetTargetPathW(hinst, L"TARGETDIR", NULL, &sz);
627 ok(hinst, !r, "got %u\n", r);
628 ok(hinst, sz == 3, "got size %lu\n", sz);
629
630 sz = 0;
631 bufferW[0] = 'q';
632 r = MsiGetTargetPathW(hinst, L"TARGETDIR", bufferW, &sz);
633 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
634 ok(hinst, bufferW[0] == 'q', "got %s\n", dbgstr_w(bufferW));
635 ok(hinst, sz == 3, "got size %lu\n", sz);
636
637 sz = 1;
638 bufferW[0] = 'q';
639 r = MsiGetTargetPathW(hinst, L"TARGETDIR", bufferW, &sz);
640 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
641 ok(hinst, !bufferW[0], "got %s\n", dbgstr_w(bufferW));
642 ok(hinst, sz == 3, "got size %lu\n", sz);
643
644 sz = 3;
645 bufferW[0] = 'q';
646 r = MsiGetTargetPathW(hinst, L"TARGETDIR", bufferW, &sz);
647 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
648 ok(hinst, !lstrcmpW(bufferW, L"C:"), "got %s\n", dbgstr_w(bufferW));
649 ok(hinst, sz == 3, "got size %lu\n", sz);
650
651 sz = 4;
652 bufferW[0] = 'q';
653 r = MsiGetTargetPathW(hinst, L"TARGETDIR", bufferW, &sz);
654 ok(hinst, !r, "got %u\n", r);
655 ok(hinst, !lstrcmpW(bufferW, L"C:\\"), "got %s\n", dbgstr_w(bufferW));
656 ok(hinst, sz == 3, "got size %lu\n", sz);
657
658 r = MsiSetTargetPathA(hinst, NULL, "C:\\subdir");
659 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
660
661 r = MsiSetTargetPathA(hinst, "MSITESTDIR", NULL);
662 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
663
664 r = MsiSetTargetPathA(hinst, "MSITESTDIR", "C:\\subdir");
665 ok(hinst, !r, "got %u\n", r);
666
667 sz = sizeof(buffer);
668 r = MsiGetTargetPathA(hinst, "MSITESTDIR", buffer, &sz);
669 ok(hinst, !r, "got %u\n", r);
670 ok(hinst, !strcmp(buffer, "C:\\subdir\\"), "got \"%s\"\n", buffer);
671
672 r = MsiSetTargetPathA(hinst, "MSITESTDIR", "C:\\");
673
674 /* test GetSourcePath() */
675
676 r = MsiGetSourcePathA(hinst, NULL, NULL, NULL);
677 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
678
679 r = MsiGetSourcePathA(hinst, "TARGETDIR", NULL, NULL );
680 ok(hinst, !r, "got %u\n", r);
681
682 r = MsiGetSourcePathA(hinst, "TARGETDIR", buffer, NULL );
683 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
684
685 /* Returned size is in bytes, not chars, but only for custom actions.
686 * Seems to be a casualty of RPC... */
687
688 srcsz = 0;
689 MsiGetSourcePathW(hinst, L"TARGETDIR", NULL, &srcsz);
690
691 sz = 0;
692 r = MsiGetSourcePathA(hinst, "TARGETDIR", NULL, &sz);
693 ok(hinst, !r, "got %u\n", r);
694 ok(hinst, sz == srcsz * 2, "got size %lu\n", sz);
695
696 sz = 0;
697 strcpy(buffer,"q");
698 r = MsiGetSourcePathA(hinst, "TARGETDIR", buffer, &sz);
699 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
700 ok(hinst, !strcmp(buffer, "q"), "got \"%s\"\n", buffer);
701 ok(hinst, sz == srcsz * 2, "got size %lu\n", sz);
702
703 sz = 1;
704 strcpy(buffer,"x");
705 r = MsiGetSourcePathA(hinst, "TARGETDIR", buffer, &sz);
706 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
707 ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
708 ok(hinst, sz == srcsz * 2, "got size %lu\n", sz);
709
710 sz = srcsz;
711 strcpy(buffer,"x");
712 r = MsiGetSourcePathA(hinst, "TARGETDIR", buffer, &sz);
713 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
714 ok(hinst, strlen(buffer) == srcsz - 1, "wrong buffer length %Iu\n", strlen(buffer));
715 ok(hinst, sz == srcsz * 2, "got size %lu\n", sz);
716
717 sz = srcsz + 1;
718 strcpy(buffer,"x");
719 r = MsiGetSourcePathA(hinst, "TARGETDIR", buffer, &sz);
720 ok(hinst, !r, "got %u\n", r);
721 ok(hinst, strlen(buffer) == srcsz, "wrong buffer length %Iu\n", strlen(buffer));
722 ok(hinst, sz == srcsz, "got size %lu\n", sz);
723
724 sz = 0;
725 r = MsiGetSourcePathW(hinst, L"TARGETDIR", NULL, &sz);
726 ok(hinst, !r, "got %u\n", r);
727 ok(hinst, sz == srcsz, "got size %lu\n", sz);
728
729 sz = 0;
730 bufferW[0] = 'q';
731 r = MsiGetSourcePathW(hinst, L"TARGETDIR", bufferW, &sz);
732 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
733 ok(hinst, bufferW[0] == 'q', "got %s\n", dbgstr_w(bufferW));
734 ok(hinst, sz == srcsz, "got size %lu\n", sz);
735
736 sz = 1;
737 bufferW[0] = 'q';
738 r = MsiGetSourcePathW(hinst, L"TARGETDIR", bufferW, &sz);
739 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
740 ok(hinst, !bufferW[0], "got %s\n", dbgstr_w(bufferW));
741 ok(hinst, sz == srcsz, "got size %lu\n", sz);
742
743 sz = srcsz;
744 bufferW[0] = 'q';
745 r = MsiGetSourcePathW(hinst, L"TARGETDIR", bufferW, &sz);
746 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
747 ok(hinst, lstrlenW(bufferW) == srcsz - 1, "wrong buffer length %d\n", lstrlenW(bufferW));
748 ok(hinst, sz == srcsz, "got size %lu\n", sz);
749
750 sz = srcsz + 1;
751 bufferW[0] = 'q';
752 r = MsiGetSourcePathW(hinst, L"TARGETDIR", bufferW, &sz);
753 ok(hinst, !r, "got %u\n", r);
754 ok(hinst, lstrlenW(bufferW) == srcsz, "wrong buffer length %d\n", lstrlenW(bufferW));
755 ok(hinst, sz == srcsz, "got size %lu\n", sz);
756 }
757
test_misc(MSIHANDLE hinst)758 static void test_misc(MSIHANDLE hinst)
759 {
760 MSICONDITION cond;
761 LANGID lang;
762 UINT r;
763
764 r = MsiSetMode(hinst, MSIRUNMODE_REBOOTATEND, FALSE);
765 ok(hinst, !r, "got %u\n", r);
766
767 lang = MsiGetLanguage(hinst);
768 ok(hinst, lang == 1033, "got %u\n", lang);
769
770 check_prop(hinst, "INSTALLLEVEL", "3");
771 r = MsiSetInstallLevel(hinst, 123);
772 ok(hinst, !r, "got %u\n", r);
773 check_prop(hinst, "INSTALLLEVEL", "123");
774 MsiSetInstallLevel(hinst, 3);
775
776 cond = MsiEvaluateConditionA(hinst, NULL);
777 ok(hinst, cond == MSICONDITION_NONE, "got %u\n", cond);
778 MsiSetPropertyA(hinst, "condprop", "1");
779 cond = MsiEvaluateConditionA(hinst, "condprop = 1");
780 ok(hinst, cond == MSICONDITION_TRUE, "got %u\n", cond);
781 }
782
test_feature_states(MSIHANDLE hinst)783 static void test_feature_states(MSIHANDLE hinst)
784 {
785 INSTALLSTATE state, action;
786 UINT r;
787
788 /* test feature states */
789
790 r = MsiGetFeatureStateA(hinst, NULL, &state, &action);
791 ok(hinst, r == ERROR_UNKNOWN_FEATURE, "got %u\n", r);
792
793 r = MsiGetFeatureStateA(hinst, "fake", &state, &action);
794 ok(hinst, r == ERROR_UNKNOWN_FEATURE, "got %u\n", r);
795
796 r = MsiGetFeatureStateA(hinst, "One", NULL, &action);
797 ok(hinst, r == RPC_X_NULL_REF_POINTER, "got %u\n", r);
798
799 r = MsiGetFeatureStateA(hinst, "One", &state, NULL);
800 ok(hinst, r == RPC_X_NULL_REF_POINTER, "got %u\n", r);
801
802 r = MsiGetFeatureStateA(hinst, "One", &state, &action);
803 ok(hinst, !r, "got %u\n", r);
804 ok(hinst, state == INSTALLSTATE_ABSENT, "got state %d\n", state);
805 ok(hinst, action == INSTALLSTATE_LOCAL, "got action %d\n", action);
806
807 r = MsiSetFeatureStateA(hinst, NULL, INSTALLSTATE_ABSENT);
808 ok(hinst, r == ERROR_UNKNOWN_FEATURE, "got %u\n", r);
809
810 r = MsiSetFeatureStateA(hinst, "One", INSTALLSTATE_ADVERTISED);
811 ok(hinst, !r, "got %u\n", r);
812
813 r = MsiGetFeatureStateA(hinst, "One", &state, &action);
814 ok(hinst, !r, "got %u\n", r);
815 ok(hinst, action == INSTALLSTATE_ADVERTISED, "got action %d\n", action);
816
817 r = MsiSetFeatureStateA(hinst, "One", INSTALLSTATE_LOCAL);
818 ok(hinst, !r, "got %u\n", r);
819
820 r = MsiGetFeatureStateA(hinst, "One", &state, &action);
821 ok(hinst, !r, "got %u\n", r);
822 ok(hinst, action == INSTALLSTATE_LOCAL, "got action %d\n", action);
823
824 /* test component states */
825
826 r = MsiGetComponentStateA(hinst, NULL, &state, &action);
827 ok(hinst, r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r);
828
829 r = MsiGetComponentStateA(hinst, "fake", &state, &action);
830 ok(hinst, r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r);
831
832 r = MsiGetComponentStateA(hinst, "One", NULL, &action);
833 ok(hinst, r == RPC_X_NULL_REF_POINTER, "got %u\n", r);
834
835 r = MsiGetComponentStateA(hinst, "One", &state, NULL);
836 ok(hinst, r == RPC_X_NULL_REF_POINTER, "got %u\n", r);
837
838 r = MsiGetComponentStateA(hinst, "One", &state, &action);
839 ok(hinst, !r, "got %u\n", r);
840 ok(hinst, state == INSTALLSTATE_ABSENT, "got state %d\n", state);
841 ok(hinst, action == INSTALLSTATE_LOCAL, "got action %d\n", action);
842
843 r = MsiGetComponentStateA(hinst, "dangler", &state, &action);
844 ok(hinst, !r, "got %u\n", r);
845 ok(hinst, state == INSTALLSTATE_ABSENT, "got state %d\n", state);
846 ok(hinst, action == INSTALLSTATE_UNKNOWN, "got action %d\n", action);
847
848 r = MsiGetComponentStateA(hinst, "component", &state, &action);
849 ok(hinst, !r, "got %u\n", r);
850 ok(hinst, state == INSTALLSTATE_UNKNOWN, "got state %d\n", state);
851 ok(hinst, action == INSTALLSTATE_LOCAL, "got action %d\n", action);
852
853 r = MsiSetComponentStateA(hinst, NULL, INSTALLSTATE_ABSENT);
854 ok(hinst, r == ERROR_UNKNOWN_COMPONENT, "got %u\n", r);
855
856 r = MsiSetComponentStateA(hinst, "One", INSTALLSTATE_SOURCE);
857 ok(hinst, !r, "got %u\n", r);
858
859 r = MsiGetComponentStateA(hinst, "One", &state, &action);
860 ok(hinst, !r, "got %u\n", r);
861 ok(hinst, state == INSTALLSTATE_ABSENT, "got state %d\n", state);
862 ok(hinst, action == INSTALLSTATE_SOURCE, "got action %d\n", action);
863
864 r = MsiSetComponentStateA(hinst, "One", INSTALLSTATE_LOCAL);
865 ok(hinst, !r, "got %u\n", r);
866
867 r = MsiGetComponentStateA(hinst, "One", &state, &action);
868 ok(hinst, !r, "got %u\n", r);
869 ok(hinst, state == INSTALLSTATE_ABSENT, "got state %d\n", state);
870 ok(hinst, action == INSTALLSTATE_LOCAL, "got action %d\n", action);
871 }
872
test_format_record(MSIHANDLE hinst)873 static void test_format_record(MSIHANDLE hinst)
874 {
875 WCHAR bufferW[10];
876 char buffer[10];
877 MSIHANDLE rec;
878 DWORD sz;
879 UINT r;
880
881 r = MsiFormatRecordA(hinst, 0, NULL, NULL);
882 ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
883
884 rec = MsiCreateRecord(1);
885 MsiRecordSetStringA(rec, 0, "foo [1]");
886 MsiRecordSetInteger(rec, 1, 123);
887
888 r = MsiFormatRecordA(hinst, rec, NULL, NULL);
889 ok(hinst, !r, "got %u\n", r);
890
891 r = MsiFormatRecordA(hinst, rec, buffer, NULL);
892 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
893
894 /* Returned size is in bytes, not chars, but only for custom actions. */
895
896 sz = 0;
897 r = MsiFormatRecordA(hinst, rec, NULL, &sz);
898 ok(hinst, !r, "got %u\n", r);
899 ok(hinst, sz == 14, "got size %lu\n", sz);
900
901 sz = 0;
902 strcpy(buffer,"q");
903 r = MsiFormatRecordA(hinst, rec, buffer, &sz);
904 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
905 ok(hinst, !strcmp(buffer, "q"), "got \"%s\"\n", buffer);
906 ok(hinst, sz == 14, "got size %lu\n", sz);
907
908 sz = 1;
909 strcpy(buffer,"x");
910 r = MsiFormatRecordA(hinst, rec, buffer, &sz);
911 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
912 ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
913 ok(hinst, sz == 14, "got size %lu\n", sz);
914
915 sz = 7;
916 strcpy(buffer,"x");
917 r = MsiFormatRecordA(hinst, rec, buffer, &sz);
918 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
919 ok(hinst, !strcmp(buffer, "foo 12"), "got \"%s\"\n", buffer);
920 ok(hinst, sz == 14, "got size %lu\n", sz);
921
922 sz = 8;
923 strcpy(buffer,"x");
924 r = MsiFormatRecordA(hinst, rec, buffer, &sz);
925 ok(hinst, !r, "got %u\n", r);
926 ok(hinst, !strcmp(buffer, "foo 123"), "got \"%s\"\n", buffer);
927 ok(hinst, sz == 7, "got size %lu\n", sz);
928
929 r = MsiFormatRecordW(hinst, rec, NULL, NULL);
930 ok(hinst, !r, "got %u\n", r);
931
932 r = MsiFormatRecordW(hinst, rec, bufferW, NULL);
933 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
934
935 sz = 0;
936 r = MsiFormatRecordW(hinst, rec, NULL, &sz);
937 ok(hinst, !r, "got %u\n", r);
938 ok(hinst, sz == 7, "got size %lu\n", sz);
939
940 sz = 0;
941 bufferW[0] = 'q';
942 r = MsiFormatRecordW(hinst, rec, bufferW, &sz);
943 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
944 ok(hinst, bufferW[0] == 'q', "got %s\n", dbgstr_w(bufferW));
945 ok(hinst, sz == 7, "got size %lu\n", sz);
946
947 sz = 1;
948 bufferW[0] = 'q';
949 r = MsiFormatRecordW(hinst, rec, bufferW, &sz);
950 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
951 ok(hinst, !bufferW[0], "got %s\n", dbgstr_w(bufferW));
952 ok(hinst, sz == 7, "got size %lu\n", sz);
953
954 sz = 7;
955 bufferW[0] = 'q';
956 r = MsiFormatRecordW(hinst, rec, bufferW, &sz);
957 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
958 ok(hinst, !lstrcmpW(bufferW, L"foo 12"), "got %s\n", dbgstr_w(bufferW));
959 ok(hinst, sz == 7, "got size %lu\n", sz);
960
961 sz = 8;
962 bufferW[0] = 'q';
963 r = MsiFormatRecordW(hinst, rec, bufferW, &sz);
964 ok(hinst, !r, "got %u\n", r);
965 ok(hinst, !lstrcmpW(bufferW, L"foo 123"), "got %s\n", dbgstr_w(bufferW));
966 ok(hinst, sz == 7, "got size %lu\n", sz);
967
968 /* check that properties work */
969 MsiSetPropertyA(hinst, "fmtprop", "foobar");
970 MsiRecordSetStringA(rec, 0, "[fmtprop]");
971 sz = sizeof(buffer);
972 r = MsiFormatRecordA(hinst, rec, buffer, &sz);
973 ok(hinst, !r, "got %u\n", r);
974 ok(hinst, !strcmp(buffer, "foobar"), "got \"%s\"\n", buffer);
975 ok(hinst, sz == 6, "got size %lu\n", sz);
976
977 MsiCloseHandle(rec);
978 }
979
test_costs(MSIHANDLE hinst)980 static void test_costs(MSIHANDLE hinst)
981 {
982 WCHAR bufferW[10];
983 char buffer[10];
984 int cost, temp;
985 DWORD sz;
986 UINT r;
987
988 cost = 0xdead;
989 r = MsiGetFeatureCostA(hinst, NULL, MSICOSTTREE_CHILDREN, INSTALLSTATE_LOCAL, &cost);
990 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
991 todo_wine
992 ok(hinst, !cost, "got %d\n", cost);
993
994 r = MsiGetFeatureCostA(hinst, "One", MSICOSTTREE_CHILDREN, INSTALLSTATE_LOCAL, NULL);
995 ok(hinst, r == RPC_X_NULL_REF_POINTER, "got %u\n", r);
996
997 cost = 0xdead;
998 r = MsiGetFeatureCostA(hinst, "One", MSICOSTTREE_CHILDREN, INSTALLSTATE_LOCAL, &cost);
999 ok(hinst, !r, "got %u\n", r);
1000 todo_wine
1001 ok(hinst, cost == 8, "got %d\n", cost);
1002
1003 sz = cost = temp = 0xdead;
1004 r = MsiEnumComponentCostsA(hinst, "One", 0, INSTALLSTATE_LOCAL, NULL, &sz, &cost, &temp);
1005 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
1006 ok(hinst, sz == 0xdead, "got size %lu\n", sz);
1007 ok(hinst, cost == 0xdead, "got cost %d\n", cost);
1008 ok(hinst, temp == 0xdead, "got temp %d\n", temp);
1009
1010 cost = temp = 0xdead;
1011 r = MsiEnumComponentCostsA(hinst, "One", 0, INSTALLSTATE_LOCAL, buffer, NULL, &cost, &temp);
1012 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
1013 ok(hinst, cost == 0xdead, "got cost %d\n", cost);
1014 ok(hinst, temp == 0xdead, "got temp %d\n", temp);
1015
1016 sz = temp = 0xdead;
1017 r = MsiEnumComponentCostsA(hinst, "One", 0, INSTALLSTATE_LOCAL, buffer, &sz, NULL, &temp);
1018 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
1019 ok(hinst, sz == 0xdead, "got size %lu\n", sz);
1020 ok(hinst, temp == 0xdead, "got temp %d\n", temp);
1021
1022 sz = cost = 0xdead;
1023 r = MsiEnumComponentCostsA(hinst, "One", 0, INSTALLSTATE_LOCAL, buffer, &sz, &cost, NULL);
1024 ok(hinst, r == ERROR_INVALID_PARAMETER, "got %u\n", r);
1025 ok(hinst, sz == 0xdead, "got size %lu\n", sz);
1026 ok(hinst, cost == 0xdead, "got cost %d\n", cost);
1027
1028 cost = temp = 0xdead;
1029 sz = sizeof(buffer);
1030 r = MsiEnumComponentCostsA(hinst, NULL, 0, INSTALLSTATE_LOCAL, buffer, &sz, &cost, &temp);
1031 ok(hinst, !r, "got %u\n", r);
1032 ok(hinst, sz == 2, "got size %lu\n", sz);
1033 ok(hinst, !strcmp(buffer, "C:"), "got '%s'\n", buffer);
1034 ok(hinst, !cost, "got cost %d\n", cost);
1035 ok(hinst, temp && temp != 0xdead, "got temp %d\n", temp);
1036
1037 cost = temp = 0xdead;
1038 sz = sizeof(buffer);
1039 r = MsiEnumComponentCostsA(hinst, "One", 0, INSTALLSTATE_LOCAL, buffer, &sz, &cost, &temp);
1040 ok(hinst, !r, "got %u\n", r);
1041 ok(hinst, sz == 2, "got size %lu\n", sz);
1042 ok(hinst, !strcmp(buffer, "C:"), "got '%s'\n", buffer);
1043 ok(hinst, cost == 8, "got cost %d\n", cost);
1044 ok(hinst, !temp, "got temp %d\n", temp);
1045
1046 /* same string behaviour */
1047 cost = temp = 0xdead;
1048 sz = 0;
1049 strcpy(buffer,"q");
1050 r = MsiEnumComponentCostsA(hinst, "One", 0, INSTALLSTATE_LOCAL, buffer, &sz, &cost, &temp);
1051 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
1052 ok(hinst, !strcmp(buffer, "q"), "got \"%s\"\n", buffer);
1053 todo_wine
1054 ok(hinst, sz == 4, "got size %lu\n", sz);
1055 ok(hinst, cost == 8, "got cost %d\n", cost);
1056 ok(hinst, !temp, "got temp %d\n", temp);
1057
1058 sz = 1;
1059 strcpy(buffer,"x");
1060 r = MsiEnumComponentCostsA(hinst, "One", 0, INSTALLSTATE_LOCAL, buffer, &sz, &cost, &temp);
1061 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
1062 todo_wine {
1063 ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
1064 ok(hinst, sz == 4, "got size %lu\n", sz);
1065 }
1066
1067 sz = 2;
1068 strcpy(buffer,"x");
1069 r = MsiEnumComponentCostsA(hinst, "One", 0, INSTALLSTATE_LOCAL, buffer, &sz, &cost, &temp);
1070 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
1071 todo_wine {
1072 ok(hinst, !strcmp(buffer, "C"), "got \"%s\"\n", buffer);
1073 ok(hinst, sz == 4, "got size %lu\n", sz);
1074 }
1075
1076 sz = 3;
1077 strcpy(buffer,"x");
1078 r = MsiEnumComponentCostsA(hinst, "One", 0, INSTALLSTATE_LOCAL, buffer, &sz, &cost, &temp);
1079 ok(hinst, !r, "got %u\n", r);
1080 ok(hinst, !strcmp(buffer, "C:"), "got \"%s\"\n", buffer);
1081 ok(hinst, sz == 2, "got size %lu\n", sz);
1082
1083 sz = 0;
1084 bufferW[0] = 'q';
1085 r = MsiEnumComponentCostsW(hinst, L"One", 0, INSTALLSTATE_LOCAL, bufferW, &sz, &cost, &temp);
1086 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
1087 ok(hinst, bufferW[0] == 'q', "got %s\n", dbgstr_w(bufferW));
1088 ok(hinst, sz == 2, "got size %lu\n", sz);
1089
1090 sz = 1;
1091 bufferW[0] = 'q';
1092 r = MsiEnumComponentCostsW(hinst, L"One", 0, INSTALLSTATE_LOCAL, bufferW, &sz, &cost, &temp);
1093 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
1094 ok(hinst, !bufferW[0], "got %s\n", dbgstr_w(bufferW));
1095 ok(hinst, sz == 2, "got size %lu\n", sz);
1096
1097 sz = 2;
1098 bufferW[0] = 'q';
1099 r = MsiEnumComponentCostsW(hinst, L"One", 0, INSTALLSTATE_LOCAL, bufferW, &sz, &cost, &temp);
1100 ok(hinst, r == ERROR_MORE_DATA, "got %u\n", r);
1101 ok(hinst, !lstrcmpW(bufferW, L"C"), "got %s\n", dbgstr_w(bufferW));
1102 ok(hinst, sz == 2, "got size %lu\n", sz);
1103
1104 sz = 3;
1105 bufferW[0] = 'q';
1106 r = MsiEnumComponentCostsW(hinst, L"One", 0, INSTALLSTATE_LOCAL, bufferW, &sz, &cost, &temp);
1107 ok(hinst, !r, "got %u\n", r);
1108 ok(hinst, !lstrcmpW(bufferW, L"C:"), "got %s\n", dbgstr_w(bufferW));
1109 ok(hinst, sz == 2, "got size %lu\n", sz);
1110 }
1111
test_invalid_functions(MSIHANDLE hinst)1112 static void test_invalid_functions(MSIHANDLE hinst)
1113 {
1114 char path[MAX_PATH], package_name[20];
1115 MSIHANDLE db, preview, package;
1116 UINT r;
1117
1118 r = MsiGetDatabaseState(hinst);
1119 ok(hinst, r == MSIDBSTATE_ERROR, "got %u\n", r);
1120
1121 db = MsiGetActiveDatabase(hinst);
1122 ok(hinst, db, "MsiGetActiveDatabase failed\n");
1123
1124 r = MsiDatabaseGenerateTransformA(db, db, "bogus.mst", 0, 0);
1125 todo_wine ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
1126
1127 r = MsiDatabaseApplyTransformA(db, "bogus.mst", 0);
1128 ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
1129
1130 r = MsiCreateTransformSummaryInfoA(db, db, "bogus.mst", 0, 0);
1131 todo_wine ok(hinst, r == ERROR_INSTALL_PACKAGE_OPEN_FAILED, "got %u\n", r);
1132
1133 GetCurrentDirectoryA(sizeof(path), path);
1134 r = MsiDatabaseExportA(db, "Test", path, "bogus.idt");
1135 ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
1136
1137 r = MsiDatabaseImportA(db, path, "bogus.idt");
1138 ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
1139
1140 r = MsiDatabaseCommit(db);
1141 ok(hinst, r == ERROR_SUCCESS, "got %u\n", r);
1142
1143 r = MsiDatabaseMergeA(db, db, "MergeErrors");
1144 ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
1145
1146 r = MsiGetDatabaseState(db);
1147 ok(hinst, r == MSIDBSTATE_ERROR, "got %u\n", r);
1148
1149 r = MsiEnableUIPreview(db, &preview);
1150 ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
1151
1152 sprintf(package_name, "#%lu", db);
1153 r = MsiOpenPackageA(package_name, &package);
1154 ok(hinst, r == ERROR_INVALID_HANDLE, "got %u\n", r);
1155
1156 MsiCloseHandle(db);
1157 }
1158
test_view_get_error(MSIHANDLE hinst)1159 static void test_view_get_error(MSIHANDLE hinst)
1160 {
1161 MSIHANDLE db, view, rec;
1162 char buffer[5];
1163 MSIDBERROR err;
1164 DWORD sz;
1165 UINT r;
1166
1167 db = MsiGetActiveDatabase(hinst);
1168 ok(hinst, db, "MsiGetActiveDatabase failed\n");
1169
1170 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `test2`", &view);
1171 ok(hinst, !r, "got %u\n", r);
1172
1173 r = MsiViewExecute(view, 0);
1174 ok(hinst, !r, "got %u\n", r);
1175
1176 sz = 0;
1177 err = MsiViewGetErrorA(0, NULL, &sz);
1178 todo_wine ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
1179 ok(hinst, sz == 0, "got size %lu\n", sz);
1180
1181 err = MsiViewGetErrorA(view, NULL, NULL);
1182 ok(hinst, err == MSIDBERROR_INVALIDARG, "got %d\n", err);
1183
1184 sz = 0;
1185 err = MsiViewGetErrorA(view, NULL, &sz);
1186 ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
1187 ok(hinst, sz == 0, "got size %lu\n", sz);
1188
1189 sz = 0;
1190 strcpy(buffer, "x");
1191 err = MsiViewGetErrorA(view, buffer, &sz);
1192 ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
1193 ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n", buffer);
1194 ok(hinst, sz == 0, "got size %lu\n", sz);
1195
1196 sz = 1;
1197 strcpy(buffer, "x");
1198 err = MsiViewGetErrorA(view, buffer, &sz);
1199 ok(hinst, err == MSIDBERROR_NOERROR, "got %d\n", err);
1200 ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
1201 ok(hinst, sz == 0, "got size %lu\n", sz);
1202
1203 rec = MsiCreateRecord(2);
1204 MsiRecordSetInteger(rec, 1, 1);
1205 MsiRecordSetInteger(rec, 2, 2);
1206 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
1207 ok(hinst, r == ERROR_INVALID_DATA, "got %u\n", r);
1208
1209 sz = 2;
1210 strcpy(buffer, "x");
1211 err = MsiViewGetErrorA(view, buffer, &sz);
1212 ok(hinst, err == MSIDBERROR_DUPLICATEKEY, "got %d\n", err);
1213 ok(hinst, !strcmp(buffer, "A"), "got \"%s\"\n", buffer);
1214 ok(hinst, sz == 1, "got size %lu\n", sz);
1215
1216 sz = 2;
1217 strcpy(buffer, "x");
1218 err = MsiViewGetErrorA(view, buffer, &sz);
1219 todo_wine ok(hinst, err == MSIDBERROR_NOERROR, "got %d\n", err);
1220 todo_wine ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
1221 todo_wine ok(hinst, sz == 0, "got size %lu\n", sz);
1222
1223 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
1224 ok(hinst, r == ERROR_INVALID_DATA, "got %u\n", r);
1225
1226 sz = 1;
1227 strcpy(buffer, "x");
1228 err = MsiViewGetErrorA(view, buffer, &sz);
1229 ok(hinst, err == MSIDBERROR_MOREDATA, "got %d\n", err);
1230 ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
1231 ok(hinst, sz == 1, "got size %lu\n", sz);
1232
1233 sz = 1;
1234 strcpy(buffer, "x");
1235 err = MsiViewGetErrorA(view, buffer, &sz);
1236 todo_wine ok(hinst, err == MSIDBERROR_NOERROR, "got %d\n", err);
1237 ok(hinst, !buffer[0], "got \"%s\"\n", buffer);
1238 todo_wine ok(hinst, sz == 0, "got size %lu\n", sz);
1239
1240 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
1241 ok(hinst, r == ERROR_INVALID_DATA, "got %u\n", r);
1242
1243 sz = 0;
1244 strcpy(buffer, "x");
1245 err = MsiViewGetErrorA(view, buffer, &sz);
1246 ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
1247 ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n", buffer);
1248 ok(hinst, sz == 0, "got size %lu\n", sz);
1249
1250 sz = 0;
1251 strcpy(buffer, "x");
1252 err = MsiViewGetErrorA(view, buffer, &sz);
1253 ok(hinst, err == MSIDBERROR_FUNCTIONERROR, "got %d\n", err);
1254 ok(hinst, !strcmp(buffer, "x"), "got \"%s\"\n", buffer);
1255 ok(hinst, sz == 0, "got size %lu\n", sz);
1256
1257 MsiCloseHandle(rec);
1258 MsiCloseHandle(view);
1259 MsiCloseHandle(db);
1260 }
1261
1262 /* Main test. Anything that doesn't depend on a specific install configuration
1263 * or have undesired side effects should go here. */
main_test(MSIHANDLE hinst)1264 UINT WINAPI main_test(MSIHANDLE hinst)
1265 {
1266 IUnknown *unk = NULL;
1267 HRESULT hr;
1268
1269 /* Test for an MTA apartment */
1270 hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
1271 ok(hinst, hr == S_OK, "CoCreateInstance failed with %08lx\n", hr);
1272
1273 if (unk) IUnknown_Release(unk);
1274
1275 /* but ours is uninitialized */
1276 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1277 ok(hinst, hr == S_OK, "got %#lx\n", hr);
1278 CoUninitialize();
1279
1280 test_props(hinst);
1281 test_db(hinst);
1282 test_doaction(hinst);
1283 test_targetpath(hinst);
1284 test_misc(hinst);
1285 test_feature_states(hinst);
1286 test_format_record(hinst);
1287 test_costs(hinst);
1288 test_invalid_functions(hinst);
1289 test_view_get_error(hinst);
1290
1291 return ERROR_SUCCESS;
1292 }
1293
test_retval(MSIHANDLE hinst)1294 UINT WINAPI test_retval(MSIHANDLE hinst)
1295 {
1296 char prop[10];
1297 DWORD len = sizeof(prop);
1298 UINT retval;
1299
1300 MsiGetPropertyA(hinst, "TEST_RETVAL", prop, &len);
1301 sscanf(prop, "%u", &retval);
1302 return retval;
1303 }
1304
append_file(MSIHANDLE hinst,const char * filename,const char * text)1305 static void append_file(MSIHANDLE hinst, const char *filename, const char *text)
1306 {
1307 DWORD size;
1308 HANDLE file = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1309 ok(hinst, file != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError());
1310
1311 SetFilePointer(file, 0, NULL, FILE_END);
1312 WriteFile(file, text, strlen(text), &size, NULL);
1313 CloseHandle(file);
1314 }
1315
da_immediate(MSIHANDLE hinst)1316 UINT WINAPI da_immediate(MSIHANDLE hinst)
1317 {
1318 char prop[300];
1319 DWORD len = sizeof(prop);
1320
1321 MsiGetPropertyA(hinst, "TESTPATH", prop, &len);
1322
1323 append_file(hinst, prop, "one");
1324
1325 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_SCHEDULED), "shouldn't be scheduled\n");
1326 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_ROLLBACK), "shouldn't be rollback\n");
1327 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_COMMIT), "shouldn't be commit\n");
1328
1329 return ERROR_SUCCESS;
1330 }
1331
da_deferred(MSIHANDLE hinst)1332 UINT WINAPI da_deferred(MSIHANDLE hinst)
1333 {
1334 char prop[300];
1335 DWORD len = sizeof(prop);
1336 LANGID lang;
1337 UINT r;
1338
1339 /* Test that we were in fact deferred */
1340 r = MsiGetPropertyA(hinst, "CustomActionData", prop, &len);
1341 ok(hinst, r == ERROR_SUCCESS, "got %u\n", r);
1342 ok(hinst, prop[0], "CustomActionData was empty\n");
1343
1344 append_file(hinst, prop, "two");
1345
1346 /* Test available properties */
1347 len = sizeof(prop);
1348 r = MsiGetPropertyA(hinst, "ProductCode", prop, &len);
1349 ok(hinst, r == ERROR_SUCCESS, "got %u\n", r);
1350 ok(hinst, prop[0], "got %s\n", prop);
1351
1352 len = sizeof(prop);
1353 r = MsiGetPropertyA(hinst, "UserSID", prop, &len);
1354 ok(hinst, r == ERROR_SUCCESS, "got %u\n", r);
1355 ok(hinst, prop[0], "got %s\n", prop);
1356
1357 len = sizeof(prop);
1358 r = MsiGetPropertyA(hinst, "TESTPATH", prop, &len);
1359 ok(hinst, r == ERROR_SUCCESS, "got %u\n", r);
1360 todo_wine
1361 ok(hinst, !prop[0], "got %s\n", prop);
1362
1363 /* Test modes */
1364 ok(hinst, MsiGetMode(hinst, MSIRUNMODE_SCHEDULED), "should be scheduled\n");
1365 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_ROLLBACK), "shouldn't be rollback\n");
1366 ok(hinst, !MsiGetMode(hinst, MSIRUNMODE_COMMIT), "shouldn't be commit\n");
1367
1368 lang = MsiGetLanguage(hinst);
1369 ok(hinst, lang != ERROR_INVALID_HANDLE, "MsiGetLanguage failed\n");
1370
1371 return ERROR_SUCCESS;
1372 }
1373
1374 static int global_state;
1375
process1(MSIHANDLE hinst)1376 UINT WINAPI process1(MSIHANDLE hinst)
1377 {
1378 SetEnvironmentVariableA("MSI_PROCESS_TEST","1");
1379 global_state++;
1380 return ERROR_SUCCESS;
1381 }
1382
process2(MSIHANDLE hinst)1383 UINT WINAPI process2(MSIHANDLE hinst)
1384 {
1385 char env[2] = {0};
1386 DWORD r = GetEnvironmentVariableA("MSI_PROCESS_TEST", env, sizeof(env));
1387 ok(hinst, r == 1, "got %lu, error %lu\n", r, GetLastError());
1388 ok(hinst, !strcmp(env, "1"), "got %s\n", env);
1389 ok(hinst, !global_state, "got global_state %d\n", global_state);
1390 return ERROR_SUCCESS;
1391 }
1392
async1(MSIHANDLE hinst)1393 UINT WINAPI async1(MSIHANDLE hinst)
1394 {
1395 HANDLE event = CreateEventA(NULL, TRUE, FALSE, "wine_msi_async_test");
1396 HANDLE event2 = CreateEventA(NULL, TRUE, FALSE, "wine_msi_async_test2");
1397 DWORD r = WaitForSingleObject(event, 10000);
1398 ok(hinst, !r, "wait timed out\n");
1399 SetEvent(event2);
1400 return ERROR_SUCCESS;
1401 }
1402
async2(MSIHANDLE hinst)1403 UINT WINAPI async2(MSIHANDLE hinst)
1404 {
1405 HANDLE event = CreateEventA(NULL, TRUE, FALSE, "wine_msi_async_test");
1406 HANDLE event2 = CreateEventA(NULL, TRUE, FALSE, "wine_msi_async_test2");
1407 DWORD r;
1408 SetEvent(event);
1409 r = WaitForSingleObject(event2, 10000);
1410 ok(hinst, !r, "wait timed out\n");
1411 return ERROR_SUCCESS;
1412 }
1413
pf_exists(const char * file)1414 static BOOL pf_exists(const char *file)
1415 {
1416 char path[MAX_PATH];
1417
1418 if (FAILED(SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path)))
1419 SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
1420 strcat(path, "\\");
1421 strcat(path, file);
1422 return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;
1423 }
1424
cf_present(MSIHANDLE hinst)1425 UINT WINAPI cf_present(MSIHANDLE hinst)
1426 {
1427 ok(hinst, pf_exists("msitest\\first"), "folder absent\n");
1428 ok(hinst, pf_exists("msitest\\second"), "folder absent\n");
1429 ok(hinst, pf_exists("msitest\\third"), "folder absent\n");
1430 return ERROR_SUCCESS;
1431 }
1432
cf_absent(MSIHANDLE hinst)1433 UINT WINAPI cf_absent(MSIHANDLE hinst)
1434 {
1435 ok(hinst, !pf_exists("msitest\\first"), "folder present\n");
1436 ok(hinst, !pf_exists("msitest\\second"), "folder present\n");
1437 ok(hinst, !pf_exists("msitest\\third"), "folder present\n");
1438 return ERROR_SUCCESS;
1439 }
1440
file_present(MSIHANDLE hinst)1441 UINT WINAPI file_present(MSIHANDLE hinst)
1442 {
1443 ok(hinst, pf_exists("msitest\\first\\one.txt"), "file absent\n");
1444 ok(hinst, pf_exists("msitest\\second\\two.txt"), "file absent\n");
1445 return ERROR_SUCCESS;
1446 }
1447
file_absent(MSIHANDLE hinst)1448 UINT WINAPI file_absent(MSIHANDLE hinst)
1449 {
1450 ok(hinst, !pf_exists("msitest\\first\\one.txt"), "file present\n");
1451 ok(hinst, !pf_exists("msitest\\second\\two.txt"), "file present\n");
1452 return ERROR_SUCCESS;
1453 }
1454
crs_present(MSIHANDLE hinst)1455 UINT WINAPI crs_present(MSIHANDLE hinst)
1456 {
1457 ok(hinst, pf_exists("msitest\\shortcut.lnk"), "shortcut absent\n");
1458 return ERROR_SUCCESS;
1459 }
1460
crs_absent(MSIHANDLE hinst)1461 UINT WINAPI crs_absent(MSIHANDLE hinst)
1462 {
1463 ok(hinst, !pf_exists("msitest\\shortcut.lnk"), "shortcut present\n");
1464 return ERROR_SUCCESS;
1465 }
1466
sds_present(MSIHANDLE hinst)1467 UINT WINAPI sds_present(MSIHANDLE hinst)
1468 {
1469 SC_HANDLE manager, service;
1470 manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1471 service = OpenServiceA(manager, "TestService3", GENERIC_ALL);
1472 ok(hinst, !!service, "service absent: %lu\n", GetLastError());
1473 CloseServiceHandle(service);
1474 CloseServiceHandle(manager);
1475 return ERROR_SUCCESS;
1476 }
1477
sds_absent(MSIHANDLE hinst)1478 UINT WINAPI sds_absent(MSIHANDLE hinst)
1479 {
1480 SC_HANDLE manager, service;
1481 manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1482 service = OpenServiceA(manager, "TestService3", GENERIC_ALL);
1483 ok(hinst, !service, "service present\n");
1484 if (service) CloseServiceHandle(service);
1485 CloseServiceHandle(manager);
1486 return ERROR_SUCCESS;
1487 }
1488
sis_present(MSIHANDLE hinst)1489 UINT WINAPI sis_present(MSIHANDLE hinst)
1490 {
1491 SC_HANDLE manager, service;
1492 manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1493 service = OpenServiceA(manager, "TestService", GENERIC_ALL);
1494 ok(hinst, !!service, "service absent: %lu\n", GetLastError());
1495 CloseServiceHandle(service);
1496 CloseServiceHandle(manager);
1497 return ERROR_SUCCESS;
1498 }
1499
sis_absent(MSIHANDLE hinst)1500 UINT WINAPI sis_absent(MSIHANDLE hinst)
1501 {
1502 SC_HANDLE manager, service;
1503 manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1504 service = OpenServiceA(manager, "TestService", GENERIC_ALL);
1505 ok(hinst, !service, "service present\n");
1506 if (service) CloseServiceHandle(service);
1507 CloseServiceHandle(manager);
1508 return ERROR_SUCCESS;
1509 }
1510
sss_started(MSIHANDLE hinst)1511 UINT WINAPI sss_started(MSIHANDLE hinst)
1512 {
1513 SC_HANDLE manager, service;
1514 SERVICE_STATUS status;
1515 BOOL ret;
1516
1517 manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1518 service = OpenServiceA(manager, "Spooler", SC_MANAGER_ALL_ACCESS);
1519 ret = QueryServiceStatus(service, &status);
1520 ok(hinst, ret, "QueryServiceStatus failed: %lu\n", GetLastError());
1521 ok(hinst, status.dwCurrentState == SERVICE_RUNNING, "got %lu\n", status.dwCurrentState);
1522
1523 CloseServiceHandle(service);
1524 CloseServiceHandle(manager);
1525 return ERROR_SUCCESS;
1526 }
1527
sss_stopped(MSIHANDLE hinst)1528 UINT WINAPI sss_stopped(MSIHANDLE hinst)
1529 {
1530 SC_HANDLE manager, service;
1531 SERVICE_STATUS status;
1532 BOOL ret;
1533
1534 manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1535 service = OpenServiceA(manager, "Spooler", SC_MANAGER_ALL_ACCESS);
1536 ret = QueryServiceStatus(service, &status);
1537 ok(hinst, ret, "QueryServiceStatus failed: %lu\n", GetLastError());
1538 ok(hinst, status.dwCurrentState == SERVICE_STOPPED, "got %lu\n", status.dwCurrentState);
1539
1540 CloseServiceHandle(service);
1541 CloseServiceHandle(manager);
1542 return ERROR_SUCCESS;
1543 }
1544
rd_present(MSIHANDLE hinst)1545 UINT WINAPI rd_present(MSIHANDLE hinst)
1546 {
1547 ok(hinst, pf_exists("msitest\\original2.txt"), "file absent\n");
1548 ok(hinst, pf_exists("msitest\\duplicate.txt"), "file absent\n");
1549 ok(hinst, !pf_exists("msitest\\original3.txt"), "file present\n");
1550 ok(hinst, !pf_exists("msitest\\duplicate2.txt"), "file present\n");
1551 return ERROR_SUCCESS;
1552 }
1553
rd_absent(MSIHANDLE hinst)1554 UINT WINAPI rd_absent(MSIHANDLE hinst)
1555 {
1556 ok(hinst, !pf_exists("msitest\\original2.txt"), "file present\n");
1557 ok(hinst, !pf_exists("msitest\\duplicate.txt"), "file present\n");
1558 ok(hinst, !pf_exists("msitest\\original3.txt"), "file present\n");
1559 ok(hinst, !pf_exists("msitest\\duplicate2.txt"), "file present\n");
1560 return ERROR_SUCCESS;
1561 }
1562
odbc_present(MSIHANDLE hinst)1563 UINT WINAPI odbc_present(MSIHANDLE hinst)
1564 {
1565 int gotdriver = 0, gotdriver2 = 0;
1566 char buffer[1000], *p;
1567 WORD len;
1568 BOOL r;
1569
1570 buffer[0] = 0;
1571 len = sizeof(buffer);
1572 r = SQLGetInstalledDrivers(buffer, sizeof(buffer), &len);
1573 if (r) ok(hinst, len < sizeof(buffer), "buffer too small\n");
1574 for (p = buffer; *p; p += strlen(p) + 1)
1575 {
1576 if (!strcmp(p, "ODBC test driver"))
1577 gotdriver = 1;
1578 if (!strcmp(p, "ODBC test driver2"))
1579 gotdriver2 = 1;
1580 }
1581 ok(hinst, gotdriver, "driver absent\n");
1582 ok(hinst, gotdriver2, "driver 2 absent\n");
1583 return ERROR_SUCCESS;
1584 }
1585
odbc_absent(MSIHANDLE hinst)1586 UINT WINAPI odbc_absent(MSIHANDLE hinst)
1587 {
1588 int gotdriver = 0, gotdriver2 = 0;
1589 char buffer[1000], *p;
1590 WORD len;
1591 BOOL r;
1592
1593 buffer[0] = 0;
1594 len = sizeof(buffer);
1595 r = SQLGetInstalledDrivers(buffer, sizeof(buffer), &len);
1596 if (r) ok(hinst, len < sizeof(buffer), "buffer too small\n");
1597 for (p = buffer; *p; p += strlen(p) + 1)
1598 {
1599 if (!strcmp(p, "ODBC test driver"))
1600 gotdriver = 1;
1601 if (!strcmp(p, "ODBC test driver2"))
1602 gotdriver2 = 1;
1603 }
1604 ok(hinst, !gotdriver, "driver present\n");
1605 ok(hinst, !gotdriver2, "driver 2 present\n");
1606 return ERROR_SUCCESS;
1607 }
1608
mov_present(MSIHANDLE hinst)1609 UINT WINAPI mov_present(MSIHANDLE hinst)
1610 {
1611 ok(hinst, pf_exists("msitest\\canada"), "file absent\n");
1612 ok(hinst, pf_exists("msitest\\dominica"), "file absent\n");
1613 return ERROR_SUCCESS;
1614 }
1615
mov_absent(MSIHANDLE hinst)1616 UINT WINAPI mov_absent(MSIHANDLE hinst)
1617 {
1618 ok(hinst, !pf_exists("msitest\\canada"), "file present\n");
1619 ok(hinst, !pf_exists("msitest\\dominica"), "file present\n");
1620 return ERROR_SUCCESS;
1621 }
1622
check_reg_str(MSIHANDLE hinst,HKEY key,const char * name,const char * expect)1623 static void check_reg_str(MSIHANDLE hinst, HKEY key, const char *name, const char *expect)
1624 {
1625 char value[300];
1626 DWORD sz;
1627 LONG res;
1628
1629 sz = sizeof(value);
1630 res = RegQueryValueExA(key, name, NULL, NULL, (BYTE *)value, &sz);
1631 if (expect)
1632 {
1633 ok(hinst, !res, "failed to get value \"%s\": %ld\n", name, res);
1634 ok(hinst, !strcmp(value, expect), "\"%s\": expected \"%s\", got \"%s\"\n",
1635 name, expect, value);
1636 }
1637 else
1638 ok(hinst, res == ERROR_FILE_NOT_FOUND, "\"%s\": expected missing, got %ld\n",
1639 name, res);
1640 }
1641
1642 static const char path_dotnet[] = "Software\\Microsoft\\Installer\\Assemblies\\Global";
1643 static const char name_dotnet[] = "Wine.Dotnet.Assembly,processorArchitecture=\"MSIL\","
1644 "publicKeyToken=\"abcdef0123456789\",version=\"1.0.0.0\",culture=\"neutral\"";
1645
pa_present(MSIHANDLE hinst)1646 UINT WINAPI pa_present(MSIHANDLE hinst)
1647 {
1648 HKEY key;
1649 LONG res;
1650
1651 res = RegOpenKeyA(HKEY_CURRENT_USER, path_dotnet, &key);
1652 ok(hinst, !res, "got %ld\n", res);
1653 check_reg_str(hinst, key, name_dotnet, "rcHQPHq?CA@Uv-XqMI1e>Z'q,T*76M@=YEg6My?~]");
1654 RegCloseKey(key);
1655
1656 return ERROR_SUCCESS;
1657 }
1658
pa_absent(MSIHANDLE hinst)1659 UINT WINAPI pa_absent(MSIHANDLE hinst)
1660 {
1661 HKEY key;
1662 LONG res;
1663
1664 res = RegOpenKeyA(HKEY_CURRENT_USER, path_dotnet, &key);
1665 ok(hinst, !res || res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1666 if (!res)
1667 {
1668 check_reg_str(hinst, key, name_dotnet, NULL);
1669 RegCloseKey(key);
1670 }
1671 return ERROR_SUCCESS;
1672 }
1673
1674 static const char ppc_key[] = "Software\\Microsoft\\Windows\\CurrentVersion\\"
1675 "Installer\\UserData\\S-1-5-18\\Components\\CBABC2FDCCB35E749A8944D8C1C098B5";
1676
ppc_present(MSIHANDLE hinst)1677 UINT WINAPI ppc_present(MSIHANDLE hinst)
1678 {
1679 char expect[MAX_PATH];
1680 HKEY key;
1681 UINT r;
1682
1683 r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, ppc_key, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &key);
1684 ok(hinst, !r, "got %u\n", r);
1685
1686 if (FAILED(SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, expect)))
1687 SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, expect);
1688 strcat(expect, "\\msitest\\maximus");
1689 check_reg_str(hinst, key, "84A88FD7F6998CE40A22FB59F6B9C2BB", expect);
1690
1691 RegCloseKey(key);
1692 return ERROR_SUCCESS;
1693 }
1694
ppc_absent(MSIHANDLE hinst)1695 UINT WINAPI ppc_absent(MSIHANDLE hinst)
1696 {
1697 HKEY key;
1698 UINT r;
1699
1700 r = RegOpenKeyExA(HKEY_LOCAL_MACHINE, ppc_key, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &key);
1701 ok(hinst, r == ERROR_FILE_NOT_FOUND, "got %u\n", r);
1702 return ERROR_SUCCESS;
1703 }
1704
1705 static const char pub_key[] = "Software\\Microsoft\\Installer\\Components\\0CBCFA296AC907244845745CEEB2F8AA";
1706
pub_present(MSIHANDLE hinst)1707 UINT WINAPI pub_present(MSIHANDLE hinst)
1708 {
1709 HKEY key;
1710 LONG res;
1711
1712 res = RegOpenKeyA(HKEY_CURRENT_USER, pub_key, &key);
1713 ok(hinst, !res, "got %ld\n", res);
1714 res = RegQueryValueExA(key, "english.txt", NULL, NULL, NULL, NULL);
1715 ok(hinst, !res, "got %ld\n", res);
1716 RegCloseKey(key);
1717 return ERROR_SUCCESS;
1718 }
1719
pub_absent(MSIHANDLE hinst)1720 UINT WINAPI pub_absent(MSIHANDLE hinst)
1721 {
1722 HKEY key;
1723 LONG res;
1724
1725 res = RegOpenKeyA(HKEY_CURRENT_USER, pub_key, &key);
1726 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1727 return ERROR_SUCCESS;
1728 }
1729
1730 static const char pf_classkey[] = "Installer\\Features\\84A88FD7F6998CE40A22FB59F6B9C2BB";
1731 static const char pf_userkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\"
1732 "Installer\\UserData\\S-1-5-18\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB\\Features";
1733
pf_present(MSIHANDLE hinst)1734 UINT WINAPI pf_present(MSIHANDLE hinst)
1735 {
1736 HKEY key;
1737 LONG res;
1738
1739 res = RegOpenKeyExA(HKEY_CLASSES_ROOT, pf_classkey, 0, KEY_READ | KEY_WOW64_64KEY, &key);
1740 ok(hinst, !res, "got %ld\n", res);
1741 check_reg_str(hinst, key, "feature", "");
1742 check_reg_str(hinst, key, "montecristo", "");
1743 RegCloseKey(key);
1744
1745 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, pf_userkey, 0, KEY_READ | KEY_WOW64_64KEY, &key);
1746 ok(hinst, !res, "got %ld\n", res);
1747 check_reg_str(hinst, key, "feature", "VGtfp^p+,?82@JU1j_KE");
1748 check_reg_str(hinst, key, "montecristo", "VGtfp^p+,?82@JU1j_KE");
1749 RegCloseKey(key);
1750
1751 return ERROR_SUCCESS;
1752 }
1753
pf_absent(MSIHANDLE hinst)1754 UINT WINAPI pf_absent(MSIHANDLE hinst)
1755 {
1756 HKEY key;
1757 LONG res;
1758
1759 res = RegOpenKeyExA(HKEY_CLASSES_ROOT, pf_classkey, 0, KEY_READ | KEY_WOW64_64KEY, &key);
1760 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1761
1762 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, pf_userkey, 0, KEY_READ | KEY_WOW64_64KEY, &key);
1763 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1764
1765 return ERROR_SUCCESS;
1766 }
1767
1768 static const char pp_prodkey[] = "Installer\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
1769
pp_present(MSIHANDLE hinst)1770 UINT WINAPI pp_present(MSIHANDLE hinst)
1771 {
1772 HKEY key;
1773 LONG res;
1774
1775 res = RegOpenKeyExA(HKEY_CLASSES_ROOT, pp_prodkey, 0, KEY_READ | KEY_WOW64_64KEY, &key);
1776 ok(hinst, !res, "got %ld\n", res);
1777 check_reg_str(hinst, key, "ProductName", "MSITEST");
1778 check_reg_str(hinst, key, "PackageCode", "AC75740029052C94DA02821EECD05F2F");
1779 check_reg_str(hinst, key, "Clients", ":");
1780
1781 RegCloseKey(key);
1782 return ERROR_SUCCESS;
1783 }
1784
pp_absent(MSIHANDLE hinst)1785 UINT WINAPI pp_absent(MSIHANDLE hinst)
1786 {
1787 HKEY key;
1788 LONG res;
1789
1790 res = RegOpenKeyExA(HKEY_CLASSES_ROOT, pp_prodkey, 0, KEY_READ | KEY_WOW64_64KEY, &key);
1791 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1792
1793 return ERROR_SUCCESS;
1794 }
1795
rci_present(MSIHANDLE hinst)1796 UINT WINAPI rci_present(MSIHANDLE hinst)
1797 {
1798 HKEY key;
1799 LONG res;
1800
1801 res = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID\\{110913E7-86D1-4BF3-9922-BA103FCDDDFA}",
1802 0, KEY_READ | KEY_WOW64_32KEY, &key);
1803 ok(hinst, !res, "got %ld\n", res);
1804 RegCloseKey(key);
1805
1806 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "FileType\\{110913E7-86D1-4BF3-9922-BA103FCDDDFA}", &key);
1807 ok(hinst, !res, "got %ld\n", res);
1808 RegCloseKey(key);
1809
1810 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "AppID\\{CFCC3B38-E683-497D-9AB4-CB40AAFE307F}", &key);
1811 ok(hinst, !res, "got %ld\n", res);
1812 RegCloseKey(key);
1813
1814 return ERROR_SUCCESS;
1815 }
1816
rci_absent(MSIHANDLE hinst)1817 UINT WINAPI rci_absent(MSIHANDLE hinst)
1818 {
1819 HKEY key;
1820 LONG res;
1821
1822 res = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID\\{110913E7-86D1-4BF3-9922-BA103FCDDDFA}",
1823 0, KEY_READ | KEY_WOW64_32KEY, &key);
1824 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1825
1826 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "FileType\\{110913E7-86D1-4BF3-9922-BA103FCDDDFA}", &key);
1827 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1828
1829 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "AppID\\{CFCC3B38-E683-497D-9AB4-CB40AAFE307F}", &key);
1830 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1831
1832 return ERROR_SUCCESS;
1833 }
1834
rei_present(MSIHANDLE hinst)1835 UINT WINAPI rei_present(MSIHANDLE hinst)
1836 {
1837 HKEY key;
1838 LONG res;
1839
1840 res = RegOpenKeyA(HKEY_CLASSES_ROOT, ".extension", &key);
1841 ok(hinst, !res, "got %ld\n", res);
1842 RegCloseKey(key);
1843
1844 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "Prog.Id.1\\shell\\Open\\command", &key);
1845 ok(hinst, !res, "got %ld\n", res);
1846 RegCloseKey(key);
1847
1848 return ERROR_SUCCESS;
1849 }
1850
rei_absent(MSIHANDLE hinst)1851 UINT WINAPI rei_absent(MSIHANDLE hinst)
1852 {
1853 HKEY key;
1854 LONG res;
1855
1856 res = RegOpenKeyA(HKEY_CLASSES_ROOT, ".extension", &key);
1857 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1858
1859 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "Prog.Id.1\\shell\\Open\\command", &key);
1860 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1861
1862 return ERROR_SUCCESS;
1863 }
1864
1865 static const char font_key[] = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
1866
font_present(MSIHANDLE hinst)1867 UINT WINAPI font_present(MSIHANDLE hinst)
1868 {
1869 HKEY key;
1870 LONG res;
1871
1872 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, font_key, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &key);
1873 ok(hinst, !res, "got %ld\n", res);
1874 res = RegQueryValueExA(key, "msi test font", NULL, NULL, NULL, NULL);
1875 ok(hinst, !res, "got %ld\n", res);
1876 RegCloseKey(key);
1877
1878 return ERROR_SUCCESS;
1879 }
1880
font_absent(MSIHANDLE hinst)1881 UINT WINAPI font_absent(MSIHANDLE hinst)
1882 {
1883 HKEY key;
1884 LONG res;
1885
1886 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, font_key, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &key);
1887 ok(hinst, !res, "got %ld\n", res);
1888 check_reg_str(hinst, key, "msi test font", NULL);
1889 RegCloseKey(key);
1890
1891 return ERROR_SUCCESS;
1892 }
1893
rmi_present(MSIHANDLE hinst)1894 UINT WINAPI rmi_present(MSIHANDLE hinst)
1895 {
1896 HKEY key;
1897 LONG res;
1898
1899 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "MIME\\Database\\Content Type\\mime/type", &key);
1900 ok(hinst, !res, "got %ld\n", res);
1901
1902 return ERROR_SUCCESS;
1903 }
1904
rmi_absent(MSIHANDLE hinst)1905 UINT WINAPI rmi_absent(MSIHANDLE hinst)
1906 {
1907 HKEY key;
1908 LONG res;
1909
1910 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "MIME\\Database\\Content Type\\mime/type", &key);
1911 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1912
1913 return ERROR_SUCCESS;
1914 }
1915
1916 static const char rp_key[] = "Software\\Microsoft\\Windows\\CurrentVersion\\"
1917 "Uninstall\\{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
1918
rp_present(MSIHANDLE hinst)1919 UINT WINAPI rp_present(MSIHANDLE hinst)
1920 {
1921 HKEY key;
1922 LONG res;
1923
1924 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, rp_key, 0, KEY_READ | KEY_WOW64_32KEY, &key);
1925 ok(hinst, !res, "got %ld\n", res);
1926 check_reg_str(hinst, key, "DisplayName", "MSITEST");
1927 RegCloseKey(key);
1928
1929 return ERROR_SUCCESS;
1930 }
1931
rp_absent(MSIHANDLE hinst)1932 UINT WINAPI rp_absent(MSIHANDLE hinst)
1933 {
1934 HKEY key;
1935 LONG res;
1936
1937 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, rp_key, 0, KEY_READ | KEY_WOW64_32KEY, &key);
1938 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1939
1940 return ERROR_SUCCESS;
1941 }
1942
rpi_present(MSIHANDLE hinst)1943 UINT WINAPI rpi_present(MSIHANDLE hinst)
1944 {
1945 HKEY key;
1946 LONG res;
1947
1948 res = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID\\{110913E7-86D1-4BF3-9922-BA103FCDDDFA}",
1949 0, KEY_READ | KEY_WOW64_32KEY, &key);
1950 ok(hinst, !res, "got %ld\n", res);
1951 RegCloseKey(key);
1952
1953 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "Winetest.Class.1", &key);
1954 ok(hinst, !res, "got %ld\n", res);
1955 RegCloseKey(key);
1956
1957 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "Winetest.Class", &key);
1958 ok(hinst, !res, "got %ld\n", res);
1959 RegCloseKey(key);
1960
1961 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "Winetest.Class.2", &key);
1962 ok(hinst, !res, "got %ld\n", res);
1963 RegCloseKey(key);
1964
1965 return ERROR_SUCCESS;
1966 }
1967
rpi_absent(MSIHANDLE hinst)1968 UINT WINAPI rpi_absent(MSIHANDLE hinst)
1969 {
1970 HKEY key;
1971 LONG res;
1972
1973 res = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID\\{110913E7-86D1-4BF3-9922-BA103FCDDDFA}",
1974 0, KEY_READ | KEY_WOW64_32KEY, &key);
1975 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1976
1977 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "Winetest.Class.1", &key);
1978 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1979
1980 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "Winetest.Class", &key);
1981 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1982
1983 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "Winetest.Class.2", &key);
1984 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
1985
1986 return ERROR_SUCCESS;
1987 }
1988
1989 static const CHAR ru_key[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
1990 "\\UserData\\S-1-5-18\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties";
1991
ru_present(MSIHANDLE hinst)1992 UINT WINAPI ru_present(MSIHANDLE hinst)
1993 {
1994 HKEY key;
1995 LONG res;
1996
1997 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, ru_key, 0, KEY_READ | KEY_WOW64_64KEY, &key);
1998 ok(hinst, !res, "got %ld\n", res);
1999 check_reg_str(hinst, key, "ProductID", "none");
2000 RegCloseKey(key);
2001
2002 return ERROR_SUCCESS;
2003 }
2004
ru_absent(MSIHANDLE hinst)2005 UINT WINAPI ru_absent(MSIHANDLE hinst)
2006 {
2007 HKEY key;
2008 LONG res;
2009
2010 res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, ru_key, 0, KEY_READ | KEY_WOW64_64KEY, &key);
2011 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
2012
2013 return ERROR_SUCCESS;
2014 }
2015
2016 static const GUID LIBID_register_test =
2017 {0xeac5166a, 0x9734, 0x4d91, {0x87,0x8f, 0x1d,0xd0,0x23,0x04,0xc6,0x6c}};
2018
tl_present(MSIHANDLE hinst)2019 UINT WINAPI tl_present(MSIHANDLE hinst)
2020 {
2021 ITypeLib *tlb;
2022 HRESULT hr;
2023
2024 hr = LoadRegTypeLib(&LIBID_register_test, 7, 1, 0, &tlb);
2025 ok(hinst, hr == S_OK, "got %#lx\n", hr);
2026 ITypeLib_Release(tlb);
2027
2028 return ERROR_SUCCESS;
2029 }
2030
tl_absent(MSIHANDLE hinst)2031 UINT WINAPI tl_absent(MSIHANDLE hinst)
2032 {
2033 ITypeLib *tlb;
2034 HRESULT hr;
2035
2036 hr = LoadRegTypeLib(&LIBID_register_test, 7, 1, 0, &tlb);
2037 ok(hinst, hr == TYPE_E_LIBNOTREGISTERED, "got %#lx\n", hr);
2038
2039 return ERROR_SUCCESS;
2040 }
2041
sr_present(MSIHANDLE hinst)2042 UINT WINAPI sr_present(MSIHANDLE hinst)
2043 {
2044 HKEY key;
2045 LONG res;
2046
2047 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "selfreg_test", &key);
2048 ok(hinst, !res, "got %ld\n", res);
2049 RegCloseKey(key);
2050
2051 return ERROR_SUCCESS;
2052 }
2053
sr_absent(MSIHANDLE hinst)2054 UINT WINAPI sr_absent(MSIHANDLE hinst)
2055 {
2056 HKEY key;
2057 LONG res;
2058
2059 res = RegOpenKeyA(HKEY_CLASSES_ROOT, "selfreg_test", &key);
2060 ok(hinst, res == ERROR_FILE_NOT_FOUND, "got %ld\n", res);
2061
2062 return ERROR_SUCCESS;
2063 }
2064
env_present(MSIHANDLE hinst)2065 UINT WINAPI env_present(MSIHANDLE hinst)
2066 {
2067 HKEY key;
2068 LONG res;
2069
2070 res = RegOpenKeyA(HKEY_CURRENT_USER, "Environment", &key);
2071 ok(hinst, !res, "got %ld\n", res);
2072 check_reg_str(hinst, key, "MSITESTVAR3", "1");
2073 check_reg_str(hinst, key, "MSITESTVAR4", "1");
2074 RegCloseKey(key);
2075
2076 return ERROR_SUCCESS;
2077 }
2078
env_absent(MSIHANDLE hinst)2079 UINT WINAPI env_absent(MSIHANDLE hinst)
2080 {
2081 HKEY key;
2082 LONG res;
2083
2084 res = RegOpenKeyA(HKEY_CURRENT_USER, "Environment", &key);
2085 ok(hinst, !res, "got %ld\n", res);
2086 check_reg_str(hinst, key, "MSITESTVAR3", NULL);
2087 check_reg_str(hinst, key, "MSITESTVAR4", NULL);
2088 RegCloseKey(key);
2089
2090 return ERROR_SUCCESS;
2091 }
2092
ini_present(MSIHANDLE hinst)2093 UINT WINAPI ini_present(MSIHANDLE hinst)
2094 {
2095 char path[MAX_PATH], buf[10];
2096 DWORD len;
2097
2098 if (FAILED(SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path)))
2099 SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
2100 strcat(path, "\\msitest\\test.ini");
2101
2102 len = GetPrivateProfileStringA("section1", "key1", NULL, buf, sizeof(buf), path);
2103 ok(hinst, len == 6, "got %lu\n", len);
2104
2105 return ERROR_SUCCESS;
2106 }
2107
ini_absent(MSIHANDLE hinst)2108 UINT WINAPI ini_absent(MSIHANDLE hinst)
2109 {
2110 char path[MAX_PATH], buf[10];
2111 DWORD len;
2112
2113 if (FAILED(SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path)))
2114 SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
2115 strcat(path, "\\msitest\\test.ini");
2116
2117 len = GetPrivateProfileStringA("section1", "key1", NULL, buf, sizeof(buf), path);
2118 ok(hinst, !len, "got %lu\n", len);
2119
2120 return ERROR_SUCCESS;
2121 }
2122
wrv_present(MSIHANDLE hinst)2123 UINT WINAPI wrv_present(MSIHANDLE hinst)
2124 {
2125 HKEY key;
2126 LONG res;
2127
2128 res = RegOpenKeyA(HKEY_CURRENT_USER, "msitest", &key);
2129 ok(hinst, !res, "got %ld\n", res);
2130 check_reg_str(hinst, key, "sz", "string");
2131 RegCloseKey(key);
2132
2133 return ERROR_SUCCESS;
2134 }
2135
wrv_absent(MSIHANDLE hinst)2136 UINT WINAPI wrv_absent(MSIHANDLE hinst)
2137 {
2138 HKEY key;
2139 LONG res;
2140
2141 res = RegOpenKeyA(HKEY_CURRENT_USER, "msitest", &key);
2142 ok(hinst, !res, "got %ld\n", res);
2143 check_reg_str(hinst, key, "sz", NULL);
2144 RegCloseKey(key);
2145
2146 return ERROR_SUCCESS;
2147 }
2148