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