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