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 = sizeof(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 lstrcatW(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 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(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1557 { 1558 MSIPACKAGE *package = NULL; 1559 UINT ret; 1560 1561 TRACE("%s %08x %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 %08x 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("(%d)\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=%08x, hRecord=%u)\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=%08x, 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=%08x, 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 %d sized buffer for %s\n", *pchValueBuf, 2218 debugstr_w(szName)); 2219 else 2220 { 2221 *pchValueBuf = 0; 2222 TRACE("property %s not found\n", debugstr_w(szName)); 2223 } 2224 2225 return rc; 2226 } 2227 2228 LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) 2229 { 2230 DWORD sz = 0; 2231 LPWSTR str; 2232 UINT r; 2233 2234 r = msi_get_property(db, prop, NULL, &sz); 2235 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2236 return NULL; 2237 2238 sz++; 2239 str = msi_alloc(sz * sizeof(WCHAR)); 2240 r = msi_get_property(db, prop, str, &sz); 2241 if (r != ERROR_SUCCESS) 2242 { 2243 msi_free(str); 2244 str = NULL; 2245 } 2246 2247 return str; 2248 } 2249 2250 int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def ) 2251 { 2252 LPWSTR str = msi_dup_property( db, prop ); 2253 int val = str ? wcstol(str, NULL, 10) : def; 2254 msi_free(str); 2255 return val; 2256 } 2257 2258 UINT WINAPI MsiGetPropertyA(MSIHANDLE hinst, const char *name, char *buf, DWORD *sz) 2259 { 2260 const WCHAR *value = L""; 2261 MSIPACKAGE *package; 2262 MSIRECORD *row; 2263 WCHAR *nameW; 2264 int len = 0; 2265 UINT r; 2266 2267 if (!name) 2268 return ERROR_INVALID_PARAMETER; 2269 2270 if (!(nameW = strdupAtoW(name))) 2271 return ERROR_OUTOFMEMORY; 2272 2273 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE); 2274 if (!package) 2275 { 2276 WCHAR *value = NULL, *tmp; 2277 MSIHANDLE remote; 2278 DWORD len; 2279 2280 if (!(remote = msi_get_remote(hinst))) 2281 { 2282 heap_free(nameW); 2283 return ERROR_INVALID_HANDLE; 2284 } 2285 2286 __TRY 2287 { 2288 r = remote_GetProperty(remote, nameW, &value, &len); 2289 } 2290 __EXCEPT(rpc_filter) 2291 { 2292 r = GetExceptionCode(); 2293 } 2294 __ENDTRY 2295 2296 heap_free(nameW); 2297 2298 if (!r) 2299 { 2300 /* String might contain embedded nulls. 2301 * Native returns the correct size but truncates the string. */ 2302 tmp = heap_alloc_zero((len + 1) * sizeof(WCHAR)); 2303 if (!tmp) 2304 { 2305 midl_user_free(value); 2306 return ERROR_OUTOFMEMORY; 2307 } 2308 lstrcpyW(tmp, value); 2309 2310 r = msi_strncpyWtoA(tmp, len, buf, sz, TRUE); 2311 2312 heap_free(tmp); 2313 } 2314 midl_user_free(value); 2315 return r; 2316 } 2317 2318 row = msi_get_property_row(package->db, nameW); 2319 if (row) 2320 value = msi_record_get_string(row, 1, &len); 2321 2322 r = msi_strncpyWtoA(value, len, buf, sz, FALSE); 2323 2324 heap_free(nameW); 2325 if (row) msiobj_release(&row->hdr); 2326 msiobj_release(&package->hdr); 2327 return r; 2328 } 2329 2330 UINT WINAPI MsiGetPropertyW(MSIHANDLE hinst, const WCHAR *name, WCHAR *buf, DWORD *sz) 2331 { 2332 const WCHAR *value = L""; 2333 MSIPACKAGE *package; 2334 MSIRECORD *row; 2335 int len = 0; 2336 UINT r; 2337 2338 if (!name) 2339 return ERROR_INVALID_PARAMETER; 2340 2341 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE); 2342 if (!package) 2343 { 2344 WCHAR *value = NULL, *tmp; 2345 MSIHANDLE remote; 2346 DWORD len; 2347 2348 if (!(remote = msi_get_remote(hinst))) 2349 return ERROR_INVALID_HANDLE; 2350 2351 __TRY 2352 { 2353 r = remote_GetProperty(remote, name, &value, &len); 2354 } 2355 __EXCEPT(rpc_filter) 2356 { 2357 r = GetExceptionCode(); 2358 } 2359 __ENDTRY 2360 2361 if (!r) 2362 { 2363 /* String might contain embedded nulls. 2364 * Native returns the correct size but truncates the string. */ 2365 tmp = heap_alloc_zero((len + 1) * sizeof(WCHAR)); 2366 if (!tmp) 2367 { 2368 midl_user_free(value); 2369 return ERROR_OUTOFMEMORY; 2370 } 2371 lstrcpyW(tmp, value); 2372 2373 r = msi_strncpyW(tmp, len, buf, sz); 2374 2375 heap_free(tmp); 2376 } 2377 midl_user_free(value); 2378 return r; 2379 } 2380 2381 row = msi_get_property_row(package->db, name); 2382 if (row) 2383 value = msi_record_get_string(row, 1, &len); 2384 2385 r = msi_strncpyW(value, len, buf, sz); 2386 2387 if (row) msiobj_release(&row->hdr); 2388 msiobj_release(&package->hdr); 2389 return r; 2390 } 2391 2392 MSIHANDLE __cdecl s_remote_GetActiveDatabase(MSIHANDLE hinst) 2393 { 2394 return MsiGetActiveDatabase(hinst); 2395 } 2396 2397 UINT __cdecl s_remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value, DWORD *size) 2398 { 2399 WCHAR empty[1]; 2400 UINT r; 2401 2402 *size = 0; 2403 r = MsiGetPropertyW(hinst, property, empty, size); 2404 if (r == ERROR_MORE_DATA) 2405 { 2406 ++*size; 2407 *value = midl_user_allocate(*size * sizeof(WCHAR)); 2408 if (!*value) 2409 return ERROR_OUTOFMEMORY; 2410 r = MsiGetPropertyW(hinst, property, *value, size); 2411 } 2412 return r; 2413 } 2414 2415 UINT __cdecl s_remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value) 2416 { 2417 return MsiSetPropertyW(hinst, property, value); 2418 } 2419 2420 int __cdecl s_remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, struct wire_record *remote_rec) 2421 { 2422 MSIHANDLE rec; 2423 int ret; 2424 UINT r; 2425 2426 if ((r = unmarshal_record(remote_rec, &rec))) 2427 return r; 2428 2429 ret = MsiProcessMessage(hinst, message, rec); 2430 2431 MsiCloseHandle(rec); 2432 return ret; 2433 } 2434 2435 UINT __cdecl s_remote_DoAction(MSIHANDLE hinst, LPCWSTR action) 2436 { 2437 return MsiDoActionW(hinst, action); 2438 } 2439 2440 UINT __cdecl s_remote_Sequence(MSIHANDLE hinst, LPCWSTR table, int sequence) 2441 { 2442 return MsiSequenceW(hinst, table, sequence); 2443 } 2444 2445 UINT __cdecl s_remote_GetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value) 2446 { 2447 WCHAR empty[1]; 2448 DWORD size = 0; 2449 UINT r; 2450 2451 r = MsiGetTargetPathW(hinst, folder, empty, &size); 2452 if (r == ERROR_MORE_DATA) 2453 { 2454 *value = midl_user_allocate(++size * sizeof(WCHAR)); 2455 if (!*value) 2456 return ERROR_OUTOFMEMORY; 2457 r = MsiGetTargetPathW(hinst, folder, *value, &size); 2458 } 2459 return r; 2460 } 2461 2462 UINT __cdecl s_remote_SetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPCWSTR value) 2463 { 2464 return MsiSetTargetPathW(hinst, folder, value); 2465 } 2466 2467 UINT __cdecl s_remote_GetSourcePath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value) 2468 { 2469 WCHAR empty[1]; 2470 DWORD size = 1; 2471 UINT r; 2472 2473 r = MsiGetSourcePathW(hinst, folder, empty, &size); 2474 if (r == ERROR_MORE_DATA) 2475 { 2476 *value = midl_user_allocate(++size * sizeof(WCHAR)); 2477 if (!*value) 2478 return ERROR_OUTOFMEMORY; 2479 r = MsiGetSourcePathW(hinst, folder, *value, &size); 2480 } 2481 return r; 2482 } 2483 2484 BOOL __cdecl s_remote_GetMode(MSIHANDLE hinst, MSIRUNMODE mode) 2485 { 2486 return MsiGetMode(hinst, mode); 2487 } 2488 2489 UINT __cdecl s_remote_SetMode(MSIHANDLE hinst, MSIRUNMODE mode, BOOL state) 2490 { 2491 return MsiSetMode(hinst, mode, state); 2492 } 2493 2494 UINT __cdecl s_remote_GetFeatureState(MSIHANDLE hinst, LPCWSTR feature, 2495 INSTALLSTATE *installed, INSTALLSTATE *action) 2496 { 2497 return MsiGetFeatureStateW(hinst, feature, installed, action); 2498 } 2499 2500 UINT __cdecl s_remote_SetFeatureState(MSIHANDLE hinst, LPCWSTR feature, INSTALLSTATE state) 2501 { 2502 return MsiSetFeatureStateW(hinst, feature, state); 2503 } 2504 2505 UINT __cdecl s_remote_GetComponentState(MSIHANDLE hinst, LPCWSTR component, 2506 INSTALLSTATE *installed, INSTALLSTATE *action) 2507 { 2508 return MsiGetComponentStateW(hinst, component, installed, action); 2509 } 2510 2511 UINT __cdecl s_remote_SetComponentState(MSIHANDLE hinst, LPCWSTR component, INSTALLSTATE state) 2512 { 2513 return MsiSetComponentStateW(hinst, component, state); 2514 } 2515 2516 LANGID __cdecl s_remote_GetLanguage(MSIHANDLE hinst) 2517 { 2518 return MsiGetLanguage(hinst); 2519 } 2520 2521 UINT __cdecl s_remote_SetInstallLevel(MSIHANDLE hinst, int level) 2522 { 2523 return MsiSetInstallLevel(hinst, level); 2524 } 2525 2526 UINT __cdecl s_remote_FormatRecord(MSIHANDLE hinst, struct wire_record *remote_rec, LPWSTR *value) 2527 { 2528 WCHAR empty[1]; 2529 DWORD size = 0; 2530 MSIHANDLE rec; 2531 UINT r; 2532 2533 if ((r = unmarshal_record(remote_rec, &rec))) 2534 return r; 2535 2536 r = MsiFormatRecordW(hinst, rec, empty, &size); 2537 if (r == ERROR_MORE_DATA) 2538 { 2539 *value = midl_user_allocate(++size * sizeof(WCHAR)); 2540 if (!*value) 2541 { 2542 MsiCloseHandle(rec); 2543 return ERROR_OUTOFMEMORY; 2544 } 2545 r = MsiFormatRecordW(hinst, rec, *value, &size); 2546 } 2547 2548 MsiCloseHandle(rec); 2549 return r; 2550 } 2551 2552 MSICONDITION __cdecl s_remote_EvaluateCondition(MSIHANDLE hinst, LPCWSTR condition) 2553 { 2554 return MsiEvaluateConditionW(hinst, condition); 2555 } 2556 2557 UINT __cdecl s_remote_GetFeatureCost(MSIHANDLE hinst, LPCWSTR feature, 2558 MSICOSTTREE cost_tree, INSTALLSTATE state, INT *cost) 2559 { 2560 return MsiGetFeatureCostW(hinst, feature, cost_tree, state, cost); 2561 } 2562 2563 UINT __cdecl s_remote_EnumComponentCosts(MSIHANDLE hinst, LPCWSTR component, 2564 DWORD index, INSTALLSTATE state, LPWSTR drive, INT *cost, INT *temp) 2565 { 2566 DWORD size = 3; 2567 return MsiEnumComponentCostsW(hinst, component, index, state, drive, &size, cost, temp); 2568 } 2569 2570 UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options, 2571 LPCWSTR property, LPWSTR value) 2572 { 2573 MSISOURCELISTINFO *info; 2574 2575 LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry ) 2576 { 2577 if (!wcscmp( info->value, value )) return ERROR_SUCCESS; 2578 } 2579 2580 info = msi_alloc(sizeof(MSISOURCELISTINFO)); 2581 if (!info) 2582 return ERROR_OUTOFMEMORY; 2583 2584 info->context = context; 2585 info->options = options; 2586 info->property = property; 2587 info->value = strdupW(value); 2588 list_add_head(&package->sourcelist_info, &info->entry); 2589 2590 return ERROR_SUCCESS; 2591 } 2592 2593 UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options, 2594 DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt) 2595 { 2596 MSIMEDIADISK *disk; 2597 2598 LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry ) 2599 { 2600 if (disk->disk_id == disk_id) return ERROR_SUCCESS; 2601 } 2602 2603 disk = msi_alloc(sizeof(MSIMEDIADISK)); 2604 if (!disk) 2605 return ERROR_OUTOFMEMORY; 2606 2607 disk->context = context; 2608 disk->options = options; 2609 disk->disk_id = disk_id; 2610 disk->volume_label = strdupW(volume_label); 2611 disk->disk_prompt = strdupW(disk_prompt); 2612 list_add_head(&package->sourcelist_media, &disk->entry); 2613 2614 return ERROR_SUCCESS; 2615 } 2616