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
32 static int todo_level
, todo_do_loop
;
34 static void ok_(MSIHANDLE hinst
, int todo
, const char *file
, int line
, int condition
, const char *msg
, ...)
36 static char buffer
[2000];
40 va_start(valist
, msg
);
41 vsprintf(buffer
, msg
, valist
);
44 record
= MsiCreateRecord(5);
45 MsiRecordSetInteger(record
, 1, todo
);
46 MsiRecordSetStringA(record
, 2, file
);
47 MsiRecordSetInteger(record
, 3, line
);
48 MsiRecordSetInteger(record
, 4, condition
);
49 MsiRecordSetStringA(record
, 5, buffer
);
50 MsiProcessMessage(hinst
, INSTALLMESSAGE_USER
, record
);
51 MsiCloseHandle(record
);
54 static void winetest_start_todo( int is_todo
)
56 todo_level
= (todo_level
<< 1) | (is_todo
!= 0);
60 static int winetest_loop_todo(void)
62 int do_loop
=todo_do_loop
;
67 static void winetest_end_todo(void)
72 #define ok(hinst, condition, ...) ok_(hinst, todo_level, __FILE__, __LINE__, condition, __VA_ARGS__)
73 #define todo_wine_if(is_todo) for (winetest_start_todo(is_todo); \
74 winetest_loop_todo(); \
76 #define todo_wine todo_wine_if(1)
78 static const char *dbgstr_w(WCHAR
*str
)
80 static char buffer
[300], *p
;
82 if (!str
) return "(null)";
87 while ((*p
++ = *str
++));
94 static void check_prop(MSIHANDLE hinst
, const char *prop
, const char *expect
)
96 char buffer
[10] = "x";
97 DWORD sz
= sizeof(buffer
);
98 UINT r
= MsiGetPropertyA(hinst
, prop
, buffer
, &sz
);
99 ok(hinst
, !r
, "'%s': got %u\n", prop
, r
);
100 ok(hinst
, sz
== strlen(buffer
), "'%s': expected %u, got %u\n", prop
, strlen(buffer
), sz
);
101 ok(hinst
, !strcmp(buffer
, expect
), "expected '%s', got '%s'\n", expect
, buffer
);
104 static void test_props(MSIHANDLE hinst
)
106 static const WCHAR booW
[] = {'b','o','o',0};
107 static const WCHAR xyzW
[] = {'x','y','z',0};
108 static const WCHAR xyW
[] = {'x','y',0};
114 /* test invalid values */
115 r
= MsiGetPropertyA(hinst
, NULL
, NULL
, NULL
);
116 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
118 r
= MsiGetPropertyA(hinst
, "boo", NULL
, NULL
);
119 ok(hinst
, !r
, "got %u\n", r
);
121 r
= MsiGetPropertyA(hinst
, "boo", buffer
, NULL
);
122 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
125 r
= MsiGetPropertyA(hinst
, "boo", NULL
, &sz
);
126 ok(hinst
, !r
, "got %u\n", r
);
127 ok(hinst
, sz
== 0, "got size %u\n", sz
);
131 r
= MsiGetPropertyA(hinst
, "boo", buffer
, &sz
);
132 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
133 ok(hinst
, !strcmp(buffer
, "x"), "got \"%s\"\n", buffer
);
134 ok(hinst
, sz
== 0, "got size %u\n", sz
);
138 r
= MsiGetPropertyA(hinst
, "boo", buffer
, &sz
);
139 ok(hinst
, !r
, "got %u\n", r
);
140 ok(hinst
, !buffer
[0], "got \"%s\"\n", buffer
);
141 ok(hinst
, sz
== 0, "got size %u\n", sz
);
143 /* set the property to something */
144 r
= MsiSetPropertyA(hinst
, NULL
, NULL
);
145 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
147 r
= MsiSetPropertyA(hinst
, "", NULL
);
148 ok(hinst
, !r
, "got %u\n", r
);
150 r
= MsiSetPropertyA(hinst
, "", "asdf");
151 ok(hinst
, r
== ERROR_FUNCTION_FAILED
, "got %u\n", r
);
153 r
= MsiSetPropertyA(hinst
, "=", "asdf");
154 ok(hinst
, !r
, "got %u\n", r
);
155 check_prop(hinst
, "=", "asdf");
157 r
= MsiSetPropertyA(hinst
, " ", "asdf");
158 ok(hinst
, !r
, "got %u\n", r
);
159 check_prop(hinst
, " ", "asdf");
161 r
= MsiSetPropertyA(hinst
, "'", "asdf");
162 ok(hinst
, !r
, "got %u\n", r
);
163 check_prop(hinst
, "'", "asdf");
165 r
= MsiSetPropertyA(hinst
, "boo", NULL
);
166 ok(hinst
, !r
, "got %u\n", r
);
167 check_prop(hinst
, "boo", "");
169 r
= MsiSetPropertyA(hinst
, "boo", "");
170 ok(hinst
, !r
, "got %u\n", r
);
171 check_prop(hinst
, "boo", "");
173 r
= MsiSetPropertyA(hinst
, "boo", "xyz");
174 ok(hinst
, !r
, "got %u\n", r
);
175 check_prop(hinst
, "boo", "xyz");
177 r
= MsiGetPropertyA(hinst
, "boo", NULL
, NULL
);
178 ok(hinst
, !r
, "got %u\n", r
);
180 r
= MsiGetPropertyA(hinst
, "boo", buffer
, NULL
);
181 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
183 /* Returned size is in bytes, not chars, but only for custom actions.
184 * Seems to be a casualty of RPC... */
187 r
= MsiGetPropertyA(hinst
, "boo", NULL
, &sz
);
188 ok(hinst
, !r
, "got %u\n", r
);
189 ok(hinst
, sz
== 6, "got size %u\n", sz
);
193 r
= MsiGetPropertyA(hinst
, "boo", buffer
, &sz
);
194 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
195 ok(hinst
, !strcmp(buffer
, "q"), "got \"%s\"\n", buffer
);
196 ok(hinst
, sz
== 6, "got size %u\n", sz
);
200 r
= MsiGetPropertyA(hinst
, "boo", buffer
, &sz
);
201 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
202 ok(hinst
, !buffer
[0], "got \"%s\"\n", buffer
);
203 ok(hinst
, sz
== 6, "got size %u\n", sz
);
207 r
= MsiGetPropertyA(hinst
, "boo", buffer
, &sz
);
208 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
209 ok(hinst
, !strcmp(buffer
, "xy"), "got \"%s\"\n", buffer
);
210 ok(hinst
, sz
== 6, "got size %u\n", sz
);
214 r
= MsiGetPropertyA(hinst
, "boo", buffer
, &sz
);
215 ok(hinst
, !r
, "got %u\n", r
);
216 ok(hinst
, !strcmp(buffer
, "xyz"), "got \"%s\"\n", buffer
);
217 ok(hinst
, sz
== 3, "got size %u\n", sz
);
219 r
= MsiGetPropertyW(hinst
, booW
, NULL
, NULL
);
220 ok(hinst
, !r
, "got %u\n", r
);
222 r
= MsiGetPropertyW(hinst
, booW
, bufferW
, NULL
);
223 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
226 r
= MsiGetPropertyW(hinst
, booW
, NULL
, &sz
);
227 ok(hinst
, !r
, "got %u\n", r
);
228 ok(hinst
, sz
== 3, "got size %u\n", sz
);
231 lstrcpyW(bufferW
, booW
);
232 r
= MsiGetPropertyW(hinst
, booW
, bufferW
, &sz
);
233 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
234 ok(hinst
, !lstrcmpW(bufferW
, booW
), "got %s\n", dbgstr_w(bufferW
));
235 ok(hinst
, sz
== 3, "got size %u\n", sz
);
238 lstrcpyW(bufferW
, booW
);
239 r
= MsiGetPropertyW(hinst
, booW
, bufferW
, &sz
);
240 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
241 ok(hinst
, !bufferW
[0], "got %s\n", dbgstr_w(bufferW
));
242 ok(hinst
, sz
== 3, "got size %u\n", sz
);
245 lstrcpyW(bufferW
, booW
);
246 r
= MsiGetPropertyW(hinst
, booW
, bufferW
, &sz
);
247 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
248 ok(hinst
, !lstrcmpW(bufferW
, xyW
), "got %s\n", dbgstr_w(bufferW
));
249 ok(hinst
, sz
== 3, "got size %u\n", sz
);
252 lstrcpyW(bufferW
, booW
);
253 r
= MsiGetPropertyW(hinst
, booW
, bufferW
, &sz
);
254 ok(hinst
, !r
, "got %u\n", r
);
255 ok(hinst
, !lstrcmpW(bufferW
, xyzW
), "got %s\n", dbgstr_w(bufferW
));
256 ok(hinst
, sz
== 3, "got size %u\n", sz
);
258 r
= MsiSetPropertyA(hinst
, "boo", NULL
);
259 ok(hinst
, !r
, "got %u\n", r
);
260 check_prop(hinst
, "boo", "");
263 r
= MsiGetPropertyA(hinst
, "embednullprop", NULL
, &sz
);
264 ok(hinst
, !r
, "got %u\n", r
);
265 ok(hinst
, sz
== 6, "got size %u\n", sz
);
268 memset(buffer
, 0xcc, sizeof(buffer
));
269 r
= MsiGetPropertyA(hinst
, "embednullprop", buffer
, &sz
);
270 ok(hinst
, !r
, "got %u\n", r
);
271 ok(hinst
, sz
== 3, "got size %u\n", sz
);
272 ok(hinst
, !memcmp(buffer
, "a\0\0\0\xcc", 5), "wrong data\n");
275 static void test_db(MSIHANDLE hinst
)
277 MSIHANDLE hdb
, view
, rec
, rec2
, suminfo
;
282 hdb
= MsiGetActiveDatabase(hinst
);
283 ok(hinst
, hdb
, "MsiGetActiveDatabase failed\n");
285 r
= MsiDatabaseIsTablePersistentA(hdb
, "Test");
286 ok(hinst
, r
== MSICONDITION_TRUE
, "got %u\n", r
);
288 r
= MsiDatabaseOpenViewA(hdb
, NULL
, &view
);
289 ok(hinst
, r
== ERROR_BAD_QUERY_SYNTAX
, "got %u\n", r
);
291 r
= MsiDatabaseOpenViewA(hdb
, "SELECT * FROM `Test`", NULL
);
292 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
294 r
= MsiDatabaseOpenViewA(hdb
, "SELECT * FROM `Test`", &view
);
295 ok(hinst
, !r
, "got %u\n", r
);
297 r
= MsiViewGetColumnInfo(view
, MSICOLINFO_NAMES
, &rec2
);
298 ok(hinst
, !r
, "got %u\n", r
);
301 r
= MsiRecordGetStringA(rec2
, 1, buffer
, &sz
);
302 ok(hinst
, !r
, "got %u\n", r
);
303 ok(hinst
, sz
== strlen(buffer
), "got size %u\n", sz
);
304 ok(hinst
, !strcmp(buffer
, "Name"), "got '%s'\n", buffer
);
306 r
= MsiCloseHandle(rec2
);
307 ok(hinst
, !r
, "got %u\n", r
);
309 r
= MsiViewExecute(view
, 0);
310 ok(hinst
, !r
, "got %u\n", r
);
312 r
= MsiViewFetch(view
, &rec2
);
313 ok(hinst
, !r
, "got %u\n", r
);
315 r
= MsiRecordGetFieldCount(rec2
);
316 ok(hinst
, r
== 3, "got %u\n", r
);
319 r
= MsiRecordGetStringA(rec2
, 1, buffer
, &sz
);
320 ok(hinst
, !r
, "got %u\n", r
);
321 ok(hinst
, sz
== strlen(buffer
), "got size %u\n", sz
);
322 ok(hinst
, !strcmp(buffer
, "one"), "got '%s'\n", buffer
);
324 r
= MsiRecordGetInteger(rec2
, 2);
325 ok(hinst
, r
== 1, "got %d\n", r
);
328 r
= MsiRecordReadStream(rec2
, 3, buffer
, &sz
);
329 ok(hinst
, !r
, "got %u\n", r
);
330 ok(hinst
, !memcmp(buffer
, "unus", 4), "wrong data\n");
332 r
= MsiCloseHandle(rec2
);
333 ok(hinst
, !r
, "got %u\n", r
);
335 r
= MsiViewFetch(view
, &rec2
);
336 ok(hinst
, !r
, "got %u\n", r
);
338 r
= MsiRecordGetFieldCount(rec2
);
339 ok(hinst
, r
== 3, "got %u\n", r
);
342 r
= MsiRecordGetStringA(rec2
, 1, buffer
, &sz
);
343 ok(hinst
, !r
, "got %u\n", r
);
344 ok(hinst
, sz
== strlen(buffer
), "got size %u\n", sz
);
345 ok(hinst
, !strcmp(buffer
, "two"), "got '%s'\n", buffer
);
347 r
= MsiRecordGetInteger(rec2
, 2);
348 ok(hinst
, r
== 2, "got %d\n", r
);
351 r
= MsiRecordReadStream(rec2
, 3, buffer
, &sz
);
352 ok(hinst
, !r
, "got %u\n", r
);
353 ok(hinst
, !memcmp(buffer
, "duo", 3), "wrong data\n");
355 r
= MsiViewModify(view
, MSIMODIFY_REFRESH
, 0);
356 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
358 r
= MsiRecordSetStringA(rec2
, 1, "three");
359 ok(hinst
, !r
, "got %u\n", r
);
361 r
= MsiRecordSetInteger(rec2
, 2, 3);
362 ok(hinst
, !r
, "got %u\n", r
);
364 r
= MsiRecordSetInteger(rec2
, 3, 3);
365 ok(hinst
, !r
, "got %u\n", r
);
367 r
= MsiViewModify(view
, MSIMODIFY_REFRESH
, rec2
);
368 ok(hinst
, !r
, "got %d\n", r
);
371 r
= MsiRecordGetStringA(rec2
, 1, buffer
, &sz
);
372 ok(hinst
, !r
, "got %u\n", r
);
373 ok(hinst
, sz
== strlen(buffer
), "got size %u\n", sz
);
374 ok(hinst
, !strcmp(buffer
, "two"), "got '%s'\n", buffer
);
376 r
= MsiRecordGetInteger(rec2
, 2);
377 ok(hinst
, r
== 2, "got %d\n", r
);
380 r
= MsiRecordReadStream(rec2
, 3, buffer
, &sz
);
381 ok(hinst
, !r
, "got %u\n", r
);
382 ok(hinst
, !memcmp(buffer
, "duo", 3), "wrong data\n");
384 r
= MsiCloseHandle(rec2
);
385 ok(hinst
, !r
, "got %u\n", r
);
387 r
= MsiViewFetch(view
, &rec2
);
388 ok(hinst
, r
== ERROR_NO_MORE_ITEMS
, "got %u\n", r
);
389 ok(hinst
, !rec2
, "got %u\n", rec2
);
391 r
= MsiViewClose(view
);
392 ok(hinst
, !r
, "got %u\n", r
);
394 r
= MsiCloseHandle(view
);
395 ok(hinst
, !r
, "got %u\n", r
);
397 r
= MsiDatabaseOpenViewA(hdb
, "SELECT * FROM `Test` WHERE `Name` = ?", &view
);
398 ok(hinst
, !r
, "got %u\n", r
);
400 rec
= MsiCreateRecord(1);
401 MsiRecordSetStringA(rec
, 1, "one");
403 r
= MsiViewExecute(view
, rec
);
404 ok(hinst
, !r
, "got %u\n", r
);
406 r
= MsiViewFetch(view
, &rec2
);
407 ok(hinst
, !r
, "got %u\n", r
);
409 r
= MsiRecordGetInteger(rec2
, 2);
410 ok(hinst
, r
== 1, "got %d\n", r
);
412 r
= MsiCloseHandle(rec2
);
413 ok(hinst
, !r
, "got %u\n", r
);
415 r
= MsiViewFetch(view
, &rec2
);
416 ok(hinst
, r
== ERROR_NO_MORE_ITEMS
, "got %u\n", r
);
417 ok(hinst
, !rec2
, "got %u\n", rec2
);
419 r
= MsiCloseHandle(rec
);
420 ok(hinst
, !r
, "got %u\n", r
);
422 r
= MsiCloseHandle(view
);
423 ok(hinst
, !r
, "got %u\n", r
);
425 /* test MsiDatabaseGetPrimaryKeys() */
426 r
= MsiDatabaseGetPrimaryKeysA(hdb
, "Test", &rec
);
427 ok(hinst
, !r
, "got %u\n", r
);
429 r
= MsiRecordGetFieldCount(rec
);
430 ok(hinst
, r
== 1, "got %d\n", r
);
433 r
= MsiRecordGetStringA(rec
, 0, buffer
, &sz
);
434 ok(hinst
, !r
, "got %u\n", r
);
435 ok(hinst
, sz
== strlen(buffer
), "got size %u\n", sz
);
436 ok(hinst
, !strcmp(buffer
, "Test"), "got '%s'\n", buffer
);
439 r
= MsiRecordGetStringA(rec
, 1, buffer
, &sz
);
440 ok(hinst
, !r
, "got %u\n", r
);
441 ok(hinst
, sz
== strlen(buffer
), "got size %u\n", sz
);
442 ok(hinst
, !strcmp(buffer
, "Name"), "got '%s'\n", buffer
);
444 r
= MsiCloseHandle(rec
);
445 ok(hinst
, !r
, "got %u\n", r
);
447 r
= MsiGetSummaryInformationA(hdb
, NULL
, 1, NULL
);
448 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
450 r
= MsiGetSummaryInformationA(hdb
, NULL
, 1, &suminfo
);
451 ok(hinst
, !r
, "got %u\n", r
);
453 r
= MsiCloseHandle(suminfo
);
454 ok(hinst
, !r
, "got %u\n", r
);
456 r
= MsiCloseHandle(hdb
);
457 ok(hinst
, !r
, "got %u\n", r
);
460 static void test_doaction(MSIHANDLE hinst
)
464 r
= MsiDoActionA(hinst
, "nested51");
465 ok(hinst
, !r
, "got %u\n", r
);
466 check_prop(hinst
, "nested", "1");
468 r
= MsiDoActionA(hinst
, "nested1");
469 ok(hinst
, !r
, "got %u\n", r
);
470 check_prop(hinst
, "nested", "2");
472 r
= MsiSequenceA(hinst
, NULL
, 0);
473 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
475 r
= MsiSequenceA(hinst
, "TestSequence", 0);
476 ok(hinst
, !r
, "got %u\n", r
);
477 check_prop(hinst
, "nested", "1");
480 UINT WINAPI
nested(MSIHANDLE hinst
)
482 MsiSetPropertyA(hinst
, "nested", "2");
484 return ERROR_SUCCESS
;
487 static void test_targetpath(MSIHANDLE hinst
)
489 static const WCHAR targetdirW
[] = {'T','A','R','G','E','T','D','I','R',0};
490 static const WCHAR xyzW
[] = {'C',':','\\',0};
491 static const WCHAR xyW
[] = {'C',':',0};
497 /* test invalid values */
498 r
= MsiGetTargetPathA(hinst
, NULL
, NULL
, NULL
);
499 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
501 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", NULL
, NULL
);
502 ok(hinst
, !r
, "got %u\n", r
);
504 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", buffer
, NULL
);
505 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
507 /* Returned size is in bytes, not chars, but only for custom actions.
508 * Seems to be a casualty of RPC... */
511 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", NULL
, &sz
);
512 ok(hinst
, !r
, "got %u\n", r
);
513 ok(hinst
, sz
== 6, "got size %u\n", sz
);
517 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", buffer
, &sz
);
518 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
519 ok(hinst
, !strcmp(buffer
, "q"), "got \"%s\"\n", buffer
);
520 ok(hinst
, sz
== 6, "got size %u\n", sz
);
524 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", buffer
, &sz
);
525 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
526 ok(hinst
, !buffer
[0], "got \"%s\"\n", buffer
);
527 ok(hinst
, sz
== 6, "got size %u\n", sz
);
531 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", buffer
, &sz
);
532 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
533 ok(hinst
, !strcmp(buffer
, "C:"), "got \"%s\"\n", buffer
);
534 ok(hinst
, sz
== 6, "got size %u\n", sz
);
538 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", buffer
, &sz
);
539 ok(hinst
, !r
, "got %u\n", r
);
540 ok(hinst
, !strcmp(buffer
, "C:\\"), "got \"%s\"\n", buffer
);
541 ok(hinst
, sz
== 3, "got size %u\n", sz
);
544 r
= MsiGetTargetPathW(hinst
, targetdirW
, NULL
, &sz
);
545 ok(hinst
, !r
, "got %u\n", r
);
546 ok(hinst
, sz
== 3, "got size %u\n", sz
);
550 r
= MsiGetTargetPathW(hinst
, targetdirW
, bufferW
, &sz
);
551 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
552 ok(hinst
, bufferW
[0] == 'q', "got %s\n", dbgstr_w(bufferW
));
553 ok(hinst
, sz
== 3, "got size %u\n", sz
);
557 r
= MsiGetTargetPathW(hinst
, targetdirW
, bufferW
, &sz
);
558 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
559 ok(hinst
, !bufferW
[0], "got %s\n", dbgstr_w(bufferW
));
560 ok(hinst
, sz
== 3, "got size %u\n", sz
);
564 r
= MsiGetTargetPathW(hinst
, targetdirW
, bufferW
, &sz
);
565 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
566 ok(hinst
, !lstrcmpW(bufferW
, xyW
), "got %s\n", dbgstr_w(bufferW
));
567 ok(hinst
, sz
== 3, "got size %u\n", sz
);
571 r
= MsiGetTargetPathW(hinst
, targetdirW
, bufferW
, &sz
);
572 ok(hinst
, !r
, "got %u\n", r
);
573 ok(hinst
, !lstrcmpW(bufferW
, xyzW
), "got %s\n", dbgstr_w(bufferW
));
574 ok(hinst
, sz
== 3, "got size %u\n", sz
);
576 r
= MsiSetTargetPathA(hinst
, NULL
, "C:\\subdir");
577 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
579 r
= MsiSetTargetPathA(hinst
, "TARGETDIR", NULL
);
580 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
582 r
= MsiSetTargetPathA(hinst
, "TARGETDIR", "C:\\subdir");
583 ok(hinst
, !r
, "got %u\n", r
);
586 r
= MsiGetTargetPathA(hinst
, "TARGETDIR", buffer
, &sz
);
587 ok(hinst
, !r
, "got %u\n", r
);
588 ok(hinst
, !strcmp(buffer
, "C:\\subdir\\"), "got \"%s\"\n", buffer
);
590 r
= MsiSetTargetPathA(hinst
, "TARGETDIR", "C:\\");
592 /* test GetSourcePath() */
594 r
= MsiGetSourcePathA(hinst
, NULL
, NULL
, NULL
);
595 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
597 r
= MsiGetSourcePathA(hinst
, "TARGETDIR", NULL
, NULL
);
598 ok(hinst
, !r
, "got %u\n", r
);
600 r
= MsiGetSourcePathA(hinst
, "TARGETDIR", buffer
, NULL
);
601 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
603 /* Returned size is in bytes, not chars, but only for custom actions.
604 * Seems to be a casualty of RPC... */
607 MsiGetSourcePathW(hinst
, targetdirW
, NULL
, &srcsz
);
610 r
= MsiGetSourcePathA(hinst
, "TARGETDIR", NULL
, &sz
);
611 ok(hinst
, !r
, "got %u\n", r
);
612 ok(hinst
, sz
== srcsz
* 2, "got size %u\n", sz
);
616 r
= MsiGetSourcePathA(hinst
, "TARGETDIR", buffer
, &sz
);
617 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
618 ok(hinst
, !strcmp(buffer
, "q"), "got \"%s\"\n", buffer
);
619 ok(hinst
, sz
== srcsz
* 2, "got size %u\n", sz
);
623 r
= MsiGetSourcePathA(hinst
, "TARGETDIR", buffer
, &sz
);
624 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
625 ok(hinst
, !buffer
[0], "got \"%s\"\n", buffer
);
626 ok(hinst
, sz
== srcsz
* 2, "got size %u\n", sz
);
630 r
= MsiGetSourcePathA(hinst
, "TARGETDIR", buffer
, &sz
);
631 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
632 ok(hinst
, strlen(buffer
) == srcsz
- 1, "wrong buffer length %d\n", strlen(buffer
));
633 ok(hinst
, sz
== srcsz
* 2, "got size %u\n", sz
);
637 r
= MsiGetSourcePathA(hinst
, "TARGETDIR", buffer
, &sz
);
638 ok(hinst
, !r
, "got %u\n", r
);
639 ok(hinst
, strlen(buffer
) == srcsz
, "wrong buffer length %d\n", strlen(buffer
));
640 ok(hinst
, sz
== srcsz
, "got size %u\n", sz
);
643 r
= MsiGetSourcePathW(hinst
, targetdirW
, NULL
, &sz
);
644 ok(hinst
, !r
, "got %u\n", r
);
645 ok(hinst
, sz
== srcsz
, "got size %u\n", sz
);
649 r
= MsiGetSourcePathW(hinst
, targetdirW
, bufferW
, &sz
);
650 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
651 ok(hinst
, bufferW
[0] == 'q', "got %s\n", dbgstr_w(bufferW
));
652 ok(hinst
, sz
== srcsz
, "got size %u\n", sz
);
656 r
= MsiGetSourcePathW(hinst
, targetdirW
, bufferW
, &sz
);
657 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
658 ok(hinst
, !bufferW
[0], "got %s\n", dbgstr_w(bufferW
));
659 ok(hinst
, sz
== srcsz
, "got size %u\n", sz
);
663 r
= MsiGetSourcePathW(hinst
, targetdirW
, bufferW
, &sz
);
664 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
665 ok(hinst
, lstrlenW(bufferW
) == srcsz
- 1, "wrong buffer length %d\n", lstrlenW(bufferW
));
666 ok(hinst
, sz
== srcsz
, "got size %u\n", sz
);
670 r
= MsiGetSourcePathW(hinst
, targetdirW
, bufferW
, &sz
);
671 ok(hinst
, !r
, "got %u\n", r
);
672 ok(hinst
, lstrlenW(bufferW
) == srcsz
, "wrong buffer length %d\n", lstrlenW(bufferW
));
673 ok(hinst
, sz
== srcsz
, "got size %u\n", sz
);
676 static void test_misc(MSIHANDLE hinst
)
682 r
= MsiSetMode(hinst
, MSIRUNMODE_REBOOTATEND
, FALSE
);
683 ok(hinst
, !r
, "got %u\n", r
);
685 lang
= MsiGetLanguage(hinst
);
686 ok(hinst
, lang
== 1033, "got %u\n", lang
);
688 check_prop(hinst
, "INSTALLLEVEL", "3");
689 r
= MsiSetInstallLevel(hinst
, 123);
690 ok(hinst
, !r
, "got %u\n", r
);
691 check_prop(hinst
, "INSTALLLEVEL", "123");
692 MsiSetInstallLevel(hinst
, 3);
694 cond
= MsiEvaluateConditionA(hinst
, NULL
);
695 ok(hinst
, cond
== MSICONDITION_NONE
, "got %u\n", cond
);
696 MsiSetPropertyA(hinst
, "condprop", "1");
697 cond
= MsiEvaluateConditionA(hinst
, "condprop = 1");
698 ok(hinst
, cond
== MSICONDITION_TRUE
, "got %u\n", cond
);
701 static void test_feature_states(MSIHANDLE hinst
)
703 INSTALLSTATE state
, action
;
706 /* test feature states */
708 r
= MsiGetFeatureStateA(hinst
, NULL
, &state
, &action
);
709 ok(hinst
, r
== ERROR_UNKNOWN_FEATURE
, "got %u\n", r
);
711 r
= MsiGetFeatureStateA(hinst
, "fake", &state
, &action
);
712 ok(hinst
, r
== ERROR_UNKNOWN_FEATURE
, "got %u\n", r
);
714 r
= MsiGetFeatureStateA(hinst
, "One", NULL
, &action
);
715 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
717 r
= MsiGetFeatureStateA(hinst
, "One", &state
, NULL
);
718 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
720 r
= MsiGetFeatureStateA(hinst
, "One", &state
, &action
);
721 ok(hinst
, !r
, "got %u\n", r
);
722 ok(hinst
, state
== INSTALLSTATE_ABSENT
, "got state %d\n", state
);
723 ok(hinst
, action
== INSTALLSTATE_LOCAL
, "got action %d\n", action
);
725 r
= MsiSetFeatureStateA(hinst
, NULL
, INSTALLSTATE_ABSENT
);
726 ok(hinst
, r
== ERROR_UNKNOWN_FEATURE
, "got %u\n", r
);
728 r
= MsiSetFeatureStateA(hinst
, "One", INSTALLSTATE_ADVERTISED
);
729 ok(hinst
, !r
, "got %u\n", r
);
731 r
= MsiGetFeatureStateA(hinst
, "One", &state
, &action
);
732 ok(hinst
, !r
, "got %u\n", r
);
733 ok(hinst
, action
== INSTALLSTATE_ADVERTISED
, "got action %d\n", action
);
735 r
= MsiSetFeatureStateA(hinst
, "One", INSTALLSTATE_LOCAL
);
736 ok(hinst
, !r
, "got %u\n", r
);
738 r
= MsiGetFeatureStateA(hinst
, "One", &state
, &action
);
739 ok(hinst
, !r
, "got %u\n", r
);
740 ok(hinst
, action
== INSTALLSTATE_LOCAL
, "got action %d\n", action
);
742 /* test component states */
744 r
= MsiGetComponentStateA(hinst
, NULL
, &state
, &action
);
745 ok(hinst
, r
== ERROR_UNKNOWN_COMPONENT
, "got %u\n", r
);
747 r
= MsiGetComponentStateA(hinst
, "fake", &state
, &action
);
748 ok(hinst
, r
== ERROR_UNKNOWN_COMPONENT
, "got %u\n", r
);
750 r
= MsiGetComponentStateA(hinst
, "One", NULL
, &action
);
751 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
753 r
= MsiGetComponentStateA(hinst
, "One", &state
, NULL
);
754 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
756 r
= MsiGetComponentStateA(hinst
, "One", &state
, &action
);
757 ok(hinst
, !r
, "got %u\n", r
);
758 ok(hinst
, state
== INSTALLSTATE_ABSENT
, "got state %d\n", state
);
759 ok(hinst
, action
== INSTALLSTATE_LOCAL
, "got action %d\n", action
);
761 r
= MsiGetComponentStateA(hinst
, "dangler", &state
, &action
);
762 ok(hinst
, !r
, "got %u\n", r
);
763 ok(hinst
, state
== INSTALLSTATE_ABSENT
, "got state %d\n", state
);
764 ok(hinst
, action
== INSTALLSTATE_UNKNOWN
, "got action %d\n", action
);
766 r
= MsiGetComponentStateA(hinst
, "component", &state
, &action
);
767 ok(hinst
, !r
, "got %u\n", r
);
768 ok(hinst
, state
== INSTALLSTATE_UNKNOWN
, "got state %d\n", state
);
769 ok(hinst
, action
== INSTALLSTATE_LOCAL
, "got action %d\n", action
);
771 r
= MsiSetComponentStateA(hinst
, NULL
, INSTALLSTATE_ABSENT
);
772 ok(hinst
, r
== ERROR_UNKNOWN_COMPONENT
, "got %u\n", r
);
774 r
= MsiSetComponentStateA(hinst
, "One", INSTALLSTATE_SOURCE
);
775 ok(hinst
, !r
, "got %u\n", r
);
777 r
= MsiGetComponentStateA(hinst
, "One", &state
, &action
);
778 ok(hinst
, !r
, "got %u\n", r
);
779 ok(hinst
, state
== INSTALLSTATE_ABSENT
, "got state %d\n", state
);
780 ok(hinst
, action
== INSTALLSTATE_SOURCE
, "got action %d\n", action
);
782 r
= MsiSetComponentStateA(hinst
, "One", INSTALLSTATE_LOCAL
);
783 ok(hinst
, !r
, "got %u\n", r
);
785 r
= MsiGetComponentStateA(hinst
, "One", &state
, &action
);
786 ok(hinst
, !r
, "got %u\n", r
);
787 ok(hinst
, state
== INSTALLSTATE_ABSENT
, "got state %d\n", state
);
788 ok(hinst
, action
== INSTALLSTATE_LOCAL
, "got action %d\n", action
);
791 static void test_format_record(MSIHANDLE hinst
)
793 static const WCHAR xyzW
[] = {'f','o','o',' ','1','2','3',0};
794 static const WCHAR xyW
[] = {'f','o','o',' ','1','2',0};
801 r
= MsiFormatRecordA(hinst
, 0, NULL
, NULL
);
802 ok(hinst
, r
== ERROR_INVALID_HANDLE
, "got %u\n", r
);
804 rec
= MsiCreateRecord(1);
805 MsiRecordSetStringA(rec
, 0, "foo [1]");
806 MsiRecordSetInteger(rec
, 1, 123);
808 r
= MsiFormatRecordA(hinst
, rec
, NULL
, NULL
);
809 ok(hinst
, !r
, "got %u\n", r
);
811 r
= MsiFormatRecordA(hinst
, rec
, buffer
, NULL
);
812 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
814 /* Returned size is in bytes, not chars, but only for custom actions. */
817 r
= MsiFormatRecordA(hinst
, rec
, NULL
, &sz
);
818 ok(hinst
, !r
, "got %u\n", r
);
819 ok(hinst
, sz
== 14, "got size %u\n", sz
);
823 r
= MsiFormatRecordA(hinst
, rec
, buffer
, &sz
);
824 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
825 ok(hinst
, !strcmp(buffer
, "q"), "got \"%s\"\n", buffer
);
826 ok(hinst
, sz
== 14, "got size %u\n", sz
);
830 r
= MsiFormatRecordA(hinst
, rec
, buffer
, &sz
);
831 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
832 ok(hinst
, !buffer
[0], "got \"%s\"\n", buffer
);
833 ok(hinst
, sz
== 14, "got size %u\n", sz
);
837 r
= MsiFormatRecordA(hinst
, rec
, buffer
, &sz
);
838 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
839 ok(hinst
, !strcmp(buffer
, "foo 12"), "got \"%s\"\n", buffer
);
840 ok(hinst
, sz
== 14, "got size %u\n", sz
);
844 r
= MsiFormatRecordA(hinst
, rec
, buffer
, &sz
);
845 ok(hinst
, !r
, "got %u\n", r
);
846 ok(hinst
, !strcmp(buffer
, "foo 123"), "got \"%s\"\n", buffer
);
847 ok(hinst
, sz
== 7, "got size %u\n", sz
);
849 r
= MsiFormatRecordW(hinst
, rec
, NULL
, NULL
);
850 ok(hinst
, !r
, "got %u\n", r
);
852 r
= MsiFormatRecordW(hinst
, rec
, bufferW
, NULL
);
853 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
856 r
= MsiFormatRecordW(hinst
, rec
, NULL
, &sz
);
857 ok(hinst
, !r
, "got %u\n", r
);
858 ok(hinst
, sz
== 7, "got size %u\n", sz
);
862 r
= MsiFormatRecordW(hinst
, rec
, bufferW
, &sz
);
863 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
864 ok(hinst
, bufferW
[0] == 'q', "got %s\n", dbgstr_w(bufferW
));
865 ok(hinst
, sz
== 7, "got size %u\n", sz
);
869 r
= MsiFormatRecordW(hinst
, rec
, bufferW
, &sz
);
870 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
871 ok(hinst
, !bufferW
[0], "got %s\n", dbgstr_w(bufferW
));
872 ok(hinst
, sz
== 7, "got size %u\n", sz
);
876 r
= MsiFormatRecordW(hinst
, rec
, bufferW
, &sz
);
877 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
878 ok(hinst
, !lstrcmpW(bufferW
, xyW
), "got %s\n", dbgstr_w(bufferW
));
879 ok(hinst
, sz
== 7, "got size %u\n", sz
);
883 r
= MsiFormatRecordW(hinst
, rec
, bufferW
, &sz
);
884 ok(hinst
, !r
, "got %u\n", r
);
885 ok(hinst
, !lstrcmpW(bufferW
, xyzW
), "got %s\n", dbgstr_w(bufferW
));
886 ok(hinst
, sz
== 7, "got size %u\n", sz
);
888 /* check that properties work */
889 MsiSetPropertyA(hinst
, "fmtprop", "foobar");
890 MsiRecordSetStringA(rec
, 0, "[fmtprop]");
892 r
= MsiFormatRecordA(hinst
, rec
, buffer
, &sz
);
893 ok(hinst
, !r
, "got %u\n", r
);
894 ok(hinst
, !strcmp(buffer
, "foobar"), "got \"%s\"\n", buffer
);
895 ok(hinst
, sz
== 6, "got size %u\n", sz
);
900 static void test_costs(MSIHANDLE hinst
)
902 static const WCHAR oneW
[] = {'O','n','e',0};
903 static const WCHAR xyzW
[] = {'C',':',0};
904 static const WCHAR xyW
[] = {'C',0};
912 r
= MsiGetFeatureCostA(hinst
, NULL
, MSICOSTTREE_CHILDREN
, INSTALLSTATE_LOCAL
, &cost
);
913 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
915 ok(hinst
, !cost
, "got %d\n", cost
);
917 r
= MsiGetFeatureCostA(hinst
, "One", MSICOSTTREE_CHILDREN
, INSTALLSTATE_LOCAL
, NULL
);
918 ok(hinst
, r
== RPC_X_NULL_REF_POINTER
, "got %u\n", r
);
921 r
= MsiGetFeatureCostA(hinst
, "One", MSICOSTTREE_CHILDREN
, INSTALLSTATE_LOCAL
, &cost
);
922 ok(hinst
, !r
, "got %u\n", r
);
924 ok(hinst
, cost
== 8, "got %d\n", cost
);
926 sz
= cost
= temp
= 0xdead;
927 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, NULL
, &sz
, &cost
, &temp
);
928 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
929 ok(hinst
, sz
== 0xdead, "got size %d\n", sz
);
930 ok(hinst
, cost
== 0xdead, "got cost %d\n", cost
);
931 ok(hinst
, temp
== 0xdead, "got temp %d\n", temp
);
933 cost
= temp
= 0xdead;
934 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, NULL
, &cost
, &temp
);
935 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
936 ok(hinst
, cost
== 0xdead, "got cost %d\n", cost
);
937 ok(hinst
, temp
== 0xdead, "got temp %d\n", temp
);
940 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, NULL
, &temp
);
941 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
942 ok(hinst
, sz
== 0xdead, "got size %d\n", sz
);
943 ok(hinst
, temp
== 0xdead, "got temp %d\n", temp
);
946 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, &cost
, NULL
);
947 ok(hinst
, r
== ERROR_INVALID_PARAMETER
, "got %u\n", r
);
948 ok(hinst
, sz
== 0xdead, "got size %d\n", sz
);
949 ok(hinst
, cost
== 0xdead, "got cost %d\n", cost
);
951 cost
= temp
= 0xdead;
953 r
= MsiEnumComponentCostsA(hinst
, NULL
, 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, &cost
, &temp
);
954 ok(hinst
, !r
, "got %u\n", r
);
955 ok(hinst
, sz
== 2, "got size %u\n", sz
);
956 ok(hinst
, !strcmp(buffer
, "C:"), "got '%s'\n", buffer
);
957 ok(hinst
, !cost
, "got cost %d\n", cost
);
958 ok(hinst
, temp
&& temp
!= 0xdead, "got temp %d\n", temp
);
960 cost
= temp
= 0xdead;
962 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, &cost
, &temp
);
963 ok(hinst
, !r
, "got %u\n", r
);
964 ok(hinst
, sz
== 2, "got size %u\n", sz
);
965 ok(hinst
, !strcmp(buffer
, "C:"), "got '%s'\n", buffer
);
966 ok(hinst
, cost
== 8, "got cost %d\n", cost
);
967 ok(hinst
, !temp
, "got temp %d\n", temp
);
969 /* same string behaviour */
970 cost
= temp
= 0xdead;
973 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, &cost
, &temp
);
974 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
975 ok(hinst
, !strcmp(buffer
, "q"), "got \"%s\"\n", buffer
);
977 ok(hinst
, sz
== 4, "got size %u\n", sz
);
978 ok(hinst
, cost
== 8, "got cost %d\n", cost
);
979 ok(hinst
, !temp
, "got temp %d\n", temp
);
983 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, &cost
, &temp
);
984 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
986 ok(hinst
, !buffer
[0], "got \"%s\"\n", buffer
);
987 ok(hinst
, sz
== 4, "got size %u\n", sz
);
992 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, &cost
, &temp
);
993 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
995 ok(hinst
, !strcmp(buffer
, "C"), "got \"%s\"\n", buffer
);
996 ok(hinst
, sz
== 4, "got size %u\n", sz
);
1001 r
= MsiEnumComponentCostsA(hinst
, "One", 0, INSTALLSTATE_LOCAL
, buffer
, &sz
, &cost
, &temp
);
1002 ok(hinst
, !r
, "got %u\n", r
);
1003 ok(hinst
, !strcmp(buffer
, "C:"), "got \"%s\"\n", buffer
);
1004 ok(hinst
, sz
== 2, "got size %u\n", sz
);
1008 r
= MsiEnumComponentCostsW(hinst
, oneW
, 0, INSTALLSTATE_LOCAL
, bufferW
, &sz
, &cost
, &temp
);
1009 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
1010 ok(hinst
, bufferW
[0] == 'q', "got %s\n", dbgstr_w(bufferW
));
1011 ok(hinst
, sz
== 2, "got size %u\n", sz
);
1015 r
= MsiEnumComponentCostsW(hinst
, oneW
, 0, INSTALLSTATE_LOCAL
, bufferW
, &sz
, &cost
, &temp
);
1016 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
1017 ok(hinst
, !bufferW
[0], "got %s\n", dbgstr_w(bufferW
));
1018 ok(hinst
, sz
== 2, "got size %u\n", sz
);
1022 r
= MsiEnumComponentCostsW(hinst
, oneW
, 0, INSTALLSTATE_LOCAL
, bufferW
, &sz
, &cost
, &temp
);
1023 ok(hinst
, r
== ERROR_MORE_DATA
, "got %u\n", r
);
1024 ok(hinst
, !lstrcmpW(bufferW
, xyW
), "got %s\n", dbgstr_w(bufferW
));
1025 ok(hinst
, sz
== 2, "got size %u\n", sz
);
1029 r
= MsiEnumComponentCostsW(hinst
, oneW
, 0, INSTALLSTATE_LOCAL
, bufferW
, &sz
, &cost
, &temp
);
1030 ok(hinst
, !r
, "got %u\n", r
);
1031 ok(hinst
, !lstrcmpW(bufferW
, xyzW
), "got %s\n", dbgstr_w(bufferW
));
1032 ok(hinst
, sz
== 2, "got size %u\n", sz
);
1035 /* Main test. Anything that doesn't depend on a specific install configuration
1036 * or have undesired side effects should go here. */
1037 UINT WINAPI
main_test(MSIHANDLE hinst
)
1040 IUnknown
*unk
= NULL
;
1043 /* Test for an MTA apartment */
1044 hr
= CoCreateInstance(&CLSID_XMLDocument
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&unk
);
1045 ok(hinst
, hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1047 if (unk
) IUnknown_Release(unk
);
1049 /* but ours is uninitialized */
1050 hr
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1051 ok(hinst
, hr
== S_OK
, "got %#x\n", hr
);
1054 /* Test MsiGetDatabaseState() */
1055 res
= MsiGetDatabaseState(hinst
);
1057 ok(hinst
, res
== MSIDBSTATE_ERROR
, "expected MSIDBSTATE_ERROR, got %u\n", res
);
1061 test_doaction(hinst
);
1062 test_targetpath(hinst
);
1064 test_feature_states(hinst
);
1065 test_format_record(hinst
);
1068 return ERROR_SUCCESS
;
1071 UINT WINAPI
test_retval(MSIHANDLE hinst
)
1074 DWORD len
= sizeof(prop
);
1077 MsiGetPropertyA(hinst
, "TEST_RETVAL", prop
, &len
);
1078 sscanf(prop
, "%u", &retval
);
1082 static void append_file(MSIHANDLE hinst
, const char *filename
, const char *text
)
1085 HANDLE file
= CreateFileA(filename
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
1086 ok(hinst
, file
!= INVALID_HANDLE_VALUE
, "CreateFile failed, error %u\n", GetLastError());
1088 SetFilePointer(file
, 0, NULL
, FILE_END
);
1089 WriteFile(file
, text
, strlen(text
), &size
, NULL
);
1093 UINT WINAPI
da_immediate(MSIHANDLE hinst
)
1096 DWORD len
= sizeof(prop
);
1098 MsiGetPropertyA(hinst
, "TESTPATH", prop
, &len
);
1100 append_file(hinst
, prop
, "one");
1102 ok(hinst
, !MsiGetMode(hinst
, MSIRUNMODE_SCHEDULED
), "shouldn't be scheduled\n");
1103 ok(hinst
, !MsiGetMode(hinst
, MSIRUNMODE_ROLLBACK
), "shouldn't be rollback\n");
1104 ok(hinst
, !MsiGetMode(hinst
, MSIRUNMODE_COMMIT
), "shouldn't be commit\n");
1106 return ERROR_SUCCESS
;
1109 UINT WINAPI
da_deferred(MSIHANDLE hinst
)
1112 DWORD len
= sizeof(prop
);
1116 /* Test that we were in fact deferred */
1117 r
= MsiGetPropertyA(hinst
, "CustomActionData", prop
, &len
);
1118 ok(hinst
, r
== ERROR_SUCCESS
, "got %u\n", r
);
1119 ok(hinst
, prop
[0], "CustomActionData was empty\n");
1121 append_file(hinst
, prop
, "two");
1123 /* Test available properties */
1125 r
= MsiGetPropertyA(hinst
, "ProductCode", prop
, &len
);
1126 ok(hinst
, r
== ERROR_SUCCESS
, "got %u\n", r
);
1127 ok(hinst
, prop
[0], "got %s\n", prop
);
1130 r
= MsiGetPropertyA(hinst
, "UserSID", prop
, &len
);
1131 ok(hinst
, r
== ERROR_SUCCESS
, "got %u\n", r
);
1132 ok(hinst
, prop
[0], "got %s\n", prop
);
1135 r
= MsiGetPropertyA(hinst
, "TESTPATH", prop
, &len
);
1136 ok(hinst
, r
== ERROR_SUCCESS
, "got %u\n", r
);
1138 ok(hinst
, !prop
[0], "got %s\n", prop
);
1141 ok(hinst
, MsiGetMode(hinst
, MSIRUNMODE_SCHEDULED
), "should be scheduled\n");
1142 ok(hinst
, !MsiGetMode(hinst
, MSIRUNMODE_ROLLBACK
), "shouldn't be rollback\n");
1143 ok(hinst
, !MsiGetMode(hinst
, MSIRUNMODE_COMMIT
), "shouldn't be commit\n");
1145 lang
= MsiGetLanguage(hinst
);
1146 ok(hinst
, lang
!= ERROR_INVALID_HANDLE
, "MsiGetLanguage failed\n");
1148 return ERROR_SUCCESS
;
1151 static BOOL
pf_exists(const char *file
)
1153 char path
[MAX_PATH
];
1155 if (FAILED(SHGetFolderPathA(NULL
, CSIDL_PROGRAM_FILESX86
, NULL
, 0, path
)))
1156 SHGetFolderPathA(NULL
, CSIDL_PROGRAM_FILES
, NULL
, 0, path
);
1159 return GetFileAttributesA(path
) != INVALID_FILE_ATTRIBUTES
;
1162 UINT WINAPI
cf_present(MSIHANDLE hinst
)
1164 todo_wine_if(!MsiGetMode(hinst
, MSIRUNMODE_SCHEDULED
)) {
1165 ok(hinst
, pf_exists("msitest\\first"), "folder absent\n");
1166 ok(hinst
, pf_exists("msitest\\second"), "folder absent\n");
1167 ok(hinst
, pf_exists("msitest\\third"), "folder absent\n");
1169 return ERROR_SUCCESS
;
1172 UINT WINAPI
cf_absent(MSIHANDLE hinst
)
1174 todo_wine_if(!MsiGetMode(hinst
, MSIRUNMODE_SCHEDULED
)) {
1175 ok(hinst
, !pf_exists("msitest\\first"), "folder present\n");
1176 ok(hinst
, !pf_exists("msitest\\second"), "folder present\n");
1177 ok(hinst
, !pf_exists("msitest\\third"), "folder present\n");
1179 return ERROR_SUCCESS
;
1182 UINT WINAPI
crs_present(MSIHANDLE hinst
)
1184 todo_wine_if(!MsiGetMode(hinst
, MSIRUNMODE_SCHEDULED
))
1185 ok(hinst
, pf_exists("msitest\\shortcut.lnk"), "shortcut absent\n");
1186 return ERROR_SUCCESS
;
1189 UINT WINAPI
crs_absent(MSIHANDLE hinst
)
1191 todo_wine_if(!MsiGetMode(hinst
, MSIRUNMODE_SCHEDULED
))
1192 ok(hinst
, !pf_exists("msitest\\shortcut.lnk"), "shortcut present\n");
1193 return ERROR_SUCCESS
;