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