1 /* 2 * Implementation of the Microsoft Installer (msi.dll) 3 * 4 * Copyright 2004 Aric Stewart for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "msipriv.h" 22 23 #include <wininet.h> 24 25 WINE_DEFAULT_DEBUG_CHANNEL(msi); 26 27 static void free_feature( MSIFEATURE *feature ) 28 { 29 struct list *item, *cursor; 30 31 LIST_FOR_EACH_SAFE( item, cursor, &feature->Children ) 32 { 33 FeatureList *fl = LIST_ENTRY( item, FeatureList, entry ); 34 list_remove( &fl->entry ); 35 msi_free( fl ); 36 } 37 38 LIST_FOR_EACH_SAFE( item, cursor, &feature->Components ) 39 { 40 ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); 41 list_remove( &cl->entry ); 42 msi_free( cl ); 43 } 44 msi_free( feature->Feature ); 45 msi_free( feature->Feature_Parent ); 46 msi_free( feature->Directory ); 47 msi_free( feature->Description ); 48 msi_free( feature->Title ); 49 msi_free( feature ); 50 } 51 52 static void free_folder( MSIFOLDER *folder ) 53 { 54 struct list *item, *cursor; 55 56 LIST_FOR_EACH_SAFE( item, cursor, &folder->children ) 57 { 58 FolderList *fl = LIST_ENTRY( item, FolderList, entry ); 59 list_remove( &fl->entry ); 60 msi_free( fl ); 61 } 62 msi_free( folder->Parent ); 63 msi_free( folder->Directory ); 64 msi_free( folder->TargetDefault ); 65 msi_free( folder->SourceLongPath ); 66 msi_free( folder->SourceShortPath ); 67 msi_free( folder->ResolvedTarget ); 68 msi_free( folder->ResolvedSource ); 69 msi_free( folder ); 70 } 71 72 static void free_extension( MSIEXTENSION *ext ) 73 { 74 struct list *item, *cursor; 75 76 LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs ) 77 { 78 MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry ); 79 80 list_remove( &verb->entry ); 81 msi_free( verb->Verb ); 82 msi_free( verb->Command ); 83 msi_free( verb->Argument ); 84 msi_free( verb ); 85 } 86 87 msi_free( ext->Extension ); 88 msi_free( ext->ProgIDText ); 89 msi_free( ext ); 90 } 91 92 static void free_assembly( MSIASSEMBLY *assembly ) 93 { 94 msi_free( assembly->feature ); 95 msi_free( assembly->manifest ); 96 msi_free( assembly->application ); 97 msi_free( assembly->display_name ); 98 if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir ); 99 msi_free( assembly->tempdir ); 100 msi_free( assembly ); 101 } 102 103 void msi_free_action_script( MSIPACKAGE *package, UINT script ) 104 { 105 UINT i; 106 for (i = 0; i < package->script->ActionCount[script]; i++) 107 msi_free( package->script->Actions[script][i] ); 108 109 msi_free( package->script->Actions[script] ); 110 package->script->Actions[script] = NULL; 111 package->script->ActionCount[script] = 0; 112 } 113 114 static void free_package_structures( MSIPACKAGE *package ) 115 { 116 struct list *item, *cursor; 117 118 LIST_FOR_EACH_SAFE( item, cursor, &package->features ) 119 { 120 MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry ); 121 list_remove( &feature->entry ); 122 free_feature( feature ); 123 } 124 125 LIST_FOR_EACH_SAFE( item, cursor, &package->folders ) 126 { 127 MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry ); 128 list_remove( &folder->entry ); 129 free_folder( folder ); 130 } 131 132 LIST_FOR_EACH_SAFE( item, cursor, &package->files ) 133 { 134 MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry ); 135 136 list_remove( &file->entry ); 137 msi_free( file->File ); 138 msi_free( file->FileName ); 139 msi_free( file->ShortName ); 140 msi_free( file->LongName ); 141 msi_free( file->Version ); 142 msi_free( file->Language ); 143 if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath ); 144 msi_free( file->TargetPath ); 145 msi_free( file ); 146 } 147 148 LIST_FOR_EACH_SAFE( item, cursor, &package->components ) 149 { 150 MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry ); 151 152 list_remove( &comp->entry ); 153 msi_free( comp->Component ); 154 msi_free( comp->ComponentId ); 155 msi_free( comp->Directory ); 156 msi_free( comp->Condition ); 157 msi_free( comp->KeyPath ); 158 msi_free( comp->FullKeypath ); 159 if (comp->assembly) free_assembly( comp->assembly ); 160 msi_free( comp ); 161 } 162 163 LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches ) 164 { 165 MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry ); 166 167 list_remove( &patch->entry ); 168 msi_free( patch->path ); 169 msi_free( patch ); 170 } 171 172 /* clean up extension, progid, class and verb structures */ 173 LIST_FOR_EACH_SAFE( item, cursor, &package->classes ) 174 { 175 MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry ); 176 177 list_remove( &cls->entry ); 178 msi_free( cls->clsid ); 179 msi_free( cls->Context ); 180 msi_free( cls->Description ); 181 msi_free( cls->FileTypeMask ); 182 msi_free( cls->IconPath ); 183 msi_free( cls->DefInprocHandler ); 184 msi_free( cls->DefInprocHandler32 ); 185 msi_free( cls->Argument ); 186 msi_free( cls->ProgIDText ); 187 msi_free( cls ); 188 } 189 190 LIST_FOR_EACH_SAFE( item, cursor, &package->extensions ) 191 { 192 MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry ); 193 194 list_remove( &ext->entry ); 195 free_extension( ext ); 196 } 197 198 LIST_FOR_EACH_SAFE( item, cursor, &package->progids ) 199 { 200 MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry ); 201 202 list_remove( &progid->entry ); 203 msi_free( progid->ProgID ); 204 msi_free( progid->Description ); 205 msi_free( progid->IconPath ); 206 msi_free( progid ); 207 } 208 209 LIST_FOR_EACH_SAFE( item, cursor, &package->mimes ) 210 { 211 MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry ); 212 213 list_remove( &mt->entry ); 214 msi_free( mt->suffix ); 215 msi_free( mt->clsid ); 216 msi_free( mt->ContentType ); 217 msi_free( mt ); 218 } 219 220 LIST_FOR_EACH_SAFE( item, cursor, &package->appids ) 221 { 222 MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry ); 223 224 list_remove( &appid->entry ); 225 msi_free( appid->AppID ); 226 msi_free( appid->RemoteServerName ); 227 msi_free( appid->LocalServer ); 228 msi_free( appid->ServiceParameters ); 229 msi_free( appid->DllSurrogate ); 230 msi_free( appid ); 231 } 232 233 LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info ) 234 { 235 MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry ); 236 237 list_remove( &info->entry ); 238 msi_free( info->value ); 239 msi_free( info ); 240 } 241 242 LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media ) 243 { 244 MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry ); 245 246 list_remove( &info->entry ); 247 msi_free( info->volume_label ); 248 msi_free( info->disk_prompt ); 249 msi_free( info ); 250 } 251 252 if (package->script) 253 { 254 INT i; 255 UINT j; 256 257 for (i = 0; i < SCRIPT_MAX; i++) 258 msi_free_action_script( package, i ); 259 260 for (j = 0; j < package->script->UniqueActionsCount; j++) 261 msi_free( package->script->UniqueActions[j] ); 262 263 msi_free( package->script->UniqueActions ); 264 msi_free( package->script ); 265 } 266 267 LIST_FOR_EACH_SAFE( item, cursor, &package->binaries ) 268 { 269 MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry ); 270 271 list_remove( &binary->entry ); 272 if (binary->module) 273 FreeLibrary( binary->module ); 274 if (!DeleteFileW( binary->tmpfile )) 275 ERR("failed to delete %s (%u)\n", debugstr_w(binary->tmpfile), GetLastError()); 276 msi_free( binary->source ); 277 msi_free( binary->tmpfile ); 278 msi_free( binary ); 279 } 280 281 LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams ) 282 { 283 MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry ); 284 285 list_remove( &cab->entry ); 286 IStorage_Release( cab->storage ); 287 msi_free( cab->stream ); 288 msi_free( cab ); 289 } 290 291 LIST_FOR_EACH_SAFE( item, cursor, &package->patches ) 292 { 293 MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry ); 294 295 list_remove( &patch->entry ); 296 if (patch->delete_on_close && !DeleteFileW( patch->localfile )) 297 { 298 ERR("failed to delete %s (%u)\n", debugstr_w(patch->localfile), GetLastError()); 299 } 300 msi_free_patchinfo( patch ); 301 } 302 303 msi_free( package->BaseURL ); 304 msi_free( package->PackagePath ); 305 msi_free( package->ProductCode ); 306 msi_free( package->ActionFormat ); 307 msi_free( package->LastAction ); 308 msi_free( package->langids ); 309 310 /* cleanup control event subscriptions */ 311 msi_event_cleanup_all_subscriptions( package ); 312 } 313 314 static void MSI_FreePackage( MSIOBJECTHDR *arg) 315 { 316 MSIPACKAGE *package = (MSIPACKAGE *)arg; 317 318 msi_destroy_assembly_caches( package ); 319 320 if( package->dialog ) 321 msi_dialog_destroy( package->dialog ); 322 323 msiobj_release( &package->db->hdr ); 324 free_package_structures(package); 325 CloseHandle( package->log_file ); 326 327 if (package->delete_on_close) DeleteFileW( package->localfile ); 328 msi_free( package->localfile ); 329 } 330 331 static UINT create_temp_property_table(MSIPACKAGE *package) 332 { 333 static const WCHAR query[] = { 334 'C','R','E','A','T','E',' ','T','A','B','L','E',' ', 335 '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ', 336 '`','_','P','r','o','p','e','r','t','y','`',' ', 337 'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ', 338 'T','E','M','P','O','R','A','R','Y',',',' ', 339 '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ', 340 'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y', 341 ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ', 342 '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0}; 343 MSIQUERY *view; 344 UINT rc; 345 346 rc = MSI_DatabaseOpenViewW(package->db, query, &view); 347 if (rc != ERROR_SUCCESS) 348 return rc; 349 350 rc = MSI_ViewExecute(view, 0); 351 MSI_ViewClose(view); 352 msiobj_release(&view->hdr); 353 return rc; 354 } 355 356 UINT msi_clone_properties( MSIDATABASE *db ) 357 { 358 static const WCHAR query_select[] = { 359 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 360 '`','P','r','o','p','e','r','t','y','`',0}; 361 static const WCHAR query_insert[] = { 362 'I','N','S','E','R','T',' ','I','N','T','O',' ', 363 '`','_','P','r','o','p','e','r','t','y','`',' ', 364 '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 365 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 366 static const WCHAR query_update[] = { 367 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 368 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ', 369 'W','H','E','R','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','?',0}; 370 MSIQUERY *view_select; 371 UINT rc; 372 373 rc = MSI_DatabaseOpenViewW( db, query_select, &view_select ); 374 if (rc != ERROR_SUCCESS) 375 return rc; 376 377 rc = MSI_ViewExecute( view_select, 0 ); 378 if (rc != ERROR_SUCCESS) 379 { 380 MSI_ViewClose( view_select ); 381 msiobj_release( &view_select->hdr ); 382 return rc; 383 } 384 385 while (1) 386 { 387 MSIQUERY *view_insert, *view_update; 388 MSIRECORD *rec_select; 389 390 rc = MSI_ViewFetch( view_select, &rec_select ); 391 if (rc != ERROR_SUCCESS) 392 break; 393 394 rc = MSI_DatabaseOpenViewW( db, query_insert, &view_insert ); 395 if (rc != ERROR_SUCCESS) 396 { 397 msiobj_release( &rec_select->hdr ); 398 continue; 399 } 400 401 rc = MSI_ViewExecute( view_insert, rec_select ); 402 MSI_ViewClose( view_insert ); 403 msiobj_release( &view_insert->hdr ); 404 if (rc != ERROR_SUCCESS) 405 { 406 MSIRECORD *rec_update; 407 408 TRACE("insert failed, trying update\n"); 409 410 rc = MSI_DatabaseOpenViewW( db, query_update, &view_update ); 411 if (rc != ERROR_SUCCESS) 412 { 413 WARN("open view failed %u\n", rc); 414 msiobj_release( &rec_select->hdr ); 415 continue; 416 } 417 418 rec_update = MSI_CreateRecord( 2 ); 419 MSI_RecordCopyField( rec_select, 1, rec_update, 2 ); 420 MSI_RecordCopyField( rec_select, 2, rec_update, 1 ); 421 rc = MSI_ViewExecute( view_update, rec_update ); 422 if (rc != ERROR_SUCCESS) 423 WARN("update failed %u\n", rc); 424 425 MSI_ViewClose( view_update ); 426 msiobj_release( &view_update->hdr ); 427 msiobj_release( &rec_update->hdr ); 428 } 429 430 msiobj_release( &rec_select->hdr ); 431 } 432 433 MSI_ViewClose( view_select ); 434 msiobj_release( &view_select->hdr ); 435 return rc; 436 } 437 438 /* 439 * set_installed_prop 440 * 441 * Sets the "Installed" property to indicate that 442 * the product is installed for the current user. 443 */ 444 static UINT set_installed_prop( MSIPACKAGE *package ) 445 { 446 HKEY hkey; 447 UINT r; 448 449 if (!package->ProductCode) return ERROR_FUNCTION_FAILED; 450 451 r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE ); 452 if (r == ERROR_SUCCESS) 453 { 454 RegCloseKey( hkey ); 455 msi_set_property( package->db, szInstalled, szOne, -1 ); 456 } 457 return r; 458 } 459 460 static UINT set_user_sid_prop( MSIPACKAGE *package ) 461 { 462 SID_NAME_USE use; 463 LPWSTR user_name; 464 LPWSTR sid_str = NULL, dom = NULL; 465 DWORD size, dom_size; 466 PSID psid = NULL; 467 UINT r = ERROR_FUNCTION_FAILED; 468 469 size = 0; 470 GetUserNameW( NULL, &size ); 471 472 user_name = msi_alloc( (size + 1) * sizeof(WCHAR) ); 473 if (!user_name) 474 return ERROR_OUTOFMEMORY; 475 476 if (!GetUserNameW( user_name, &size )) 477 goto done; 478 479 size = 0; 480 dom_size = 0; 481 LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use ); 482 483 psid = msi_alloc( size ); 484 dom = msi_alloc( dom_size*sizeof (WCHAR) ); 485 if (!psid || !dom) 486 { 487 r = ERROR_OUTOFMEMORY; 488 goto done; 489 } 490 491 if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use )) 492 goto done; 493 494 if (!ConvertSidToStringSidW( psid, &sid_str )) 495 goto done; 496 497 r = msi_set_property( package->db, szUserSID, sid_str, -1 ); 498 499 done: 500 LocalFree( sid_str ); 501 msi_free( dom ); 502 msi_free( psid ); 503 msi_free( user_name ); 504 505 return r; 506 } 507 508 static LPWSTR get_fusion_filename(MSIPACKAGE *package) 509 { 510 HKEY netsetup; 511 LONG res; 512 LPWSTR file = NULL; 513 DWORD index = 0, size; 514 WCHAR ver[MAX_PATH]; 515 WCHAR name[MAX_PATH]; 516 WCHAR windir[MAX_PATH]; 517 518 static const WCHAR fusion[] = {'f','u','s','i','o','n','.','d','l','l',0}; 519 static const WCHAR sub[] = { 520 'S','o','f','t','w','a','r','e','\\', 521 'M','i','c','r','o','s','o','f','t','\\', 522 'N','E','T',' ','F','r','a','m','e','w','o','r','k',' ','S','e','t','u','p','\\', 523 'N','D','P',0 524 }; 525 static const WCHAR subdir[] = { 526 'M','i','c','r','o','s','o','f','t','.','N','E','T','\\', 527 'F','r','a','m','e','w','o','r','k','\\',0 528 }; 529 530 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, sub, 0, KEY_ENUMERATE_SUB_KEYS, &netsetup); 531 if (res != ERROR_SUCCESS) 532 return NULL; 533 534 GetWindowsDirectoryW(windir, MAX_PATH); 535 536 ver[0] = '\0'; 537 size = MAX_PATH; 538 while (RegEnumKeyExW(netsetup, index, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) 539 { 540 index++; 541 542 /* verify existence of fusion.dll .Net 3.0 does not install a new one */ 543 if (strcmpW( ver, name ) < 0) 544 { 545 LPWSTR check; 546 size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(name) +lstrlenW(fusion) + 3; 547 check = msi_alloc(size * sizeof(WCHAR)); 548 549 if (!check) 550 { 551 msi_free(file); 552 return NULL; 553 } 554 555 lstrcpyW(check, windir); 556 lstrcatW(check, szBackSlash); 557 lstrcatW(check, subdir); 558 lstrcatW(check, name); 559 lstrcatW(check, szBackSlash); 560 lstrcatW(check, fusion); 561 562 if(GetFileAttributesW(check) != INVALID_FILE_ATTRIBUTES) 563 { 564 msi_free(file); 565 file = check; 566 lstrcpyW(ver, name); 567 } 568 else 569 msi_free(check); 570 } 571 } 572 573 RegCloseKey(netsetup); 574 return file; 575 } 576 577 typedef struct tagLANGANDCODEPAGE 578 { 579 WORD wLanguage; 580 WORD wCodePage; 581 } LANGANDCODEPAGE; 582 583 static void set_msi_assembly_prop(MSIPACKAGE *package) 584 { 585 UINT val_len; 586 DWORD size, handle; 587 LPVOID version = NULL; 588 WCHAR buf[MAX_PATH]; 589 LPWSTR fusion, verstr; 590 LANGANDCODEPAGE *translate; 591 592 static const WCHAR netasm[] = { 593 'M','s','i','N','e','t','A','s','s','e','m','b','l','y','S','u','p','p','o','r','t',0 594 }; 595 static const WCHAR translation[] = { 596 '\\','V','a','r','F','i','l','e','I','n','f','o', 597 '\\','T','r','a','n','s','l','a','t','i','o','n',0 598 }; 599 static const WCHAR verfmt[] = { 600 '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o', 601 '\\','%','0','4','x','%','0','4','x', 602 '\\','P','r','o','d','u','c','t','V','e','r','s','i','o','n',0 603 }; 604 605 fusion = get_fusion_filename(package); 606 if (!fusion) 607 return; 608 609 size = GetFileVersionInfoSizeW(fusion, &handle); 610 if (!size) 611 goto done; 612 613 version = msi_alloc(size); 614 if (!version) 615 goto done; 616 617 if (!GetFileVersionInfoW(fusion, handle, size, version)) 618 goto done; 619 620 if (!VerQueryValueW(version, translation, (LPVOID *)&translate, &val_len)) 621 goto done; 622 623 sprintfW(buf, verfmt, translate[0].wLanguage, translate[0].wCodePage); 624 625 if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len)) 626 goto done; 627 628 if (!val_len || !verstr) 629 goto done; 630 631 msi_set_property( package->db, netasm, verstr, -1 ); 632 633 done: 634 msi_free(fusion); 635 msi_free(version); 636 } 637 638 static VOID set_installer_properties(MSIPACKAGE *package) 639 { 640 WCHAR *ptr; 641 OSVERSIONINFOEXW OSVersion; 642 MEMORYSTATUSEX msex; 643 DWORD verval, len; 644 WCHAR pth[MAX_PATH], verstr[11], bufstr[22]; 645 HDC dc; 646 HKEY hkey; 647 LPWSTR username, companyname; 648 SYSTEM_INFO sys_info; 649 SYSTEMTIME systemtime; 650 LANGID langid; 651 652 static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0}; 653 static const WCHAR szProgramFilesFolder[] = {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0}; 654 static const WCHAR szCommonAppDataFolder[] = {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0}; 655 static const WCHAR szFavoritesFolder[] = {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0}; 656 static const WCHAR szFontsFolder[] = {'F','o','n','t','s','F','o','l','d','e','r',0}; 657 static const WCHAR szSendToFolder[] = {'S','e','n','d','T','o','F','o','l','d','e','r',0}; 658 static const WCHAR szStartMenuFolder[] = {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0}; 659 static const WCHAR szStartupFolder[] = {'S','t','a','r','t','u','p','F','o','l','d','e','r',0}; 660 static const WCHAR szTemplateFolder[] = {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0}; 661 static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0}; 662 static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0}; 663 static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0}; 664 static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0}; 665 static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0}; 666 static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0}; 667 static const WCHAR szMyPicturesFolder[] = {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0}; 668 static const WCHAR szPersonalFolder[] = {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0}; 669 static const WCHAR szWindowsVolume[] = {'W','i','n','d','o','w','s','V','o','l','u','m','e',0}; 670 static const WCHAR szPrivileged[] = {'P','r','i','v','i','l','e','g','e','d',0}; 671 static const WCHAR szVersion9x[] = {'V','e','r','s','i','o','n','9','X',0}; 672 static const WCHAR szVersionNT[] = {'V','e','r','s','i','o','n','N','T',0}; 673 static const WCHAR szMsiNTProductType[] = {'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0}; 674 static const WCHAR szFormat[] = {'%','u',0}; 675 static const WCHAR szFormat2[] = {'%','u','.','%','u',0}; 676 static const WCHAR szWindowsBuild[] = {'W','i','n','d','o','w','s','B','u','i','l','d',0}; 677 static const WCHAR szServicePackLevel[] = {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0}; 678 static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 }; 679 static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 }; 680 static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 }; 681 static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0}; 682 static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0}; 683 static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0}; 684 static const WCHAR szIntFormat[] = {'%','d',0}; 685 static const WCHAR szMsiAMD64[] = { 'M','s','i','A','M','D','6','4',0 }; 686 static const WCHAR szMsix64[] = { 'M','s','i','x','6','4',0 }; 687 static const WCHAR szSystem64Folder[] = { 'S','y','s','t','e','m','6','4','F','o','l','d','e','r',0 }; 688 static const WCHAR szCommonFiles64Folder[] = { 'C','o','m','m','o','n','F','i','l','e','s','6','4','F','o','l','d','e','r',0 }; 689 static const WCHAR szProgramFiles64Folder[] = { 'P','r','o','g','r','a','m','F','i','l','e','s','6','4','F','o','l','d','e','r',0 }; 690 static const WCHAR szVersionNT64[] = { 'V','e','r','s','i','o','n','N','T','6','4',0 }; 691 static const WCHAR szUserInfo[] = { 692 'S','O','F','T','W','A','R','E','\\', 693 'M','i','c','r','o','s','o','f','t','\\', 694 'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\', 695 'U','s','e','r',' ','I','n','f','o',0 696 }; 697 static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 }; 698 static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 }; 699 static const WCHAR szCurrentVersion[] = { 700 'S','O','F','T','W','A','R','E','\\', 701 'M','i','c','r','o','s','o','f','t','\\', 702 'W','i','n','d','o','w','s',' ','N','T','\\', 703 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0 704 }; 705 static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0}; 706 static const WCHAR szRegisteredOrganization[] = { 707 'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0 708 }; 709 static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0}; 710 static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0}; 711 static const WCHAR szDate[] = {'D','a','t','e',0}; 712 static const WCHAR szTime[] = {'T','i','m','e',0}; 713 static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0}; 714 static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0}; 715 static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0}; 716 static const WCHAR szLogonUser[] = {'L','o','g','o','n','U','s','e','r',0}; 717 static const WCHAR szNetHoodFolder[] = {'N','e','t','H','o','o','d','F','o','l','d','e','r',0}; 718 static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0}; 719 static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0}; 720 static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0}; 721 static const WCHAR szBrowseProperty[] = {'_','B','r','o','w','s','e','P','r','o','p','e','r','t','y',0}; 722 static const WCHAR szInstallDir[] = {'I','N','S','T','A','L','L','D','I','R',0}; 723 724 /* 725 * Other things that probably should be set: 726 * 727 * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging 728 * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport 729 */ 730 731 SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth); 732 strcatW(pth, szBackSlash); 733 msi_set_property( package->db, szCommonAppDataFolder, pth, -1 ); 734 735 SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth); 736 strcatW(pth, szBackSlash); 737 msi_set_property( package->db, szFavoritesFolder, pth, -1 ); 738 739 SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth); 740 strcatW(pth, szBackSlash); 741 msi_set_property( package->db, szFontsFolder, pth, -1 ); 742 743 SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth); 744 strcatW(pth, szBackSlash); 745 msi_set_property( package->db, szSendToFolder, pth, -1 ); 746 747 SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth); 748 strcatW(pth, szBackSlash); 749 msi_set_property( package->db, szStartMenuFolder, pth, -1 ); 750 751 SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth); 752 strcatW(pth, szBackSlash); 753 msi_set_property( package->db, szStartupFolder, pth, -1 ); 754 755 SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth); 756 strcatW(pth, szBackSlash); 757 msi_set_property( package->db, szTemplateFolder, pth, -1 ); 758 759 SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth); 760 strcatW(pth, szBackSlash); 761 msi_set_property( package->db, szDesktopFolder, pth, -1 ); 762 763 /* FIXME: set to AllUsers profile path if ALLUSERS is set */ 764 SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth); 765 strcatW(pth, szBackSlash); 766 msi_set_property( package->db, szProgramMenuFolder, pth, -1 ); 767 768 SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth); 769 strcatW(pth, szBackSlash); 770 msi_set_property( package->db, szAdminToolsFolder, pth, -1 ); 771 772 SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth); 773 strcatW(pth, szBackSlash); 774 msi_set_property( package->db, szAppDataFolder, pth, -1 ); 775 776 SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth); 777 strcatW(pth, szBackSlash); 778 msi_set_property( package->db, szSystemFolder, pth, -1 ); 779 msi_set_property( package->db, szSystem16Folder, pth, -1 ); 780 781 SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth); 782 strcatW(pth, szBackSlash); 783 msi_set_property( package->db, szLocalAppDataFolder, pth, -1 ); 784 785 SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth); 786 strcatW(pth, szBackSlash); 787 msi_set_property( package->db, szMyPicturesFolder, pth, -1 ); 788 789 SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth); 790 strcatW(pth, szBackSlash); 791 msi_set_property( package->db, szPersonalFolder, pth, -1 ); 792 793 SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 794 strcatW(pth, szBackSlash); 795 msi_set_property( package->db, szWindowsFolder, pth, -1 ); 796 797 SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth); 798 strcatW(pth, szBackSlash); 799 msi_set_property( package->db, szPrintHoodFolder, pth, -1 ); 800 801 SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth); 802 strcatW(pth, szBackSlash); 803 msi_set_property( package->db, szNetHoodFolder, pth, -1 ); 804 805 SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth); 806 strcatW(pth, szBackSlash); 807 msi_set_property( package->db, szRecentFolder, pth, -1 ); 808 809 /* Physical Memory is specified in MB. Using total amount. */ 810 msex.dwLength = sizeof(msex); 811 GlobalMemoryStatusEx( &msex ); 812 len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) ); 813 msi_set_property( package->db, szPhysicalMemory, bufstr, len ); 814 815 SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 816 ptr = strchrW(pth,'\\'); 817 if (ptr) *(ptr + 1) = 0; 818 msi_set_property( package->db, szWindowsVolume, pth, -1 ); 819 820 len = GetTempPathW(MAX_PATH, pth); 821 msi_set_property( package->db, szTempFolder, pth, len ); 822 823 /* in a wine environment the user is always admin and privileged */ 824 msi_set_property( package->db, szAdminUser, szOne, -1 ); 825 msi_set_property( package->db, szPrivileged, szOne, -1 ); 826 827 /* set the os things */ 828 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); 829 GetVersionExW((OSVERSIONINFOW *)&OSVersion); 830 verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100; 831 len = sprintfW( verstr, szFormat, verval ); 832 switch (OSVersion.dwPlatformId) 833 { 834 case VER_PLATFORM_WIN32_WINDOWS: 835 msi_set_property( package->db, szVersion9x, verstr, len ); 836 break; 837 case VER_PLATFORM_WIN32_NT: 838 msi_set_property( package->db, szVersionNT, verstr, len ); 839 len = sprintfW( bufstr, szFormat,OSVersion.wProductType ); 840 msi_set_property( package->db, szMsiNTProductType, bufstr, len ); 841 break; 842 } 843 len = sprintfW( bufstr, szFormat, OSVersion.dwBuildNumber ); 844 msi_set_property( package->db, szWindowsBuild, bufstr, len ); 845 len = sprintfW( bufstr, szFormat, OSVersion.wServicePackMajor ); 846 msi_set_property( package->db, szServicePackLevel, bufstr, len ); 847 848 len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION ); 849 msi_set_property( package->db, szVersionMsi, bufstr, len ); 850 len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 ); 851 msi_set_property( package->db, szVersionDatabase, bufstr, len ); 852 853 GetNativeSystemInfo( &sys_info ); 854 len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel ); 855 msi_set_property( package->db, szIntel, bufstr, len ); 856 if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) 857 { 858 GetSystemDirectoryW( pth, MAX_PATH ); 859 PathAddBackslashW( pth ); 860 msi_set_property( package->db, szSystemFolder, pth, -1 ); 861 862 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); 863 PathAddBackslashW( pth ); 864 msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 865 866 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); 867 PathAddBackslashW( pth ); 868 msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 869 } 870 else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) 871 { 872 msi_set_property( package->db, szMsiAMD64, bufstr, -1 ); 873 msi_set_property( package->db, szMsix64, bufstr, -1 ); 874 msi_set_property( package->db, szVersionNT64, verstr, -1 ); 875 876 GetSystemDirectoryW( pth, MAX_PATH ); 877 PathAddBackslashW( pth ); 878 msi_set_property( package->db, szSystem64Folder, pth, -1 ); 879 880 GetSystemWow64DirectoryW( pth, MAX_PATH ); 881 PathAddBackslashW( pth ); 882 msi_set_property( package->db, szSystemFolder, pth, -1 ); 883 884 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth ); 885 PathAddBackslashW( pth ); 886 msi_set_property( package->db, szProgramFiles64Folder, pth, -1 ); 887 888 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth ); 889 PathAddBackslashW( pth ); 890 msi_set_property( package->db, szProgramFilesFolder, pth, -1 ); 891 892 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth ); 893 PathAddBackslashW( pth ); 894 msi_set_property( package->db, szCommonFiles64Folder, pth, -1 ); 895 896 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth ); 897 PathAddBackslashW( pth ); 898 msi_set_property( package->db, szCommonFilesFolder, pth, -1 ); 899 } 900 901 /* Screen properties. */ 902 dc = GetDC(0); 903 len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) ); 904 msi_set_property( package->db, szScreenX, bufstr, len ); 905 len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) ); 906 msi_set_property( package->db, szScreenY, bufstr, len ); 907 len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) ); 908 msi_set_property( package->db, szColorBits, bufstr, len ); 909 ReleaseDC(0, dc); 910 911 /* USERNAME and COMPANYNAME */ 912 username = msi_dup_property( package->db, szUSERNAME ); 913 companyname = msi_dup_property( package->db, szCOMPANYNAME ); 914 915 if ((!username || !companyname) && 916 RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS) 917 { 918 if (!username && 919 (username = msi_reg_get_val_str( hkey, szDefName ))) 920 msi_set_property( package->db, szUSERNAME, username, -1 ); 921 if (!companyname && 922 (companyname = msi_reg_get_val_str( hkey, szDefCompany ))) 923 msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 924 CloseHandle( hkey ); 925 } 926 if ((!username || !companyname) && 927 RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS) 928 { 929 if (!username && 930 (username = msi_reg_get_val_str( hkey, szRegisteredUser ))) 931 msi_set_property( package->db, szUSERNAME, username, -1 ); 932 if (!companyname && 933 (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization ))) 934 msi_set_property( package->db, szCOMPANYNAME, companyname, -1 ); 935 CloseHandle( hkey ); 936 } 937 msi_free( username ); 938 msi_free( companyname ); 939 940 if ( set_user_sid_prop( package ) != ERROR_SUCCESS) 941 ERR("Failed to set the UserSID property\n"); 942 943 /* Date and time properties */ 944 GetSystemTime( &systemtime ); 945 if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime, 946 NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) )) 947 msi_set_property( package->db, szDate, bufstr, -1 ); 948 else 949 ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError()); 950 951 if (GetTimeFormatW( LOCALE_USER_DEFAULT, 952 TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, 953 &systemtime, NULL, bufstr, 954 sizeof(bufstr)/sizeof(bufstr[0]) )) 955 msi_set_property( package->db, szTime, bufstr, -1 ); 956 else 957 ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError()); 958 959 set_msi_assembly_prop( package ); 960 961 langid = GetUserDefaultLangID(); 962 len = sprintfW( bufstr, szIntFormat, langid ); 963 msi_set_property( package->db, szUserLanguageID, bufstr, len ); 964 965 langid = GetSystemDefaultLangID(); 966 len = sprintfW( bufstr, szIntFormat, langid ); 967 msi_set_property( package->db, szSystemLangID, bufstr, len ); 968 969 len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) ); 970 msi_set_property( package->db, szProductState, bufstr, len ); 971 972 len = 0; 973 if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 974 { 975 WCHAR *username; 976 if ((username = msi_alloc( len * sizeof(WCHAR) ))) 977 { 978 if (GetUserNameW( username, &len )) 979 msi_set_property( package->db, szLogonUser, username, len - 1 ); 980 msi_free( username ); 981 } 982 } 983 len = 0; 984 if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW) 985 { 986 WCHAR *computername; 987 if ((computername = msi_alloc( len * sizeof(WCHAR) ))) 988 { 989 if (GetComputerNameW( computername, &len )) 990 msi_set_property( package->db, szComputerName, computername, len ); 991 msi_free( computername ); 992 } 993 } 994 msi_set_property( package->db, szBrowseProperty, szInstallDir, -1 ); 995 } 996 997 static MSIPACKAGE *msi_alloc_package( void ) 998 { 999 MSIPACKAGE *package; 1000 1001 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE), 1002 MSI_FreePackage ); 1003 if( package ) 1004 { 1005 list_init( &package->components ); 1006 list_init( &package->features ); 1007 list_init( &package->files ); 1008 list_init( &package->filepatches ); 1009 list_init( &package->tempfiles ); 1010 list_init( &package->folders ); 1011 list_init( &package->subscriptions ); 1012 list_init( &package->appids ); 1013 list_init( &package->classes ); 1014 list_init( &package->mimes ); 1015 list_init( &package->extensions ); 1016 list_init( &package->progids ); 1017 list_init( &package->RunningActions ); 1018 list_init( &package->sourcelist_info ); 1019 list_init( &package->sourcelist_media ); 1020 list_init( &package->patches ); 1021 list_init( &package->binaries ); 1022 list_init( &package->cabinet_streams ); 1023 } 1024 1025 return package; 1026 } 1027 1028 static UINT msi_load_admin_properties(MSIPACKAGE *package) 1029 { 1030 BYTE *data; 1031 UINT r, sz; 1032 1033 static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0}; 1034 1035 r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz); 1036 if (r != ERROR_SUCCESS) 1037 return r; 1038 1039 r = msi_parse_command_line(package, (WCHAR *)data, TRUE); 1040 1041 msi_free(data); 1042 return r; 1043 } 1044 1045 void msi_adjust_privilege_properties( MSIPACKAGE *package ) 1046 { 1047 /* FIXME: this should depend on the user's privileges */ 1048 if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2) 1049 { 1050 TRACE("resetting ALLUSERS property from 2 to 1\n"); 1051 msi_set_property( package->db, szAllUsers, szOne, -1 ); 1052 } 1053 msi_set_property( package->db, szAdminUser, szOne, -1 ); 1054 } 1055 1056 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) 1057 { 1058 static const WCHAR fmtW[] = {'%','u',0}; 1059 MSIPACKAGE *package; 1060 WCHAR uilevel[11]; 1061 int len; 1062 UINT r; 1063 1064 TRACE("%p\n", db); 1065 1066 package = msi_alloc_package(); 1067 if (package) 1068 { 1069 msiobj_addref( &db->hdr ); 1070 package->db = db; 1071 1072 package->WordCount = 0; 1073 package->PackagePath = strdupW( db->path ); 1074 package->BaseURL = strdupW( base_url ); 1075 1076 create_temp_property_table( package ); 1077 msi_clone_properties( package->db ); 1078 msi_adjust_privilege_properties( package ); 1079 1080 package->ProductCode = msi_dup_property( package->db, szProductCode ); 1081 package->script = msi_alloc_zero( sizeof(MSISCRIPT) ); 1082 1083 set_installer_properties( package ); 1084 1085 package->ui_level = gUILevel; 1086 len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK ); 1087 msi_set_property( package->db, szUILevel, uilevel, len ); 1088 1089 r = msi_load_suminfo_properties( package ); 1090 if (r != ERROR_SUCCESS) 1091 { 1092 msiobj_release( &package->hdr ); 1093 return NULL; 1094 } 1095 1096 if (package->WordCount & msidbSumInfoSourceTypeAdminImage) 1097 msi_load_admin_properties( package ); 1098 1099 package->log_file = INVALID_HANDLE_VALUE; 1100 } 1101 return package; 1102 } 1103 1104 UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) 1105 { 1106 LPINTERNET_CACHE_ENTRY_INFOW cache_entry; 1107 DWORD size = 0; 1108 HRESULT hr; 1109 1110 /* call will always fail, because size is 0, 1111 * but will return ERROR_FILE_NOT_FOUND first 1112 * if the file doesn't exist 1113 */ 1114 GetUrlCacheEntryInfoW( szUrl, NULL, &size ); 1115 if ( GetLastError() != ERROR_FILE_NOT_FOUND ) 1116 { 1117 cache_entry = msi_alloc( size ); 1118 if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) ) 1119 { 1120 UINT error = GetLastError(); 1121 msi_free( cache_entry ); 1122 return error; 1123 } 1124 1125 lstrcpyW( filename, cache_entry->lpszLocalFileName ); 1126 msi_free( cache_entry ); 1127 return ERROR_SUCCESS; 1128 } 1129 1130 hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL ); 1131 if ( FAILED(hr) ) 1132 { 1133 WARN("failed to download %s to cache file\n", debugstr_w(szUrl)); 1134 return ERROR_FUNCTION_FAILED; 1135 } 1136 1137 return ERROR_SUCCESS; 1138 } 1139 1140 UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix ) 1141 { 1142 static const WCHAR szInstaller[] = { 1143 '\\','I','n','s','t','a','l','l','e','r','\\',0}; 1144 static const WCHAR fmt[] = {'%','x',0}; 1145 DWORD time, len, i, offset; 1146 HANDLE handle; 1147 1148 time = GetTickCount(); 1149 GetWindowsDirectoryW( path, MAX_PATH ); 1150 strcatW( path, szInstaller ); 1151 CreateDirectoryW( path, NULL ); 1152 1153 len = strlenW(path); 1154 for (i = 0; i < 0x10000; i++) 1155 { 1156 offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff ); 1157 memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) ); 1158 handle = CreateFileW( path, GENERIC_WRITE, 0, NULL, 1159 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); 1160 if (handle != INVALID_HANDLE_VALUE) 1161 { 1162 CloseHandle(handle); 1163 break; 1164 } 1165 if (GetLastError() != ERROR_FILE_EXISTS && 1166 GetLastError() != ERROR_SHARING_VIOLATION) 1167 return ERROR_FUNCTION_FAILED; 1168 } 1169 1170 return ERROR_SUCCESS; 1171 } 1172 1173 static enum platform parse_platform( const WCHAR *str ) 1174 { 1175 if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL; 1176 else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64; 1177 else if (!strcmpW( str, szX64 ) || !strcmpW( str, szAMD64 )) return PLATFORM_X64; 1178 else if (!strcmpW( str, szARM )) return PLATFORM_ARM; 1179 return PLATFORM_UNKNOWN; 1180 } 1181 1182 static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package ) 1183 { 1184 WCHAR *template, *p, *q, *platform; 1185 DWORD i, count; 1186 1187 package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); 1188 TRACE("version: %d\n", package->version); 1189 1190 template = msi_suminfo_dup_string( si, PID_TEMPLATE ); 1191 if (!template) 1192 return ERROR_SUCCESS; /* native accepts missing template property */ 1193 1194 TRACE("template: %s\n", debugstr_w(template)); 1195 1196 p = strchrW( template, ';' ); 1197 if (!p) 1198 { 1199 WARN("invalid template string %s\n", debugstr_w(template)); 1200 msi_free( template ); 1201 return ERROR_PATCH_PACKAGE_INVALID; 1202 } 1203 *p = 0; 1204 platform = template; 1205 if ((q = strchrW( platform, ',' ))) *q = 0; 1206 package->platform = parse_platform( platform ); 1207 while (package->platform == PLATFORM_UNKNOWN && q) 1208 { 1209 platform = q + 1; 1210 if ((q = strchrW( platform, ',' ))) *q = 0; 1211 package->platform = parse_platform( platform ); 1212 } 1213 if (package->platform == PLATFORM_UNKNOWN) 1214 { 1215 WARN("unknown platform %s\n", debugstr_w(template)); 1216 msi_free( template ); 1217 return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1218 } 1219 p++; 1220 if (!*p) 1221 { 1222 msi_free( template ); 1223 return ERROR_SUCCESS; 1224 } 1225 count = 1; 1226 for (q = p; (q = strchrW( q, ',' )); q++) count++; 1227 1228 package->langids = msi_alloc( count * sizeof(LANGID) ); 1229 if (!package->langids) 1230 { 1231 msi_free( template ); 1232 return ERROR_OUTOFMEMORY; 1233 } 1234 1235 i = 0; 1236 while (*p) 1237 { 1238 q = strchrW( p, ',' ); 1239 if (q) *q = 0; 1240 package->langids[i] = atoiW( p ); 1241 if (!q) break; 1242 p = q + 1; 1243 i++; 1244 } 1245 package->num_langids = i + 1; 1246 1247 msi_free( template ); 1248 return ERROR_SUCCESS; 1249 } 1250 1251 static UINT validate_package( MSIPACKAGE *package ) 1252 { 1253 UINT i; 1254 1255 if (package->platform == PLATFORM_INTEL64) 1256 return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1257 #ifndef __arm__ 1258 if (package->platform == PLATFORM_ARM) 1259 return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1260 #endif 1261 if (package->platform == PLATFORM_X64) 1262 { 1263 if (!is_64bit && !is_wow64) 1264 return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1265 if (package->version < 200) 1266 return ERROR_INSTALL_PACKAGE_INVALID; 1267 } 1268 if (!package->num_langids) 1269 { 1270 return ERROR_SUCCESS; 1271 } 1272 for (i = 0; i < package->num_langids; i++) 1273 { 1274 LANGID langid = package->langids[i]; 1275 1276 if (PRIMARYLANGID( langid ) == LANG_NEUTRAL) 1277 { 1278 langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) ); 1279 } 1280 if (SUBLANGID( langid ) == SUBLANG_NEUTRAL) 1281 { 1282 langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) ); 1283 } 1284 if (IsValidLocale( langid, LCID_INSTALLED )) 1285 return ERROR_SUCCESS; 1286 } 1287 return ERROR_INSTALL_LANGUAGE_UNSUPPORTED; 1288 } 1289 1290 static WCHAR *get_product_code( MSIDATABASE *db ) 1291 { 1292 static const WCHAR query[] = { 1293 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 1294 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',' ', 1295 'W','H','E','R','E',' ','`','P','r','o','p','e','r','t','y','`','=', 1296 '\'','P','r','o','d','u','c','t','C','o','d','e','\'',0}; 1297 MSIQUERY *view; 1298 MSIRECORD *rec; 1299 WCHAR *ret = NULL; 1300 1301 if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) 1302 { 1303 return NULL; 1304 } 1305 if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS) 1306 { 1307 MSI_ViewClose( view ); 1308 msiobj_release( &view->hdr ); 1309 return NULL; 1310 } 1311 if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) 1312 { 1313 ret = strdupW( MSI_RecordGetString( rec, 1 ) ); 1314 msiobj_release( &rec->hdr ); 1315 } 1316 MSI_ViewClose( view ); 1317 msiobj_release( &view->hdr ); 1318 return ret; 1319 } 1320 1321 static UINT get_registered_local_package( const WCHAR *product, const WCHAR *package, WCHAR *localfile ) 1322 { 1323 MSIINSTALLCONTEXT context; 1324 HKEY product_key, props_key; 1325 WCHAR *registered_package = NULL, unsquashed[GUID_SIZE]; 1326 UINT r; 1327 1328 r = msi_locate_product( product, &context ); 1329 if (r != ERROR_SUCCESS) 1330 return r; 1331 1332 r = MSIREG_OpenProductKey( product, NULL, context, &product_key, FALSE ); 1333 if (r != ERROR_SUCCESS) 1334 return r; 1335 1336 r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE ); 1337 if (r != ERROR_SUCCESS) 1338 { 1339 RegCloseKey( product_key ); 1340 return r; 1341 } 1342 r = ERROR_FUNCTION_FAILED; 1343 registered_package = msi_reg_get_val_str( product_key, INSTALLPROPERTY_PACKAGECODEW ); 1344 if (!registered_package) 1345 goto done; 1346 1347 unsquash_guid( registered_package, unsquashed ); 1348 if (!strcmpiW( package, unsquashed )) 1349 { 1350 WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); 1351 if (!filename) 1352 goto done; 1353 1354 strcpyW( localfile, filename ); 1355 msi_free( filename ); 1356 r = ERROR_SUCCESS; 1357 } 1358 done: 1359 msi_free( registered_package ); 1360 RegCloseKey( props_key ); 1361 RegCloseKey( product_key ); 1362 return r; 1363 } 1364 1365 static WCHAR *get_package_code( MSIDATABASE *db ) 1366 { 1367 WCHAR *ret; 1368 MSISUMMARYINFO *si; 1369 UINT r; 1370 1371 r = msi_get_suminfo( db->storage, 0, &si ); 1372 if (r != ERROR_SUCCESS) 1373 { 1374 r = msi_get_db_suminfo( db, 0, &si ); 1375 if (r != ERROR_SUCCESS) 1376 { 1377 WARN("failed to load summary info %u\n", r); 1378 return NULL; 1379 } 1380 } 1381 ret = msi_suminfo_dup_string( si, PID_REVNUMBER ); 1382 msiobj_release( &si->hdr ); 1383 return ret; 1384 } 1385 1386 static UINT get_local_package( const WCHAR *filename, WCHAR *localfile ) 1387 { 1388 WCHAR *product_code, *package_code; 1389 MSIDATABASE *db; 1390 UINT r; 1391 1392 if ((r = MSI_OpenDatabaseW( filename, MSIDBOPEN_READONLY, &db )) != ERROR_SUCCESS) 1393 { 1394 if (GetFileAttributesW( filename ) == INVALID_FILE_ATTRIBUTES) 1395 return ERROR_FILE_NOT_FOUND; 1396 return r; 1397 } 1398 if (!(product_code = get_product_code( db ))) 1399 { 1400 msiobj_release( &db->hdr ); 1401 return ERROR_INSTALL_PACKAGE_INVALID; 1402 } 1403 if (!(package_code = get_package_code( db ))) 1404 { 1405 msi_free( product_code ); 1406 msiobj_release( &db->hdr ); 1407 return ERROR_INSTALL_PACKAGE_INVALID; 1408 } 1409 r = get_registered_local_package( product_code, package_code, localfile ); 1410 msi_free( package_code ); 1411 msi_free( product_code ); 1412 msiobj_release( &db->hdr ); 1413 return r; 1414 } 1415 1416 UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package ) 1417 { 1418 UINT r; 1419 1420 if (UrlIsW( package, URLIS_URL )) 1421 r = msi_set_property( db, szOriginalDatabase, package, -1 ); 1422 else if (package[0] == '#') 1423 r = msi_set_property( db, szOriginalDatabase, db->path, -1 ); 1424 else 1425 { 1426 DWORD len; 1427 WCHAR *path; 1428 1429 if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError(); 1430 if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; 1431 len = GetFullPathNameW( package, len, path, NULL ); 1432 r = msi_set_property( db, szOriginalDatabase, path, len ); 1433 msi_free( path ); 1434 } 1435 return r; 1436 } 1437 1438 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) 1439 { 1440 static const WCHAR dotmsi[] = {'.','m','s','i',0}; 1441 MSIDATABASE *db; 1442 MSIPACKAGE *package; 1443 MSIHANDLE handle; 1444 LPWSTR ptr, base_url = NULL; 1445 UINT r; 1446 WCHAR localfile[MAX_PATH], cachefile[MAX_PATH]; 1447 LPCWSTR file = szPackage; 1448 DWORD index = 0; 1449 MSISUMMARYINFO *si; 1450 BOOL delete_on_close = FALSE; 1451 1452 TRACE("%s %p\n", debugstr_w(szPackage), pPackage); 1453 1454 localfile[0] = 0; 1455 if( szPackage[0] == '#' ) 1456 { 1457 handle = atoiW(&szPackage[1]); 1458 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE ); 1459 if( !db ) 1460 { 1461 IWineMsiRemoteDatabase *remote_database; 1462 1463 remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( handle ); 1464 if ( !remote_database ) 1465 return ERROR_INVALID_HANDLE; 1466 1467 IWineMsiRemoteDatabase_Release( remote_database ); 1468 WARN("MsiOpenPackage not allowed during a custom action!\n"); 1469 1470 return ERROR_FUNCTION_FAILED; 1471 } 1472 } 1473 else 1474 { 1475 if ( UrlIsW( szPackage, URLIS_URL ) ) 1476 { 1477 r = msi_download_file( szPackage, cachefile ); 1478 if (r != ERROR_SUCCESS) 1479 return r; 1480 1481 file = cachefile; 1482 1483 base_url = strdupW( szPackage ); 1484 if (!base_url) 1485 return ERROR_OUTOFMEMORY; 1486 1487 ptr = strrchrW( base_url, '/' ); 1488 if (ptr) *(ptr + 1) = '\0'; 1489 } 1490 r = get_local_package( file, localfile ); 1491 if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES) 1492 { 1493 r = msi_create_empty_local_file( localfile, dotmsi ); 1494 if (r != ERROR_SUCCESS) 1495 { 1496 msi_free ( base_url ); 1497 return r; 1498 } 1499 1500 if (!CopyFileW( file, localfile, FALSE )) 1501 { 1502 r = GetLastError(); 1503 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); 1504 DeleteFileW( localfile ); 1505 msi_free ( base_url ); 1506 return r; 1507 } 1508 delete_on_close = TRUE; 1509 } 1510 TRACE("opening package %s\n", debugstr_w( localfile )); 1511 r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); 1512 if (r != ERROR_SUCCESS) 1513 { 1514 msi_free ( base_url ); 1515 return r; 1516 } 1517 } 1518 package = MSI_CreatePackage( db, base_url ); 1519 msi_free( base_url ); 1520 msiobj_release( &db->hdr ); 1521 if (!package) return ERROR_INSTALL_PACKAGE_INVALID; 1522 package->localfile = strdupW( localfile ); 1523 package->delete_on_close = delete_on_close; 1524 1525 r = msi_get_suminfo( db->storage, 0, &si ); 1526 if (r != ERROR_SUCCESS) 1527 { 1528 r = msi_get_db_suminfo( db, 0, &si ); 1529 if (r != ERROR_SUCCESS) 1530 { 1531 WARN("failed to load summary info\n"); 1532 msiobj_release( &package->hdr ); 1533 return ERROR_INSTALL_PACKAGE_INVALID; 1534 } 1535 } 1536 r = parse_suminfo( si, package ); 1537 msiobj_release( &si->hdr ); 1538 if (r != ERROR_SUCCESS) 1539 { 1540 WARN("failed to parse summary info %u\n", r); 1541 msiobj_release( &package->hdr ); 1542 return r; 1543 } 1544 r = validate_package( package ); 1545 if (r != ERROR_SUCCESS) 1546 { 1547 msiobj_release( &package->hdr ); 1548 return r; 1549 } 1550 msi_set_property( package->db, szDatabase, db->path, -1 ); 1551 set_installed_prop( package ); 1552 msi_set_context( package ); 1553 1554 while (1) 1555 { 1556 WCHAR patch_code[GUID_SIZE]; 1557 r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context, 1558 MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL ); 1559 if (r != ERROR_SUCCESS) 1560 break; 1561 1562 TRACE("found registered patch %s\n", debugstr_w(patch_code)); 1563 1564 r = msi_apply_registered_patch( package, patch_code ); 1565 if (r != ERROR_SUCCESS) 1566 { 1567 ERR("registered patch failed to apply %u\n", r); 1568 msiobj_release( &package->hdr ); 1569 return r; 1570 } 1571 index++; 1572 } 1573 if (index) msi_adjust_privilege_properties( package ); 1574 1575 r = msi_set_original_database_property( package->db, szPackage ); 1576 if (r != ERROR_SUCCESS) 1577 { 1578 msiobj_release( &package->hdr ); 1579 return r; 1580 } 1581 if (gszLogFile) 1582 package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 1583 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 1584 *pPackage = package; 1585 return ERROR_SUCCESS; 1586 } 1587 1588 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1589 { 1590 MSIPACKAGE *package = NULL; 1591 UINT ret; 1592 1593 TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage ); 1594 1595 if( !szPackage || !phPackage ) 1596 return ERROR_INVALID_PARAMETER; 1597 1598 if ( !*szPackage ) 1599 { 1600 FIXME("Should create an empty database and package\n"); 1601 return ERROR_FUNCTION_FAILED; 1602 } 1603 1604 if( dwOptions ) 1605 FIXME("dwOptions %08x not supported\n", dwOptions); 1606 1607 ret = MSI_OpenPackageW( szPackage, &package ); 1608 if( ret == ERROR_SUCCESS ) 1609 { 1610 *phPackage = alloc_msihandle( &package->hdr ); 1611 if (! *phPackage) 1612 ret = ERROR_NOT_ENOUGH_MEMORY; 1613 msiobj_release( &package->hdr ); 1614 } 1615 1616 return ret; 1617 } 1618 1619 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) 1620 { 1621 return MsiOpenPackageExW( szPackage, 0, phPackage ); 1622 } 1623 1624 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1625 { 1626 LPWSTR szwPack = NULL; 1627 UINT ret; 1628 1629 if( szPackage ) 1630 { 1631 szwPack = strdupAtoW( szPackage ); 1632 if( !szwPack ) 1633 return ERROR_OUTOFMEMORY; 1634 } 1635 1636 ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); 1637 1638 msi_free( szwPack ); 1639 1640 return ret; 1641 } 1642 1643 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) 1644 { 1645 return MsiOpenPackageExA( szPackage, 0, phPackage ); 1646 } 1647 1648 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall) 1649 { 1650 MSIPACKAGE *package; 1651 MSIHANDLE handle = 0; 1652 IUnknown *remote_unk; 1653 IWineMsiRemotePackage *remote_package; 1654 1655 TRACE("(%d)\n",hInstall); 1656 1657 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 1658 if( package) 1659 { 1660 handle = alloc_msihandle( &package->db->hdr ); 1661 msiobj_release( &package->hdr ); 1662 } 1663 else if ((remote_unk = msi_get_remote(hInstall))) 1664 { 1665 if (IUnknown_QueryInterface(remote_unk, &IID_IWineMsiRemotePackage, 1666 (LPVOID *)&remote_package) == S_OK) 1667 { 1668 IWineMsiRemotePackage_GetActiveDatabase(remote_package, &handle); 1669 IWineMsiRemotePackage_Release(remote_package); 1670 } 1671 else 1672 { 1673 WARN("remote handle %d is not a package\n", hInstall); 1674 } 1675 IUnknown_Release(remote_unk); 1676 } 1677 1678 return handle; 1679 } 1680 1681 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) 1682 { 1683 static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0}; 1684 static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0}; 1685 static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0}; 1686 MSIRECORD *uirow; 1687 LPWSTR deformated, message; 1688 DWORD i, len, total_len, log_type = 0; 1689 INT rc = 0; 1690 char *msg; 1691 1692 TRACE("%x\n", eMessageType); 1693 1694 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_FATALEXIT) 1695 log_type |= INSTALLLOGMODE_FATALEXIT; 1696 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR) 1697 log_type |= INSTALLLOGMODE_ERROR; 1698 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING) 1699 log_type |= INSTALLLOGMODE_WARNING; 1700 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_USER) 1701 log_type |= INSTALLLOGMODE_USER; 1702 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO) 1703 log_type |= INSTALLLOGMODE_INFO; 1704 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_RESOLVESOURCE) 1705 log_type |= INSTALLLOGMODE_RESOLVESOURCE; 1706 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_OUTOFDISKSPACE) 1707 log_type |= INSTALLLOGMODE_OUTOFDISKSPACE; 1708 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA) 1709 log_type |= INSTALLLOGMODE_COMMONDATA; 1710 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART) 1711 log_type |= INSTALLLOGMODE_ACTIONSTART; 1712 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA) 1713 log_type |= INSTALLLOGMODE_ACTIONDATA; 1714 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS) 1715 log_type |= INSTALLLOGMODE_PROGRESS; 1716 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE) 1717 log_type |= INSTALLLOGMODE_INITIALIZE; 1718 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE) 1719 log_type |= INSTALLLOGMODE_TERMINATE; 1720 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_SHOWDIALOG) 1721 log_type |= INSTALLLOGMODE_SHOWDIALOG; 1722 1723 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART) 1724 { 1725 static const WCHAR template_s[]= 1726 {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ',0}; 1727 static const WCHAR format[] = 1728 {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; 1729 WCHAR timet[0x100]; 1730 LPCWSTR action_text, action; 1731 LPWSTR deformatted = NULL; 1732 1733 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100); 1734 1735 action = MSI_RecordGetString(record, 1); 1736 action_text = MSI_RecordGetString(record, 2); 1737 1738 if (!action || !action_text) 1739 return IDOK; 1740 1741 deformat_string(package, action_text, &deformatted); 1742 1743 len = strlenW(timet) + strlenW(action) + strlenW(template_s); 1744 if (deformatted) 1745 len += strlenW(deformatted); 1746 message = msi_alloc(len*sizeof(WCHAR)); 1747 sprintfW(message, template_s, timet, action); 1748 if (deformatted) 1749 strcatW(message, deformatted); 1750 msi_free(deformatted); 1751 } 1752 else 1753 { 1754 static const WCHAR format[] = {'%','u',':',' ',0}; 1755 UINT count = MSI_RecordGetFieldCount( record ); 1756 WCHAR *p; 1757 1758 total_len = 1; 1759 for (i = 1; i <= count; i++) 1760 { 1761 len = 0; 1762 MSI_RecordGetStringW( record, i, NULL, &len ); 1763 total_len += len + 13; 1764 } 1765 p = message = msi_alloc( total_len * sizeof(WCHAR) ); 1766 if (!p) return ERROR_OUTOFMEMORY; 1767 1768 for (i = 1; i <= count; i++) 1769 { 1770 if (count > 1) 1771 { 1772 len = sprintfW( p, format, i ); 1773 total_len -= len; 1774 p += len; 1775 } 1776 len = total_len; 1777 MSI_RecordGetStringW( record, i, p, &len ); 1778 total_len -= len; 1779 p += len; 1780 if (count > 1 && total_len) 1781 { 1782 *p++ = ' '; 1783 total_len--; 1784 } 1785 } 1786 p[0] = 0; 1787 } 1788 1789 TRACE("%p %p %p %x %x %s\n", gUIHandlerA, gUIHandlerW, gUIHandlerRecord, 1790 gUIFilter, log_type, debugstr_w(message)); 1791 1792 /* convert it to ASCII */ 1793 len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL ); 1794 msg = msi_alloc( len ); 1795 WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL ); 1796 1797 if (gUIHandlerW && (gUIFilter & log_type)) 1798 { 1799 rc = gUIHandlerW( gUIContext, eMessageType, message ); 1800 } 1801 else if (gUIHandlerA && (gUIFilter & log_type)) 1802 { 1803 rc = gUIHandlerA( gUIContext, eMessageType, msg ); 1804 } 1805 else if (gUIHandlerRecord && (gUIFilter & log_type)) 1806 { 1807 MSIHANDLE rec = MsiCreateRecord( 1 ); 1808 MsiRecordSetStringW( rec, 0, message ); 1809 rc = gUIHandlerRecord( gUIContext, eMessageType, rec ); 1810 MsiCloseHandle( rec ); 1811 } 1812 1813 if (!rc && package->log_file != INVALID_HANDLE_VALUE && 1814 (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS) 1815 { 1816 DWORD written; 1817 WriteFile( package->log_file, msg, len - 1, &written, NULL ); 1818 WriteFile( package->log_file, "\n", 1, &written, NULL ); 1819 } 1820 msi_free( msg ); 1821 msi_free( message ); 1822 1823 switch (eMessageType & 0xff000000) 1824 { 1825 case INSTALLMESSAGE_ACTIONDATA: 1826 deformat_string(package, MSI_RecordGetString(record, 2), &deformated); 1827 uirow = MSI_CreateRecord(1); 1828 MSI_RecordSetStringW(uirow, 1, deformated); 1829 msi_free(deformated); 1830 1831 msi_event_fire( package, szActionData, uirow ); 1832 msiobj_release(&uirow->hdr); 1833 1834 if (package->action_progress_increment) 1835 { 1836 uirow = MSI_CreateRecord(2); 1837 MSI_RecordSetInteger(uirow, 1, 2); 1838 MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); 1839 msi_event_fire( package, szSetProgress, uirow ); 1840 msiobj_release(&uirow->hdr); 1841 } 1842 break; 1843 1844 case INSTALLMESSAGE_ACTIONSTART: 1845 deformat_string(package, MSI_RecordGetString(record, 2), &deformated); 1846 uirow = MSI_CreateRecord(1); 1847 MSI_RecordSetStringW(uirow, 1, deformated); 1848 msi_free(deformated); 1849 1850 msi_event_fire( package, szActionText, uirow ); 1851 1852 msiobj_release(&uirow->hdr); 1853 break; 1854 1855 case INSTALLMESSAGE_PROGRESS: 1856 msi_event_fire( package, szSetProgress, record ); 1857 break; 1858 } 1859 1860 return ERROR_SUCCESS; 1861 } 1862 1863 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, 1864 MSIHANDLE hRecord) 1865 { 1866 UINT ret = ERROR_INVALID_HANDLE; 1867 MSIPACKAGE *package = NULL; 1868 MSIRECORD *record = NULL; 1869 1870 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 1871 if( !package ) 1872 { 1873 HRESULT hr; 1874 IWineMsiRemotePackage *remote_package; 1875 1876 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 1877 if (!remote_package) 1878 return ERROR_INVALID_HANDLE; 1879 1880 hr = IWineMsiRemotePackage_ProcessMessage( remote_package, eMessageType, hRecord ); 1881 1882 IWineMsiRemotePackage_Release( remote_package ); 1883 1884 if (FAILED(hr)) 1885 { 1886 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 1887 return HRESULT_CODE(hr); 1888 1889 return ERROR_FUNCTION_FAILED; 1890 } 1891 1892 return ERROR_SUCCESS; 1893 } 1894 1895 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); 1896 if( !record ) 1897 goto out; 1898 1899 ret = MSI_ProcessMessage( package, eMessageType, record ); 1900 1901 out: 1902 msiobj_release( &package->hdr ); 1903 if( record ) 1904 msiobj_release( &record->hdr ); 1905 1906 return ret; 1907 } 1908 1909 /* property code */ 1910 1911 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue ) 1912 { 1913 LPWSTR szwName = NULL, szwValue = NULL; 1914 UINT r = ERROR_OUTOFMEMORY; 1915 1916 szwName = strdupAtoW( szName ); 1917 if( szName && !szwName ) 1918 goto end; 1919 1920 szwValue = strdupAtoW( szValue ); 1921 if( szValue && !szwValue ) 1922 goto end; 1923 1924 r = MsiSetPropertyW( hInstall, szwName, szwValue); 1925 1926 end: 1927 msi_free( szwName ); 1928 msi_free( szwValue ); 1929 1930 return r; 1931 } 1932 1933 void msi_reset_folders( MSIPACKAGE *package, BOOL source ) 1934 { 1935 MSIFOLDER *folder; 1936 1937 LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry ) 1938 { 1939 if ( source ) 1940 { 1941 msi_free( folder->ResolvedSource ); 1942 folder->ResolvedSource = NULL; 1943 } 1944 else 1945 { 1946 msi_free( folder->ResolvedTarget ); 1947 folder->ResolvedTarget = NULL; 1948 } 1949 } 1950 } 1951 1952 UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len ) 1953 { 1954 static const WCHAR insert_query[] = { 1955 'I','N','S','E','R','T',' ','I','N','T','O',' ', 1956 '`','_','P','r','o','p','e','r','t','y','`',' ', 1957 '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 1958 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 1959 static const WCHAR update_query[] = { 1960 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 1961 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ', 1962 '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 1963 static const WCHAR delete_query[] = { 1964 'D','E','L','E','T','E',' ','F','R','O','M',' ', 1965 '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ', 1966 '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 1967 MSIQUERY *view; 1968 MSIRECORD *row = NULL; 1969 DWORD sz = 0; 1970 WCHAR query[1024]; 1971 UINT rc; 1972 1973 TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len); 1974 1975 if (!name) 1976 return ERROR_INVALID_PARAMETER; 1977 1978 /* this one is weird... */ 1979 if (!name[0]) 1980 return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; 1981 1982 if (value && len < 0) len = strlenW( value ); 1983 1984 rc = msi_get_property( db, name, 0, &sz ); 1985 if (!value || (!*value && !len)) 1986 { 1987 sprintfW( query, delete_query, name ); 1988 } 1989 else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) 1990 { 1991 sprintfW( query, update_query, name ); 1992 row = MSI_CreateRecord(1); 1993 msi_record_set_string( row, 1, value, len ); 1994 } 1995 else 1996 { 1997 strcpyW( query, insert_query ); 1998 row = MSI_CreateRecord(2); 1999 msi_record_set_string( row, 1, name, -1 ); 2000 msi_record_set_string( row, 2, value, len ); 2001 } 2002 2003 rc = MSI_DatabaseOpenViewW(db, query, &view); 2004 if (rc == ERROR_SUCCESS) 2005 { 2006 rc = MSI_ViewExecute(view, row); 2007 MSI_ViewClose(view); 2008 msiobj_release(&view->hdr); 2009 } 2010 if (row) msiobj_release(&row->hdr); 2011 return rc; 2012 } 2013 2014 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue) 2015 { 2016 MSIPACKAGE *package; 2017 UINT ret; 2018 2019 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 2020 if( !package ) 2021 { 2022 HRESULT hr; 2023 BSTR name = NULL, value = NULL; 2024 IWineMsiRemotePackage *remote_package; 2025 2026 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 2027 if (!remote_package) 2028 return ERROR_INVALID_HANDLE; 2029 2030 name = SysAllocString( szName ); 2031 value = SysAllocString( szValue ); 2032 if ((!name && szName) || (!value && szValue)) 2033 { 2034 SysFreeString( name ); 2035 SysFreeString( value ); 2036 IWineMsiRemotePackage_Release( remote_package ); 2037 return ERROR_OUTOFMEMORY; 2038 } 2039 2040 hr = IWineMsiRemotePackage_SetProperty( remote_package, name, value ); 2041 2042 SysFreeString( name ); 2043 SysFreeString( value ); 2044 IWineMsiRemotePackage_Release( remote_package ); 2045 2046 if (FAILED(hr)) 2047 { 2048 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 2049 return HRESULT_CODE(hr); 2050 2051 return ERROR_FUNCTION_FAILED; 2052 } 2053 2054 return ERROR_SUCCESS; 2055 } 2056 2057 ret = msi_set_property( package->db, szName, szValue, -1 ); 2058 if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir )) 2059 msi_reset_folders( package, TRUE ); 2060 2061 msiobj_release( &package->hdr ); 2062 return ret; 2063 } 2064 2065 static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name ) 2066 { 2067 static const WCHAR query[]= { 2068 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 2069 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ', 2070 'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0}; 2071 MSIRECORD *rec, *row = NULL; 2072 MSIQUERY *view; 2073 UINT r; 2074 2075 if (!name || !*name) 2076 return NULL; 2077 2078 rec = MSI_CreateRecord(1); 2079 if (!rec) 2080 return NULL; 2081 2082 MSI_RecordSetStringW(rec, 1, name); 2083 2084 r = MSI_DatabaseOpenViewW(db, query, &view); 2085 if (r == ERROR_SUCCESS) 2086 { 2087 MSI_ViewExecute(view, rec); 2088 MSI_ViewFetch(view, &row); 2089 MSI_ViewClose(view); 2090 msiobj_release(&view->hdr); 2091 } 2092 msiobj_release(&rec->hdr); 2093 return row; 2094 } 2095 2096 /* internal function, not compatible with MsiGetPropertyW */ 2097 UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName, 2098 LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2099 { 2100 MSIRECORD *row; 2101 UINT rc = ERROR_FUNCTION_FAILED; 2102 2103 TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf); 2104 2105 row = msi_get_property_row( db, szName ); 2106 2107 if (*pchValueBuf > 0) 2108 szValueBuf[0] = 0; 2109 2110 if (row) 2111 { 2112 rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf); 2113 msiobj_release(&row->hdr); 2114 } 2115 2116 if (rc == ERROR_SUCCESS) 2117 TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf), 2118 debugstr_w(szName)); 2119 else if (rc == ERROR_MORE_DATA) 2120 TRACE("need %d sized buffer for %s\n", *pchValueBuf, 2121 debugstr_w(szName)); 2122 else 2123 { 2124 *pchValueBuf = 0; 2125 TRACE("property %s not found\n", debugstr_w(szName)); 2126 } 2127 2128 return rc; 2129 } 2130 2131 LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) 2132 { 2133 DWORD sz = 0; 2134 LPWSTR str; 2135 UINT r; 2136 2137 r = msi_get_property(db, prop, NULL, &sz); 2138 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2139 return NULL; 2140 2141 sz++; 2142 str = msi_alloc(sz * sizeof(WCHAR)); 2143 r = msi_get_property(db, prop, str, &sz); 2144 if (r != ERROR_SUCCESS) 2145 { 2146 msi_free(str); 2147 str = NULL; 2148 } 2149 2150 return str; 2151 } 2152 2153 int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def ) 2154 { 2155 LPWSTR str = msi_dup_property( db, prop ); 2156 int val = str ? atoiW(str) : def; 2157 msi_free(str); 2158 return val; 2159 } 2160 2161 static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, 2162 awstring *szValueBuf, LPDWORD pchValueBuf ) 2163 { 2164 MSIPACKAGE *package; 2165 MSIRECORD *row = NULL; 2166 UINT r = ERROR_FUNCTION_FAILED; 2167 LPCWSTR val = NULL; 2168 DWORD len = 0; 2169 2170 TRACE("%u %s %p %p\n", handle, debugstr_w(name), 2171 szValueBuf->str.w, pchValueBuf ); 2172 2173 if (!name) 2174 return ERROR_INVALID_PARAMETER; 2175 2176 package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ); 2177 if (!package) 2178 { 2179 HRESULT hr; 2180 IWineMsiRemotePackage *remote_package; 2181 LPWSTR value = NULL; 2182 BSTR bname; 2183 2184 remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle ); 2185 if (!remote_package) 2186 return ERROR_INVALID_HANDLE; 2187 2188 bname = SysAllocString( name ); 2189 if (!bname) 2190 { 2191 IWineMsiRemotePackage_Release( remote_package ); 2192 return ERROR_OUTOFMEMORY; 2193 } 2194 2195 hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len ); 2196 if (FAILED(hr)) 2197 goto done; 2198 2199 len++; 2200 value = msi_alloc(len * sizeof(WCHAR)); 2201 if (!value) 2202 { 2203 r = ERROR_OUTOFMEMORY; 2204 goto done; 2205 } 2206 2207 hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, value, &len ); 2208 if (FAILED(hr)) 2209 goto done; 2210 2211 r = msi_strcpy_to_awstring( value, len, szValueBuf, pchValueBuf ); 2212 2213 /* Bug required by Adobe installers */ 2214 if (!szValueBuf->unicode && !szValueBuf->str.a) 2215 *pchValueBuf *= sizeof(WCHAR); 2216 2217 done: 2218 IWineMsiRemotePackage_Release(remote_package); 2219 SysFreeString(bname); 2220 msi_free(value); 2221 2222 if (FAILED(hr)) 2223 { 2224 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 2225 return HRESULT_CODE(hr); 2226 2227 return ERROR_FUNCTION_FAILED; 2228 } 2229 2230 return r; 2231 } 2232 2233 row = msi_get_property_row( package->db, name ); 2234 if (row) 2235 val = msi_record_get_string( row, 1, (int *)&len ); 2236 2237 if (!val) 2238 val = szEmpty; 2239 2240 r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf ); 2241 2242 if (row) 2243 msiobj_release( &row->hdr ); 2244 msiobj_release( &package->hdr ); 2245 2246 return r; 2247 } 2248 2249 UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName, 2250 LPSTR szValueBuf, LPDWORD pchValueBuf ) 2251 { 2252 awstring val; 2253 LPWSTR name; 2254 UINT r; 2255 2256 val.unicode = FALSE; 2257 val.str.a = szValueBuf; 2258 2259 name = strdupAtoW( szName ); 2260 if (szName && !name) 2261 return ERROR_OUTOFMEMORY; 2262 2263 r = MSI_GetProperty( hInstall, name, &val, pchValueBuf ); 2264 msi_free( name ); 2265 return r; 2266 } 2267 2268 UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, 2269 LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2270 { 2271 awstring val; 2272 2273 val.unicode = TRUE; 2274 val.str.w = szValueBuf; 2275 2276 return MSI_GetProperty( hInstall, szName, &val, pchValueBuf ); 2277 } 2278 2279 typedef struct _msi_remote_package_impl { 2280 IWineMsiRemotePackage IWineMsiRemotePackage_iface; 2281 MSIHANDLE package; 2282 LONG refs; 2283 } msi_remote_package_impl; 2284 2285 static inline msi_remote_package_impl *impl_from_IWineMsiRemotePackage( IWineMsiRemotePackage *iface ) 2286 { 2287 return CONTAINING_RECORD(iface, msi_remote_package_impl, IWineMsiRemotePackage_iface); 2288 } 2289 2290 static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface, 2291 REFIID riid,LPVOID *ppobj) 2292 { 2293 if( IsEqualCLSID( riid, &IID_IUnknown ) || 2294 IsEqualCLSID( riid, &IID_IWineMsiRemotePackage ) ) 2295 { 2296 IWineMsiRemotePackage_AddRef( iface ); 2297 *ppobj = iface; 2298 return S_OK; 2299 } 2300 2301 return E_NOINTERFACE; 2302 } 2303 2304 static ULONG WINAPI mrp_AddRef( IWineMsiRemotePackage *iface ) 2305 { 2306 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2307 2308 return InterlockedIncrement( &This->refs ); 2309 } 2310 2311 static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface ) 2312 { 2313 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2314 ULONG r; 2315 2316 r = InterlockedDecrement( &This->refs ); 2317 if (r == 0) 2318 { 2319 MsiCloseHandle( This->package ); 2320 msi_free( This ); 2321 } 2322 return r; 2323 } 2324 2325 static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE handle ) 2326 { 2327 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2328 This->package = handle; 2329 return S_OK; 2330 } 2331 2332 static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle ) 2333 { 2334 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2335 IWineMsiRemoteDatabase *rdb = NULL; 2336 HRESULT hr; 2337 MSIHANDLE hdb; 2338 2339 hr = create_msi_remote_database( NULL, (LPVOID *)&rdb ); 2340 if (FAILED(hr) || !rdb) 2341 { 2342 ERR("Failed to create remote database\n"); 2343 return hr; 2344 } 2345 2346 hdb = MsiGetActiveDatabase(This->package); 2347 2348 hr = IWineMsiRemoteDatabase_SetMsiHandle( rdb, hdb ); 2349 if (FAILED(hr)) 2350 { 2351 ERR("Failed to set the database handle\n"); 2352 return hr; 2353 } 2354 2355 *handle = alloc_msi_remote_handle( (IUnknown *)rdb ); 2356 return S_OK; 2357 } 2358 2359 static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value, DWORD *size ) 2360 { 2361 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2362 UINT r = MsiGetPropertyW(This->package, property, value, size); 2363 if (r != ERROR_SUCCESS) return HRESULT_FROM_WIN32(r); 2364 return S_OK; 2365 } 2366 2367 static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value ) 2368 { 2369 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2370 UINT r = MsiSetPropertyW(This->package, property, value); 2371 return HRESULT_FROM_WIN32(r); 2372 } 2373 2374 static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record ) 2375 { 2376 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2377 UINT r = MsiProcessMessage(This->package, message, record); 2378 return HRESULT_FROM_WIN32(r); 2379 } 2380 2381 static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action ) 2382 { 2383 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2384 UINT r = MsiDoActionW(This->package, action); 2385 return HRESULT_FROM_WIN32(r); 2386 } 2387 2388 static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence ) 2389 { 2390 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2391 UINT r = MsiSequenceW(This->package, table, sequence); 2392 return HRESULT_FROM_WIN32(r); 2393 } 2394 2395 static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size ) 2396 { 2397 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2398 UINT r = MsiGetTargetPathW(This->package, folder, value, size); 2399 return HRESULT_FROM_WIN32(r); 2400 } 2401 2402 static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value) 2403 { 2404 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2405 UINT r = MsiSetTargetPathW(This->package, folder, value); 2406 return HRESULT_FROM_WIN32(r); 2407 } 2408 2409 static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size ) 2410 { 2411 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2412 UINT r = MsiGetSourcePathW(This->package, folder, value, size); 2413 return HRESULT_FROM_WIN32(r); 2414 } 2415 2416 static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret ) 2417 { 2418 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2419 *ret = MsiGetMode(This->package, mode); 2420 return S_OK; 2421 } 2422 2423 static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state ) 2424 { 2425 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2426 UINT r = MsiSetMode(This->package, mode, state); 2427 return HRESULT_FROM_WIN32(r); 2428 } 2429 2430 static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, 2431 INSTALLSTATE *installed, INSTALLSTATE *action ) 2432 { 2433 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2434 UINT r = MsiGetFeatureStateW(This->package, feature, installed, action); 2435 return HRESULT_FROM_WIN32(r); 2436 } 2437 2438 static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state ) 2439 { 2440 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2441 UINT r = MsiSetFeatureStateW(This->package, feature, state); 2442 return HRESULT_FROM_WIN32(r); 2443 } 2444 2445 static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component, 2446 INSTALLSTATE *installed, INSTALLSTATE *action ) 2447 { 2448 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2449 UINT r = MsiGetComponentStateW(This->package, component, installed, action); 2450 return HRESULT_FROM_WIN32(r); 2451 } 2452 2453 static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state ) 2454 { 2455 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2456 UINT r = MsiSetComponentStateW(This->package, component, state); 2457 return HRESULT_FROM_WIN32(r); 2458 } 2459 2460 static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language ) 2461 { 2462 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2463 *language = MsiGetLanguage(This->package); 2464 return S_OK; 2465 } 2466 2467 static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level ) 2468 { 2469 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2470 UINT r = MsiSetInstallLevel(This->package, level); 2471 return HRESULT_FROM_WIN32(r); 2472 } 2473 2474 static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record, 2475 BSTR *value) 2476 { 2477 DWORD size = 0; 2478 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2479 UINT r = MsiFormatRecordW(This->package, record, NULL, &size); 2480 if (r == ERROR_SUCCESS) 2481 { 2482 *value = SysAllocStringLen(NULL, size); 2483 if (!*value) 2484 return E_OUTOFMEMORY; 2485 size++; 2486 r = MsiFormatRecordW(This->package, record, *value, &size); 2487 } 2488 return HRESULT_FROM_WIN32(r); 2489 } 2490 2491 static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition ) 2492 { 2493 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2494 UINT r = MsiEvaluateConditionW(This->package, condition); 2495 return HRESULT_FROM_WIN32(r); 2496 } 2497 2498 static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature, 2499 INT cost_tree, INSTALLSTATE state, INT *cost ) 2500 { 2501 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2502 UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost); 2503 return HRESULT_FROM_WIN32(r); 2504 } 2505 2506 static HRESULT WINAPI mrp_EnumComponentCosts( IWineMsiRemotePackage *iface, BSTR component, 2507 DWORD index, INSTALLSTATE state, BSTR drive, 2508 DWORD *buflen, INT *cost, INT *temp ) 2509 { 2510 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2511 UINT r = MsiEnumComponentCostsW(This->package, component, index, state, drive, buflen, cost, temp); 2512 return HRESULT_FROM_WIN32(r); 2513 } 2514 2515 static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl = 2516 { 2517 mrp_QueryInterface, 2518 mrp_AddRef, 2519 mrp_Release, 2520 mrp_SetMsiHandle, 2521 mrp_GetActiveDatabase, 2522 mrp_GetProperty, 2523 mrp_SetProperty, 2524 mrp_ProcessMessage, 2525 mrp_DoAction, 2526 mrp_Sequence, 2527 mrp_GetTargetPath, 2528 mrp_SetTargetPath, 2529 mrp_GetSourcePath, 2530 mrp_GetMode, 2531 mrp_SetMode, 2532 mrp_GetFeatureState, 2533 mrp_SetFeatureState, 2534 mrp_GetComponentState, 2535 mrp_SetComponentState, 2536 mrp_GetLanguage, 2537 mrp_SetInstallLevel, 2538 mrp_FormatRecord, 2539 mrp_EvaluateCondition, 2540 mrp_GetFeatureCost, 2541 mrp_EnumComponentCosts 2542 }; 2543 2544 HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj ) 2545 { 2546 msi_remote_package_impl* This; 2547 2548 This = msi_alloc( sizeof *This ); 2549 if (!This) 2550 return E_OUTOFMEMORY; 2551 2552 This->IWineMsiRemotePackage_iface.lpVtbl = &msi_remote_package_vtbl; 2553 This->package = 0; 2554 This->refs = 1; 2555 2556 *ppObj = &This->IWineMsiRemotePackage_iface; 2557 2558 return S_OK; 2559 } 2560 2561 UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options, 2562 LPCWSTR property, LPWSTR value) 2563 { 2564 MSISOURCELISTINFO *info; 2565 2566 LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry ) 2567 { 2568 if (!strcmpW( info->value, value )) return ERROR_SUCCESS; 2569 } 2570 2571 info = msi_alloc(sizeof(MSISOURCELISTINFO)); 2572 if (!info) 2573 return ERROR_OUTOFMEMORY; 2574 2575 info->context = context; 2576 info->options = options; 2577 info->property = property; 2578 info->value = strdupW(value); 2579 list_add_head(&package->sourcelist_info, &info->entry); 2580 2581 return ERROR_SUCCESS; 2582 } 2583 2584 UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options, 2585 DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt) 2586 { 2587 MSIMEDIADISK *disk; 2588 2589 LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry ) 2590 { 2591 if (disk->disk_id == disk_id) return ERROR_SUCCESS; 2592 } 2593 2594 disk = msi_alloc(sizeof(MSIMEDIADISK)); 2595 if (!disk) 2596 return ERROR_OUTOFMEMORY; 2597 2598 disk->context = context; 2599 disk->options = options; 2600 disk->disk_id = disk_id; 2601 disk->volume_label = strdupW(volume_label); 2602 disk->disk_prompt = strdupW(disk_prompt); 2603 list_add_head(&package->sourcelist_media, &disk->entry); 2604 2605 return ERROR_SUCCESS; 2606 } 2607