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