2 * DLL for testing type 1 custom actions
4 * Copyright 2017 Zebediah Figura
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.
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.
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
22 #pragma makedep testdll
40 #define __WINE_PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args)))
42 #define __WINE_PRINTF_ATTR(fmt,args)
45 static int todo_level
, todo_do_loop
;
47 static void WINAPIV
__WINE_PRINTF_ATTR(6,7) ok_(MSIHANDLE hinst
, int todo
, const char *file
, int line
, int condition
, const char *msg
, ...)
49 static char buffer
[2000];
53 va_start(valist
, msg
);
54 vsprintf(buffer
, msg
, valist
);
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
);
67 static void winetest_start_todo( int is_todo
)
69 todo_level
= (todo_level
<< 1) | (is_todo
!= 0);
73 static int winetest_loop_todo(void)
75 int do_loop
=todo_do_loop
;
80 static void winetest_end_todo(void)
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(); \
89 #define todo_wine todo_wine_if(1)
91 static const char *dbgstr_w(WCHAR
*str
)
93 static char buffer
[300], *p
;
95 if (!str
) return "(null)";
100 while ((*p
++ = *str
++));
107 static void check_prop(MSIHANDLE hinst
, const char *prop
, const char *expect
)
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
);
117 static void test_props(MSIHANDLE hinst
)
124 /* test invalid values */
125 r
= MsiGetPropertyA(hinst
, NULL
, NULL
, NULL
);
126 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
128 r
= MsiGetPropertyA(hinst
, "boo", NULL
, NULL
);
129 ok(hinst
, !r
, "got %u\n", r
);
131 r
= MsiGetPropertyA(hinst
, "boo", buffer
, NULL
);
132 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
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
);
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
);
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
);
153 /* set the property to something */
154 r
= MsiSetPropertyA(hinst
, NULL
, NULL
);
155 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
157 r
= MsiSetPropertyA(hinst
, "", NULL
);
158 ok(hinst
, !r
, "got %u\n", r
);
160 r
= MsiSetPropertyA(hinst
, "", "asdf");
161 ok(hinst
, r
== ERROR_FUNCTION_FAILED
, "got %u\n", r
);
163 r
= MsiSetPropertyA(hinst
, "=", "asdf");
164 ok(hinst
, !r
, "got %u\n", r
);
165 check_prop(hinst
, "=", "asdf");
167 r
= MsiSetPropertyA(hinst
, " ", "asdf");
168 ok(hinst
, !r
, "got %u\n", r
);
169 check_prop(hinst
, " ", "asdf");
171 r
= MsiSetPropertyA(hinst
, "'", "asdf");
172 ok(hinst
, !r
, "got %u\n", r
);
173 check_prop(hinst
, "'", "asdf");
175 r
= MsiSetPropertyA(hinst
, "boo", NULL
);
176 ok(hinst
, !r
, "got %u\n", r
);
177 check_prop(hinst
, "boo", "");
179 r
= MsiSetPropertyA(hinst
, "boo", "");
180 ok(hinst
, !r
, "got %u\n", r
);
181 check_prop(hinst
, "boo", "");
183 r
= MsiSetPropertyA(hinst
, "boo", "xyz");
184 ok(hinst
, !r
, "got %u\n", r
);
185 check_prop(hinst
, "boo", "xyz");
187 r
= MsiGetPropertyA(hinst
, "boo", NULL
, NULL
);
188 ok(hinst
, !r
, "got %u\n", r
);
190 r
= MsiGetPropertyA(hinst
, "boo", buffer
, NULL
);
191 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
193 /* Returned size is in bytes, not chars, but only for custom actions.
194 * Seems to be a casualty of RPC... */
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
);
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
);
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
);
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
);
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
);
229 r
= MsiGetPropertyW(hinst
, L
"boo", NULL
, NULL
);
230 ok(hinst
, !r
, "got %u\n", r
);
232 r
= MsiGetPropertyW(hinst
, L
"boo", bufferW
, NULL
);
233 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
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
);
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
);
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
);
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
);
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
);
268 r
= MsiSetPropertyA(hinst
, "boo", NULL
);
269 ok(hinst
, !r
, "got %u\n", r
);
270 check_prop(hinst
, "boo", "");
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
);
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");
285 static void test_db(MSIHANDLE hinst
)
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
;
294 UINT r
, count
, type
, i
;
298 hdb
= MsiGetActiveDatabase(hinst
);
299 ok(hinst
, hdb
, "MsiGetActiveDatabase failed\n");
301 r
= MsiDatabaseIsTablePersistentA(hdb
, "Test");
302 ok(hinst
, r
== MSICONDITION_TRUE
, "got %u\n", r
);
304 r
= MsiDatabaseOpenViewA(hdb
, NULL
, &view
);
305 ok(hinst
, r
== ERROR_BAD_QUERY_SYNTAX
, "got %u\n", r
);
307 r
= MsiDatabaseOpenViewA(hdb
, "SELECT * FROM `Test`", NULL
);
308 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
310 r
= MsiDatabaseOpenViewA(hdb
, "SELECT * FROM `Test`", &view
);
311 ok(hinst
, !r
, "got %u\n", r
);
313 r
= MsiViewGetColumnInfo(view
, MSICOLINFO_NAMES
, &rec2
);
314 ok(hinst
, !r
, "got %u\n", r
);
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
);
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");
327 r
= MsiDatabaseIsTablePersistentA(hdb2
, "Test");
328 ok(hinst
, r
== MSICONDITION_TRUE
, "got %u\n", r
);
330 r
= MsiCloseHandle(hdb2
);
331 ok(hinst
, !r
, "got %u\n", r
);
333 r
= MsiCloseHandle(rec2
);
334 ok(hinst
, !r
, "got %u\n", r
);
336 r
= MsiViewExecute(view
, 0);
337 ok(hinst
, !r
, "got %u\n", r
);
339 r
= MsiViewFetch(view
, &rec2
);
340 ok(hinst
, !r
, "got %u\n", r
);
342 r
= MsiRecordGetFieldCount(rec2
);
343 ok(hinst
, r
== 3, "got %u\n", r
);
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
);
351 r
= MsiRecordGetInteger(rec2
, 2);
352 ok(hinst
, r
== 1, "got %u\n", r
);
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");
359 r
= MsiCloseHandle(rec2
);
360 ok(hinst
, !r
, "got %u\n", r
);
362 r
= MsiViewFetch(view
, &rec2
);
363 ok(hinst
, !r
, "got %u\n", r
);
365 r
= MsiRecordGetFieldCount(rec2
);
366 ok(hinst
, r
== 3, "got %u\n", r
);
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
);
374 r
= MsiRecordGetInteger(rec2
, 2);
375 ok(hinst
, r
== 2, "got %u\n", r
);
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");
382 r
= MsiViewModify(view
, MSIMODIFY_REFRESH
, 0);
383 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
385 r
= MsiRecordSetStringA(rec2
, 1, "three");
386 ok(hinst
, !r
, "got %u\n", r
);
388 r
= MsiRecordSetInteger(rec2
, 2, 3);
389 ok(hinst
, !r
, "got %u\n", r
);
391 r
= MsiRecordSetInteger(rec2
, 3, 3);
392 ok(hinst
, !r
, "got %u\n", r
);
394 r
= MsiViewModify(view
, MSIMODIFY_REFRESH
, rec2
);
395 ok(hinst
, !r
, "got %u\n", r
);
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
);
403 r
= MsiRecordGetInteger(rec2
, 2);
404 ok(hinst
, r
== 2, "got %u\n", r
);
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");
411 r
= MsiCloseHandle(rec2
);
412 ok(hinst
, !r
, "got %u\n", r
);
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
);
418 r
= MsiViewClose(view
);
419 ok(hinst
, !r
, "got %u\n", r
);
421 r
= MsiCloseHandle(view
);
422 ok(hinst
, !r
, "got %u\n", r
);
424 r
= MsiDatabaseOpenViewA(hdb
, "SELECT * FROM `Test` WHERE `Name` = ?", &view
);
425 ok(hinst
, !r
, "got %u\n", r
);
427 rec
= MsiCreateRecord(1);
428 MsiRecordSetStringA(rec
, 1, "one");
430 r
= MsiViewExecute(view
, rec
);
431 ok(hinst
, !r
, "got %u\n", r
);
433 r
= MsiViewFetch(view
, &rec2
);
434 ok(hinst
, !r
, "got %u\n", r
);
436 r
= MsiRecordGetInteger(rec2
, 2);
437 ok(hinst
, r
== 1, "got %u\n", r
);
439 r
= MsiCloseHandle(rec2
);
440 ok(hinst
, !r
, "got %u\n", r
);
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
);
446 r
= MsiCloseHandle(rec
);
447 ok(hinst
, !r
, "got %u\n", r
);
449 r
= MsiCloseHandle(view
);
450 ok(hinst
, !r
, "got %u\n", r
);
452 /* test MsiDatabaseGetPrimaryKeys() */
453 r
= MsiDatabaseGetPrimaryKeysA(hdb
, "Test", &rec
);
454 ok(hinst
, !r
, "got %u\n", r
);
456 r
= MsiRecordGetFieldCount(rec
);
457 ok(hinst
, r
== 1, "got %u\n", r
);
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
);
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
);
471 r
= MsiCloseHandle(rec
);
472 ok(hinst
, !r
, "got %u\n", r
);
474 r
= MsiGetSummaryInformationA(hdb
, NULL
, 1, NULL
);
475 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
477 r
= MsiGetSummaryInformationA(hdb
, NULL
, 1, &suminfo
);
478 ok(hinst
, !r
, "got %u\n", r
);
480 r
= MsiSummaryInfoGetPropertyCount(suminfo
, NULL
);
481 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
484 r
= MsiSummaryInfoGetPropertyCount(suminfo
, &count
);
485 ok(hinst
, !r
, "got %u\n", r
);
486 ok(hinst
, count
== 5, "got %u\n", count
);
488 r
= MsiSummaryInfoGetPropertyA(suminfo
, 0, NULL
, NULL
, NULL
, NULL
, NULL
);
489 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
491 for (i
= 0; i
< 20; i
++)
493 /* for some reason query for PID_TITLE leads to install failure under Windows */
494 if (i
== PID_TITLE
) continue;
497 int_value
= 0xdeadbeef;
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
);
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
);
509 ok(hinst
, int_value
== 0, "%u: got %u\n", i
, int_value
);
510 if (i
== PID_TEMPLATE
)
512 ok(hinst
, sz
== 5, "%u: got %lu\n", i
, sz
);
513 ok(hinst
, !lstrcmpA(buffer
, ";1033"), "%u: got %s\n", i
, buffer
);
515 else if (i
== PID_REVNUMBER
)
517 ok(hinst
, sz
== 76, "%u: got %lu\n", i
, sz
);
518 ok(hinst
, !lstrcmpA(buffer
, "{004757CA"), "%u: got %s\n", i
, buffer
);
522 ok(hinst
, sz
== sizeof(buffer
), "%u: got %lu\n", i
, sz
);
523 ok(hinst
, !*buffer
, "%u: got %s\n", i
, buffer
);
527 GetSystemTimeAsFileTime(&ft
);
529 for (i
= 0; i
< 20; i
++)
531 r
= MsiSummaryInfoSetPropertyA(suminfo
, i
, prop_type
[i
], 1252, &ft
, "");
532 ok(hinst
, r
== ERROR_FUNCTION_FAILED
, "%u: got %u\n", i
, r
);
534 r
= MsiSummaryInfoSetPropertyW(suminfo
, i
, prop_type
[i
], 1252, &ft
, L
"");
535 ok(hinst
, r
== ERROR_FUNCTION_FAILED
, "%u: got %u\n", i
, r
);
538 r
= MsiCloseHandle(suminfo
);
539 ok(hinst
, !r
, "got %u\n", r
);
541 r
= MsiCloseHandle(hdb
);
542 ok(hinst
, !r
, "got %u\n", r
);
545 static void test_doaction(MSIHANDLE hinst
)
549 r
= MsiDoActionA(hinst
, "nested51");
550 ok(hinst
, !r
, "got %u\n", r
);
551 check_prop(hinst
, "nested", "1");
553 r
= MsiDoActionA(hinst
, "nested1");
554 ok(hinst
, !r
, "got %u\n", r
);
555 check_prop(hinst
, "nested", "2");
557 r
= MsiSequenceA(hinst
, NULL
, 0);
558 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
560 r
= MsiSequenceA(hinst
, "TestSequence", 0);
561 ok(hinst
, !r
, "got %u\n", r
);
562 check_prop(hinst
, "nested", "1");
565 UINT WINAPI
nested(MSIHANDLE hinst
)
567 MsiSetPropertyA(hinst
, "nested", "2");
569 return ERROR_SUCCESS
;
572 static void test_targetpath(MSIHANDLE hinst
)
579 /* test invalid values */
580 r
= MsiGetTargetPathA(hinst
, NULL
, NULL
, NULL
);
581 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
583 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", NULL
, NULL
);
584 ok(hinst
, !r
, "got %u\n", r
);
586 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", buffer
, NULL
);
587 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
589 /* Returned size is in bytes, not chars, but only for custom actions.
590 * Seems to be a casualty of RPC... */
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
658 r
= MsiSetTargetPathA(hinst
, NULL
, "C:\\subdir");
659 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
661 r
= MsiSetTargetPathA(hinst
, "MSITESTDIR", NULL
);
662 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
664 r
= MsiSetTargetPathA(hinst
, "MSITESTDIR", "C:\\subdir");
665 ok(hinst
, !r
, "got %u\n", r
);
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
);
672 r
= MsiSetTargetPathA(hinst
, "MSITESTDIR", "C:\\");
674 /* test GetSourcePath() */
676 r
= MsiGetSourcePathA(hinst
, NULL
, NULL
, NULL
);
677 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
679 r
= MsiGetSourcePathA(hinst
, "TARGETDIR", NULL
, NULL
);
680 ok(hinst
, !r
, "got %u\n", r
);
682 r
= MsiGetSourcePathA(hinst
, "TARGETDIR", buffer
, NULL
);
683 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
685 /* Returned size is in bytes, not chars, but only for custom actions.
686 * Seems to be a casualty of RPC... */
689 MsiGetSourcePathW(hinst
, L
"TARGETDIR", NULL
, &srcsz
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
758 static void test_misc(MSIHANDLE hinst
)
764 r
= MsiSetMode(hinst
, MSIRUNMODE_REBOOTATEND
, FALSE
);
765 ok(hinst
, !r
, "got %u\n", r
);
767 lang
= MsiGetLanguage(hinst
);
768 ok(hinst
, lang
== 1033, "got %u\n", lang
);
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);
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
);
783 static void test_feature_states(MSIHANDLE hinst
)
785 INSTALLSTATE state
, action
;
788 /* test feature states */
790 r
= MsiGetFeatureStateA(hinst
, NULL
, &state
, &action
);
791 ok(hinst
, r
== ERROR_UNKNOWN_FEATURE
, "got %u\n", r
);
793 r
= MsiGetFeatureStateA(hinst
, "fake", &state
, &action
);
794 ok(hinst
, r
== ERROR_UNKNOWN_FEATURE
, "got %u\n", r
);
796 r
= MsiGetFeatureStateA(hinst
, "One", NULL
, &action
);
797 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
799 r
= MsiGetFeatureStateA(hinst
, "One", &state
, NULL
);
800 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
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
);
807 r
= MsiSetFeatureStateA(hinst
, NULL
, INSTALLSTATE_ABSENT
);
808 ok(hinst
, r
== ERROR_UNKNOWN_FEATURE
, "got %u\n", r
);
810 r
= MsiSetFeatureStateA(hinst
, "One", INSTALLSTATE_ADVERTISED
);
811 ok(hinst
, !r
, "got %u\n", r
);
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
);
817 r
= MsiSetFeatureStateA(hinst
, "One", INSTALLSTATE_LOCAL
);
818 ok(hinst
, !r
, "got %u\n", r
);
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
);
824 /* test component states */
826 r
= MsiGetComponentStateA(hinst
, NULL
, &state
, &action
);
827 ok(hinst
, r
== ERROR_UNKNOWN_COMPONENT
, "got %u\n", r
);
829 r
= MsiGetComponentStateA(hinst
, "fake", &state
, &action
);
830 ok(hinst
, r
== ERROR_UNKNOWN_COMPONENT
, "got %u\n", r
);
832 r
= MsiGetComponentStateA(hinst
, "One", NULL
, &action
);
833 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
835 r
= MsiGetComponentStateA(hinst
, "One", &state
, NULL
);
836 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
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
);
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
);
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
);
853 r
= MsiSetComponentStateA(hinst
, NULL
, INSTALLSTATE_ABSENT
);
854 ok(hinst
, r
== ERROR_UNKNOWN_COMPONENT
, "got %u\n", r
);
856 r
= MsiSetComponentStateA(hinst
, "One", INSTALLSTATE_SOURCE
);
857 ok(hinst
, !r
, "got %u\n", r
);
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
);
864 r
= MsiSetComponentStateA(hinst
, "One", INSTALLSTATE_LOCAL
);
865 ok(hinst
, !r
, "got %u\n", r
);
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
);
873 static void test_format_record(MSIHANDLE hinst
)
881 r
= MsiFormatRecordA(hinst
, 0, NULL
, NULL
);
882 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
884 rec
= MsiCreateRecord(1);
885 MsiRecordSetStringA(rec
, 0, "foo [1]");
886 MsiRecordSetInteger(rec
, 1, 123);
888 r
= MsiFormatRecordA(hinst
, rec
, NULL
, NULL
);
889 ok(hinst
, !r
, "got %u\n", r
);
891 r
= MsiFormatRecordA(hinst
, rec
, buffer
, NULL
);
892 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
894 /* Returned size is in bytes, not chars, but only for custom actions. */
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
);
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
);
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
);
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
);
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
);
929 r
= MsiFormatRecordW(hinst
, rec
, NULL
, NULL
);
930 ok(hinst
, !r
, "got %u\n", r
);
932 r
= MsiFormatRecordW(hinst
, rec
, bufferW
, NULL
);
933 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
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
);
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
);
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
);
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
);
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
);
968 /* check that properties work */
969 MsiSetPropertyA(hinst
, "fmtprop", "foobar");
970 MsiRecordSetStringA(rec
, 0, "[fmtprop]");
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
);
980 static void test_costs(MSIHANDLE hinst
)
989 r
= MsiGetFeatureCostA(hinst
, NULL
, MSICOSTTREE_CHILDREN
, INSTALLSTATE_LOCAL
, &cost
);
990 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
992 ok(hinst
, !cost
, "got %d\n", cost
);
994 r
= MsiGetFeatureCostA(hinst
, "One", MSICOSTTREE_CHILDREN
, INSTALLSTATE_LOCAL
, NULL
);
995 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
998 r
= MsiGetFeatureCostA(hinst
, "One", MSICOSTTREE_CHILDREN
, INSTALLSTATE_LOCAL
, &cost
);
999 ok(hinst
, !r
, "got %u\n", r
);
1001 ok(hinst
, cost
== 8, "got %d\n", cost
);
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
);
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
);
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
);
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
);
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
);
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
);
1046 /* same string behaviour */
1047 cost
= temp
= 0xdead;
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
);
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
);
1060 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, &cost
, &temp
);
1061 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
1063 ok(hinst
, !buffer
[0], "got \"%s\"\n", buffer
);
1064 ok(hinst
, sz
== 4, "got size %lu\n", sz
);
1069 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, &cost
, &temp
);
1070 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
1072 ok(hinst
, !strcmp(buffer
, "C"), "got \"%s\"\n", buffer
);
1073 ok(hinst
, sz
== 4, "got size %lu\n", sz
);
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
);
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
);
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
);
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
);
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
);
1112 static void test_invalid_functions(MSIHANDLE hinst
)
1114 char path
[MAX_PATH
], package_name
[20];
1115 MSIHANDLE db
, preview
, package
;
1118 r
= MsiGetDatabaseState(hinst
);
1119 ok(hinst
, r
== MSIDBSTATE_ERROR
, "got %u\n", r
);
1121 db
= MsiGetActiveDatabase(hinst
);
1122 ok(hinst
, db
, "MsiGetActiveDatabase failed\n");
1124 r
= MsiDatabaseGenerateTransformA(db
, db
, "bogus.mst", 0, 0);
1125 todo_wine
ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
1127 r
= MsiDatabaseApplyTransformA(db
, "bogus.mst", 0);
1128 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
1130 r
= MsiCreateTransformSummaryInfoA(db
, db
, "bogus.mst", 0, 0);
1131 todo_wine
ok(hinst
, r
== ERROR_INSTALL_PACKAGE_OPEN_FAILED
, "got %u\n", r
);
1133 GetCurrentDirectoryA(sizeof(path
), path
);
1134 r
= MsiDatabaseExportA(db
, "Test", path
, "bogus.idt");
1135 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
1137 r
= MsiDatabaseImportA(db
, path
, "bogus.idt");
1138 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
1140 r
= MsiDatabaseCommit(db
);
1141 ok(hinst
, r
== ERROR_SUCCESS
, "got %u\n", r
);
1143 r
= MsiDatabaseMergeA(db
, db
, "MergeErrors");
1144 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
1146 r
= MsiGetDatabaseState(db
);
1147 ok(hinst
, r
== MSIDBSTATE_ERROR
, "got %u\n", r
);
1149 r
= MsiEnableUIPreview(db
, &preview
);
1150 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
1152 sprintf(package_name
, "#%lu", db
);
1153 r
= MsiOpenPackageA(package_name
, &package
);
1154 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
1159 static void test_view_get_error(MSIHANDLE hinst
)
1161 MSIHANDLE db
, view
, rec
;
1167 db
= MsiGetActiveDatabase(hinst
);
1168 ok(hinst
, db
, "MsiGetActiveDatabase failed\n");
1170 r
= MsiDatabaseOpenViewA(db
, "SELECT * FROM `test2`", &view
);
1171 ok(hinst
, !r
, "got %u\n", r
);
1173 r
= MsiViewExecute(view
, 0);
1174 ok(hinst
, !r
, "got %u\n", r
);
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
);
1181 err
= MsiViewGetErrorA(view
, NULL
, NULL
);
1182 ok(hinst
, err
== MSIDBERROR_INVALIDARG
, "got %d\n", err
);
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
);
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
);
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
);
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
);
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
);
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
);
1223 r
= MsiViewModify(view
, MSIMODIFY_VALIDATE_NEW
, rec
);
1224 ok(hinst
, r
== ERROR_INVALID_DATA
, "got %u\n", r
);
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
);
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
);
1240 r
= MsiViewModify(view
, MSIMODIFY_VALIDATE_NEW
, rec
);
1241 ok(hinst
, r
== ERROR_INVALID_DATA
, "got %u\n", r
);
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
);
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
);
1257 MsiCloseHandle(rec
);
1258 MsiCloseHandle(view
);
1262 /* Main test. Anything that doesn't depend on a specific install configuration
1263 * or have undesired side effects should go here. */
1264 UINT WINAPI
main_test(MSIHANDLE hinst
)
1266 IUnknown
*unk
= NULL
;
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
);
1273 if (unk
) IUnknown_Release(unk
);
1275 /* but ours is uninitialized */
1276 hr
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1277 ok(hinst
, hr
== S_OK
, "got %#lx\n", hr
);
1282 test_doaction(hinst
);
1283 test_targetpath(hinst
);
1285 test_feature_states(hinst
);
1286 test_format_record(hinst
);
1288 test_invalid_functions(hinst
);
1289 test_view_get_error(hinst
);
1291 return ERROR_SUCCESS
;
1294 UINT WINAPI
test_retval(MSIHANDLE hinst
)
1297 DWORD len
= sizeof(prop
);
1300 MsiGetPropertyA(hinst
, "TEST_RETVAL", prop
, &len
);
1301 sscanf(prop
, "%u", &retval
);
1305 static void append_file(MSIHANDLE hinst
, const char *filename
, const char *text
)
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());
1311 SetFilePointer(file
, 0, NULL
, FILE_END
);
1312 WriteFile(file
, text
, strlen(text
), &size
, NULL
);
1316 UINT WINAPI
da_immediate(MSIHANDLE hinst
)
1319 DWORD len
= sizeof(prop
);
1321 MsiGetPropertyA(hinst
, "TESTPATH", prop
, &len
);
1323 append_file(hinst
, prop
, "one");
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");
1329 return ERROR_SUCCESS
;
1332 UINT WINAPI
da_deferred(MSIHANDLE hinst
)
1335 DWORD len
= sizeof(prop
);
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");
1344 append_file(hinst
, prop
, "two");
1346 /* Test available properties */
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
);
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
);
1358 r
= MsiGetPropertyA(hinst
, "TESTPATH", prop
, &len
);
1359 ok(hinst
, r
== ERROR_SUCCESS
, "got %u\n", r
);
1361 ok(hinst
, !prop
[0], "got %s\n", prop
);
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");
1368 lang
= MsiGetLanguage(hinst
);
1369 ok(hinst
, lang
!= ERROR_INVALID_HANDLE
, "MsiGetLanguage failed\n");
1371 return ERROR_SUCCESS
;
1374 static int global_state
;
1376 UINT WINAPI
process1(MSIHANDLE hinst
)
1378 SetEnvironmentVariableA("MSI_PROCESS_TEST","1");
1380 return ERROR_SUCCESS
;
1383 UINT WINAPI
process2(MSIHANDLE hinst
)
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
;
1393 UINT WINAPI
async1(MSIHANDLE hinst
)
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");
1400 return ERROR_SUCCESS
;
1403 UINT WINAPI
async2(MSIHANDLE hinst
)
1405 HANDLE event
= CreateEventA(NULL
, TRUE
, FALSE
, "wine_msi_async_test");
1406 HANDLE event2
= CreateEventA(NULL
, TRUE
, FALSE
, "wine_msi_async_test2");
1409 r
= WaitForSingleObject(event2
, 10000);
1410 ok(hinst
, !r
, "wait timed out\n");
1411 return ERROR_SUCCESS
;
1414 static BOOL
pf_exists(const char *file
)
1416 char path
[MAX_PATH
];
1418 if (FAILED(SHGetFolderPathA(NULL
, CSIDL_PROGRAM_FILESX86
, NULL
, 0, path
)))
1419 SHGetFolderPathA(NULL
, CSIDL_PROGRAM_FILES
, NULL
, 0, path
);
1422 return GetFileAttributesA(path
) != INVALID_FILE_ATTRIBUTES
;
1425 UINT WINAPI
cf_present(MSIHANDLE hinst
)
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
;
1433 UINT WINAPI
cf_absent(MSIHANDLE hinst
)
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
;
1441 UINT WINAPI
file_present(MSIHANDLE hinst
)
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
;
1448 UINT WINAPI
file_absent(MSIHANDLE hinst
)
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
;
1455 UINT WINAPI
crs_present(MSIHANDLE hinst
)
1457 ok(hinst
, pf_exists("msitest\\shortcut.lnk"), "shortcut absent\n");
1458 return ERROR_SUCCESS
;
1461 UINT WINAPI
crs_absent(MSIHANDLE hinst
)
1463 ok(hinst
, !pf_exists("msitest\\shortcut.lnk"), "shortcut present\n");
1464 return ERROR_SUCCESS
;
1467 UINT WINAPI
sds_present(MSIHANDLE hinst
)
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
;
1478 UINT WINAPI
sds_absent(MSIHANDLE hinst
)
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
;
1489 UINT WINAPI
sis_present(MSIHANDLE hinst
)
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
;
1500 UINT WINAPI
sis_absent(MSIHANDLE hinst
)
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
;
1511 UINT WINAPI
sss_started(MSIHANDLE hinst
)
1513 SC_HANDLE manager
, service
;
1514 SERVICE_STATUS status
;
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
);
1523 CloseServiceHandle(service
);
1524 CloseServiceHandle(manager
);
1525 return ERROR_SUCCESS
;
1528 UINT WINAPI
sss_stopped(MSIHANDLE hinst
)
1530 SC_HANDLE manager
, service
;
1531 SERVICE_STATUS status
;
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
);
1540 CloseServiceHandle(service
);
1541 CloseServiceHandle(manager
);
1542 return ERROR_SUCCESS
;
1545 UINT WINAPI
rd_present(MSIHANDLE hinst
)
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
;
1554 UINT WINAPI
rd_absent(MSIHANDLE hinst
)
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
;
1563 UINT WINAPI
odbc_present(MSIHANDLE hinst
)
1565 int gotdriver
= 0, gotdriver2
= 0;
1566 char buffer
[1000], *p
;
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)
1576 if (!strcmp(p
, "ODBC test driver"))
1578 if (!strcmp(p
, "ODBC test driver2"))
1581 ok(hinst
, gotdriver
, "driver absent\n");
1582 ok(hinst
, gotdriver2
, "driver 2 absent\n");
1583 return ERROR_SUCCESS
;
1586 UINT WINAPI
odbc_absent(MSIHANDLE hinst
)
1588 int gotdriver
= 0, gotdriver2
= 0;
1589 char buffer
[1000], *p
;
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)
1599 if (!strcmp(p
, "ODBC test driver"))
1601 if (!strcmp(p
, "ODBC test driver2"))
1604 ok(hinst
, !gotdriver
, "driver present\n");
1605 ok(hinst
, !gotdriver2
, "driver 2 present\n");
1606 return ERROR_SUCCESS
;
1609 UINT WINAPI
mov_present(MSIHANDLE hinst
)
1611 ok(hinst
, pf_exists("msitest\\canada"), "file absent\n");
1612 ok(hinst
, pf_exists("msitest\\dominica"), "file absent\n");
1613 return ERROR_SUCCESS
;
1616 UINT WINAPI
mov_absent(MSIHANDLE hinst
)
1618 ok(hinst
, !pf_exists("msitest\\canada"), "file present\n");
1619 ok(hinst
, !pf_exists("msitest\\dominica"), "file present\n");
1620 return ERROR_SUCCESS
;
1623 static void check_reg_str(MSIHANDLE hinst
, HKEY key
, const char *name
, const char *expect
)
1630 res
= RegQueryValueExA(key
, name
, NULL
, NULL
, (BYTE
*)value
, &sz
);
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
);
1638 ok(hinst
, res
== ERROR_FILE_NOT_FOUND
, "\"%s\": expected missing, got %ld\n",
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\"";
1646 UINT WINAPI
pa_present(MSIHANDLE hinst
)
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?~]");
1656 return ERROR_SUCCESS
;
1659 UINT WINAPI
pa_absent(MSIHANDLE hinst
)
1664 res
= RegOpenKeyA(HKEY_CURRENT_USER
, path_dotnet
, &key
);
1665 ok(hinst
, !res
|| res
== ERROR_FILE_NOT_FOUND
, "got %ld\n", res
);
1668 check_reg_str(hinst
, key
, name_dotnet
, NULL
);
1671 return ERROR_SUCCESS
;
1674 static const char ppc_key
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\"
1675 "Installer\\UserData\\S-1-5-18\\Components\\CBABC2FDCCB35E749A8944D8C1C098B5";
1677 UINT WINAPI
ppc_present(MSIHANDLE hinst
)
1679 char expect
[MAX_PATH
];
1683 r
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, ppc_key
, 0, KEY_QUERY_VALUE
| KEY_WOW64_64KEY
, &key
);
1684 ok(hinst
, !r
, "got %u\n", r
);
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
);
1692 return ERROR_SUCCESS
;
1695 UINT WINAPI
ppc_absent(MSIHANDLE hinst
)
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
;
1705 static const char pub_key
[] = "Software\\Microsoft\\Installer\\Components\\0CBCFA296AC907244845745CEEB2F8AA";
1707 UINT WINAPI
pub_present(MSIHANDLE hinst
)
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
);
1717 return ERROR_SUCCESS
;
1720 UINT WINAPI
pub_absent(MSIHANDLE hinst
)
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
;
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";
1734 UINT WINAPI
pf_present(MSIHANDLE hinst
)
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", "");
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");
1751 return ERROR_SUCCESS
;
1754 UINT WINAPI
pf_absent(MSIHANDLE hinst
)
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
);
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
);
1765 return ERROR_SUCCESS
;
1768 static const char pp_prodkey
[] = "Installer\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
1770 UINT WINAPI
pp_present(MSIHANDLE hinst
)
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", ":");
1782 return ERROR_SUCCESS
;
1785 UINT WINAPI
pp_absent(MSIHANDLE hinst
)
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
);
1793 return ERROR_SUCCESS
;
1796 UINT WINAPI
rci_present(MSIHANDLE hinst
)
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
);
1806 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "FileType\\{110913E7-86D1-4BF3-9922-BA103FCDDDFA}", &key
);
1807 ok(hinst
, !res
, "got %ld\n", res
);
1810 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "AppID\\{CFCC3B38-E683-497D-9AB4-CB40AAFE307F}", &key
);
1811 ok(hinst
, !res
, "got %ld\n", res
);
1814 return ERROR_SUCCESS
;
1817 UINT WINAPI
rci_absent(MSIHANDLE hinst
)
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
);
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
);
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
);
1832 return ERROR_SUCCESS
;
1835 UINT WINAPI
rei_present(MSIHANDLE hinst
)
1840 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, ".extension", &key
);
1841 ok(hinst
, !res
, "got %ld\n", res
);
1844 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "Prog.Id.1\\shell\\Open\\command", &key
);
1845 ok(hinst
, !res
, "got %ld\n", res
);
1848 return ERROR_SUCCESS
;
1851 UINT WINAPI
rei_absent(MSIHANDLE hinst
)
1856 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, ".extension", &key
);
1857 ok(hinst
, res
== ERROR_FILE_NOT_FOUND
, "got %ld\n", res
);
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
);
1862 return ERROR_SUCCESS
;
1865 static const char font_key
[] = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
1867 UINT WINAPI
font_present(MSIHANDLE hinst
)
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
);
1878 return ERROR_SUCCESS
;
1881 UINT WINAPI
font_absent(MSIHANDLE hinst
)
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
);
1891 return ERROR_SUCCESS
;
1894 UINT WINAPI
rmi_present(MSIHANDLE hinst
)
1899 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "MIME\\Database\\Content Type\\mime/type", &key
);
1900 ok(hinst
, !res
, "got %ld\n", res
);
1902 return ERROR_SUCCESS
;
1905 UINT WINAPI
rmi_absent(MSIHANDLE hinst
)
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
);
1913 return ERROR_SUCCESS
;
1916 static const char rp_key
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\"
1917 "Uninstall\\{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
1919 UINT WINAPI
rp_present(MSIHANDLE hinst
)
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");
1929 return ERROR_SUCCESS
;
1932 UINT WINAPI
rp_absent(MSIHANDLE hinst
)
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
);
1940 return ERROR_SUCCESS
;
1943 UINT WINAPI
rpi_present(MSIHANDLE hinst
)
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
);
1953 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "Winetest.Class.1", &key
);
1954 ok(hinst
, !res
, "got %ld\n", res
);
1957 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "Winetest.Class", &key
);
1958 ok(hinst
, !res
, "got %ld\n", res
);
1961 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "Winetest.Class.2", &key
);
1962 ok(hinst
, !res
, "got %ld\n", res
);
1965 return ERROR_SUCCESS
;
1968 UINT WINAPI
rpi_absent(MSIHANDLE hinst
)
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
);
1977 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "Winetest.Class.1", &key
);
1978 ok(hinst
, res
== ERROR_FILE_NOT_FOUND
, "got %ld\n", res
);
1980 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "Winetest.Class", &key
);
1981 ok(hinst
, res
== ERROR_FILE_NOT_FOUND
, "got %ld\n", res
);
1983 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "Winetest.Class.2", &key
);
1984 ok(hinst
, res
== ERROR_FILE_NOT_FOUND
, "got %ld\n", res
);
1986 return ERROR_SUCCESS
;
1989 static const CHAR ru_key
[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
1990 "\\UserData\\S-1-5-18\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties";
1992 UINT WINAPI
ru_present(MSIHANDLE hinst
)
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");
2002 return ERROR_SUCCESS
;
2005 UINT WINAPI
ru_absent(MSIHANDLE hinst
)
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
);
2013 return ERROR_SUCCESS
;
2016 static const GUID LIBID_register_test
=
2017 {0xeac5166a, 0x9734, 0x4d91, {0x87,0x8f, 0x1d,0xd0,0x23,0x04,0xc6,0x6c}};
2019 UINT WINAPI
tl_present(MSIHANDLE hinst
)
2024 hr
= LoadRegTypeLib(&LIBID_register_test
, 7, 1, 0, &tlb
);
2025 ok(hinst
, hr
== S_OK
, "got %#lx\n", hr
);
2026 ITypeLib_Release(tlb
);
2028 return ERROR_SUCCESS
;
2031 UINT WINAPI
tl_absent(MSIHANDLE hinst
)
2036 hr
= LoadRegTypeLib(&LIBID_register_test
, 7, 1, 0, &tlb
);
2037 ok(hinst
, hr
== TYPE_E_LIBNOTREGISTERED
, "got %#lx\n", hr
);
2039 return ERROR_SUCCESS
;
2042 UINT WINAPI
sr_present(MSIHANDLE hinst
)
2047 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "selfreg_test", &key
);
2048 ok(hinst
, !res
, "got %ld\n", res
);
2051 return ERROR_SUCCESS
;
2054 UINT WINAPI
sr_absent(MSIHANDLE hinst
)
2059 res
= RegOpenKeyA(HKEY_CLASSES_ROOT
, "selfreg_test", &key
);
2060 ok(hinst
, res
== ERROR_FILE_NOT_FOUND
, "got %ld\n", res
);
2062 return ERROR_SUCCESS
;
2065 UINT WINAPI
env_present(MSIHANDLE hinst
)
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");
2076 return ERROR_SUCCESS
;
2079 UINT WINAPI
env_absent(MSIHANDLE hinst
)
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
);
2090 return ERROR_SUCCESS
;
2093 UINT WINAPI
ini_present(MSIHANDLE hinst
)
2095 char path
[MAX_PATH
], buf
[10];
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");
2102 len
= GetPrivateProfileStringA("section1", "key1", NULL
, buf
, sizeof(buf
), path
);
2103 ok(hinst
, len
== 6, "got %lu\n", len
);
2105 return ERROR_SUCCESS
;
2108 UINT WINAPI
ini_absent(MSIHANDLE hinst
)
2110 char path
[MAX_PATH
], buf
[10];
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");
2117 len
= GetPrivateProfileStringA("section1", "key1", NULL
, buf
, sizeof(buf
), path
);
2118 ok(hinst
, !len
, "got %lu\n", len
);
2120 return ERROR_SUCCESS
;
2123 UINT WINAPI
wrv_present(MSIHANDLE hinst
)
2128 res
= RegOpenKeyA(HKEY_CURRENT_USER
, "msitest", &key
);
2129 ok(hinst
, !res
, "got %ld\n", res
);
2130 check_reg_str(hinst
, key
, "sz", "string");
2133 return ERROR_SUCCESS
;
2136 UINT WINAPI
wrv_absent(MSIHANDLE hinst
)
2141 res
= RegOpenKeyA(HKEY_CURRENT_USER
, "msitest", &key
);
2142 ok(hinst
, !res
, "got %ld\n", res
);
2143 check_reg_str(hinst
, key
, "sz", NULL
);
2146 return ERROR_SUCCESS
;