1 /* 2 * Copyright (C) 2007 Mike McCormack for CodeWeavers 3 * Copyright (C) 2007 Misha Koshelev 4 * 5 * A test program for Microsoft Installer OLE automation functionality. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define COBJMACROS 23 24 #include <stdio.h> 25 26 #include <initguid.h> 27 #include <windows.h> 28 #include <msiquery.h> 29 #include <msidefs.h> 30 #include <msi.h> 31 #include <fci.h> 32 #include <oaidl.h> 33 34 #include "wine/test.h" 35 36 #ifdef __REACTOS__ 37 #include "ole2.h" 38 #endif 39 40 static BOOL is_wow64; 41 42 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD); 43 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); 44 45 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); 46 47 static const char *msifile = "winetest-automation.msi"; 48 static FILETIME systemtime; 49 static CHAR CURR_DIR[MAX_PATH]; 50 static EXCEPINFO excepinfo; 51 52 /* 53 * OLE automation data 54 **/ 55 static IDispatch *pInstaller; 56 57 /* msi database data */ 58 59 static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" 60 "s72\tS38\ts72\ti2\tS255\tS72\n" 61 "Component\tComponent\n" 62 "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n" 63 "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n" 64 "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n" 65 "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n" 66 "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n" 67 "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n" 68 "component\t\tMSITESTDIR\t0\t1\tfile\n"; 69 70 static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n" 71 "s72\tS72\tl255\n" 72 "Directory\tDirectory\n" 73 "CABOUTDIR\tMSITESTDIR\tcabout\n" 74 "CHANGEDDIR\tMSITESTDIR\tchanged:second\n" 75 "FIRSTDIR\tMSITESTDIR\tfirst\n" 76 "MSITESTDIR\tProgramFilesFolder\tmsitest\n" 77 "NEWDIR\tCABOUTDIR\tnew\n" 78 "ProgramFilesFolder\tTARGETDIR\t.\n" 79 "TARGETDIR\t\tSourceDir\n"; 80 81 static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n" 82 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n" 83 "Feature\tFeature\n" 84 "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n" 85 "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n" 86 "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n" 87 "Three\tOne\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n" 88 "Two\tOne\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n" 89 "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"; 90 91 static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n" 92 "s38\ts72\n" 93 "FeatureComponents\tFeature_\tComponent_\n" 94 "Five\tFive\n" 95 "Four\tFour\n" 96 "One\tOne\n" 97 "Three\tThree\n" 98 "Two\tTwo\n" 99 "feature\tcomponent\n"; 100 101 static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n" 102 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n" 103 "File\tFile\n" 104 "five.txt\tFive\tfive.txt\t1000\t\t\t0\t5\n" 105 "four.txt\tFour\tfour.txt\t1000\t\t\t0\t4\n" 106 "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n" 107 "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n" 108 "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n" 109 "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"; 110 111 static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n" 112 "s72\tS255\tI2\n" 113 "InstallExecuteSequence\tAction\n" 114 "AllocateRegistrySpace\tNOT Installed\t1550\n" 115 "CostFinalize\t\t1000\n" 116 "CostInitialize\t\t800\n" 117 "FileCost\t\t900\n" 118 "InstallFiles\t\t4000\n" 119 "RegisterProduct\t\t6100\n" 120 "PublishProduct\t\t6400\n" 121 "InstallFinalize\t\t6600\n" 122 "InstallInitialize\t\t1500\n" 123 "InstallValidate\t\t1400\n" 124 "LaunchConditions\t\t100\n" 125 "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000\n"; 126 127 static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n" 128 "i2\ti4\tL64\tS255\tS32\tS72\n" 129 "Media\tDiskId\n" 130 "1\t5\t\t\tDISK1\t\n"; 131 132 static const CHAR property_dat[] = "Property\tValue\n" 133 "s72\tl0\n" 134 "Property\tProperty\n" 135 "DefaultUIFont\tDlgFont8\n" 136 "HASUIRUN\t0\n" 137 "INSTALLLEVEL\t3\n" 138 "InstallMode\tTypical\n" 139 "Manufacturer\tWine\n" 140 "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n" 141 "ProductCode\t{837450fa-a39b-4bc8-b321-08b393f784b3}\n" 142 "ProductID\tnone\n" 143 "ProductLanguage\t1033\n" 144 "ProductName\tMSITEST\n" 145 "ProductVersion\t1.1.1\n" 146 "PROMPTROLLBACKCOST\tP\n" 147 "Setup\tSetup\n" 148 "UpgradeCode\t{CE067E8D-2E1A-4367-B734-4EB2BDAD6565}\n" 149 "MSIFASTINSTALL\t1\n"; 150 151 static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n" 152 "s72\ti2\tl255\tL255\tL0\ts72\n" 153 "Registry\tRegistry\n" 154 "Apples\t1\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n" 155 "Oranges\t1\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n" 156 "regdata\t1\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n" 157 "OrderTest\t1\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent\n"; 158 159 typedef struct _msi_table 160 { 161 const CHAR *filename; 162 const CHAR *data; 163 int size; 164 } msi_table; 165 166 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)} 167 168 static const msi_table tables[] = 169 { 170 ADD_TABLE(component), 171 ADD_TABLE(directory), 172 ADD_TABLE(feature), 173 ADD_TABLE(feature_comp), 174 ADD_TABLE(file), 175 ADD_TABLE(install_exec_seq), 176 ADD_TABLE(media), 177 ADD_TABLE(property), 178 ADD_TABLE(registry) 179 }; 180 181 typedef struct _msi_summary_info 182 { 183 UINT property; 184 UINT datatype; 185 INT iValue; 186 FILETIME *pftValue; 187 const CHAR *szValue; 188 } msi_summary_info; 189 190 #define ADD_INFO_I2(property, iValue) {property, VT_I2, iValue, NULL, NULL} 191 #define ADD_INFO_I4(property, iValue) {property, VT_I4, iValue, NULL, NULL} 192 #define ADD_INFO_LPSTR(property, szValue) {property, VT_LPSTR, 0, NULL, szValue} 193 #define ADD_INFO_FILETIME(property, pftValue) {property, VT_FILETIME, 0, pftValue, NULL} 194 195 static const msi_summary_info summary_info[] = 196 { 197 ADD_INFO_LPSTR(PID_TEMPLATE, ";1033"), 198 ADD_INFO_LPSTR(PID_REVNUMBER, "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}"), 199 ADD_INFO_I4(PID_PAGECOUNT, 100), 200 ADD_INFO_I4(PID_WORDCOUNT, 0), 201 ADD_INFO_FILETIME(PID_CREATE_DTM, &systemtime), 202 ADD_INFO_FILETIME(PID_LASTPRINTED, &systemtime) 203 }; 204 205 static void init_functionpointers(void) 206 { 207 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll"); 208 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); 209 210 #define GET_PROC(dll, func) \ 211 p ## func = (void *)GetProcAddress(dll, #func); \ 212 if(!p ## func) \ 213 trace("GetProcAddress(%s) failed\n", #func); 214 215 GET_PROC(hadvapi32, RegDeleteKeyExA) 216 GET_PROC(hkernel32, IsWow64Process) 217 218 #undef GET_PROC 219 } 220 221 static BOOL is_process_limited(void) 222 { 223 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; 224 PSID Group = NULL; 225 BOOL IsInGroup; 226 HANDLE token; 227 228 if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, 229 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) || 230 !CheckTokenMembership(NULL, Group, &IsInGroup)) 231 { 232 trace("Could not check if the current user is an administrator\n"); 233 FreeSid(Group); 234 return FALSE; 235 } 236 FreeSid(Group); 237 238 if (!IsInGroup) 239 { 240 /* Only administrators have enough privileges for these tests */ 241 return TRUE; 242 } 243 244 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) 245 { 246 BOOL ret; 247 TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault; 248 DWORD size; 249 250 ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size); 251 CloseHandle(token); 252 return (ret && type == TokenElevationTypeLimited); 253 } 254 return FALSE; 255 } 256 257 static LONG delete_key_portable( HKEY key, LPCSTR subkey, REGSAM access ) 258 { 259 if (pRegDeleteKeyExA) 260 return pRegDeleteKeyExA( key, subkey, access, 0 ); 261 return RegDeleteKeyA( key, subkey ); 262 } 263 264 /* 265 * Database Helpers 266 */ 267 268 static void write_file(const CHAR *filename, const char *data, int data_size) 269 { 270 DWORD size; 271 272 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL, 273 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 274 WriteFile(hf, data, data_size, &size, NULL); 275 CloseHandle(hf); 276 } 277 278 static void write_msi_summary_info(MSIHANDLE db, const msi_summary_info *info, int num_info) 279 { 280 MSIHANDLE summary; 281 UINT r; 282 int j; 283 284 r = MsiGetSummaryInformationA(db, NULL, num_info, &summary); 285 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 286 287 /* import summary information into the stream */ 288 for (j = 0; j < num_info; j++) 289 { 290 const msi_summary_info *entry = &info[j]; 291 292 r = MsiSummaryInfoSetPropertyA(summary, entry->property, entry->datatype, 293 entry->iValue, entry->pftValue, entry->szValue); 294 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 295 } 296 297 /* write the summary changes back to the stream */ 298 r = MsiSummaryInfoPersist(summary); 299 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 300 301 MsiCloseHandle(summary); 302 } 303 304 static void create_database(const CHAR *name, const msi_table *tables, int num_tables, 305 const msi_summary_info *info, int num_info) 306 { 307 MSIHANDLE db; 308 UINT r; 309 WCHAR *nameW; 310 int j, len; 311 312 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 ); 313 if (!(nameW = malloc( len * sizeof(WCHAR) ))) return; 314 MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len ); 315 316 r = MsiOpenDatabaseW(nameW, MSIDBOPEN_CREATE, &db); 317 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 318 319 /* import the tables into the database */ 320 for (j = 0; j < num_tables; j++) 321 { 322 const msi_table *table = &tables[j]; 323 324 write_file(table->filename, table->data, (table->size - 1) * sizeof(char)); 325 326 r = MsiDatabaseImportA(db, CURR_DIR, table->filename); 327 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 328 329 DeleteFileA(table->filename); 330 } 331 332 write_msi_summary_info(db, info, num_info); 333 334 r = MsiDatabaseCommit(db); 335 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 336 337 MsiCloseHandle(db); 338 free( nameW ); 339 } 340 341 static BOOL create_package(LPWSTR path) 342 { 343 DWORD len; 344 345 /* Prepare package */ 346 create_database(msifile, tables, ARRAY_SIZE(tables), summary_info, ARRAY_SIZE(summary_info)); 347 348 len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, 349 CURR_DIR, -1, path, MAX_PATH); 350 ok(len, "MultiByteToWideChar returned error %lu\n", GetLastError()); 351 if (!len) 352 return FALSE; 353 354 lstrcatW(path, L"\\winetest-automation.msi"); 355 return TRUE; 356 } 357 358 /* 359 * Installation helpers 360 */ 361 362 static char PROG_FILES_DIR[MAX_PATH]; 363 364 static BOOL get_program_files_dir(LPSTR buf) 365 { 366 HKEY hkey; 367 DWORD type = REG_EXPAND_SZ, size; 368 369 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey)) 370 return FALSE; 371 372 size = MAX_PATH; 373 if (RegQueryValueExA(hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)buf, &size) && 374 RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size)) 375 return FALSE; 376 377 RegCloseKey(hkey); 378 return TRUE; 379 } 380 381 static void create_file(const CHAR *name, DWORD size) 382 { 383 HANDLE file; 384 DWORD written, left; 385 386 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 387 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name); 388 WriteFile(file, name, strlen(name), &written, NULL); 389 WriteFile(file, "\n", strlen("\n"), &written, NULL); 390 391 left = size - lstrlenA(name) - 1; 392 393 SetFilePointer(file, left, NULL, FILE_CURRENT); 394 SetEndOfFile(file); 395 396 CloseHandle(file); 397 } 398 399 static void create_test_files(void) 400 { 401 CreateDirectoryA("msitest", NULL); 402 create_file("msitest\\one.txt", 100); 403 CreateDirectoryA("msitest\\first", NULL); 404 create_file("msitest\\first\\two.txt", 100); 405 CreateDirectoryA("msitest\\second", NULL); 406 create_file("msitest\\second\\three.txt", 100); 407 CreateDirectoryA("msitest\\cabout",NULL); 408 create_file("msitest\\cabout\\four.txt", 100); 409 CreateDirectoryA("msitest\\cabout\\new",NULL); 410 create_file("msitest\\cabout\\new\\five.txt", 100); 411 create_file("msitest\\filename", 100); 412 } 413 414 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file) 415 { 416 CHAR path[MAX_PATH]; 417 418 lstrcpyA(path, PROG_FILES_DIR); 419 lstrcatA(path, "\\"); 420 lstrcatA(path, rel_path); 421 422 if (is_file) 423 return DeleteFileA(path); 424 else 425 return RemoveDirectoryA(path); 426 } 427 428 static void delete_test_files(void) 429 { 430 DeleteFileA(msifile); 431 DeleteFileA("msitest\\cabout\\new\\five.txt"); 432 DeleteFileA("msitest\\cabout\\four.txt"); 433 DeleteFileA("msitest\\second\\three.txt"); 434 DeleteFileA("msitest\\first\\two.txt"); 435 DeleteFileA("msitest\\one.txt"); 436 DeleteFileA("msitest\\filename"); 437 RemoveDirectoryA("msitest\\cabout\\new"); 438 RemoveDirectoryA("msitest\\cabout"); 439 RemoveDirectoryA("msitest\\second"); 440 RemoveDirectoryA("msitest\\first"); 441 RemoveDirectoryA("msitest"); 442 } 443 444 /* 445 * Automation helpers and tests 446 */ 447 448 /* ok-like statement which takes two unicode strings or one unicode and one ANSI string as arguments */ 449 static CHAR string1[MAX_PATH], string2[MAX_PATH]; 450 451 #define ok_w2(format, szString1, szString2) \ 452 \ 453 do { \ 454 WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \ 455 WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \ 456 if (lstrcmpA(string1, string2) != 0) \ 457 ok(0, format, string1, string2); \ 458 } while(0); 459 460 #define ok_w2n(format, szString1, szString2, len) \ 461 \ 462 if (memcmp(szString1, szString2, len * sizeof(WCHAR)) != 0) \ 463 { \ 464 WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \ 465 WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \ 466 ok(0, format, string1, string2); \ 467 } 468 469 #define ok_aw(format, aString, wString) \ 470 \ 471 WideCharToMultiByte(CP_ACP, 0, wString, -1, string1, MAX_PATH, NULL, NULL); \ 472 if (lstrcmpA(string1, aString) != 0) \ 473 ok(0, format, string1, aString); \ 474 475 #define ok_awplus(format, extra, aString, wString) \ 476 \ 477 WideCharToMultiByte(CP_ACP, 0, wString, -1, string1, MAX_PATH, NULL, NULL); \ 478 if (lstrcmpA(string1, aString) != 0) \ 479 ok(0, format, extra, string1, aString); \ 480 481 /* exception checker */ 482 #define ok_exception(hr, szDescription) \ 483 if (hr == DISP_E_EXCEPTION) \ 484 { \ 485 /* Compare wtype, source, and destination */ \ 486 ok(excepinfo.wCode == 1000, "Exception info was %d, expected 1000\n", excepinfo.wCode); \ 487 \ 488 ok(excepinfo.bstrSource != NULL, "Exception source was NULL\n"); \ 489 if (excepinfo.bstrSource) \ 490 ok_w2("Exception source was \"%s\" but expected to be \"%s\"\n", excepinfo.bstrSource, L"Msi API Error"); \ 491 \ 492 ok(excepinfo.bstrDescription != NULL, "Exception description was NULL\n"); \ 493 if (excepinfo.bstrDescription) \ 494 ok_w2("Exception description was \"%s\" but expected to be \"%s\"\n", excepinfo.bstrDescription, szDescription); \ 495 \ 496 SysFreeString(excepinfo.bstrSource); \ 497 SysFreeString(excepinfo.bstrDescription); \ 498 SysFreeString(excepinfo.bstrHelpFile); \ 499 } 500 501 static DISPID get_dispid( IDispatch *disp, const char *name ) 502 { 503 LPOLESTR str; 504 UINT len; 505 DISPID id = -1; 506 HRESULT r; 507 508 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 ); 509 str = malloc( len * sizeof(WCHAR) ); 510 if (str) 511 { 512 MultiByteToWideChar(CP_ACP, 0, name, -1, str, len ); 513 r = IDispatch_GetIDsOfNames( disp, &IID_NULL, &str, 1, 0, &id ); 514 free( str ); 515 if (r != S_OK) 516 return -1; 517 } 518 519 return id; 520 } 521 522 typedef struct { 523 DISPID did; 524 const char *name; 525 BOOL todo; 526 } get_did_t; 527 528 static const get_did_t get_did_data[] = { 529 { 1, "CreateRecord" }, 530 { 2, "OpenPackage" }, 531 { 3, "OpenProduct" }, 532 { 4, "OpenDatabase" }, 533 { 5, "SummaryInformation" }, 534 { 6, "UILevel" }, 535 { 7, "EnableLog" }, 536 { 8, "InstallProduct" }, 537 { 9, "Version" }, 538 { 10, "LastErrorRecord" }, 539 { 11, "RegistryValue" }, 540 { 12, "Environment" }, 541 { 13, "FileAttributes" }, 542 { 15, "FileSize" }, 543 { 16, "FileVersion" }, 544 { 17, "ProductState" }, 545 { 18, "ProductInfo" }, 546 { 19, "ConfigureProduct", TRUE }, 547 { 20, "ReinstallProduct", TRUE }, 548 { 21, "CollectUserInfo", TRUE }, 549 { 22, "ApplyPatch", TRUE }, 550 { 23, "FeatureParent", TRUE }, 551 { 24, "FeatureState", TRUE }, 552 { 25, "UseFeature", TRUE }, 553 { 26, "FeatureUsageCount", TRUE }, 554 { 27, "FeatureUsageDate", TRUE }, 555 { 28, "ConfigureFeature", TRUE }, 556 { 29, "ReinstallFeature", TRUE }, 557 { 30, "ProvideComponent", TRUE }, 558 { 31, "ComponentPath", TRUE }, 559 { 32, "ProvideQualifiedComponent", TRUE }, 560 { 33, "QualifierDescription", TRUE }, 561 { 34, "ComponentQualifiers", TRUE }, 562 { 35, "Products" }, 563 { 36, "Features", TRUE }, 564 { 37, "Components", TRUE }, 565 { 38, "ComponentClients", TRUE }, 566 { 39, "Patches", TRUE }, 567 { 40, "RelatedProducts" }, 568 { 41, "PatchInfo", TRUE }, 569 { 42, "PatchTransforms", TRUE }, 570 { 43, "AddSource", TRUE }, 571 { 44, "ClearSourceList", TRUE }, 572 { 45, "ForceSourceListResolution", TRUE }, 573 { 46, "ShortcutTarget", TRUE }, 574 { 47, "FileHash", TRUE }, 575 { 48, "FileSignatureInfo", TRUE }, 576 { 0 } 577 }; 578 579 static void test_dispid(void) 580 { 581 const get_did_t *ptr = get_did_data; 582 DISPID dispid; 583 584 while (ptr->name) 585 { 586 dispid = get_dispid(pInstaller, ptr->name); 587 todo_wine_if (ptr->todo) 588 ok(dispid == ptr->did, "%s: expected %ld, got %ld\n", ptr->name, ptr->did, dispid); 589 ptr++; 590 } 591 592 dispid = get_dispid(pInstaller, "RemovePatches"); 593 ok(dispid == 49 || dispid == -1, "Expected 49 or -1, got %ld\n", dispid); 594 dispid = get_dispid(pInstaller, "ApplyMultiplePatches"); 595 ok(dispid == 51 || dispid == -1, "Expected 51 or -1, got %ld\n", dispid); 596 dispid = get_dispid(pInstaller, "ProductsEx"); 597 ok(dispid == 52 || dispid == -1, "Expected 52 or -1, got %ld\n", dispid); 598 dispid = get_dispid(pInstaller, "PatchesEx"); 599 ok(dispid == 55 || dispid == -1, "Expected 55 or -1, got %ld\n", dispid); 600 dispid = get_dispid(pInstaller, "ExtractPatchXMLData"); 601 ok(dispid == 57 || dispid == -1, "Expected 57 or -1, got %ld\n", dispid); 602 dispid = get_dispid( pInstaller, "ProductElevated" ); 603 ok(dispid == 59 || dispid == -1, "Expected 59 or -1, got %ld\n", dispid); 604 dispid = get_dispid( pInstaller, "ProvideAssembly" ); 605 ok(dispid == 60 || dispid == -1, "Expected 60 or -1, got %ld\n", dispid); 606 dispid = get_dispid( pInstaller, "ProductInfoFromScript" ); 607 ok(dispid == 61 || dispid == -1, "Expected 61 or -1, got %ld\n", dispid); 608 dispid = get_dispid( pInstaller, "AdvertiseProduct" ); 609 ok(dispid == 62 || dispid == -1, "Expected 62 or -1, got %ld\n", dispid); 610 dispid = get_dispid( pInstaller, "CreateAdvertiseScript" ); 611 ok(dispid == 63 || dispid == -1, "Expected 63 or -1, got %ld\n", dispid); 612 dispid = get_dispid( pInstaller, "PatchFiles" ); 613 ok(dispid == 65 || dispid == -1, "Expected 65 or -1, got %ld\n", dispid); 614 } 615 616 /* Test basic IDispatch functions */ 617 static void test_dispatch(void) 618 { 619 HRESULT hr; 620 DISPID dispid; 621 OLECHAR *name; 622 VARIANT varresult; 623 VARIANTARG vararg[3]; 624 WCHAR path[MAX_PATH]; 625 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 626 627 /* Test getting ID of a function name that does not exist */ 628 name = (WCHAR *)L"winetest-automation.msi"; 629 hr = IDispatch_GetIDsOfNames(pInstaller, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid); 630 ok(hr == DISP_E_UNKNOWNNAME, "IDispatch::GetIDsOfNames returned %#lx\n", hr); 631 632 /* Test invoking this function */ 633 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, NULL, NULL, NULL, NULL); 634 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr); 635 636 /* Test getting ID of a function name that does exist */ 637 name = (WCHAR *)L"OpenPackage"; 638 hr = IDispatch_GetIDsOfNames(pInstaller, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid); 639 ok(hr == S_OK, "IDispatch::GetIDsOfNames returned %#lx\n", hr); 640 641 /* Test invoking this function (without parameters passed) */ 642 if (0) /* All of these crash MSI on Windows XP */ 643 { 644 IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, NULL, NULL, NULL, NULL); 645 IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, NULL, NULL, &excepinfo, NULL); 646 VariantInit(&varresult); 647 IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, NULL, &varresult, &excepinfo, NULL); 648 } 649 650 /* Try with NULL params */ 651 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 652 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr); 653 654 /* Try one empty parameter */ 655 dispparams.rgvarg = vararg; 656 dispparams.cArgs = 1; 657 VariantInit(&vararg[0]); 658 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 659 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr); 660 661 /* Try two empty parameters */ 662 dispparams.cArgs = 2; 663 VariantInit(&vararg[0]); 664 VariantInit(&vararg[1]); 665 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 666 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr); 667 668 /* Try one parameter, the required BSTR. Second parameter is optional. 669 * NOTE: The specified package does not exist, which is why the call fails. 670 */ 671 dispparams.cArgs = 1; 672 VariantInit(&vararg[0]); 673 V_VT(&vararg[0]) = VT_BSTR; 674 V_BSTR(&vararg[0]) = SysAllocString(L"winetest-automation.msi"); 675 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 676 ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned %#lx\n", hr); 677 ok_exception(hr, L"OpenPackage,PackagePath,Options"); 678 VariantClear(&vararg[0]); 679 680 /* Provide the required BSTR and an empty second parameter. 681 * NOTE: The specified package does not exist, which is why the call fails. 682 */ 683 dispparams.cArgs = 2; 684 VariantInit(&vararg[1]); 685 V_VT(&vararg[1]) = VT_BSTR; 686 V_BSTR(&vararg[1]) = SysAllocString(L"winetest-automation.msi"); 687 VariantInit(&vararg[0]); 688 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 689 ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned %#lx\n", hr); 690 ok_exception(hr, L"OpenPackage,PackagePath,Options"); 691 VariantClear(&vararg[1]); 692 693 /* Provide the required BSTR and two empty parameters. 694 * NOTE: The specified package does not exist, which is why the call fails. 695 */ 696 dispparams.cArgs = 3; 697 VariantInit(&vararg[2]); 698 V_VT(&vararg[2]) = VT_BSTR; 699 V_BSTR(&vararg[2]) = SysAllocString(L"winetest-automation.msi"); 700 VariantInit(&vararg[1]); 701 VariantInit(&vararg[0]); 702 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 703 ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned %#lx\n", hr); 704 ok_exception(hr, L"OpenPackage,PackagePath,Options"); 705 VariantClear(&vararg[2]); 706 707 /* Provide the required BSTR and a second parameter with the wrong type. */ 708 dispparams.cArgs = 2; 709 VariantInit(&vararg[1]); 710 V_VT(&vararg[1]) = VT_BSTR; 711 V_BSTR(&vararg[1]) = SysAllocString(L"winetest-automation.msi"); 712 VariantInit(&vararg[0]); 713 V_VT(&vararg[0]) = VT_BSTR; 714 V_BSTR(&vararg[0]) = SysAllocString(L"winetest-automation.msi"); 715 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 716 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr); 717 VariantClear(&vararg[0]); 718 VariantClear(&vararg[1]); 719 720 /* Create a proper installer package. */ 721 create_package(path); 722 723 /* Try one parameter, the required BSTR. Second parameter is optional. 724 * Proper installer package exists. Path to the package is relative. 725 */ 726 dispparams.cArgs = 1; 727 VariantInit(&vararg[0]); 728 V_VT(&vararg[0]) = VT_BSTR; 729 V_BSTR(&vararg[0]) = SysAllocString(L"winetest-automation.msi"); 730 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 731 todo_wine ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned %#lx\n", hr); 732 ok_exception(hr, L"OpenPackage,PackagePath,Options"); 733 VariantClear(&vararg[0]); 734 if (hr != DISP_E_EXCEPTION) 735 VariantClear(&varresult); 736 737 /* Try one parameter, the required BSTR. Second parameter is optional. 738 * Proper installer package exists. Path to the package is absolute. 739 */ 740 dispparams.cArgs = 1; 741 VariantInit(&vararg[0]); 742 V_VT(&vararg[0]) = VT_BSTR; 743 V_BSTR(&vararg[0]) = SysAllocString(path); 744 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 745 if (hr == DISP_E_EXCEPTION) 746 { 747 skip("OpenPackage failed, insufficient rights?\n"); 748 DeleteFileW(path); 749 return; 750 } 751 ok(hr == S_OK, "IDispatch::Invoke returned %#lx\n", hr); 752 VariantClear(&vararg[0]); 753 VariantClear(&varresult); 754 755 /* Provide the required BSTR and an empty second parameter. Proper 756 * installation package exists. 757 */ 758 dispparams.cArgs = 2; 759 VariantInit(&vararg[1]); 760 V_VT(&vararg[1]) = VT_BSTR; 761 V_BSTR(&vararg[1]) = SysAllocString(path); 762 VariantInit(&vararg[0]); 763 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 764 ok(hr == S_OK, "IDispatch::Invoke returned %#lx\n", hr); 765 VariantClear(&vararg[1]); 766 VariantClear(&varresult); 767 768 /* Provide the required BSTR and two empty parameters. Proper 769 * installation package exists. 770 */ 771 dispparams.cArgs = 3; 772 VariantInit(&vararg[2]); 773 V_VT(&vararg[2]) = VT_BSTR; 774 V_BSTR(&vararg[2]) = SysAllocString(path); 775 VariantInit(&vararg[1]); 776 VariantInit(&vararg[0]); 777 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 778 ok(hr == S_OK, "IDispatch::Invoke returned %#lx\n", hr); 779 VariantClear(&vararg[2]); 780 VariantClear(&varresult); 781 782 /* Provide the required BSTR and a second parameter with the wrong type. */ 783 dispparams.cArgs = 2; 784 VariantInit(&vararg[1]); 785 V_VT(&vararg[1]) = VT_BSTR; 786 V_BSTR(&vararg[1]) = SysAllocString(path); 787 VariantInit(&vararg[0]); 788 V_VT(&vararg[0]) = VT_BSTR; 789 V_BSTR(&vararg[0]) = SysAllocString(path); 790 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 791 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr); 792 VariantClear(&vararg[0]); 793 VariantClear(&vararg[1]); 794 795 /* Provide the required BSTR and a second parameter that can be coerced to 796 * VT_I4. 797 */ 798 dispparams.cArgs = 2; 799 VariantInit(&vararg[1]); 800 V_VT(&vararg[1]) = VT_BSTR; 801 V_BSTR(&vararg[1]) = SysAllocString(path); 802 VariantInit(&vararg[0]); 803 V_VT(&vararg[0]) = VT_I2; 804 V_BSTR(&vararg[0]) = 0; 805 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 806 ok(hr == S_OK, "IDispatch::Invoke returned %#lx\n", hr); 807 VariantClear(&vararg[1]); 808 VariantClear(&varresult); 809 810 DeleteFileW(path); 811 812 /* Test invoking a method as a DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT */ 813 VariantInit(&vararg[0]); 814 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL); 815 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr); 816 817 VariantInit(&vararg[0]); 818 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL); 819 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr); 820 821 /* Test invoking a read-only property as DISPATCH_PROPERTYPUT or as a DISPATCH_METHOD */ 822 name = (WCHAR *)L"ProductState"; 823 hr = IDispatch_GetIDsOfNames(pInstaller, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid); 824 ok(hr == S_OK, "IDispatch::GetIDsOfNames returned %#lx\n", hr); 825 826 dispparams.rgvarg = NULL; 827 dispparams.cArgs = 0; 828 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL); 829 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr); 830 831 dispparams.rgvarg = NULL; 832 dispparams.cArgs = 0; 833 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL); 834 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr); 835 } 836 837 /* invocation helper function */ 838 static int _invoke_todo_vtResult = 0; 839 840 static HRESULT invoke(IDispatch *pDispatch, LPCSTR szName, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, VARTYPE vtResult) 841 { 842 OLECHAR *name = NULL; 843 DISPID dispid; 844 HRESULT hr; 845 UINT i; 846 UINT len; 847 848 memset(pVarResult, 0, sizeof(VARIANT)); 849 VariantInit(pVarResult); 850 851 len = MultiByteToWideChar(CP_ACP, 0, szName, -1, NULL, 0 ); 852 name = malloc(len * sizeof(WCHAR)); 853 if (!name) return E_FAIL; 854 MultiByteToWideChar(CP_ACP, 0, szName, -1, name, len ); 855 hr = IDispatch_GetIDsOfNames(pDispatch, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid); 856 free(name); 857 ok(hr == S_OK, "IDispatch::GetIDsOfNames returned %#lx\n", hr); 858 if (hr != S_OK) return hr; 859 860 memset(&excepinfo, 0, sizeof(excepinfo)); 861 hr = IDispatch_Invoke(pDispatch, dispid, &IID_NULL, LOCALE_NEUTRAL, wFlags, pDispParams, pVarResult, &excepinfo, NULL); 862 863 if (hr == S_OK) 864 { 865 todo_wine_if (_invoke_todo_vtResult) 866 ok(V_VT(pVarResult) == vtResult, "Variant result type is %d, expected %d\n", V_VT(pVarResult), vtResult); 867 if (vtResult != VT_EMPTY) 868 { 869 hr = VariantChangeTypeEx(pVarResult, pVarResult, LOCALE_NEUTRAL, 0, vtResult); 870 ok(hr == S_OK, "VariantChangeTypeEx returned %#lx\n", hr); 871 } 872 } 873 874 for (i=0; i<pDispParams->cArgs; i++) 875 VariantClear(&pDispParams->rgvarg[i]); 876 877 return hr; 878 } 879 880 /* Object_Property helper functions */ 881 882 static HRESULT Installer_CreateRecord(int count, IDispatch **pRecord) 883 { 884 VARIANT varresult; 885 VARIANTARG vararg[1]; 886 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 887 HRESULT hr; 888 889 VariantInit(&vararg[0]); 890 V_VT(&vararg[0]) = VT_I4; 891 V_I4(&vararg[0]) = count; 892 893 hr = invoke(pInstaller, "CreateRecord", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH); 894 *pRecord = V_DISPATCH(&varresult); 895 return hr; 896 } 897 898 static HRESULT Installer_RegistryValue(HKEY hkey, LPCWSTR szKey, VARIANT vValue, VARIANT *pVarResult, VARTYPE vtExpect) 899 { 900 VARIANTARG vararg[3]; 901 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 902 903 VariantInit(&vararg[2]); 904 V_VT(&vararg[2]) = VT_I4; 905 V_I4(&vararg[2]) = (INT_PTR)hkey; 906 VariantInit(&vararg[1]); 907 V_VT(&vararg[1]) = VT_BSTR; 908 V_BSTR(&vararg[1]) = SysAllocString(szKey); 909 VariantInit(&vararg[0]); 910 VariantCopy(&vararg[0], &vValue); 911 VariantClear(&vValue); 912 913 return invoke(pInstaller, "RegistryValue", DISPATCH_METHOD, &dispparams, pVarResult, vtExpect); 914 } 915 916 static HRESULT Installer_RegistryValueE(HKEY hkey, LPCWSTR szKey, BOOL *pBool) 917 { 918 VARIANT varresult; 919 VARIANTARG vararg; 920 HRESULT hr; 921 922 VariantInit(&vararg); 923 V_VT(&vararg) = VT_EMPTY; 924 hr = Installer_RegistryValue(hkey, szKey, vararg, &varresult, VT_BOOL); 925 *pBool = V_BOOL(&varresult); 926 VariantClear(&varresult); 927 return hr; 928 } 929 930 static HRESULT Installer_RegistryValueW(HKEY hkey, LPCWSTR szKey, LPCWSTR szValue, LPWSTR szString) 931 { 932 VARIANT varresult; 933 VARIANTARG vararg; 934 HRESULT hr; 935 936 VariantInit(&vararg); 937 V_VT(&vararg) = VT_BSTR; 938 V_BSTR(&vararg) = SysAllocString(szValue); 939 940 hr = Installer_RegistryValue(hkey, szKey, vararg, &varresult, VT_BSTR); 941 if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult)); 942 VariantClear(&varresult); 943 return hr; 944 } 945 946 static HRESULT Installer_RegistryValueI(HKEY hkey, LPCWSTR szKey, int iValue, LPWSTR szString, VARTYPE vtResult) 947 { 948 VARIANT varresult; 949 VARIANTARG vararg; 950 HRESULT hr; 951 952 VariantInit(&vararg); 953 V_VT(&vararg) = VT_I4; 954 V_I4(&vararg) = iValue; 955 956 hr = Installer_RegistryValue(hkey, szKey, vararg, &varresult, vtResult); 957 if (SUCCEEDED(hr) && vtResult == VT_BSTR) lstrcpyW(szString, V_BSTR(&varresult)); 958 VariantClear(&varresult); 959 return hr; 960 } 961 962 static HRESULT Installer_OpenPackage(LPCWSTR szPackagePath, int options, IDispatch **pSession) 963 { 964 VARIANT varresult; 965 VARIANTARG vararg[2]; 966 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 967 HRESULT hr; 968 969 VariantInit(&vararg[1]); 970 V_VT(&vararg[1]) = VT_BSTR; 971 V_BSTR(&vararg[1]) = SysAllocString(szPackagePath); 972 VariantInit(&vararg[0]); 973 V_VT(&vararg[0]) = VT_I4; 974 V_I4(&vararg[0]) = options; 975 976 hr = invoke(pInstaller, "OpenPackage", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH); 977 *pSession = V_DISPATCH(&varresult); 978 return hr; 979 } 980 981 static HRESULT Installer_OpenDatabase(LPCWSTR szDatabasePath, int openmode, IDispatch **pDatabase) 982 { 983 VARIANT varresult; 984 VARIANTARG vararg[2]; 985 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 986 HRESULT hr; 987 988 VariantInit(&vararg[1]); 989 V_VT(&vararg[1]) = VT_BSTR; 990 V_BSTR(&vararg[1]) = SysAllocString(szDatabasePath); 991 VariantInit(&vararg[0]); 992 V_VT(&vararg[0]) = VT_I4; 993 V_I4(&vararg[0]) = openmode; 994 995 hr = invoke(pInstaller, "OpenDatabase", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH); 996 *pDatabase = V_DISPATCH(&varresult); 997 return hr; 998 } 999 1000 static HRESULT Installer_InstallProduct(LPCWSTR szPackagePath, LPCWSTR szPropertyValues) 1001 { 1002 VARIANT varresult; 1003 VARIANTARG vararg[2]; 1004 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1005 1006 VariantInit(&vararg[1]); 1007 V_VT(&vararg[1]) = VT_BSTR; 1008 V_BSTR(&vararg[1]) = SysAllocString(szPackagePath); 1009 VariantInit(&vararg[0]); 1010 V_VT(&vararg[0]) = VT_BSTR; 1011 V_BSTR(&vararg[0]) = SysAllocString(szPropertyValues); 1012 1013 return invoke(pInstaller, "InstallProduct", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY); 1014 } 1015 1016 static HRESULT Installer_ProductState(LPCWSTR szProduct, int *pInstallState) 1017 { 1018 VARIANT varresult; 1019 VARIANTARG vararg[1]; 1020 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1021 HRESULT hr; 1022 1023 VariantInit(&vararg[0]); 1024 V_VT(&vararg[0]) = VT_BSTR; 1025 V_BSTR(&vararg[0]) = SysAllocString(szProduct); 1026 1027 hr = invoke(pInstaller, "ProductState", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); 1028 *pInstallState = V_I4(&varresult); 1029 VariantClear(&varresult); 1030 return hr; 1031 } 1032 1033 static HRESULT Installer_ProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szString) 1034 { 1035 VARIANT varresult; 1036 VARIANTARG vararg[2]; 1037 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1038 HRESULT hr; 1039 1040 VariantInit(&vararg[1]); 1041 V_VT(&vararg[1]) = VT_BSTR; 1042 V_BSTR(&vararg[1]) = SysAllocString(szProduct); 1043 VariantInit(&vararg[0]); 1044 V_VT(&vararg[0]) = VT_BSTR; 1045 V_BSTR(&vararg[0]) = SysAllocString(szAttribute); 1046 1047 hr = invoke(pInstaller, "ProductInfo", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); 1048 if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult)); 1049 VariantClear(&varresult); 1050 return hr; 1051 } 1052 1053 static HRESULT Installer_Products(IDispatch **pStringList) 1054 { 1055 VARIANT varresult; 1056 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1057 HRESULT hr; 1058 1059 hr = invoke(pInstaller, "Products", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH); 1060 *pStringList = V_DISPATCH(&varresult); 1061 return hr; 1062 } 1063 1064 static HRESULT Installer_RelatedProducts(LPCWSTR szProduct, IDispatch **pStringList) 1065 { 1066 VARIANT varresult; 1067 VARIANTARG vararg[1]; 1068 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1069 HRESULT hr; 1070 1071 VariantInit(&vararg[0]); 1072 V_VT(&vararg[0]) = VT_BSTR; 1073 V_BSTR(&vararg[0]) = SysAllocString(szProduct); 1074 1075 hr = invoke(pInstaller, "RelatedProducts", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH); 1076 *pStringList = V_DISPATCH(&varresult); 1077 return hr; 1078 } 1079 1080 static HRESULT Installer_VersionGet(LPWSTR szVersion) 1081 { 1082 VARIANT varresult; 1083 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1084 HRESULT hr; 1085 1086 hr = invoke(pInstaller, "Version", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); 1087 if (V_BSTR(&varresult)) lstrcpyW(szVersion, V_BSTR(&varresult)); 1088 VariantClear(&varresult); 1089 return hr; 1090 } 1091 1092 static HRESULT Installer_UILevelPut(int level) 1093 { 1094 VARIANT varresult; 1095 VARIANTARG vararg; 1096 DISPID dispid = DISPID_PROPERTYPUT; 1097 DISPPARAMS dispparams = {&vararg, &dispid, sizeof(vararg)/sizeof(VARIANTARG), 1}; 1098 1099 VariantInit(&vararg); 1100 V_VT(&vararg) = VT_I4; 1101 V_I4(&vararg) = level; 1102 1103 return invoke(pInstaller, "UILevel", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY); 1104 } 1105 1106 static HRESULT Installer_SummaryInformation(BSTR PackagePath, int UpdateCount, IDispatch **pSumInfo) 1107 { 1108 VARIANT varresult; 1109 VARIANTARG vararg[2]; 1110 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1111 HRESULT hr; 1112 1113 VariantInit(&vararg[1]); 1114 V_VT(&vararg[1]) = VT_BSTR; 1115 V_BSTR(&vararg[1]) = SysAllocString(PackagePath); 1116 VariantInit(&vararg[0]); 1117 V_VT(&vararg[0]) = VT_I4; 1118 V_I4(&vararg[0]) = UpdateCount; 1119 1120 hr = invoke(pInstaller, "SummaryInformation", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH); 1121 *pSumInfo = V_DISPATCH(&varresult); 1122 return hr; 1123 } 1124 1125 static HRESULT Session_Installer(IDispatch *pSession, IDispatch **pInst) 1126 { 1127 VARIANT varresult; 1128 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1129 HRESULT hr; 1130 1131 hr = invoke(pSession, "Installer", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH); 1132 *pInst = V_DISPATCH(&varresult); 1133 return hr; 1134 } 1135 1136 static HRESULT Session_PropertyGet(IDispatch *pSession, LPCWSTR szName, LPWSTR szReturn) 1137 { 1138 VARIANT varresult; 1139 VARIANTARG vararg[1]; 1140 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1141 HRESULT hr; 1142 1143 VariantInit(&vararg[0]); 1144 V_VT(&vararg[0]) = VT_BSTR; 1145 V_BSTR(&vararg[0]) = SysAllocString(szName); 1146 1147 hr = invoke(pSession, "Property", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); 1148 if (V_BSTR(&varresult)) lstrcpyW(szReturn, V_BSTR(&varresult)); 1149 VariantClear(&varresult); 1150 return hr; 1151 } 1152 1153 static HRESULT Session_PropertyPut(IDispatch *pSession, LPCWSTR szName, LPCWSTR szValue) 1154 { 1155 VARIANT varresult; 1156 VARIANTARG vararg[2]; 1157 DISPID dispid = DISPID_PROPERTYPUT; 1158 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1}; 1159 1160 VariantInit(&vararg[1]); 1161 V_VT(&vararg[1]) = VT_BSTR; 1162 V_BSTR(&vararg[1]) = SysAllocString(szName); 1163 VariantInit(&vararg[0]); 1164 V_VT(&vararg[0]) = VT_BSTR; 1165 V_BSTR(&vararg[0]) = SysAllocString(szValue); 1166 1167 return invoke(pSession, "Property", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY); 1168 } 1169 1170 static HRESULT Session_LanguageGet(IDispatch *pSession, UINT *pLangId) 1171 { 1172 VARIANT varresult; 1173 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1174 HRESULT hr; 1175 1176 hr = invoke(pSession, "Language", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); 1177 *pLangId = V_I4(&varresult); 1178 VariantClear(&varresult); 1179 return hr; 1180 } 1181 1182 static HRESULT Session_ModeGet(IDispatch *pSession, int iFlag, VARIANT_BOOL *mode) 1183 { 1184 VARIANT varresult; 1185 VARIANTARG vararg[1]; 1186 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1187 HRESULT hr; 1188 1189 VariantInit(&vararg[0]); 1190 V_VT(&vararg[0]) = VT_I4; 1191 V_I4(&vararg[0]) = iFlag; 1192 1193 hr = invoke(pSession, "Mode", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BOOL); 1194 *mode = V_BOOL(&varresult); 1195 VariantClear(&varresult); 1196 return hr; 1197 } 1198 1199 static HRESULT Session_ModePut(IDispatch *pSession, int iFlag, VARIANT_BOOL mode) 1200 { 1201 VARIANT varresult; 1202 VARIANTARG vararg[2]; 1203 DISPID dispid = DISPID_PROPERTYPUT; 1204 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1}; 1205 1206 VariantInit(&vararg[1]); 1207 V_VT(&vararg[1]) = VT_I4; 1208 V_I4(&vararg[1]) = iFlag; 1209 VariantInit(&vararg[0]); 1210 V_VT(&vararg[0]) = VT_BOOL; 1211 V_BOOL(&vararg[0]) = mode; 1212 1213 return invoke(pSession, "Mode", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY); 1214 } 1215 1216 static HRESULT Session_Database(IDispatch *pSession, IDispatch **pDatabase) 1217 { 1218 VARIANT varresult; 1219 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1220 HRESULT hr; 1221 1222 hr = invoke(pSession, "Database", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH); 1223 *pDatabase = V_DISPATCH(&varresult); 1224 return hr; 1225 } 1226 1227 static HRESULT Session_DoAction(IDispatch *pSession, LPCWSTR szAction, int *iReturn) 1228 { 1229 VARIANT varresult; 1230 VARIANTARG vararg[1]; 1231 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1232 HRESULT hr; 1233 1234 VariantInit(&vararg[0]); 1235 V_VT(&vararg[0]) = VT_BSTR; 1236 V_BSTR(&vararg[0]) = SysAllocString(szAction); 1237 1238 hr = invoke(pSession, "DoAction", DISPATCH_METHOD, &dispparams, &varresult, VT_I4); 1239 *iReturn = V_I4(&varresult); 1240 VariantClear(&varresult); 1241 return hr; 1242 } 1243 1244 static HRESULT Session_EvaluateCondition(IDispatch *pSession, LPCWSTR szCondition, int *iReturn) 1245 { 1246 VARIANT varresult; 1247 VARIANTARG vararg[1]; 1248 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1249 HRESULT hr; 1250 1251 VariantInit(&vararg[0]); 1252 V_VT(&vararg[0]) = VT_BSTR; 1253 V_BSTR(&vararg[0]) = SysAllocString(szCondition); 1254 1255 hr = invoke(pSession, "EvaluateCondition", DISPATCH_METHOD, &dispparams, &varresult, VT_I4); 1256 *iReturn = V_I4(&varresult); 1257 VariantClear(&varresult); 1258 return hr; 1259 } 1260 1261 static HRESULT Session_Message(IDispatch *pSession, LONG kind, IDispatch *record, int *ret) 1262 { 1263 VARIANT varresult; 1264 VARIANTARG vararg[2]; 1265 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1266 HRESULT hr; 1267 1268 VariantInit(&varresult); 1269 V_VT(vararg) = VT_DISPATCH; 1270 V_DISPATCH(vararg) = record; 1271 V_VT(vararg+1) = VT_I4; 1272 V_I4(vararg+1) = kind; 1273 1274 hr = invoke(pSession, "Message", DISPATCH_METHOD, &dispparams, &varresult, VT_I4); 1275 1276 ok(V_VT(&varresult) == VT_I4, "V_VT(varresult) = %d\n", V_VT(&varresult)); 1277 *ret = V_I4(&varresult); 1278 1279 return hr; 1280 } 1281 1282 static HRESULT Session_SetInstallLevel(IDispatch *pSession, LONG iInstallLevel) 1283 { 1284 VARIANT varresult; 1285 VARIANTARG vararg[1]; 1286 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1287 1288 VariantInit(&vararg[0]); 1289 V_VT(&vararg[0]) = VT_I4; 1290 V_I4(&vararg[0]) = iInstallLevel; 1291 1292 return invoke(pSession, "SetInstallLevel", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY); 1293 } 1294 1295 static HRESULT Session_FeatureCurrentState(IDispatch *pSession, LPCWSTR szName, int *pState) 1296 { 1297 VARIANT varresult; 1298 VARIANTARG vararg[1]; 1299 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1300 HRESULT hr; 1301 1302 VariantInit(&vararg[0]); 1303 V_VT(&vararg[0]) = VT_BSTR; 1304 V_BSTR(&vararg[0]) = SysAllocString(szName); 1305 1306 hr = invoke(pSession, "FeatureCurrentState", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); 1307 *pState = V_I4(&varresult); 1308 VariantClear(&varresult); 1309 return hr; 1310 } 1311 1312 static HRESULT Session_FeatureRequestStateGet(IDispatch *pSession, LPCWSTR szName, int *pState) 1313 { 1314 VARIANT varresult; 1315 VARIANTARG vararg[1]; 1316 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1317 HRESULT hr; 1318 1319 VariantInit(&vararg[0]); 1320 V_VT(&vararg[0]) = VT_BSTR; 1321 V_BSTR(&vararg[0]) = SysAllocString(szName); 1322 1323 hr = invoke(pSession, "FeatureRequestState", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); 1324 *pState = V_I4(&varresult); 1325 VariantClear(&varresult); 1326 return hr; 1327 } 1328 1329 static HRESULT Session_FeatureRequestStatePut(IDispatch *pSession, LPCWSTR szName, int iState) 1330 { 1331 VARIANT varresult; 1332 VARIANTARG vararg[2]; 1333 DISPID dispid = DISPID_PROPERTYPUT; 1334 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1}; 1335 1336 VariantInit(&vararg[1]); 1337 V_VT(&vararg[1]) = VT_BSTR; 1338 V_BSTR(&vararg[1]) = SysAllocString(szName); 1339 VariantInit(&vararg[0]); 1340 V_VT(&vararg[0]) = VT_I4; 1341 V_I4(&vararg[0]) = iState; 1342 1343 return invoke(pSession, "FeatureRequestState", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY); 1344 } 1345 1346 static HRESULT Database_OpenView(IDispatch *pDatabase, LPCWSTR szSql, IDispatch **pView) 1347 { 1348 VARIANT varresult; 1349 VARIANTARG vararg[1]; 1350 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1351 HRESULT hr; 1352 1353 VariantInit(&vararg[0]); 1354 V_VT(&vararg[0]) = VT_BSTR; 1355 V_BSTR(&vararg[0]) = SysAllocString(szSql); 1356 1357 hr = invoke(pDatabase, "OpenView", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH); 1358 *pView = V_DISPATCH(&varresult); 1359 return hr; 1360 } 1361 1362 static HRESULT Database_SummaryInformation(IDispatch *pDatabase, int iUpdateCount, IDispatch **pSummaryInfo) 1363 { 1364 VARIANT varresult; 1365 VARIANTARG vararg[1]; 1366 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1367 HRESULT hr; 1368 1369 VariantInit(&vararg[0]); 1370 V_VT(&vararg[0]) = VT_I4; 1371 V_I4(&vararg[0]) = iUpdateCount; 1372 1373 hr = invoke(pDatabase, "SummaryInformation", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH); 1374 *pSummaryInfo = V_DISPATCH(&varresult); 1375 return hr; 1376 } 1377 1378 static HRESULT View_Execute(IDispatch *pView, IDispatch *pRecord) 1379 { 1380 VARIANT varresult; 1381 VARIANTARG vararg[1]; 1382 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1383 1384 VariantInit(&vararg[0]); 1385 V_VT(&vararg[0]) = VT_DISPATCH; 1386 V_DISPATCH(&vararg[0]) = pRecord; 1387 1388 return invoke(pView, "Execute", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY); 1389 } 1390 1391 static HRESULT View_Fetch(IDispatch *pView, IDispatch **ppRecord) 1392 { 1393 VARIANT varresult; 1394 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1395 HRESULT hr = invoke(pView, "Fetch", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH); 1396 *ppRecord = V_DISPATCH(&varresult); 1397 return hr; 1398 } 1399 1400 static HRESULT View_Modify(IDispatch *pView, int iMode, IDispatch *pRecord) 1401 { 1402 VARIANT varresult; 1403 VARIANTARG vararg[2]; 1404 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1405 1406 VariantInit(&vararg[1]); 1407 V_VT(&vararg[1]) = VT_I4; 1408 V_I4(&vararg[1]) = iMode; 1409 VariantInit(&vararg[0]); 1410 V_VT(&vararg[0]) = VT_DISPATCH; 1411 V_DISPATCH(&vararg[0]) = pRecord; 1412 if (pRecord) 1413 IDispatch_AddRef(pRecord); /* VariantClear in invoke will call IDispatch_Release */ 1414 1415 return invoke(pView, "Modify", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY); 1416 } 1417 1418 static HRESULT View_Close(IDispatch *pView) 1419 { 1420 VARIANT varresult; 1421 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1422 return invoke(pView, "Close", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY); 1423 } 1424 1425 static HRESULT Record_FieldCountGet(IDispatch *pRecord, int *pFieldCount) 1426 { 1427 VARIANT varresult; 1428 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1429 HRESULT hr = invoke(pRecord, "FieldCount", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); 1430 *pFieldCount = V_I4(&varresult); 1431 VariantClear(&varresult); 1432 return hr; 1433 } 1434 1435 static HRESULT Record_StringDataGet(IDispatch *pRecord, int iField, LPWSTR szString) 1436 { 1437 VARIANT varresult; 1438 VARIANTARG vararg[1]; 1439 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1440 HRESULT hr; 1441 1442 VariantInit(&vararg[0]); 1443 V_VT(&vararg[0]) = VT_I4; 1444 V_I4(&vararg[0]) = iField; 1445 1446 hr = invoke(pRecord, "StringData", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); 1447 if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult)); 1448 VariantClear(&varresult); 1449 return hr; 1450 } 1451 1452 static HRESULT Record_StringDataPut(IDispatch *pRecord, int iField, LPCWSTR szString) 1453 { 1454 VARIANT varresult; 1455 VARIANTARG vararg[2]; 1456 DISPID dispid = DISPID_PROPERTYPUT; 1457 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1}; 1458 1459 VariantInit(&vararg[1]); 1460 V_VT(&vararg[1]) = VT_I4; 1461 V_I4(&vararg[1]) = iField; 1462 VariantInit(&vararg[0]); 1463 V_VT(&vararg[0]) = VT_BSTR; 1464 V_BSTR(&vararg[0]) = SysAllocString(szString); 1465 1466 return invoke(pRecord, "StringData", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY); 1467 } 1468 1469 static HRESULT Record_IntegerDataGet(IDispatch *pRecord, int iField, int *pValue) 1470 { 1471 VARIANT varresult; 1472 VARIANTARG vararg[1]; 1473 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1474 HRESULT hr; 1475 1476 VariantInit(&vararg[0]); 1477 V_VT(&vararg[0]) = VT_I4; 1478 V_I4(&vararg[0]) = iField; 1479 1480 hr = invoke(pRecord, "IntegerData", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); 1481 *pValue = V_I4(&varresult); 1482 VariantClear(&varresult); 1483 return hr; 1484 } 1485 1486 static HRESULT Record_IntegerDataPut(IDispatch *pRecord, int iField, int iValue) 1487 { 1488 VARIANT varresult; 1489 VARIANTARG vararg[2]; 1490 DISPID dispid = DISPID_PROPERTYPUT; 1491 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1}; 1492 1493 VariantInit(&vararg[1]); 1494 V_VT(&vararg[1]) = VT_I4; 1495 V_I4(&vararg[1]) = iField; 1496 VariantInit(&vararg[0]); 1497 V_VT(&vararg[0]) = VT_I4; 1498 V_I4(&vararg[0]) = iValue; 1499 1500 return invoke(pRecord, "IntegerData", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY); 1501 } 1502 1503 static HRESULT StringList__NewEnum(IDispatch *pList, IUnknown **ppEnumVARIANT) 1504 { 1505 VARIANT varresult; 1506 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1507 HRESULT hr = invoke(pList, "_NewEnum", DISPATCH_METHOD, &dispparams, &varresult, VT_UNKNOWN); 1508 *ppEnumVARIANT = V_UNKNOWN(&varresult); 1509 return hr; 1510 } 1511 1512 static HRESULT StringList_Item(IDispatch *pStringList, int iIndex, LPWSTR szString) 1513 { 1514 VARIANT varresult; 1515 VARIANTARG vararg[1]; 1516 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1517 HRESULT hr; 1518 1519 VariantInit(&vararg[0]); 1520 V_VT(&vararg[0]) = VT_I4; 1521 V_I4(&vararg[0]) = iIndex; 1522 1523 hr = invoke(pStringList, "Item", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); 1524 if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult)); 1525 VariantClear(&varresult); 1526 return hr; 1527 } 1528 1529 static HRESULT StringList_Count(IDispatch *pStringList, int *pCount) 1530 { 1531 VARIANT varresult; 1532 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1533 HRESULT hr = invoke(pStringList, "Count", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); 1534 *pCount = V_I4(&varresult); 1535 VariantClear(&varresult); 1536 return hr; 1537 } 1538 1539 static HRESULT SummaryInfo_PropertyGet(IDispatch *pSummaryInfo, int pid, VARIANT *pVarResult, VARTYPE vtExpect) 1540 { 1541 VARIANTARG vararg[1]; 1542 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0}; 1543 1544 VariantInit(&vararg[0]); 1545 V_VT(&vararg[0]) = VT_I4; 1546 V_I4(&vararg[0]) = pid; 1547 return invoke(pSummaryInfo, "Property", DISPATCH_PROPERTYGET, &dispparams, pVarResult, vtExpect); 1548 } 1549 1550 static HRESULT SummaryInfo_PropertyPut(IDispatch *pSummaryInfo, int pid, VARIANT *pVariant) 1551 { 1552 VARIANT varresult; 1553 VARIANTARG vararg[2]; 1554 DISPID dispid = DISPID_PROPERTYPUT; 1555 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1}; 1556 1557 VariantInit(&vararg[1]); 1558 V_VT(&vararg[1]) = VT_I4; 1559 V_I4(&vararg[1]) = pid; 1560 VariantInit(&vararg[0]); 1561 VariantCopyInd(vararg, pVariant); 1562 1563 return invoke(pSummaryInfo, "Property", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY); 1564 } 1565 1566 static HRESULT SummaryInfo_PropertyCountGet(IDispatch *pSummaryInfo, int *pCount) 1567 { 1568 VARIANT varresult; 1569 DISPPARAMS dispparams = {NULL, NULL, 0, 0}; 1570 HRESULT hr; 1571 1572 hr = invoke(pSummaryInfo, "PropertyCount", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); 1573 *pCount = V_I4(&varresult); 1574 VariantClear(&varresult); 1575 return hr; 1576 } 1577 1578 /* Test the various objects */ 1579 1580 #define TEST_SUMMARYINFO_PROPERTIES_MODIFIED 4 1581 1582 static void test_SummaryInfo(IDispatch *pSummaryInfo, const msi_summary_info *info, int num_info, BOOL readonly) 1583 { 1584 VARIANT varresult, var; 1585 SYSTEMTIME st; 1586 HRESULT hr; 1587 int j; 1588 1589 /* SummaryInfo::PropertyCount */ 1590 hr = SummaryInfo_PropertyCountGet(pSummaryInfo, &j); 1591 ok(hr == S_OK, "SummaryInfo_PropertyCount failed, hresult %#lx\n", hr); 1592 ok(j == num_info, "SummaryInfo_PropertyCount returned %d, expected %d\n", j, num_info); 1593 1594 /* SummaryInfo::Property, get for properties we have set */ 1595 for (j = 0; j < num_info; j++) 1596 { 1597 const msi_summary_info *entry = &info[j]; 1598 1599 int vt = entry->datatype; 1600 if (vt == VT_LPSTR) vt = VT_BSTR; 1601 else if (vt == VT_FILETIME) vt = VT_DATE; 1602 else if (vt == VT_I2) vt = VT_I4; 1603 1604 hr = SummaryInfo_PropertyGet(pSummaryInfo, entry->property, &varresult, vt); 1605 ok(hr == S_OK, "SummaryInfo_Property (pid %d) failed, hresult %#lx\n", entry->property, hr); 1606 if (V_VT(&varresult) != vt) 1607 skip("Skipping property tests due to type mismatch\n"); 1608 else if (vt == VT_I4) 1609 ok(V_I4(&varresult) == entry->iValue, "SummaryInfo_Property (pid %d) I4 result expected to be %d, but was %ld\n", 1610 entry->property, entry->iValue, V_I4(&varresult)); 1611 else if (vt == VT_DATE) 1612 { 1613 FILETIME ft; 1614 DATE d; 1615 1616 FileTimeToLocalFileTime(entry->pftValue, &ft); 1617 FileTimeToSystemTime(&ft, &st); 1618 SystemTimeToVariantTime(&st, &d); 1619 ok(d == V_DATE(&varresult), "SummaryInfo_Property (pid %d) DATE result expected to be %lf, but was %lf\n", entry->property, d, V_DATE(&varresult)); 1620 } 1621 else if (vt == VT_BSTR) 1622 { 1623 ok_awplus("SummaryInfo_Property (pid %d) BSTR result expected to be %s, but was %s\n", entry->property, entry->szValue, V_BSTR(&varresult)); 1624 } 1625 else 1626 skip("SummaryInfo_Property (pid %d) unhandled result type %d\n", entry->property, vt); 1627 1628 VariantClear(&varresult); 1629 } 1630 1631 /* SummaryInfo::Property, get; invalid arguments */ 1632 1633 /* Invalid pids */ 1634 hr = SummaryInfo_PropertyGet(pSummaryInfo, -1, &varresult, VT_EMPTY); 1635 ok(hr == DISP_E_EXCEPTION, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1636 ok_exception(hr, L"Property,Pid"); 1637 1638 hr = SummaryInfo_PropertyGet(pSummaryInfo, 1000, &varresult, VT_EMPTY); 1639 ok(hr == DISP_E_EXCEPTION, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1640 ok_exception(hr, L"Property,Pid"); 1641 1642 /* Unsupported pids */ 1643 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_DICTIONARY, &varresult, VT_EMPTY); 1644 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1645 1646 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_THUMBNAIL, &varresult, VT_EMPTY); 1647 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1648 1649 /* Pids we have not set, one for each type */ 1650 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CODEPAGE, &varresult, VT_EMPTY); 1651 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1652 1653 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_TITLE, &varresult, VT_EMPTY); 1654 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1655 1656 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_EDITTIME, &varresult, VT_EMPTY); 1657 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1658 1659 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CHARCOUNT, &varresult, VT_EMPTY); 1660 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1661 1662 if (!readonly) 1663 { 1664 /* SummaryInfo::Property, put; one for each type */ 1665 1666 /* VT_I2 */ 1667 VariantInit(&var); 1668 V_VT(&var) = VT_I2; 1669 V_I2(&var) = 1; 1670 hr = SummaryInfo_PropertyPut(pSummaryInfo, PID_CODEPAGE, &var); 1671 ok(hr == S_OK, "SummaryInfo_PropertyPut failed, hresult %#lx\n", hr); 1672 1673 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CODEPAGE, &varresult, VT_I4 /* NOT VT_I2 */); 1674 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1675 ok(V_I2(&var) == V_I2(&varresult), "SummaryInfo_PropertyGet expected %d, but returned %d\n", V_I2(&var), V_I2(&varresult)); 1676 VariantClear(&varresult); 1677 VariantClear(&var); 1678 1679 /* VT_BSTR */ 1680 V_VT(&var) = VT_BSTR; 1681 V_BSTR(&var) = SysAllocString(L"Title"); 1682 hr = SummaryInfo_PropertyPut(pSummaryInfo, PID_TITLE, &var); 1683 ok(hr == S_OK, "SummaryInfo_PropertyPut failed, hresult %#lx\n", hr); 1684 1685 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_TITLE, &varresult, V_VT(&var)); 1686 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1687 ok_w2("SummaryInfo_PropertyGet expected %s, but returned %s\n", V_BSTR(&var), V_BSTR(&varresult)); 1688 VariantClear(&varresult); 1689 VariantClear(&var); 1690 1691 /* VT_DATE */ 1692 V_VT(&var) = VT_DATE; 1693 FileTimeToSystemTime(&systemtime, &st); 1694 SystemTimeToVariantTime(&st, &V_DATE(&var)); 1695 hr = SummaryInfo_PropertyPut(pSummaryInfo, PID_LASTSAVE_DTM, &var); 1696 ok(hr == S_OK, "SummaryInfo_PropertyPut failed, hresult %#lx\n", hr); 1697 1698 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_LASTSAVE_DTM, &varresult, V_VT(&var)); 1699 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1700 ok(V_DATE(&var) == V_DATE(&varresult), "SummaryInfo_PropertyGet expected %lf, but returned %lf\n", V_DATE(&var), V_DATE(&varresult)); 1701 VariantClear(&varresult); 1702 VariantClear(&var); 1703 1704 /* VT_I4 */ 1705 V_VT(&var) = VT_I4; 1706 V_I4(&var) = 1000; 1707 hr = SummaryInfo_PropertyPut(pSummaryInfo, PID_CHARCOUNT, &var); 1708 ok(hr == S_OK, "SummaryInfo_PropertyPut failed, hresult %#lx\n", hr); 1709 1710 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CHARCOUNT, &varresult, V_VT(&var)); 1711 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr); 1712 ok(V_I4(&var) == V_I4(&varresult), "SummaryInfo_PropertyGet expected %ld, but returned %ld\n", V_I4(&var), V_I4(&varresult)); 1713 VariantClear(&varresult); 1714 VariantClear(&var); 1715 1716 /* SummaryInfo::PropertyCount */ 1717 hr = SummaryInfo_PropertyCountGet(pSummaryInfo, &j); 1718 ok(hr == S_OK, "SummaryInfo_PropertyCount failed, hresult %#lx\n", hr); 1719 ok(j == num_info+4, "SummaryInfo_PropertyCount returned %d, expected %d\n", j, num_info); 1720 } 1721 } 1722 1723 static void test_Database(IDispatch *pDatabase, BOOL readonly) 1724 { 1725 IDispatch *pView = NULL, *pSummaryInfo = NULL; 1726 HRESULT hr; 1727 1728 hr = Database_OpenView(pDatabase, L"SELECT `Feature` FROM `Feature` WHERE `Feature_Parent`='One'", &pView); 1729 ok(hr == S_OK, "Database_OpenView failed, hresult %#lx\n", hr); 1730 if (hr == S_OK) 1731 { 1732 IDispatch *pRecord = NULL; 1733 WCHAR szString[MAX_PATH]; 1734 1735 /* View::Execute */ 1736 hr = View_Execute(pView, NULL); 1737 ok(hr == S_OK, "View_Execute failed, hresult %#lx\n", hr); 1738 1739 /* View::Fetch */ 1740 hr = View_Fetch(pView, &pRecord); 1741 ok(hr == S_OK, "View_Fetch failed, hresult %#lx\n", hr); 1742 ok(pRecord != NULL, "View_Fetch should not have returned NULL record\n"); 1743 if (pRecord) 1744 { 1745 /* Record::StringDataGet */ 1746 memset(szString, 0, sizeof(szString)); 1747 hr = Record_StringDataGet(pRecord, 1, szString); 1748 ok(hr == S_OK, "Record_StringDataGet failed, hresult %#lx\n", hr); 1749 ok_w2("Record_StringDataGet result was %s but expected %s\n", szString, L"Three"); 1750 1751 /* Record::StringDataPut with correct index */ 1752 hr = Record_StringDataPut(pRecord, 1, L"Two"); 1753 ok(hr == S_OK, "Record_StringDataPut failed, hresult %#lx\n", hr); 1754 1755 /* Record::StringDataGet */ 1756 memset(szString, 0, sizeof(szString)); 1757 hr = Record_StringDataGet(pRecord, 1, szString); 1758 ok(hr == S_OK, "Record_StringDataGet failed, hresult %#lx\n", hr); 1759 ok_w2("Record_StringDataGet result was %s but expected %s\n", szString, L"Two"); 1760 1761 /* Record::StringDataPut with incorrect index */ 1762 hr = Record_StringDataPut(pRecord, -1, szString); 1763 ok(hr == DISP_E_EXCEPTION, "Record_StringDataPut failed, hresult %#lx\n", hr); 1764 ok_exception(hr, L"StringData,Field"); 1765 1766 /* View::Modify with incorrect parameters */ 1767 hr = View_Modify(pView, -5, NULL); 1768 ok(hr == DISP_E_EXCEPTION, "View_Modify failed, hresult %#lx\n", hr); 1769 ok_exception(hr, L"Modify,Mode,Record"); 1770 1771 hr = View_Modify(pView, -5, pRecord); 1772 ok(hr == DISP_E_EXCEPTION, "View_Modify failed, hresult %#lx\n", hr); 1773 ok_exception(hr, L"Modify,Mode,Record"); 1774 1775 hr = View_Modify(pView, MSIMODIFY_REFRESH, NULL); 1776 ok(hr == DISP_E_EXCEPTION, "View_Modify failed, hresult %#lx\n", hr); 1777 ok_exception(hr, L"Modify,Mode,Record"); 1778 1779 hr = View_Modify(pView, MSIMODIFY_REFRESH, pRecord); 1780 ok(hr == S_OK, "View_Modify failed, hresult %#lx\n", hr); 1781 1782 /* Record::StringDataGet, confirm that the record is back to its unmodified value */ 1783 memset(szString, 0, sizeof(szString)); 1784 hr = Record_StringDataGet(pRecord, 1, szString); 1785 ok(hr == S_OK, "Record_StringDataGet failed, hresult %#lx\n", hr); 1786 todo_wine ok_w2("Record_StringDataGet result was %s but expected %s\n", szString, L"Three"); 1787 1788 IDispatch_Release(pRecord); 1789 } 1790 1791 /* View::Fetch */ 1792 hr = View_Fetch(pView, &pRecord); 1793 ok(hr == S_OK, "View_Fetch failed, hresult %#lx\n", hr); 1794 ok(pRecord != NULL, "View_Fetch should not have returned NULL record\n"); 1795 if (pRecord) 1796 { 1797 /* Record::StringDataGet */ 1798 memset(szString, 0, sizeof(szString)); 1799 hr = Record_StringDataGet(pRecord, 1, szString); 1800 ok(hr == S_OK, "Record_StringDataGet failed, hresult %#lx\n", hr); 1801 ok_w2("Record_StringDataGet result was %s but expected %s\n", szString, L"Two"); 1802 1803 IDispatch_Release(pRecord); 1804 } 1805 1806 /* View::Fetch */ 1807 hr = View_Fetch(pView, &pRecord); 1808 ok(hr == S_OK, "View_Fetch failed, hresult %#lx\n", hr); 1809 ok(pRecord == NULL, "View_Fetch should have returned NULL record\n"); 1810 if (pRecord) 1811 IDispatch_Release(pRecord); 1812 1813 /* View::Close */ 1814 hr = View_Close(pView); 1815 ok(hr == S_OK, "View_Close failed, hresult %#lx\n", hr); 1816 1817 IDispatch_Release(pView); 1818 } 1819 1820 /* Database::SummaryInformation */ 1821 hr = Database_SummaryInformation(pDatabase, TEST_SUMMARYINFO_PROPERTIES_MODIFIED, &pSummaryInfo); 1822 ok(hr == S_OK, "Database_SummaryInformation failed, hresult %#lx\n", hr); 1823 ok(pSummaryInfo != NULL, "Database_SummaryInformation should not have returned NULL record\n"); 1824 if (pSummaryInfo) 1825 { 1826 test_SummaryInfo(pSummaryInfo, summary_info, ARRAY_SIZE(summary_info), readonly); 1827 IDispatch_Release(pSummaryInfo); 1828 } 1829 } 1830 1831 static void test_Session(IDispatch *pSession) 1832 { 1833 WCHAR stringw[MAX_PATH]; 1834 CHAR string[MAX_PATH]; 1835 UINT len; 1836 VARIANT_BOOL bool; 1837 int myint; 1838 IDispatch *pDatabase = NULL, *pInst = NULL, *record = NULL; 1839 ULONG refs_before, refs_after; 1840 HRESULT hr; 1841 1842 /* Session::Installer */ 1843 hr = Session_Installer(pSession, &pInst); 1844 ok(hr == S_OK, "Session_Installer failed, hresult %#lx\n", hr); 1845 ok(pInst != NULL, "Session_Installer returned NULL IDispatch pointer\n"); 1846 ok(pInst == pInstaller, "Session_Installer does not match Installer instance from CoCreateInstance\n"); 1847 refs_before = IDispatch_AddRef(pInst); 1848 1849 hr = Session_Installer(pSession, &pInst); 1850 ok(hr == S_OK, "Session_Installer failed, hresult %#lx\n", hr); 1851 ok(pInst != NULL, "Session_Installer returned NULL IDispatch pointer\n"); 1852 ok(pInst == pInstaller, "Session_Installer does not match Installer instance from CoCreateInstance\n"); 1853 refs_after = IDispatch_Release(pInst); 1854 ok(refs_before == refs_after, "got %lu and %lu\n", refs_before, refs_after); 1855 1856 /* Session::Property, get */ 1857 memset(stringw, 0, sizeof(stringw)); 1858 hr = Session_PropertyGet(pSession, L"ProductName", stringw); 1859 ok(hr == S_OK, "Session_PropertyGet failed, hresult %#lx\n", hr); 1860 if (lstrcmpW(stringw, L"MSITEST") != 0) 1861 { 1862 len = WideCharToMultiByte(CP_ACP, 0, stringw, -1, string, MAX_PATH, NULL, NULL); 1863 ok(len, "WideCharToMultiByteChar returned error %lu\n", GetLastError()); 1864 ok(0, "Property \"ProductName\" expected to be \"MSITEST\" but was \"%s\"\n", string); 1865 } 1866 1867 /* Session::Property, put */ 1868 hr = Session_PropertyPut(pSession, L"ProductName", L"ProductName"); 1869 ok(hr == S_OK, "Session_PropertyPut failed, hresult %#lx\n", hr); 1870 memset(stringw, 0, sizeof(stringw)); 1871 hr = Session_PropertyGet(pSession, L"ProductName", stringw); 1872 ok(hr == S_OK, "Session_PropertyGet failed, hresult %#lx\n", hr); 1873 if (lstrcmpW(stringw, L"ProductName") != 0) 1874 { 1875 len = WideCharToMultiByte(CP_ACP, 0, stringw, -1, string, MAX_PATH, NULL, NULL); 1876 ok(len, "WideCharToMultiByteChar returned error %lu\n", GetLastError()); 1877 ok(0, "Property \"ProductName\" expected to be \"ProductName\" but was \"%s\"\n", string); 1878 } 1879 1880 /* Try putting a property using empty property identifier */ 1881 hr = Session_PropertyPut(pSession, L"", L"ProductName"); 1882 ok(hr == DISP_E_EXCEPTION, "Session_PropertyPut failed, hresult %#lx\n", hr); 1883 ok_exception(hr, L"Property,Name"); 1884 1885 /* Try putting a property using illegal property identifier */ 1886 hr = Session_PropertyPut(pSession, L"=", L"ProductName"); 1887 ok(hr == S_OK, "Session_PropertyPut failed, hresult %#lx\n", hr); 1888 1889 /* Session::Language, get */ 1890 hr = Session_LanguageGet(pSession, &len); 1891 ok(hr == S_OK, "Session_LanguageGet failed, hresult %#lx\n", hr); 1892 /* Not sure how to check the language is correct */ 1893 1894 /* Session::Mode, get */ 1895 hr = Session_ModeGet(pSession, MSIRUNMODE_REBOOTATEND, &bool); 1896 ok(hr == S_OK, "Session_ModeGet failed, hresult %#lx\n", hr); 1897 ok(!bool, "Reboot at end session mode is %d\n", bool); 1898 1899 hr = Session_ModeGet(pSession, MSIRUNMODE_MAINTENANCE, &bool); 1900 ok(hr == S_OK, "Session_ModeGet failed, hresult %#lx\n", hr); 1901 ok(!bool, "Maintenance mode is %d\n", bool); 1902 1903 /* Session::Mode, put */ 1904 hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTATEND, VARIANT_TRUE); 1905 ok(hr == S_OK, "Session_ModePut failed, hresult %#lx\n", hr); 1906 hr = Session_ModeGet(pSession, MSIRUNMODE_REBOOTATEND, &bool); 1907 ok(hr == S_OK, "Session_ModeGet failed, hresult %#lx\n", hr); 1908 ok(bool, "Reboot at end session mode is %d, expected 1\n", bool); 1909 hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTATEND, VARIANT_FALSE); /* set it again so we don't reboot */ 1910 ok(hr == S_OK, "Session_ModePut failed, hresult %#lx\n", hr); 1911 1912 hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTNOW, VARIANT_TRUE); 1913 ok(hr == S_OK, "Session_ModePut failed, hresult %#lx\n", hr); 1914 ok_exception(hr, L"Mode,Flag"); 1915 1916 hr = Session_ModeGet(pSession, MSIRUNMODE_REBOOTNOW, &bool); 1917 ok(hr == S_OK, "Session_ModeGet failed, hresult %#lx\n", hr); 1918 ok(bool, "Reboot now mode is %d, expected 1\n", bool); 1919 1920 hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTNOW, VARIANT_FALSE); /* set it again so we don't reboot */ 1921 ok(hr == S_OK, "Session_ModePut failed, hresult %#lx\n", hr); 1922 ok_exception(hr, L"Mode,Flag"); 1923 1924 hr = Session_ModePut(pSession, MSIRUNMODE_MAINTENANCE, VARIANT_TRUE); 1925 ok(hr == DISP_E_EXCEPTION, "Session_ModePut failed, hresult %#lx\n", hr); 1926 ok_exception(hr, L"Mode,Flag"); 1927 1928 /* Session::Database, get */ 1929 hr = Session_Database(pSession, &pDatabase); 1930 ok(hr == S_OK, "Session_Database failed, hresult %#lx\n", hr); 1931 if (hr == S_OK) 1932 { 1933 test_Database(pDatabase, TRUE); 1934 IDispatch_Release(pDatabase); 1935 } 1936 1937 /* Session::EvaluateCondition */ 1938 hr = Session_EvaluateCondition(pSession, NULL, &myint); 1939 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr); 1940 ok(myint == MSICONDITION_NONE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN); 1941 1942 hr = Session_EvaluateCondition(pSession, L"", &myint); 1943 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr); 1944 ok(myint == MSICONDITION_NONE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN); 1945 1946 hr = Session_EvaluateCondition(pSession, L"=", &myint); 1947 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr); 1948 ok(myint == MSICONDITION_ERROR, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN); 1949 1950 /* Session::DoAction(CostInitialize) must occur before the next statements */ 1951 hr = Session_DoAction(pSession, L"CostInitialize", &myint); 1952 ok(hr == S_OK, "Session_DoAction failed, hresult %#lx\n", hr); 1953 ok(myint == IDOK, "DoAction(CostInitialize) returned %d, %d expected\n", myint, IDOK); 1954 1955 /* Session::SetInstallLevel */ 1956 hr = Session_SetInstallLevel(pSession, INSTALLLEVEL_MINIMUM); 1957 ok(hr == S_OK, "Session_SetInstallLevel failed, hresult %#lx\n", hr); 1958 1959 /* Session::FeatureCurrentState, get */ 1960 hr = Session_FeatureCurrentState(pSession, L"One", &myint); 1961 ok(hr == S_OK, "Session_FeatureCurrentState failed, hresult %#lx\n", hr); 1962 ok(myint == INSTALLSTATE_UNKNOWN, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN); 1963 1964 /* Session::Message */ 1965 hr = Installer_CreateRecord(0, &record); 1966 ok(hr == S_OK, "Installer_CreateRecord failed: %#lx\n", hr); 1967 hr = Session_Message(pSession, INSTALLMESSAGE_INFO, record, &myint); 1968 ok(hr == S_OK, "Session_Message failed: %#lx\n", hr); 1969 ok(myint == 0, "Session_Message returned %x\n", myint); 1970 1971 /* Session::EvaluateCondition */ 1972 hr = Session_EvaluateCondition(pSession, L"!One>0", &myint); 1973 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr); 1974 ok(myint == MSICONDITION_FALSE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN); 1975 1976 hr = Session_EvaluateCondition(pSession, L"!One=-1", &myint); 1977 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr); 1978 ok(myint == MSICONDITION_TRUE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN); 1979 1980 /* Session::FeatureRequestState, put */ 1981 hr = Session_FeatureRequestStatePut(pSession, L"One", INSTALLSTATE_ADVERTISED); 1982 ok(hr == S_OK, "Session_FeatureRequestStatePut failed, hresult %#lx\n", hr); 1983 hr = Session_FeatureRequestStateGet(pSession, L"One", &myint); 1984 ok(hr == S_OK, "Session_FeatureRequestStateGet failed, hresult %#lx\n", hr); 1985 ok(myint == INSTALLSTATE_ADVERTISED, "Feature request state was %d but expected %d\n", myint, INSTALLSTATE_ADVERTISED); 1986 1987 /* Session::EvaluateCondition */ 1988 hr = Session_EvaluateCondition(pSession, L"$One=-1", &myint); 1989 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr); 1990 ok(myint == MSICONDITION_FALSE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN); 1991 1992 hr = Session_EvaluateCondition(pSession, L"$One>0", &myint); 1993 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr); 1994 ok(myint == MSICONDITION_TRUE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN); 1995 } 1996 1997 /* delete key and all its subkeys */ 1998 static DWORD delete_key( HKEY hkey ) 1999 { 2000 char name[MAX_PATH]; 2001 DWORD ret; 2002 2003 while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name)))) 2004 { 2005 HKEY tmp; 2006 if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp ))) 2007 { 2008 ret = delete_key( tmp ); 2009 RegCloseKey( tmp ); 2010 } 2011 if (ret) break; 2012 } 2013 if (ret != ERROR_NO_MORE_ITEMS) return ret; 2014 RegDeleteKeyA( hkey, "" ); 2015 return 0; 2016 } 2017 2018 static void test_Installer_RegistryValue(void) 2019 { 2020 static const DWORD qw[2] = { 0x12345678, 0x87654321 }; 2021 VARIANT varresult; 2022 VARIANTARG vararg; 2023 WCHAR szString[MAX_PATH]; 2024 HKEY hkey, hkey_sub; 2025 HKEY curr_user = (HKEY)1; 2026 HRESULT hr; 2027 BOOL bRet; 2028 LONG lRet; 2029 2030 /* Delete keys */ 2031 SetLastError(0xdeadbeef); 2032 lRet = RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Test", &hkey ); 2033 if (!lRet && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 2034 { 2035 win_skip("Needed W-functions are not implemented\n"); 2036 return; 2037 } 2038 if (!lRet) 2039 delete_key( hkey ); 2040 2041 /* Does our key exist? Shouldn't; check with all three possible value parameter types */ 2042 hr = Installer_RegistryValueE(curr_user, L"Software\\Wine\\Test", &bRet); 2043 ok(hr == S_OK, "Installer_RegistryValueE failed, hresult %#lx\n", hr); 2044 ok(!bRet, "Registry key expected to not exist, but Installer_RegistryValue claims it does\n"); 2045 2046 memset(szString, 0, sizeof(szString)); 2047 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", NULL, szString); 2048 ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueW failed, hresult %#lx\n", hr); 2049 2050 memset(szString, 0, sizeof(szString)); 2051 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", 0, szString, VT_BSTR); 2052 ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueI failed, hresult %#lx\n", hr); 2053 2054 /* Create key */ 2055 ok(!RegCreateKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Test", &hkey ), "RegCreateKeyW failed\n"); 2056 2057 ok(!RegSetValueExW(hkey, L"One", 0, REG_SZ, (const BYTE *)L"One", sizeof(L"one")), 2058 "RegSetValueExW failed\n"); 2059 ok(!RegSetValueExW(hkey, L"Two", 0, REG_DWORD, (const BYTE *)qw, 4), 2060 "RegSetValueExW failed\n"); 2061 ok(!RegSetValueExW(hkey, L"Three", 0, REG_BINARY, (const BYTE *)qw, 4), 2062 "RegSetValueExW failed\n"); 2063 bRet = SetEnvironmentVariableA("MSITEST", "Four"); 2064 ok(bRet, "SetEnvironmentVariableA failed %lu\n", GetLastError()); 2065 ok(!RegSetValueExW(hkey, L"Four", 0, REG_EXPAND_SZ, (const BYTE *)L"%MSITEST%", sizeof(L"%MSITEST%")), 2066 "RegSetValueExW failed\n"); 2067 ok(!RegSetValueExW(hkey, L"Five\0Hi\0", 0, REG_MULTI_SZ, (const BYTE *)L"Five\0Hi\0", sizeof(L"Five\0Hi\0")), 2068 "RegSetValueExW failed\n"); 2069 ok(!RegSetValueExW(hkey, L"Six", 0, REG_QWORD, (const BYTE *)qw, 8), 2070 "RegSetValueExW failed\n"); 2071 ok(!RegSetValueExW(hkey, L"Seven", 0, REG_NONE, NULL, 0), 2072 "RegSetValueExW failed\n"); 2073 2074 ok(!RegSetValueExW(hkey, NULL, 0, REG_SZ, (const BYTE *)L"One", sizeof(L"One")), 2075 "RegSetValueExW failed\n"); 2076 2077 ok(!RegCreateKeyW( hkey, L"Eight", &hkey_sub ), "RegCreateKeyW failed\n"); 2078 2079 /* Does our key exist? It should, and make sure we retrieve the correct default value */ 2080 bRet = FALSE; 2081 hr = Installer_RegistryValueE(curr_user, L"Software\\Wine\\Test", &bRet); 2082 ok(hr == S_OK, "Installer_RegistryValueE failed, hresult %#lx\n", hr); 2083 ok(bRet, "Registry key expected to exist, but Installer_RegistryValue claims it does not\n"); 2084 2085 memset(szString, 0, sizeof(szString)); 2086 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", NULL, szString); 2087 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr); 2088 ok_w2("Default registry value \"%s\" does not match expected \"%s\"\n", szString, L"One"); 2089 2090 /* Ask for the value of a nonexistent key */ 2091 memset(szString, 0, sizeof(szString)); 2092 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"%MSITEST%", szString); 2093 ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueW failed, hresult %#lx\n", hr); 2094 2095 /* Get values of keys */ 2096 memset(szString, 0, sizeof(szString)); 2097 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"One", szString); 2098 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr); 2099 ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, L"One"); 2100 2101 VariantInit(&vararg); 2102 V_VT(&vararg) = VT_BSTR; 2103 V_BSTR(&vararg) = SysAllocString(L"Two"); 2104 hr = Installer_RegistryValue(curr_user, L"Software\\Wine\\Test", vararg, &varresult, VT_I4); 2105 ok(hr == S_OK, "Installer_RegistryValue failed, hresult %#lx\n", hr); 2106 ok(V_I4(&varresult) == 305419896, "Registry value %ld does not match expected value\n", V_I4(&varresult)); 2107 VariantClear(&varresult); 2108 2109 memset(szString, 0, sizeof(szString)); 2110 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"Three", szString); 2111 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr); 2112 ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, L"(REG_BINARY)"); 2113 2114 memset(szString, 0, sizeof(szString)); 2115 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"Four", szString); 2116 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr); 2117 ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, L"Four"); 2118 2119 /* Vista does not NULL-terminate this case */ 2120 memset(szString, 0, sizeof(szString)); 2121 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"Five\0Hi\0", szString); 2122 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr); 2123 ok_w2n("Registry value \"%s\" does not match expected \"%s\"\n", 2124 szString, L"Five\nHi", lstrlenW(L"Five\nHi")); 2125 2126 memset(szString, 0, sizeof(szString)); 2127 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"Six", szString); 2128 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr); 2129 ok(!lstrcmpW(szString, L"(REG_\?\?)") || broken(!lstrcmpW(szString, L"(REG_]")), 2130 "Registry value does not match\n"); 2131 2132 VariantInit(&vararg); 2133 V_VT(&vararg) = VT_BSTR; 2134 V_BSTR(&vararg) = SysAllocString(L"Seven"); 2135 hr = Installer_RegistryValue(curr_user, L"Software\\Wine\\Test", vararg, &varresult, VT_EMPTY); 2136 ok(hr == S_OK, "Installer_RegistryValue failed, hresult %#lx\n", hr); 2137 2138 /* Get string class name for the key */ 2139 memset(szString, 0, sizeof(szString)); 2140 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", 0, szString, VT_BSTR); 2141 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr); 2142 ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, L""); 2143 2144 /* Get name of a value by positive number (RegEnumValue like), valid index */ 2145 memset(szString, 0, sizeof(szString)); 2146 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", 2, szString, VT_BSTR); 2147 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr); 2148 /* RegEnumValue order seems different on wine */ 2149 todo_wine ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, L"Two"); 2150 2151 /* Get name of a value by positive number (RegEnumValue like), invalid index */ 2152 memset(szString, 0, sizeof(szString)); 2153 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", 10, szString, VT_EMPTY); 2154 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr); 2155 2156 /* Get name of a subkey by negative number (RegEnumValue like), valid index */ 2157 memset(szString, 0, sizeof(szString)); 2158 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", -1, szString, VT_BSTR); 2159 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr); 2160 ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, L"Eight"); 2161 2162 /* Get name of a subkey by negative number (RegEnumValue like), invalid index */ 2163 memset(szString, 0, sizeof(szString)); 2164 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", -10, szString, VT_EMPTY); 2165 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr); 2166 2167 /* clean up */ 2168 delete_key(hkey); 2169 } 2170 2171 static void test_Installer_Products(BOOL bProductInstalled) 2172 { 2173 WCHAR szString[MAX_PATH]; 2174 HRESULT hr; 2175 int idx; 2176 IUnknown *pUnk = NULL; 2177 IEnumVARIANT *pEnum = NULL; 2178 VARIANT var; 2179 ULONG celt; 2180 int iCount, iValue; 2181 IDispatch *pStringList = NULL; 2182 BOOL bProductFound = FALSE; 2183 2184 /* Installer::Products */ 2185 hr = Installer_Products(&pStringList); 2186 ok(hr == S_OK, "Installer_Products failed, hresult %#lx\n", hr); 2187 if (hr == S_OK) 2188 { 2189 /* StringList::_NewEnum */ 2190 hr = StringList__NewEnum(pStringList, &pUnk); 2191 ok(hr == S_OK, "StringList_NewEnum failed, hresult %#lx\n", hr); 2192 if (hr == S_OK) 2193 { 2194 hr = IUnknown_QueryInterface(pUnk, &IID_IEnumVARIANT, (void **)&pEnum); 2195 ok (hr == S_OK, "IUnknown::QueryInterface returned %#lx\n", hr); 2196 } 2197 if (!pEnum) 2198 skip("IEnumVARIANT tests\n"); 2199 2200 /* StringList::Count */ 2201 hr = StringList_Count(pStringList, &iCount); 2202 ok(hr == S_OK, "StringList_Count failed, hresult %#lx\n", hr); 2203 2204 for (idx=0; idx<iCount; idx++) 2205 { 2206 /* StringList::Item */ 2207 memset(szString, 0, sizeof(szString)); 2208 hr = StringList_Item(pStringList, idx, szString); 2209 ok(hr == S_OK, "StringList_Item failed (idx %d, count %d), hresult %#lx\n", idx, iCount, hr); 2210 2211 if (hr == S_OK) 2212 { 2213 /* Installer::ProductState */ 2214 hr = Installer_ProductState(szString, &iValue); 2215 ok(hr == S_OK, "Installer_ProductState failed, hresult %#lx\n", hr); 2216 if (hr == S_OK) 2217 ok(iValue == INSTALLSTATE_DEFAULT || iValue == INSTALLSTATE_ADVERTISED, 2218 "Installer_ProductState returned %d, expected %d or %d\n", iValue, INSTALLSTATE_DEFAULT, INSTALLSTATE_ADVERTISED); 2219 2220 /* Not found our product code yet? Check */ 2221 if (!bProductFound && !lstrcmpW(szString, L"{837450fa-a39b-4bc8-b321-08b393f784b3}")) 2222 bProductFound = TRUE; 2223 2224 /* IEnumVARIANT::Next */ 2225 if (pEnum) 2226 { 2227 hr = IEnumVARIANT_Next(pEnum, 1, &var, &celt); 2228 ok(hr == S_OK, "IEnumVARIANT_Next failed (idx %d, count %d), hresult %#lx\n", idx, iCount, hr); 2229 ok(celt == 1, "%lu items were retrieved, expected 1\n", celt); 2230 ok(V_VT(&var) == VT_BSTR, "IEnumVARIANT_Next returned variant of type %d, expected %d\n", V_VT(&var), VT_BSTR); 2231 ok_w2("%s returned by StringList_Item does not match %s returned by IEnumVARIANT_Next\n", szString, V_BSTR(&var)); 2232 VariantClear(&var); 2233 } 2234 } 2235 } 2236 2237 if (bProductInstalled) 2238 { 2239 ok(bProductInstalled == bProductFound, "Product expected to %s installed but product code was %s\n", 2240 bProductInstalled ? "be" : "not be", 2241 bProductFound ? "found" : "not found"); 2242 } 2243 2244 if (pEnum) 2245 { 2246 IEnumVARIANT *pEnum2 = NULL; 2247 2248 if (0) /* Crashes on Windows XP */ 2249 { 2250 /* IEnumVARIANT::Clone, NULL pointer */ 2251 IEnumVARIANT_Clone(pEnum, NULL); 2252 } 2253 2254 /* IEnumVARIANT::Clone */ 2255 hr = IEnumVARIANT_Clone(pEnum, &pEnum2); 2256 ok(hr == S_OK, "IEnumVARIANT_Clone failed, hresult %#lx\n", hr); 2257 if (hr == S_OK) 2258 { 2259 /* IEnumVARIANT::Clone is supposed to save the position, but it actually just goes back to the beginning */ 2260 2261 /* IEnumVARIANT::Next of the clone */ 2262 if (iCount) 2263 { 2264 hr = IEnumVARIANT_Next(pEnum2, 1, &var, &celt); 2265 ok(hr == S_OK, "IEnumVARIANT_Next failed, hresult %#lx\n", hr); 2266 ok(celt == 1, "%lu items were retrieved, expected 0\n", celt); 2267 ok(V_VT(&var) == VT_BSTR, "IEnumVARIANT_Next returned variant of type %d, expected %d\n", V_VT(&var), VT_BSTR); 2268 VariantClear(&var); 2269 } 2270 else 2271 skip("IEnumVARIANT::Next of clone will not return success with 0 products\n"); 2272 2273 IEnumVARIANT_Release(pEnum2); 2274 } 2275 2276 /* IEnumVARIANT::Skip should fail */ 2277 hr = IEnumVARIANT_Skip(pEnum, 1); 2278 ok(hr == S_FALSE, "IEnumVARIANT_Skip failed, hresult %#lx\n", hr); 2279 2280 /* IEnumVARIANT::Next, NULL variant pointer */ 2281 hr = IEnumVARIANT_Next(pEnum, 1, NULL, &celt); 2282 ok(hr == S_FALSE, "IEnumVARIANT_Next failed, hresult %#lx\n", hr); 2283 ok(celt == 0, "%lu items were retrieved, expected 0\n", celt); 2284 2285 /* IEnumVARIANT::Next, should not return any more items */ 2286 hr = IEnumVARIANT_Next(pEnum, 1, &var, &celt); 2287 ok(hr == S_FALSE, "IEnumVARIANT_Next failed, hresult %#lx\n", hr); 2288 ok(celt == 0, "%lu items were retrieved, expected 0\n", celt); 2289 VariantClear(&var); 2290 2291 /* IEnumVARIANT::Reset */ 2292 hr = IEnumVARIANT_Reset(pEnum); 2293 ok(hr == S_OK, "IEnumVARIANT_Reset failed, hresult %#lx\n", hr); 2294 2295 if (iCount) 2296 { 2297 /* IEnumVARIANT::Skip to the last product */ 2298 hr = IEnumVARIANT_Skip(pEnum, iCount-1); 2299 ok(hr == S_OK, "IEnumVARIANT_Skip failed, hresult %#lx\n", hr); 2300 2301 /* IEnumVARIANT::Next should match the very last retrieved value, also makes sure it works with 2302 * NULL celt pointer. */ 2303 hr = IEnumVARIANT_Next(pEnum, 1, &var, NULL); 2304 ok(hr == S_OK, "IEnumVARIANT_Next failed (idx %d, count %d), hresult %#lx\n", idx, iCount, hr); 2305 ok(V_VT(&var) == VT_BSTR, "IEnumVARIANT_Next returned variant of type %d, expected %d\n", V_VT(&var), VT_BSTR); 2306 ok_w2("%s returned by StringList_Item does not match %s returned by IEnumVARIANT_Next\n", szString, V_BSTR(&var)); 2307 VariantClear(&var); 2308 } 2309 else 2310 skip("IEnumVARIANT::Skip impossible for 0 products\n"); 2311 } 2312 2313 /* StringList::Item using an invalid index */ 2314 memset(szString, 0, sizeof(szString)); 2315 hr = StringList_Item(pStringList, iCount, szString); 2316 ok(hr == DISP_E_BADINDEX, "StringList_Item for an invalid index did not return DISP_E_BADINDEX, hresult %#lx\n", hr); 2317 2318 if (pEnum) IEnumVARIANT_Release(pEnum); 2319 if (pUnk) IUnknown_Release(pUnk); 2320 IDispatch_Release(pStringList); 2321 } 2322 } 2323 2324 /* Delete a registry subkey, including all its subkeys (RegDeleteKey does not work on keys with subkeys without 2325 * deleting the subkeys first) */ 2326 static UINT delete_registry_key(HKEY hkeyParent, LPCSTR subkey, REGSAM access) 2327 { 2328 UINT ret; 2329 CHAR *string = NULL; 2330 HKEY hkey; 2331 DWORD dwSize; 2332 2333 ret = RegOpenKeyExA(hkeyParent, subkey, 0, access, &hkey); 2334 if (ret != ERROR_SUCCESS) return ret; 2335 ret = RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, &dwSize, NULL, NULL, NULL, NULL, NULL, NULL); 2336 if (ret != ERROR_SUCCESS) return ret; 2337 if (!(string = malloc(++dwSize))) return ERROR_NOT_ENOUGH_MEMORY; 2338 2339 while (RegEnumKeyA(hkey, 0, string, dwSize) == ERROR_SUCCESS) 2340 delete_registry_key(hkey, string, access); 2341 2342 RegCloseKey(hkey); 2343 free(string); 2344 delete_key_portable(hkeyParent, subkey, access); 2345 return ERROR_SUCCESS; 2346 } 2347 2348 /* Find a specific registry subkey at any depth within the given key and subkey and return its parent key. */ 2349 static UINT find_registry_key(HKEY hkeyParent, LPCSTR subkey, LPCSTR findkey, REGSAM access, HKEY *phkey) 2350 { 2351 UINT ret; 2352 CHAR *string = NULL; 2353 int idx = 0; 2354 HKEY hkey; 2355 DWORD dwSize; 2356 BOOL found = FALSE; 2357 2358 *phkey = 0; 2359 2360 ret = RegOpenKeyExA(hkeyParent, subkey, 0, access, &hkey); 2361 if (ret != ERROR_SUCCESS) return ret; 2362 ret = RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, &dwSize, NULL, NULL, NULL, NULL, NULL, NULL); 2363 if (ret != ERROR_SUCCESS) return ret; 2364 if (!(string = malloc(++dwSize))) return ERROR_NOT_ENOUGH_MEMORY; 2365 2366 while (!found && 2367 RegEnumKeyA(hkey, idx++, string, dwSize) == ERROR_SUCCESS) 2368 { 2369 if (!strcmp(string, findkey)) 2370 { 2371 *phkey = hkey; 2372 found = TRUE; 2373 } 2374 else if (find_registry_key(hkey, string, findkey, access, phkey) == ERROR_SUCCESS) found = TRUE; 2375 } 2376 2377 if (*phkey != hkey) RegCloseKey(hkey); 2378 free(string); 2379 return (found ? ERROR_SUCCESS : ERROR_FILE_NOT_FOUND); 2380 } 2381 2382 static void test_Installer_InstallProduct(void) 2383 { 2384 HRESULT hr; 2385 CHAR path[MAX_PATH]; 2386 WCHAR szString[MAX_PATH]; 2387 LONG res; 2388 HKEY hkey; 2389 DWORD num, size, type; 2390 int iValue, iCount; 2391 IDispatch *pStringList = NULL; 2392 REGSAM access = KEY_ALL_ACCESS; 2393 2394 if (is_process_limited()) 2395 { 2396 /* In fact InstallProduct would succeed but then Windows XP 2397 * would not allow us to clean up the registry! 2398 */ 2399 skip("Installer_InstallProduct (insufficient privileges)\n"); 2400 return; 2401 } 2402 2403 if (is_wow64) 2404 access |= KEY_WOW64_64KEY; 2405 2406 create_test_files(); 2407 2408 /* Avoid an interactive dialog in case of insufficient privileges. */ 2409 hr = Installer_UILevelPut(INSTALLUILEVEL_NONE); 2410 ok(hr == S_OK, "Expected UILevel property put invoke to return S_OK, got %#lx\n", hr); 2411 2412 /* Installer::InstallProduct */ 2413 hr = Installer_InstallProduct(L"winetest-automation.msi", NULL); 2414 if (hr == DISP_E_EXCEPTION) 2415 { 2416 skip("InstallProduct failed, insufficient rights?\n"); 2417 delete_test_files(); 2418 return; 2419 } 2420 ok(hr == S_OK, "Installer_InstallProduct failed, hresult %#lx\n", hr); 2421 2422 /* Installer::ProductState for our product code, which has been installed */ 2423 hr = Installer_ProductState(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", &iValue); 2424 ok(hr == S_OK, "Installer_ProductState failed, hresult %#lx\n", hr); 2425 ok(iValue == INSTALLSTATE_DEFAULT, "Installer_ProductState returned %d, expected %d\n", iValue, INSTALLSTATE_DEFAULT); 2426 2427 /* Installer::ProductInfo for our product code */ 2428 2429 /* NULL attribute */ 2430 memset(szString, 0, sizeof(szString)); 2431 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", NULL, szString); 2432 ok(hr == DISP_E_EXCEPTION, "Installer_ProductInfo failed, hresult %#lx\n", hr); 2433 ok_exception(hr, L"ProductInfo,Product,Attribute"); 2434 2435 /* Nonexistent attribute */ 2436 memset(szString, 0, sizeof(szString)); 2437 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"winetest-automation.msi", szString); 2438 ok(hr == DISP_E_EXCEPTION, "Installer_ProductInfo failed, hresult %#lx\n", hr); 2439 ok_exception(hr, L"ProductInfo,Product,Attribute"); 2440 2441 /* Package name */ 2442 memset(szString, 0, sizeof(szString)); 2443 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"PackageName", szString); 2444 ok(hr == S_OK, "Installer_ProductInfo failed, hresult %#lx\n", hr); 2445 todo_wine ok_w2("Installer_ProductInfo returned %s but expected %s\n", szString, L"winetest-automation.msi"); 2446 2447 /* Product name */ 2448 memset(szString, 0, sizeof(szString)); 2449 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"ProductName", szString); 2450 ok(hr == S_OK, "Installer_ProductInfo failed, hresult %#lx\n", hr); 2451 todo_wine ok_w2("Installer_ProductInfo returned %s but expected %s\n", szString, L"MSITEST"); 2452 2453 /* Installer::Products */ 2454 test_Installer_Products(TRUE); 2455 2456 /* Installer::RelatedProducts for our upgrade code */ 2457 hr = Installer_RelatedProducts(L"{CE067E8D-2E1A-4367-B734-4EB2BDAD6565}", &pStringList); 2458 ok(hr == S_OK, "Installer_RelatedProducts failed, hresult %#lx\n", hr); 2459 if (hr == S_OK) 2460 { 2461 /* StringList::Count */ 2462 hr = StringList_Count(pStringList, &iCount); 2463 ok(hr == S_OK, "StringList_Count failed, hresult %#lx\n", hr); 2464 ok(iCount == 1, "Expected one related product but found %d\n", iCount); 2465 2466 /* StringList::Item */ 2467 memset(szString, 0, sizeof(szString)); 2468 hr = StringList_Item(pStringList, 0, szString); 2469 ok(hr == S_OK, "StringList_Item failed (idx 0, count %d), hresult %#lx\n", iCount, hr); 2470 ok_w2("StringList_Item returned %s but expected %s\n", szString, L"{837450fa-a39b-4bc8-b321-08b393f784b3}"); 2471 2472 IDispatch_Release(pStringList); 2473 } 2474 2475 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"LocalPackage", szString); 2476 ok(hr == S_OK, "Installer_ProductInfo failed, hresult %#lx\n", hr); 2477 DeleteFileW( szString ); 2478 2479 /* Check & clean up installed files & registry keys */ 2480 ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n"); 2481 ok(delete_pf("msitest\\cabout\\new", FALSE), "Directory not created\n"); 2482 ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n"); 2483 ok(delete_pf("msitest\\cabout", FALSE), "Directory not created\n"); 2484 ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n"); 2485 ok(delete_pf("msitest\\changed", FALSE), "Directory not created\n"); 2486 ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n"); 2487 ok(delete_pf("msitest\\first", FALSE), "Directory not created\n"); 2488 ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n"); 2489 ok(delete_pf("msitest\\filename", TRUE), "File not installed\n"); 2490 ok(delete_pf("msitest", FALSE), "Directory not created\n"); 2491 2492 res = RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Wine\\msitest", &hkey); 2493 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2494 2495 size = MAX_PATH; 2496 type = REG_SZ; 2497 res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size); 2498 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2499 ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path); 2500 2501 size = MAX_PATH; 2502 type = REG_SZ; 2503 res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size); 2504 ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", res); 2505 2506 size = sizeof(num); 2507 type = REG_DWORD; 2508 res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size); 2509 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2510 ok(num == 314, "Expected 314, got %lu\n", num); 2511 2512 size = MAX_PATH; 2513 type = REG_SZ; 2514 res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size); 2515 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2516 ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path); 2517 2518 RegCloseKey(hkey); 2519 2520 res = RegDeleteKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Wine\\msitest"); 2521 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2522 2523 /* Remove registry keys written by RegisterProduct standard action */ 2524 res = delete_key_portable(HKEY_LOCAL_MACHINE, 2525 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{837450fa-a39b-4bc8-b321-08b393f784b3}", 2526 KEY_WOW64_32KEY); 2527 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2528 2529 res = delete_key_portable(HKEY_LOCAL_MACHINE, 2530 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UpgradeCodes\\D8E760ECA1E276347B43E42BDBDA5656", access); 2531 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2532 2533 res = find_registry_key(HKEY_LOCAL_MACHINE, 2534 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData", "af054738b93a8cb43b12803b397f483b", access, &hkey); 2535 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2536 2537 res = delete_registry_key(hkey, "af054738b93a8cb43b12803b397f483b", access); 2538 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2539 RegCloseKey(hkey); 2540 2541 res = delete_key_portable(HKEY_LOCAL_MACHINE, 2542 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\Products\\af054738b93a8cb43b12803b397f483b", access); 2543 ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", res); 2544 2545 /* Remove registry keys written by PublishProduct standard action */ 2546 res = RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Installer", &hkey); 2547 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2548 2549 res = delete_registry_key(hkey, "Products\\af054738b93a8cb43b12803b397f483b", KEY_ALL_ACCESS); 2550 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2551 2552 res = RegDeleteKeyA(hkey, "UpgradeCodes\\D8E760ECA1E276347B43E42BDBDA5656"); 2553 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res); 2554 2555 RegCloseKey(hkey); 2556 2557 /* Delete installation files we created */ 2558 delete_test_files(); 2559 } 2560 2561 static void test_Installer(void) 2562 { 2563 WCHAR szPath[MAX_PATH]; 2564 HRESULT hr; 2565 IDispatch *pSession = NULL, *pDatabase = NULL, *pRecord = NULL, *pStringList = NULL, *pSumInfo = NULL; 2566 int iValue, iCount; 2567 2568 if (!pInstaller) return; 2569 2570 /* Installer::CreateRecord */ 2571 2572 /* Test for error */ 2573 hr = Installer_CreateRecord(-1, &pRecord); 2574 ok(hr == DISP_E_EXCEPTION, "Installer_CreateRecord failed, hresult %#lx\n", hr); 2575 ok_exception(hr, L"CreateRecord,Count"); 2576 2577 /* Test for success */ 2578 hr = Installer_CreateRecord(1, &pRecord); 2579 ok(hr == S_OK, "Installer_CreateRecord failed, hresult %#lx\n", hr); 2580 ok(pRecord != NULL, "Installer_CreateRecord should not have returned NULL record\n"); 2581 if (pRecord) 2582 { 2583 /* Record::FieldCountGet */ 2584 hr = Record_FieldCountGet(pRecord, &iValue); 2585 ok(hr == S_OK, "Record_FiledCountGet failed, hresult %#lx\n", hr); 2586 ok(iValue == 1, "Record_FieldCountGet result was %d but expected 1\n", iValue); 2587 2588 /* Record::IntegerDataGet */ 2589 hr = Record_IntegerDataGet(pRecord, 1, &iValue); 2590 ok(hr == S_OK, "Record_IntegerDataGet failed, hresult %#lx\n", hr); 2591 ok(iValue == MSI_NULL_INTEGER, "Record_IntegerDataGet result was %d but expected %d\n", iValue, MSI_NULL_INTEGER); 2592 2593 /* Record::IntegerDataGet, bad index */ 2594 hr = Record_IntegerDataGet(pRecord, 10, &iValue); 2595 ok(hr == S_OK, "Record_IntegerDataGet failed, hresult %#lx\n", hr); 2596 ok(iValue == MSI_NULL_INTEGER, "Record_IntegerDataGet result was %d but expected %d\n", iValue, MSI_NULL_INTEGER); 2597 2598 /* Record::IntegerDataPut */ 2599 hr = Record_IntegerDataPut(pRecord, 1, 100); 2600 ok(hr == S_OK, "Record_IntegerDataPut failed, hresult %#lx\n", hr); 2601 2602 /* Record::IntegerDataPut, bad index */ 2603 hr = Record_IntegerDataPut(pRecord, 10, 100); 2604 ok(hr == DISP_E_EXCEPTION, "Record_IntegerDataPut failed, hresult %#lx\n", hr); 2605 ok_exception(hr, L"IntegerData,Field"); 2606 2607 /* Record::IntegerDataGet */ 2608 hr = Record_IntegerDataGet(pRecord, 1, &iValue); 2609 ok(hr == S_OK, "Record_IntegerDataGet failed, hresult %#lx\n", hr); 2610 ok(iValue == 100, "Record_IntegerDataGet result was %d but expected 100\n", iValue); 2611 2612 IDispatch_Release(pRecord); 2613 } 2614 2615 create_package(szPath); 2616 2617 /* Installer::OpenPackage */ 2618 hr = Installer_OpenPackage(szPath, 0, &pSession); 2619 if (hr == DISP_E_EXCEPTION) 2620 { 2621 skip("OpenPackage failed, insufficient rights?\n"); 2622 DeleteFileW(szPath); 2623 return; 2624 } 2625 ok(hr == S_OK, "Installer_OpenPackage failed, hresult %#lx\n", hr); 2626 if (hr == S_OK) 2627 { 2628 test_Session(pSession); 2629 IDispatch_Release(pSession); 2630 } 2631 2632 /* Installer::OpenDatabase */ 2633 hr = Installer_OpenDatabase(szPath, (INT_PTR)MSIDBOPEN_TRANSACT, &pDatabase); 2634 ok(hr == S_OK, "Installer_OpenDatabase failed, hresult %#lx\n", hr); 2635 if (hr == S_OK) 2636 { 2637 test_Database(pDatabase, FALSE); 2638 IDispatch_Release(pDatabase); 2639 } 2640 2641 /* Installer::SummaryInformation */ 2642 hr = Installer_SummaryInformation(szPath, 0, &pSumInfo); 2643 ok(hr == S_OK, "Installer_SummaryInformation failed, hresult %#lx\n", hr); 2644 if (hr == S_OK) 2645 { 2646 test_SummaryInfo(pSumInfo, summary_info, ARRAY_SIZE(summary_info), TRUE); 2647 IDispatch_Release(pSumInfo); 2648 } 2649 2650 hr = Installer_SummaryInformation(NULL, 0, &pSumInfo); 2651 ok(hr == DISP_E_EXCEPTION, "Installer_SummaryInformation failed, hresult %#lx\n", hr); 2652 2653 /* Installer::RegistryValue */ 2654 test_Installer_RegistryValue(); 2655 2656 /* Installer::ProductState for our product code, which should not be installed */ 2657 hr = Installer_ProductState(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", &iValue); 2658 ok(hr == S_OK, "Installer_ProductState failed, hresult %#lx\n", hr); 2659 ok(iValue == INSTALLSTATE_UNKNOWN, "Installer_ProductState returned %d, expected %d\n", iValue, INSTALLSTATE_UNKNOWN); 2660 2661 /* Installer::ProductInfo for our product code, which should not be installed */ 2662 2663 /* Package name */ 2664 memset(szPath, 0, sizeof(szPath)); 2665 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"PackageName", szPath); 2666 ok(hr == DISP_E_EXCEPTION, "Installer_ProductInfo failed, hresult %#lx\n", hr); 2667 ok_exception(hr, L"ProductInfo,Product,Attribute"); 2668 2669 /* NULL attribute and NULL product code */ 2670 memset(szPath, 0, sizeof(szPath)); 2671 hr = Installer_ProductInfo(NULL, NULL, szPath); 2672 ok(hr == DISP_E_EXCEPTION, "Installer_ProductInfo failed, hresult %#lx\n", hr); 2673 ok_exception(hr, L"ProductInfo,Product,Attribute"); 2674 2675 /* Installer::Products */ 2676 test_Installer_Products(FALSE); 2677 2678 /* Installer::RelatedProducts for our upgrade code, should not find anything */ 2679 hr = Installer_RelatedProducts(L"{CE067E8D-2E1A-4367-B734-4EB2BDAD6565}", &pStringList); 2680 ok(hr == S_OK, "Installer_RelatedProducts failed, hresult %#lx\n", hr); 2681 if (hr == S_OK) 2682 { 2683 /* StringList::Count */ 2684 hr = StringList_Count(pStringList, &iCount); 2685 ok(hr == S_OK, "StringList_Count failed, hresult %#lx\n", hr); 2686 ok(!iCount, "Expected no related products but found %d\n", iCount); 2687 2688 IDispatch_Release(pStringList); 2689 } 2690 2691 /* Installer::Version */ 2692 memset(szPath, 0, sizeof(szPath)); 2693 hr = Installer_VersionGet(szPath); 2694 ok(hr == S_OK, "Installer_VersionGet failed, hresult %#lx\n", hr); 2695 2696 /* Installer::InstallProduct and other tests that depend on our product being installed */ 2697 test_Installer_InstallProduct(); 2698 } 2699 2700 START_TEST(automation) 2701 { 2702 DWORD len; 2703 char temp_path[MAX_PATH], prev_path[MAX_PATH]; 2704 HRESULT hr; 2705 CLSID clsid; 2706 IUnknown *pUnk; 2707 2708 init_functionpointers(); 2709 2710 if (pIsWow64Process) 2711 pIsWow64Process(GetCurrentProcess(), &is_wow64); 2712 2713 GetSystemTimeAsFileTime(&systemtime); 2714 2715 GetCurrentDirectoryA(MAX_PATH, prev_path); 2716 GetTempPathA(MAX_PATH, temp_path); 2717 SetCurrentDirectoryA(temp_path); 2718 2719 lstrcpyA(CURR_DIR, temp_path); 2720 len = lstrlenA(CURR_DIR); 2721 2722 if(len && (CURR_DIR[len - 1] == '\\')) 2723 CURR_DIR[len - 1] = 0; 2724 2725 get_program_files_dir(PROG_FILES_DIR); 2726 2727 hr = OleInitialize(NULL); 2728 ok (hr == S_OK, "OleInitialize returned %#lx\n", hr); 2729 hr = CLSIDFromProgID(L"WindowsInstaller.Installer", &clsid); 2730 ok (hr == S_OK, "CLSIDFromProgID returned %#lx\n", hr); 2731 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk); 2732 ok(hr == S_OK, "CoCreateInstance returned %#lx\n", hr); 2733 2734 if (pUnk) 2735 { 2736 hr = IUnknown_QueryInterface(pUnk, &IID_IDispatch, (void **)&pInstaller); 2737 ok (hr == S_OK, "IUnknown::QueryInterface returned %#lx\n", hr); 2738 2739 test_dispid(); 2740 test_dispatch(); 2741 test_Installer(); 2742 2743 IDispatch_Release(pInstaller); 2744 IUnknown_Release(pUnk); 2745 } 2746 2747 OleUninitialize(); 2748 2749 SetCurrentDirectoryA(prev_path); 2750 } 2751