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