1 /* 2 * Implementation of the Microsoft Installer (msi.dll) 3 * 4 * Copyright 2004 Aric Stewart for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #define NONAMELESSUNION 22 #define NONAMELESSSTRUCT 23 #define COBJMACROS 24 #ifdef __REACTOS__ 25 #define WIN32_NO_STATUS 26 #endif 27 28 #include <stdarg.h> 29 #include "windef.h" 30 #include "winbase.h" 31 #include "winreg.h" 32 #include "winnls.h" 33 #ifdef __REACTOS__ 34 #include <ndk/rtlfuncs.h> 35 #else 36 #include "winternl.h" 37 #endif 38 #include "shlwapi.h" 39 #include "wingdi.h" 40 #include "msi.h" 41 #include "msiquery.h" 42 #include "objidl.h" 43 #include "wincrypt.h" 44 #include "winuser.h" 45 #include "wininet.h" 46 #include "winver.h" 47 #include "urlmon.h" 48 #include "shlobj.h" 49 #include "objbase.h" 50 #include "msidefs.h" 51 #include "sddl.h" 52 53 #include "wine/debug.h" 54 #include "wine/exception.h" 55 56 #include "msipriv.h" 57 #include "winemsi_s.h" 58 #include "resource.h" 59 60 WINE_DEFAULT_DEBUG_CHANNEL(msi); 61 62 static void free_feature( MSIFEATURE *feature ) 63 { 64 struct list *item, *cursor; 65 66 LIST_FOR_EACH_SAFE( item, cursor, &feature->Children ) 67 { 68 FeatureList *fl = LIST_ENTRY( item, FeatureList, entry ); 69 list_remove( &fl->entry ); 70 msi_free( fl ); 71 } 72 73 LIST_FOR_EACH_SAFE( item, cursor, &feature->Components ) 74 { 75 ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); 76 list_remove( &cl->entry ); 77 msi_free( cl ); 78 } 79 msi_free( feature->Feature ); 80 msi_free( feature->Feature_Parent ); 81 msi_free( feature->Directory ); 82 msi_free( feature->Description ); 83 msi_free( feature->Title ); 84 msi_free( feature ); 85 } 86 87 static void free_folder( MSIFOLDER *folder ) 88 { 89 struct list *item, *cursor; 90 91 LIST_FOR_EACH_SAFE( item, cursor, &folder->children ) 92 { 93 FolderList *fl = LIST_ENTRY( item, FolderList, entry ); 94 list_remove( &fl->entry ); 95 msi_free( fl ); 96 } 97 msi_free( folder->Parent ); 98 msi_free( folder->Directory ); 99 msi_free( folder->TargetDefault ); 100 msi_free( folder->SourceLongPath ); 101 msi_free( folder->SourceShortPath ); 102 msi_free( folder->ResolvedTarget ); 103 msi_free( folder->ResolvedSource ); 104 msi_free( folder ); 105 } 106 107 static void free_extension( MSIEXTENSION *ext ) 108 { 109 struct list *item, *cursor; 110 111 LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs ) 112 { 113 MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry ); 114 115 list_remove( &verb->entry ); 116 msi_free( verb->Verb ); 117 msi_free( verb->Command ); 118 msi_free( verb->Argument ); 119 msi_free( verb ); 120 } 121 122 msi_free( ext->Extension ); 123 msi_free( ext->ProgIDText ); 124 msi_free( ext ); 125 } 126 127 static void free_assembly( MSIASSEMBLY *assembly ) 128 { 129 msi_free( assembly->feature ); 130 msi_free( assembly->manifest ); 131 msi_free( assembly->application ); 132 msi_free( assembly->display_name ); 133 if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir ); 134 msi_free( assembly->tempdir ); 135 msi_free( assembly ); 136 } 137 138 void msi_free_action_script( MSIPACKAGE *package, UINT script ) 139 { 140 UINT i; 141 for (i = 0; i < package->script_actions_count[script]; i++) 142 msi_free( package->script_actions[script][i] ); 143 144 msi_free( package->script_actions[script] ); 145 package->script_actions[script] = NULL; 146 package->script_actions_count[script] = 0; 147 } 148 149 static void free_package_structures( MSIPACKAGE *package ) 150 { 151 struct list *item, *cursor; 152 int i; 153 154 LIST_FOR_EACH_SAFE( item, cursor, &package->features ) 155 { 156 MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry ); 157 list_remove( &feature->entry ); 158 free_feature( feature ); 159 } 160 161 LIST_FOR_EACH_SAFE( item, cursor, &package->folders ) 162 { 163 MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry ); 164 list_remove( &folder->entry ); 165 free_folder( folder ); 166 } 167 168 LIST_FOR_EACH_SAFE( item, cursor, &package->files ) 169 { 170 MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry ); 171 172 list_remove( &file->entry ); 173 msi_free( file->File ); 174 msi_free( file->FileName ); 175 msi_free( file->ShortName ); 176 msi_free( file->LongName ); 177 msi_free( file->Version ); 178 msi_free( file->Language ); 179 if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath ); 180 msi_free( file->TargetPath ); 181 msi_free( file ); 182 } 183 184 LIST_FOR_EACH_SAFE( item, cursor, &package->components ) 185 { 186 MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry ); 187 188 list_remove( &comp->entry ); 189 msi_free( comp->Component ); 190 msi_free( comp->ComponentId ); 191 msi_free( comp->Directory ); 192 msi_free( comp->Condition ); 193 msi_free( comp->KeyPath ); 194 msi_free( comp->FullKeypath ); 195 if (comp->assembly) free_assembly( comp->assembly ); 196 msi_free( comp ); 197 } 198 199 LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches ) 200 { 201 MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry ); 202 203 list_remove( &patch->entry ); 204 msi_free( patch->path ); 205 msi_free( patch ); 206 } 207 208 /* clean up extension, progid, class and verb structures */ 209 LIST_FOR_EACH_SAFE( item, cursor, &package->classes ) 210 { 211 MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry ); 212 213 list_remove( &cls->entry ); 214 msi_free( cls->clsid ); 215 msi_free( cls->Context ); 216 msi_free( cls->Description ); 217 msi_free( cls->FileTypeMask ); 218 msi_free( cls->IconPath ); 219 msi_free( cls->DefInprocHandler ); 220 msi_free( cls->DefInprocHandler32 ); 221 msi_free( cls->Argument ); 222 msi_free( cls->ProgIDText ); 223 msi_free( cls ); 224 } 225 226 LIST_FOR_EACH_SAFE( item, cursor, &package->extensions ) 227 { 228 MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry ); 229 230 list_remove( &ext->entry ); 231 free_extension( ext ); 232 } 233 234 LIST_FOR_EACH_SAFE( item, cursor, &package->progids ) 235 { 236 MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry ); 237 238 list_remove( &progid->entry ); 239 msi_free( progid->ProgID ); 240 msi_free( progid->Description ); 241 msi_free( progid->IconPath ); 242 msi_free( progid ); 243 } 244 245 LIST_FOR_EACH_SAFE( item, cursor, &package->mimes ) 246 { 247 MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry ); 248 249 list_remove( &mt->entry ); 250 msi_free( mt->suffix ); 251 msi_free( mt->clsid ); 252 msi_free( mt->ContentType ); 253 msi_free( mt ); 254 } 255 256 LIST_FOR_EACH_SAFE( item, cursor, &package->appids ) 257 { 258 MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry ); 259 260 list_remove( &appid->entry ); 261 msi_free( appid->AppID ); 262 msi_free( appid->RemoteServerName ); 263 msi_free( appid->LocalServer ); 264 msi_free( appid->ServiceParameters ); 265 msi_free( appid->DllSurrogate ); 266 msi_free( appid ); 267 } 268 269 LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info ) 270 { 271 MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry ); 272 273 list_remove( &info->entry ); 274 msi_free( info->value ); 275 msi_free( info ); 276 } 277 278 LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media ) 279 { 280 MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry ); 281 282 list_remove( &info->entry ); 283 msi_free( info->volume_label ); 284 msi_free( info->disk_prompt ); 285 msi_free( info ); 286 } 287 288 for (i = 0; i < SCRIPT_MAX; i++) 289 msi_free_action_script( package, i ); 290 291 for (i = 0; i < package->unique_actions_count; i++) 292 msi_free( package->unique_actions[i] ); 293 msi_free( package->unique_actions); 294 295 LIST_FOR_EACH_SAFE( item, cursor, &package->binaries ) 296 { 297 MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry ); 298 299 list_remove( &binary->entry ); 300 if (!DeleteFileW( binary->tmpfile )) 301 ERR( "failed to delete %s (%lu)\n", debugstr_w(binary->tmpfile), GetLastError() ); 302 msi_free( binary->source ); 303 msi_free( binary->tmpfile ); 304 msi_free( binary ); 305 } 306 307 LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams ) 308 { 309 MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry ); 310 311 list_remove( &cab->entry ); 312 IStorage_Release( cab->storage ); 313 msi_free( cab->stream ); 314 msi_free( cab ); 315 } 316 317 LIST_FOR_EACH_SAFE( item, cursor, &package->patches ) 318 { 319 MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry ); 320 321 list_remove( &patch->entry ); 322 if (patch->delete_on_close && !DeleteFileW( patch->localfile )) 323 { 324 ERR( "failed to delete %s (%lu)\n", debugstr_w(patch->localfile), GetLastError() ); 325 } 326 msi_free_patchinfo( patch ); 327 } 328 329 msi_free( package->PackagePath ); 330 msi_free( package->ProductCode ); 331 msi_free( package->ActionFormat ); 332 msi_free( package->LastAction ); 333 msi_free( package->LastActionTemplate ); 334 msi_free( package->langids ); 335 336 /* cleanup control event subscriptions */ 337 msi_event_cleanup_all_subscriptions( package ); 338 } 339 340 static void MSI_FreePackage( MSIOBJECTHDR *arg) 341 { 342 MSIPACKAGE *package = (MSIPACKAGE *)arg; 343 344 msi_destroy_assembly_caches( package ); 345 346 if( package->dialog ) 347 msi_dialog_destroy( package->dialog ); 348 349 msiobj_release( &package->db->hdr ); 350 free_package_structures(package); 351 CloseHandle( package->log_file ); 352 if (package->rpc_server_started) 353 RpcServerUnregisterIf(s_IWineMsiRemote_v0_0_s_ifspec, NULL, FALSE); 354 if (rpc_handle) 355 RpcBindingFree(&rpc_handle); 356 if (package->custom_server_32_process) 357 custom_stop_server(package->custom_server_32_process, package->custom_server_32_pipe); 358 if (package->custom_server_64_process) 359 custom_stop_server(package->custom_server_64_process, package->custom_server_64_pipe); 360 361 if (package->delete_on_close) DeleteFileW( package->localfile ); 362 msi_free( package->localfile ); 363 MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 364 } 365 366 static UINT create_temp_property_table(MSIPACKAGE *package) 367 { 368 MSIQUERY *view; 369 UINT rc; 370 371 rc = MSI_DatabaseOpenViewW(package->db, L"CREATE TABLE `_Property` ( `_Property` CHAR(56) NOT NULL TEMPORARY, " 372 L"`Value` CHAR(98) NOT NULL TEMPORARY PRIMARY KEY `_Property`) HOLD", &view); 373 if (rc != ERROR_SUCCESS) 374 return rc; 375 376 rc = MSI_ViewExecute(view, 0); 377 MSI_ViewClose(view); 378 msiobj_release(&view->hdr); 379 return rc; 380 } 381 382 UINT msi_clone_properties( MSIDATABASE *db ) 383 { 384 MSIQUERY *view_select; 385 UINT rc; 386 387 rc = MSI_DatabaseOpenViewW( db, L"SELECT * FROM `Property`", &view_select ); 388 if (rc != ERROR_SUCCESS) 389 return rc; 390 391 rc = MSI_ViewExecute( view_select, 0 ); 392 if (rc != ERROR_SUCCESS) 393 { 394 MSI_ViewClose( view_select ); 395 msiobj_release( &view_select->hdr ); 396 return rc; 397 } 398 399 while (1) 400 { 401 MSIQUERY *view_insert, *view_update; 402 MSIRECORD *rec_select; 403 404 rc = MSI_ViewFetch( view_select, &rec_select ); 405 if (rc != ERROR_SUCCESS) 406 break; 407 408 rc = MSI_DatabaseOpenViewW( db, L"INSERT INTO `_Property` (`_Property`,`Value`) VALUES (?,?)", &view_insert ); 409 if (rc != ERROR_SUCCESS) 410 { 411 msiobj_release( &rec_select->hdr ); 412 continue; 413 } 414 415 rc = MSI_ViewExecute( view_insert, rec_select ); 416 MSI_ViewClose( view_insert ); 417 msiobj_release( &view_insert->hdr ); 418 if (rc != ERROR_SUCCESS) 419 { 420 MSIRECORD *rec_update; 421 422 TRACE("insert failed, trying update\n"); 423 424 rc = MSI_DatabaseOpenViewW( db, L"UPDATE `_Property` SET `Value` = ? WHERE `_Property` = ?", &view_update ); 425 if (rc != ERROR_SUCCESS) 426 { 427 WARN("open view failed %u\n", rc); 428 msiobj_release( &rec_select->hdr ); 429 continue; 430 } 431 432 rec_update = MSI_CreateRecord( 2 ); 433 MSI_RecordCopyField( rec_select, 1, rec_update, 2 ); 434 MSI_RecordCopyField( rec_select, 2, rec_update, 1 ); 435 rc = MSI_ViewExecute( view_update, rec_update ); 436 if (rc != ERROR_SUCCESS) 437 WARN("update failed %u\n", rc); 438 439 MSI_ViewClose( view_update ); 440 msiobj_release( &view_update->hdr ); 441 msiobj_release( &rec_update->hdr ); 442 } 443 444 msiobj_release( &rec_select->hdr ); 445 } 446 447 MSI_ViewClose( view_select ); 448 msiobj_release( &view_select->hdr ); 449 return rc; 450 } 451 452 /* 453 * set_installed_prop 454 * 455 * Sets the "Installed" property to indicate that 456 * the product is installed for the current user. 457 */ 458 static UINT set_installed_prop( MSIPACKAGE *package ) 459 { 460 HKEY hkey; 461 UINT r; 462 463 if (!package->ProductCode) return ERROR_FUNCTION_FAILED; 464 465 r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE ); 466 if (r == ERROR_SUCCESS) 467 { 468 RegCloseKey( hkey ); 469 msi_set_property( package->db, L"Installed", L"1", -1 ); 470 } 471 return r; 472 } 473 474 static UINT set_user_sid_prop( MSIPACKAGE *package ) 475 { 476 SID_NAME_USE use; 477 LPWSTR user_name; 478 LPWSTR sid_str = NULL, dom = NULL; 479 DWORD size, dom_size; 480 PSID psid = NULL; 481 UINT r = ERROR_FUNCTION_FAILED; 482 483 size = 0; 484 GetUserNameW( NULL, &size ); 485 486 user_name = msi_alloc( (size + 1) * sizeof(WCHAR) ); 487 if (!user_name) 488 return ERROR_OUTOFMEMORY; 489 490 if (!GetUserNameW( user_name, &size )) 491 goto done; 492 493 size = 0; 494 dom_size = 0; 495 LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use ); 496 497 psid = msi_alloc( size ); 498 dom = msi_alloc( dom_size*sizeof (WCHAR) ); 499 if (!psid || !dom) 500 { 501 r = ERROR_OUTOFMEMORY; 502 goto done; 503 } 504 505 if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use )) 506 goto done; 507 508 if (!ConvertSidToStringSidW( psid, &sid_str )) 509 goto done; 510 511 r = msi_set_property( package->db, L"UserSID", sid_str, -1 ); 512 513 done: 514 LocalFree( sid_str ); 515 msi_free( dom ); 516 msi_free( psid ); 517 msi_free( user_name ); 518 519 return r; 520 } 521 522 static LPWSTR get_fusion_filename(MSIPACKAGE *package) 523 { 524 HKEY netsetup, hkey; 525 LONG res; 526 DWORD size, len, type; 527 WCHAR windir[MAX_PATH], path[MAX_PATH], *filename = NULL; 528 529 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\NET Framework Setup\\NDP", 0, KEY_CREATE_SUB_KEY, 530 &netsetup); 531 if (res != ERROR_SUCCESS) 532 return NULL; 533 534 if (!RegCreateKeyExW(netsetup, L"v4\\Client", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 535 { 536 size = sizeof(path); 537 if (!RegQueryValueExW(hkey, L"InstallPath", NULL, &type, (BYTE *)path, &size)) 538 { 539 len = lstrlenW(path) + lstrlenW(L"fusion.dll") + 2; 540 if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 541 542 lstrcpyW(filename, path); 543 lstrcatW(filename, L"\\"); 544 lstrcatW(filename, L"fusion.dll"); 545 if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 546 { 547 TRACE( "found %s\n", debugstr_w(filename) ); 548 RegCloseKey(hkey); 549 RegCloseKey(netsetup); 550 return filename; 551 } 552 } 553 RegCloseKey(hkey); 554 } 555 556 if (!RegCreateKeyExW(netsetup, L"v2.0.50727", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL)) 557 { 558 RegCloseKey(hkey); 559 GetWindowsDirectoryW(windir, MAX_PATH); 560 len = lstrlenW(windir) + lstrlenW(L"Microsoft.NET\\Framework\\") + lstrlenW(L"v2.0.50727") + 561 lstrlenW(L"fusion.dll") + 3; 562 msi_free(filename); 563 if (!(filename = msi_alloc(len * sizeof(WCHAR)))) return NULL; 564 565 lstrcpyW(filename, windir); 566 lstrcatW(filename, L"\\"); 567 lstrcatW(filename, L"Microsoft.NET\\Framework\\"); 568 lstrcatW(filename, L"v2.0.50727"); 569 lstrcatW(filename, L"\\"); 570 lstrcatW(filename, L"fusion.dll"); 571 if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) 572 { 573 TRACE( "found %s\n", debugstr_w(filename) ); 574 RegCloseKey(netsetup); 575 return filename; 576 } 577 } 578 579 RegCloseKey(netsetup); 580 return filename; 581 } 582 583 typedef struct tagLANGANDCODEPAGE 584 { 585 WORD wLanguage; 586 WORD wCodePage; 587 } LANGANDCODEPAGE; 588 589 static void set_msi_assembly_prop(MSIPACKAGE *package) 590 { 591 UINT val_len; 592 DWORD size, handle; 593 LPVOID version = NULL; 594 WCHAR buf[MAX_PATH]; 595 LPWSTR fusion, verstr; 596 LANGANDCODEPAGE *translate; 597 598 fusion = get_fusion_filename(package); 599 if (!fusion) 600 return; 601 602 size = GetFileVersionInfoSizeW(fusion, &handle); 603 if (!size) 604 goto done; 605 606 version = msi_alloc(size); 607 if (!version) 608 goto done; 609 610 if (!GetFileVersionInfoW(fusion, handle, size, version)) 611 goto done; 612 613 if (!VerQueryValueW(version, L"\\VarFileInfo\\Translation", (LPVOID *)&translate, &val_len)) 614 goto done; 615 616 swprintf(buf, ARRAY_SIZE(buf), L"\\StringFileInfo\\%04x%04x\\ProductVersion", translate[0].wLanguage, 617 translate[0].wCodePage); 618 619 if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len)) 620 goto done; 621 622 if (!val_len || !verstr) 623 goto done; 624 625 msi_set_property( package->db, L"MsiNetAssemblySupport", verstr, -1 ); 626 627 done: 628 msi_free(fusion); 629 msi_free(version); 630 } 631 632 static VOID set_installer_properties(MSIPACKAGE *package) 633 { 634 WCHAR *ptr; 635 RTL_OSVERSIONINFOEXW OSVersion; 636 MEMORYSTATUSEX msex; 637 DWORD verval, len, type; 638 WCHAR pth[MAX_PATH], verstr[11], bufstr[22]; 639 HDC dc; 640 HKEY hkey; 641 LPWSTR username, companyname; 642 SYSTEM_INFO sys_info; 643 LANGID langid; 644 645 /* 646 * Other things that probably should be set: 647 * 648 * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging 649 * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport 650 */ 651 652 SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth); 653 lstrcatW(pth, L"\\"); 654 msi_set_property( package->db, L"CommonAppDataFolder", pth, -1 ); 655 656 SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth); 657 lstrcatW(pth, L"\\"); 658 msi_set_property( package->db, L"FavoritesFolder", pth, -1 ); 659 660 SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth); 661 lstrcatW(pth, L"\\"); 662 msi_set_property( package->db, L"FontsFolder", pth, -1 ); 663 664 SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth); 665 lstrcatW(pth, L"\\"); 666 msi_set_property( package->db, L"SendToFolder", pth, -1 ); 667 668 SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth); 669 lstrcatW(pth, L"\\"); 670 msi_set_property( package->db, L"StartMenuFolder", pth, -1 ); 671 672 SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth); 673 lstrcatW(pth, L"\\"); 674 msi_set_property( package->db, L"StartupFolder", pth, -1 ); 675 676 SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth); 677 lstrcatW(pth, L"\\"); 678 msi_set_property( package->db, L"TemplateFolder", pth, -1 ); 679 680 SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth); 681 lstrcatW(pth, L"\\"); 682 msi_set_property( package->db, L"DesktopFolder", pth, -1 ); 683 684 /* FIXME: set to AllUsers profile path if ALLUSERS is set */ 685 SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth); 686 lstrcatW(pth, L"\\"); 687 msi_set_property( package->db, L"ProgramMenuFolder", pth, -1 ); 688 689 SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth); 690 lstrcatW(pth, L"\\"); 691 msi_set_property( package->db, L"AdminToolsFolder", pth, -1 ); 692 693 SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth); 694 lstrcatW(pth, L"\\"); 695 msi_set_property( package->db, L"AppDataFolder", pth, -1 ); 696 697 SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth); 698 lstrcatW(pth, L"\\"); 699 msi_set_property( package->db, L"SystemFolder", pth, -1 ); 700 msi_set_property( package->db, L"System16Folder", pth, -1 ); 701 702 SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth); 703 lstrcatW(pth, L"\\"); 704 msi_set_property( package->db, L"LocalAppDataFolder", pth, -1 ); 705 706 SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth); 707 lstrcatW(pth, L"\\"); 708 msi_set_property( package->db, L"MyPicturesFolder", pth, -1 ); 709 710 SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth); 711 lstrcatW(pth, L"\\"); 712 msi_set_property( package->db, L"PersonalFolder", pth, -1 ); 713 714 SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 715 lstrcatW(pth, L"\\"); 716 msi_set_property( package->db, L"WindowsFolder", pth, -1 ); 717 718 SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth); 719 lstrcatW(pth, L"\\"); 720 msi_set_property( package->db, L"PrintHoodFolder", pth, -1 ); 721 722 SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth); 723 lstrcatW(pth, L"\\"); 724 msi_set_property( package->db, L"NetHoodFolder", pth, -1 ); 725 726 SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth); 727 lstrcatW(pth, L"\\"); 728 msi_set_property( package->db, L"RecentFolder", pth, -1 ); 729 730 /* Physical Memory is specified in MB. Using total amount. */ 731 msex.dwLength = sizeof(msex); 732 GlobalMemoryStatusEx( &msex ); 733 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", (int)(msex.ullTotalPhys / 1024 / 1024) ); 734 msi_set_property( package->db, L"PhysicalMemory", bufstr, len ); 735 736 SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth); 737 ptr = wcschr(pth,'\\'); 738 if (ptr) *(ptr + 1) = 0; 739 msi_set_property( package->db, L"WindowsVolume", pth, -1 ); 740 741 len = GetTempPathW(MAX_PATH, pth); 742 msi_set_property( package->db, L"TempFolder", pth, len ); 743 744 /* in a wine environment the user is always admin and privileged */ 745 msi_set_property( package->db, L"AdminUser", L"1", -1 ); 746 msi_set_property( package->db, L"Privileged", L"1", -1 ); 747 msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 ); 748 749 /* set the os things */ 750 OSVersion.dwOSVersionInfoSize = sizeof(OSVersion); 751 RtlGetVersion((PRTL_OSVERSIONINFOW)&OSVersion); 752 verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100; 753 if (verval > 603) 754 { 755 verval = 603; 756 OSVersion.dwBuildNumber = 9600; 757 } 758 len = swprintf( verstr, ARRAY_SIZE(verstr), L"%u", verval ); 759 switch (OSVersion.dwPlatformId) 760 { 761 case VER_PLATFORM_WIN32_WINDOWS: 762 msi_set_property( package->db, L"Version9X", verstr, len ); 763 break; 764 case VER_PLATFORM_WIN32_NT: 765 msi_set_property( package->db, L"VersionNT", verstr, len ); 766 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wProductType ); 767 msi_set_property( package->db, L"MsiNTProductType", bufstr, len ); 768 break; 769 } 770 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.dwBuildNumber ); 771 msi_set_property( package->db, L"WindowsBuild", bufstr, len ); 772 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wServicePackMajor ); 773 msi_set_property( package->db, L"ServicePackLevel", bufstr, len ); 774 775 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u.%u", MSI_MAJORVERSION, MSI_MINORVERSION ); 776 msi_set_property( package->db, L"VersionMsi", bufstr, len ); 777 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", MSI_MAJORVERSION * 100 ); 778 msi_set_property( package->db, L"VersionDatabase", bufstr, len ); 779 780 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, 781 KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hkey); 782 783 GetNativeSystemInfo( &sys_info ); 784 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", sys_info.wProcessorLevel ); 785 msi_set_property( package->db, L"Intel", bufstr, len ); 786 if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) 787 { 788 GetSystemDirectoryW( pth, MAX_PATH ); 789 PathAddBackslashW( pth ); 790 msi_set_property( package->db, L"SystemFolder", pth, -1 ); 791 792 len = sizeof(pth); 793 RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len); 794 PathAddBackslashW( pth ); 795 msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 ); 796 797 len = sizeof(pth); 798 RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len); 799 PathAddBackslashW( pth ); 800 msi_set_property( package->db, L"CommonFilesFolder", pth, -1 ); 801 } 802 else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) 803 { 804 msi_set_property( package->db, L"MsiAMD64", bufstr, -1 ); 805 msi_set_property( package->db, L"Msix64", bufstr, -1 ); 806 msi_set_property( package->db, L"VersionNT64", verstr, -1 ); 807 808 GetSystemDirectoryW( pth, MAX_PATH ); 809 PathAddBackslashW( pth ); 810 msi_set_property( package->db, L"System64Folder", pth, -1 ); 811 812 GetSystemWow64DirectoryW( pth, MAX_PATH ); 813 PathAddBackslashW( pth ); 814 msi_set_property( package->db, L"SystemFolder", pth, -1 ); 815 816 len = sizeof(pth); 817 RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len); 818 PathAddBackslashW( pth ); 819 msi_set_property( package->db, L"ProgramFiles64Folder", pth, -1 ); 820 821 len = sizeof(pth); 822 RegQueryValueExW(hkey, L"ProgramFilesDir (x86)", 0, &type, (BYTE *)pth, &len); 823 PathAddBackslashW( pth ); 824 msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 ); 825 826 len = sizeof(pth); 827 RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len); 828 PathAddBackslashW( pth ); 829 msi_set_property( package->db, L"CommonFiles64Folder", pth, -1 ); 830 831 len = sizeof(pth); 832 RegQueryValueExW(hkey, L"CommonFilesDir (x86)", 0, &type, (BYTE *)pth, &len); 833 PathAddBackslashW( pth ); 834 msi_set_property( package->db, L"CommonFilesFolder", pth, -1 ); 835 } 836 837 RegCloseKey(hkey); 838 839 /* Screen properties. */ 840 dc = GetDC(0); 841 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, HORZRES) ); 842 msi_set_property( package->db, L"ScreenX", bufstr, len ); 843 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, VERTRES) ); 844 msi_set_property( package->db, L"ScreenY", bufstr, len ); 845 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, BITSPIXEL) ); 846 msi_set_property( package->db, L"ColorBits", bufstr, len ); 847 ReleaseDC(0, dc); 848 849 /* USERNAME and COMPANYNAME */ 850 username = msi_dup_property( package->db, L"USERNAME" ); 851 companyname = msi_dup_property( package->db, L"COMPANYNAME" ); 852 853 if ((!username || !companyname) && 854 RegOpenKeyW( HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey ) == ERROR_SUCCESS) 855 { 856 if (!username && 857 (username = msi_reg_get_val_str( hkey, L"DefName" ))) 858 msi_set_property( package->db, L"USERNAME", username, -1 ); 859 if (!companyname && 860 (companyname = msi_reg_get_val_str( hkey, L"DefCompany" ))) 861 msi_set_property( package->db, L"COMPANYNAME", companyname, -1 ); 862 CloseHandle( hkey ); 863 } 864 if ((!username || !companyname) && 865 RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, 866 KEY_QUERY_VALUE|KEY_WOW64_64KEY, &hkey ) == ERROR_SUCCESS) 867 { 868 if (!username && 869 (username = msi_reg_get_val_str( hkey, L"RegisteredOwner" ))) 870 msi_set_property( package->db, L"USERNAME", username, -1 ); 871 if (!companyname && 872 (companyname = msi_reg_get_val_str( hkey, L"RegisteredOrganization" ))) 873 msi_set_property( package->db, L"COMPANYNAME", companyname, -1 ); 874 CloseHandle( hkey ); 875 } 876 msi_free( username ); 877 msi_free( companyname ); 878 879 if ( set_user_sid_prop( package ) != ERROR_SUCCESS) 880 ERR("Failed to set the UserSID property\n"); 881 882 set_msi_assembly_prop( package ); 883 884 langid = GetUserDefaultLangID(); 885 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid ); 886 msi_set_property( package->db, L"UserLanguageID", bufstr, len ); 887 888 langid = GetSystemDefaultLangID(); 889 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid ); 890 msi_set_property( package->db, L"SystemLanguageID", bufstr, len ); 891 892 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", MsiQueryProductStateW(package->ProductCode) ); 893 msi_set_property( package->db, L"ProductState", bufstr, len ); 894 895 len = 0; 896 if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 897 { 898 WCHAR *username; 899 if ((username = msi_alloc( len * sizeof(WCHAR) ))) 900 { 901 if (GetUserNameW( username, &len )) 902 msi_set_property( package->db, L"LogonUser", username, len - 1 ); 903 msi_free( username ); 904 } 905 } 906 len = 0; 907 if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW) 908 { 909 WCHAR *computername; 910 if ((computername = msi_alloc( len * sizeof(WCHAR) ))) 911 { 912 if (GetComputerNameW( computername, &len )) 913 msi_set_property( package->db, L"ComputerName", computername, len ); 914 msi_free( computername ); 915 } 916 } 917 } 918 919 static MSIPACKAGE *msi_alloc_package( void ) 920 { 921 MSIPACKAGE *package; 922 923 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE), 924 MSI_FreePackage ); 925 if( package ) 926 { 927 list_init( &package->components ); 928 list_init( &package->features ); 929 list_init( &package->files ); 930 list_init( &package->filepatches ); 931 list_init( &package->tempfiles ); 932 list_init( &package->folders ); 933 list_init( &package->subscriptions ); 934 list_init( &package->appids ); 935 list_init( &package->classes ); 936 list_init( &package->mimes ); 937 list_init( &package->extensions ); 938 list_init( &package->progids ); 939 list_init( &package->RunningActions ); 940 list_init( &package->sourcelist_info ); 941 list_init( &package->sourcelist_media ); 942 list_init( &package->patches ); 943 list_init( &package->binaries ); 944 list_init( &package->cabinet_streams ); 945 } 946 947 return package; 948 } 949 950 static UINT msi_load_admin_properties(MSIPACKAGE *package) 951 { 952 BYTE *data; 953 UINT r, sz; 954 955 r = read_stream_data(package->db->storage, L"AdminProperties", FALSE, &data, &sz); 956 if (r != ERROR_SUCCESS) 957 return r; 958 959 r = msi_parse_command_line(package, (WCHAR *)data, TRUE); 960 961 msi_free(data); 962 return r; 963 } 964 965 void msi_adjust_privilege_properties( MSIPACKAGE *package ) 966 { 967 /* FIXME: this should depend on the user's privileges */ 968 if (msi_get_property_int( package->db, L"ALLUSERS", 0 ) == 2) 969 { 970 TRACE("resetting ALLUSERS property from 2 to 1\n"); 971 msi_set_property( package->db, L"ALLUSERS", L"1", -1 ); 972 } 973 msi_set_property( package->db, L"AdminUser", L"1", -1 ); 974 msi_set_property( package->db, L"Privileged", L"1", -1 ); 975 msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 ); 976 } 977 978 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db ) 979 { 980 MSIPACKAGE *package; 981 WCHAR uilevel[11]; 982 int len; 983 UINT r; 984 985 TRACE("%p\n", db); 986 987 package = msi_alloc_package(); 988 if (package) 989 { 990 msiobj_addref( &db->hdr ); 991 package->db = db; 992 993 package->LastAction = NULL; 994 package->LastActionTemplate = NULL; 995 package->LastActionResult = MSI_NULL_INTEGER; 996 package->WordCount = 0; 997 package->PackagePath = strdupW( db->path ); 998 999 create_temp_property_table( package ); 1000 msi_clone_properties( package->db ); 1001 msi_adjust_privilege_properties( package ); 1002 1003 package->ProductCode = msi_dup_property( package->db, L"ProductCode" ); 1004 1005 set_installer_properties( package ); 1006 1007 package->ui_level = gUILevel; 1008 len = swprintf( uilevel, ARRAY_SIZE(uilevel), L"%u", gUILevel & INSTALLUILEVEL_MASK ); 1009 msi_set_property( package->db, L"UILevel", uilevel, len ); 1010 1011 r = msi_load_suminfo_properties( package ); 1012 if (r != ERROR_SUCCESS) 1013 { 1014 msiobj_release( &package->hdr ); 1015 return NULL; 1016 } 1017 1018 if (package->WordCount & msidbSumInfoSourceTypeAdminImage) 1019 msi_load_admin_properties( package ); 1020 1021 package->log_file = INVALID_HANDLE_VALUE; 1022 package->script = SCRIPT_NONE; 1023 } 1024 return package; 1025 } 1026 1027 UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) 1028 { 1029 LPINTERNET_CACHE_ENTRY_INFOW cache_entry; 1030 DWORD size = 0; 1031 HRESULT hr; 1032 1033 /* call will always fail, because size is 0, 1034 * but will return ERROR_FILE_NOT_FOUND first 1035 * if the file doesn't exist 1036 */ 1037 GetUrlCacheEntryInfoW( szUrl, NULL, &size ); 1038 if ( GetLastError() != ERROR_FILE_NOT_FOUND ) 1039 { 1040 cache_entry = msi_alloc( size ); 1041 if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) ) 1042 { 1043 UINT error = GetLastError(); 1044 msi_free( cache_entry ); 1045 return error; 1046 } 1047 1048 lstrcpyW( filename, cache_entry->lpszLocalFileName ); 1049 msi_free( cache_entry ); 1050 return ERROR_SUCCESS; 1051 } 1052 1053 hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL ); 1054 if ( FAILED(hr) ) 1055 { 1056 WARN("failed to download %s to cache file\n", debugstr_w(szUrl)); 1057 return ERROR_FUNCTION_FAILED; 1058 } 1059 1060 return ERROR_SUCCESS; 1061 } 1062 1063 UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix ) 1064 { 1065 DWORD time, len, i, offset; 1066 HANDLE handle; 1067 1068 time = GetTickCount(); 1069 GetWindowsDirectoryW( path, MAX_PATH ); 1070 lstrcatW( path, L"\\Installer\\" ); 1071 CreateDirectoryW( path, NULL ); 1072 1073 len = lstrlenW(path); 1074 for (i = 0; i < 0x10000; i++) 1075 { 1076 offset = swprintf( path + len, MAX_PATH - len, L"%x", (time + i) & 0xffff ); 1077 memcpy( path + len + offset, suffix, (lstrlenW( suffix ) + 1) * sizeof(WCHAR) ); 1078 handle = CreateFileW( path, GENERIC_WRITE, 0, NULL, 1079 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); 1080 if (handle != INVALID_HANDLE_VALUE) 1081 { 1082 CloseHandle(handle); 1083 break; 1084 } 1085 if (GetLastError() != ERROR_FILE_EXISTS && 1086 GetLastError() != ERROR_SHARING_VIOLATION) 1087 return ERROR_FUNCTION_FAILED; 1088 } 1089 1090 return ERROR_SUCCESS; 1091 } 1092 1093 static enum platform parse_platform( const WCHAR *str ) 1094 { 1095 if (!str[0] || !wcscmp( str, L"Intel" )) return PLATFORM_INTEL; 1096 else if (!wcscmp( str, L"Intel64" )) return PLATFORM_INTEL64; 1097 else if (!wcscmp( str, L"x64" ) || !wcscmp( str, L"AMD64" )) return PLATFORM_X64; 1098 else if (!wcscmp( str, L"Arm" )) return PLATFORM_ARM; 1099 else if (!wcscmp( str, L"Arm64" )) return PLATFORM_ARM64; 1100 return PLATFORM_UNRECOGNIZED; 1101 } 1102 1103 static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package ) 1104 { 1105 WCHAR *template, *p, *q, *platform; 1106 DWORD i, count; 1107 1108 package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT ); 1109 TRACE("version: %d\n", package->version); 1110 1111 template = msi_suminfo_dup_string( si, PID_TEMPLATE ); 1112 if (!template) 1113 return ERROR_SUCCESS; /* native accepts missing template property */ 1114 1115 TRACE("template: %s\n", debugstr_w(template)); 1116 1117 p = wcschr( template, ';' ); 1118 if (!p) 1119 { 1120 WARN("invalid template string %s\n", debugstr_w(template)); 1121 msi_free( template ); 1122 return ERROR_PATCH_PACKAGE_INVALID; 1123 } 1124 *p = 0; 1125 platform = template; 1126 if ((q = wcschr( platform, ',' ))) *q = 0; 1127 package->platform = parse_platform( platform ); 1128 while (package->platform == PLATFORM_UNRECOGNIZED && q) 1129 { 1130 platform = q + 1; 1131 if ((q = wcschr( platform, ',' ))) *q = 0; 1132 package->platform = parse_platform( platform ); 1133 } 1134 if (package->platform == PLATFORM_UNRECOGNIZED) 1135 { 1136 WARN("unknown platform %s\n", debugstr_w(template)); 1137 msi_free( template ); 1138 return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1139 } 1140 p++; 1141 if (!*p) 1142 { 1143 msi_free( template ); 1144 return ERROR_SUCCESS; 1145 } 1146 count = 1; 1147 for (q = p; (q = wcschr( q, ',' )); q++) count++; 1148 1149 package->langids = msi_alloc( count * sizeof(LANGID) ); 1150 if (!package->langids) 1151 { 1152 msi_free( template ); 1153 return ERROR_OUTOFMEMORY; 1154 } 1155 1156 i = 0; 1157 while (*p) 1158 { 1159 q = wcschr( p, ',' ); 1160 if (q) *q = 0; 1161 package->langids[i] = wcstol( p, NULL, 10 ); 1162 if (!q) break; 1163 p = q + 1; 1164 i++; 1165 } 1166 package->num_langids = i + 1; 1167 1168 msi_free( template ); 1169 return ERROR_SUCCESS; 1170 } 1171 1172 static UINT validate_package( MSIPACKAGE *package ) 1173 { 1174 UINT i; 1175 1176 if (package->platform == PLATFORM_INTEL64) 1177 return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1178 #ifndef __arm__ 1179 if (package->platform == PLATFORM_ARM) 1180 return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1181 #endif 1182 #ifndef __aarch64__ 1183 if (package->platform == PLATFORM_ARM64) 1184 return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1185 #endif 1186 if (package->platform == PLATFORM_X64) 1187 { 1188 if (!is_64bit && !is_wow64) 1189 return ERROR_INSTALL_PLATFORM_UNSUPPORTED; 1190 if (package->version < 200) 1191 return ERROR_INSTALL_PACKAGE_INVALID; 1192 } 1193 if (!package->num_langids) 1194 { 1195 return ERROR_SUCCESS; 1196 } 1197 for (i = 0; i < package->num_langids; i++) 1198 { 1199 LANGID langid = package->langids[i]; 1200 1201 if (PRIMARYLANGID( langid ) == LANG_NEUTRAL) 1202 { 1203 langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) ); 1204 } 1205 if (SUBLANGID( langid ) == SUBLANG_NEUTRAL) 1206 { 1207 langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) ); 1208 } 1209 if (IsValidLocale( langid, LCID_INSTALLED )) 1210 return ERROR_SUCCESS; 1211 } 1212 return ERROR_INSTALL_LANGUAGE_UNSUPPORTED; 1213 } 1214 1215 static WCHAR *get_property( MSIDATABASE *db, const WCHAR *prop ) 1216 { 1217 WCHAR query[MAX_PATH]; 1218 MSIQUERY *view; 1219 MSIRECORD *rec; 1220 WCHAR *ret = NULL; 1221 1222 swprintf(query, ARRAY_SIZE(query), L"SELECT `Value` FROM `Property` WHERE `Property`='%s'", prop); 1223 if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) 1224 { 1225 return NULL; 1226 } 1227 if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS) 1228 { 1229 MSI_ViewClose( view ); 1230 msiobj_release( &view->hdr ); 1231 return NULL; 1232 } 1233 if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) 1234 { 1235 ret = strdupW( MSI_RecordGetString( rec, 1 ) ); 1236 msiobj_release( &rec->hdr ); 1237 } 1238 MSI_ViewClose( view ); 1239 msiobj_release( &view->hdr ); 1240 return ret; 1241 } 1242 1243 static WCHAR *get_product_code( MSIDATABASE *db ) 1244 { 1245 return get_property( db, L"ProductCode" ); 1246 } 1247 1248 static WCHAR *get_product_version( MSIDATABASE *db ) 1249 { 1250 return get_property( db, L"ProductVersion" ); 1251 } 1252 1253 static UINT get_registered_local_package( const WCHAR *product, WCHAR *localfile ) 1254 { 1255 MSIINSTALLCONTEXT context; 1256 WCHAR *filename; 1257 HKEY props_key; 1258 UINT r; 1259 1260 r = msi_locate_product( product, &context ); 1261 if (r != ERROR_SUCCESS) 1262 return r; 1263 1264 r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE ); 1265 if (r != ERROR_SUCCESS) 1266 return r; 1267 1268 filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); 1269 RegCloseKey( props_key ); 1270 if (!filename) 1271 return ERROR_FUNCTION_FAILED; 1272 1273 lstrcpyW( localfile, filename ); 1274 msi_free( filename ); 1275 return ERROR_SUCCESS; 1276 } 1277 1278 WCHAR *msi_get_package_code( MSIDATABASE *db ) 1279 { 1280 WCHAR *ret; 1281 MSISUMMARYINFO *si; 1282 UINT r; 1283 1284 r = msi_get_suminfo( db->storage, 0, &si ); 1285 if (r != ERROR_SUCCESS) 1286 { 1287 r = msi_get_db_suminfo( db, 0, &si ); 1288 if (r != ERROR_SUCCESS) 1289 { 1290 WARN("failed to load summary info %u\n", r); 1291 return NULL; 1292 } 1293 } 1294 ret = msi_suminfo_dup_string( si, PID_REVNUMBER ); 1295 msiobj_release( &si->hdr ); 1296 return ret; 1297 } 1298 1299 static UINT get_local_package( MSIDATABASE *db, WCHAR *localfile ) 1300 { 1301 WCHAR *product_code; 1302 UINT r; 1303 1304 if (!(product_code = get_product_code( db ))) 1305 return ERROR_INSTALL_PACKAGE_INVALID; 1306 r = get_registered_local_package( product_code, localfile ); 1307 msi_free( product_code ); 1308 return r; 1309 } 1310 1311 UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package ) 1312 { 1313 UINT r; 1314 1315 if (UrlIsW( package, URLIS_URL )) 1316 r = msi_set_property( db, L"OriginalDatabase", package, -1 ); 1317 else if (package[0] == '#') 1318 r = msi_set_property( db, L"OriginalDatabase", db->path, -1 ); 1319 else 1320 { 1321 DWORD len; 1322 WCHAR *path; 1323 1324 if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError(); 1325 if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY; 1326 len = GetFullPathNameW( package, len, path, NULL ); 1327 r = msi_set_property( db, L"OriginalDatabase", path, len ); 1328 msi_free( path ); 1329 } 1330 return r; 1331 } 1332 1333 #ifdef __REACTOS__ 1334 BOOL WINAPI ApphelpCheckRunAppEx(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PCWSTR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason, PVOID *SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize, 1335 PVOID *SxsData, PULONG SxsDataSize, PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2); 1336 BOOL WINAPI SE_DynamicShim(LPCWSTR ProcessImage, PVOID hsdb, PVOID pQueryResult, LPCSTR Module, LPDWORD lpdwDynamicToken); 1337 PVOID WINAPI SdbInitDatabase(DWORD flags, LPCWSTR path); 1338 PVOID WINAPI SdbReleaseDatabase(PVOID hsdb); 1339 1340 #define HID_DOS_PATHS 0x1 1341 #define SDB_DATABASE_MAIN_SHIM 0x80030000 1342 1343 #define APPHELP_VALID_RESULT 0x10000 1344 #define APPHELP_RESULT_FOUND 0x40000 1345 1346 static void 1347 AppHelpCheckPackage(LPCWSTR szPackage) 1348 { 1349 USHORT ExeType = 0; 1350 ULONG Reason = 0; 1351 1352 PVOID QueryResult = NULL; 1353 ULONG QueryResultSize = 0; 1354 1355 HANDLE Handle = NULL; 1356 BOOL Continue = ApphelpCheckRunAppEx( 1357 Handle, NULL, NULL, szPackage, NULL, ExeType, &Reason, &QueryResult, &QueryResultSize, NULL, 1358 NULL, NULL, NULL, NULL); 1359 1360 if (Continue) 1361 { 1362 if ((Reason & (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND)) == (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND)) 1363 { 1364 DWORD dwToken; 1365 PVOID hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL); 1366 if (hsdb) 1367 { 1368 BOOL bShim = SE_DynamicShim(szPackage, hsdb, QueryResult, "msi.dll", &dwToken); 1369 ERR("ReactOS HACK(CORE-13283): Used SE_DynamicShim %d!\n", bShim); 1370 1371 SdbReleaseDatabase(hsdb); 1372 } 1373 else 1374 { 1375 ERR("Unable to open SDB_DATABASE_MAIN_SHIM\n"); 1376 } 1377 } 1378 } 1379 1380 if (QueryResult) 1381 RtlFreeHeap(RtlGetProcessHeap(), 0, QueryResult); 1382 } 1383 #endif 1384 1385 UINT MSI_OpenPackageW(LPCWSTR szPackage, DWORD dwOptions, MSIPACKAGE **pPackage) 1386 { 1387 MSIDATABASE *db; 1388 MSIPACKAGE *package; 1389 MSIHANDLE handle; 1390 MSIRECORD *data_row, *info_row; 1391 UINT r; 1392 WCHAR localfile[MAX_PATH], cachefile[MAX_PATH]; 1393 LPCWSTR file = szPackage; 1394 DWORD index = 0; 1395 MSISUMMARYINFO *si; 1396 BOOL delete_on_close = FALSE; 1397 WCHAR *info_template, *productname, *product_code; 1398 MSIINSTALLCONTEXT context; 1399 1400 TRACE("%s %p\n", debugstr_w(szPackage), pPackage); 1401 1402 MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0); 1403 1404 localfile[0] = 0; 1405 if( szPackage[0] == '#' ) 1406 { 1407 handle = wcstol(&szPackage[1], NULL, 10); 1408 if (!(db = msihandle2msiinfo(handle, MSIHANDLETYPE_DATABASE))) 1409 return ERROR_INVALID_HANDLE; 1410 } 1411 else 1412 { 1413 WCHAR *product_version = NULL; 1414 1415 if ( UrlIsW( szPackage, URLIS_URL ) ) 1416 { 1417 r = msi_download_file( szPackage, cachefile ); 1418 if (r != ERROR_SUCCESS) 1419 return r; 1420 1421 file = cachefile; 1422 } 1423 #ifdef __REACTOS__ 1424 AppHelpCheckPackage(file); 1425 #endif 1426 1427 r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db ); 1428 if (r != ERROR_SUCCESS) 1429 { 1430 if (GetFileAttributesW( file ) == INVALID_FILE_ATTRIBUTES) 1431 return ERROR_FILE_NOT_FOUND; 1432 return r; 1433 } 1434 r = get_local_package( db, localfile ); 1435 if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES) 1436 { 1437 DWORD localfile_attr; 1438 1439 r = msi_create_empty_local_file( localfile, L".msi" ); 1440 if (r != ERROR_SUCCESS) 1441 { 1442 msiobj_release( &db->hdr ); 1443 return r; 1444 } 1445 1446 if (!CopyFileW( file, localfile, FALSE )) 1447 { 1448 r = GetLastError(); 1449 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); 1450 DeleteFileW( localfile ); 1451 msiobj_release( &db->hdr ); 1452 return r; 1453 } 1454 delete_on_close = TRUE; 1455 1456 /* Remove read-only bit, we are opening it with write access in MSI_OpenDatabaseW below. */ 1457 localfile_attr = GetFileAttributesW( localfile ); 1458 if (localfile_attr & FILE_ATTRIBUTE_READONLY) 1459 SetFileAttributesW( localfile, localfile_attr & ~FILE_ATTRIBUTE_READONLY); 1460 } 1461 else if (dwOptions & WINE_OPENPACKAGEFLAGS_RECACHE) 1462 { 1463 if (!CopyFileW( file, localfile, FALSE )) 1464 { 1465 r = GetLastError(); 1466 WARN("unable to update cached package (%u)\n", r); 1467 msiobj_release( &db->hdr ); 1468 return r; 1469 } 1470 } 1471 else 1472 product_version = get_product_version( db ); 1473 msiobj_release( &db->hdr ); 1474 TRACE("opening package %s\n", debugstr_w( localfile )); 1475 r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); 1476 if (r != ERROR_SUCCESS) 1477 return r; 1478 1479 if (product_version) 1480 { 1481 WCHAR *cache_version = get_product_version( db ); 1482 if (!product_version != !cache_version || 1483 (product_version && wcscmp(product_version, cache_version))) 1484 { 1485 msiobj_release( &db->hdr ); 1486 msi_free(product_version); 1487 msi_free(cache_version); 1488 return ERROR_PRODUCT_VERSION; 1489 } 1490 msi_free(product_version); 1491 msi_free(cache_version); 1492 } 1493 } 1494 package = MSI_CreatePackage( db ); 1495 msiobj_release( &db->hdr ); 1496 if (!package) return ERROR_INSTALL_PACKAGE_INVALID; 1497 package->localfile = strdupW( localfile ); 1498 package->delete_on_close = delete_on_close; 1499 1500 r = msi_get_suminfo( db->storage, 0, &si ); 1501 if (r != ERROR_SUCCESS) 1502 { 1503 r = msi_get_db_suminfo( db, 0, &si ); 1504 if (r != ERROR_SUCCESS) 1505 { 1506 WARN("failed to load summary info\n"); 1507 msiobj_release( &package->hdr ); 1508 return ERROR_INSTALL_PACKAGE_INVALID; 1509 } 1510 } 1511 r = parse_suminfo( si, package ); 1512 msiobj_release( &si->hdr ); 1513 if (r != ERROR_SUCCESS) 1514 { 1515 WARN("failed to parse summary info %u\n", r); 1516 msiobj_release( &package->hdr ); 1517 return r; 1518 } 1519 r = validate_package( package ); 1520 if (r != ERROR_SUCCESS) 1521 { 1522 msiobj_release( &package->hdr ); 1523 return r; 1524 } 1525 msi_set_property( package->db, L"DATABASE", db->path, -1 ); 1526 set_installed_prop( package ); 1527 msi_set_context( package ); 1528 1529 product_code = get_product_code( db ); 1530 if (msi_locate_product( product_code, &context ) == ERROR_SUCCESS) 1531 { 1532 TRACE("product already registered\n"); 1533 msi_set_property( package->db, L"ProductToBeRegistered", L"1", -1 ); 1534 } 1535 msi_free(product_code); 1536 1537 while (1) 1538 { 1539 WCHAR patch_code[GUID_SIZE]; 1540 r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context, 1541 MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL ); 1542 if (r != ERROR_SUCCESS) 1543 break; 1544 1545 TRACE("found registered patch %s\n", debugstr_w(patch_code)); 1546 1547 r = msi_apply_registered_patch( package, patch_code ); 1548 if (r != ERROR_SUCCESS) 1549 { 1550 ERR("registered patch failed to apply %u\n", r); 1551 msiobj_release( &package->hdr ); 1552 return r; 1553 } 1554 index++; 1555 } 1556 if (index) msi_adjust_privilege_properties( package ); 1557 1558 r = msi_set_original_database_property( package->db, szPackage ); 1559 if (r != ERROR_SUCCESS) 1560 { 1561 msiobj_release( &package->hdr ); 1562 return r; 1563 } 1564 if (gszLogFile) 1565 package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 1566 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 1567 1568 if (!msi_init_assembly_caches( package )) 1569 { 1570 ERR("can't initialize assembly caches\n"); 1571 msiobj_release( &package->hdr ); 1572 return ERROR_FUNCTION_FAILED; 1573 } 1574 1575 /* FIXME: when should these messages be sent? */ 1576 data_row = MSI_CreateRecord(3); 1577 if (!data_row) 1578 return ERROR_OUTOFMEMORY; 1579 MSI_RecordSetStringW(data_row, 0, NULL); 1580 MSI_RecordSetInteger(data_row, 1, 0); 1581 MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0); 1582 MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings)); 1583 MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row); 1584 1585 info_row = MSI_CreateRecord(0); 1586 if (!info_row) 1587 { 1588 msiobj_release(&data_row->hdr); 1589 return ERROR_OUTOFMEMORY; 1590 } 1591 info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART); 1592 MSI_RecordSetStringW(info_row, 0, info_template); 1593 msi_free(info_template); 1594 MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row); 1595 1596 MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 1597 1598 productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW); 1599 MSI_RecordSetInteger(data_row, 1, 1); 1600 MSI_RecordSetStringW(data_row, 2, productname); 1601 MSI_RecordSetStringW(data_row, 3, NULL); 1602 MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 1603 1604 msi_free(productname); 1605 msiobj_release(&info_row->hdr); 1606 msiobj_release(&data_row->hdr); 1607 1608 *pPackage = package; 1609 return ERROR_SUCCESS; 1610 } 1611 1612 UINT WINAPI MsiOpenPackageExW( const WCHAR *szPackage, DWORD dwOptions, MSIHANDLE *phPackage ) 1613 { 1614 MSIPACKAGE *package = NULL; 1615 UINT ret; 1616 1617 TRACE( "%s, %#lx, %p\n", debugstr_w(szPackage), dwOptions, phPackage ); 1618 1619 if( !szPackage || !phPackage ) 1620 return ERROR_INVALID_PARAMETER; 1621 1622 if ( !*szPackage ) 1623 { 1624 FIXME("Should create an empty database and package\n"); 1625 return ERROR_FUNCTION_FAILED; 1626 } 1627 1628 if( dwOptions ) 1629 FIXME( "dwOptions %#lx not supported\n", dwOptions ); 1630 1631 ret = MSI_OpenPackageW( szPackage, 0, &package ); 1632 if( ret == ERROR_SUCCESS ) 1633 { 1634 *phPackage = alloc_msihandle( &package->hdr ); 1635 if (! *phPackage) 1636 ret = ERROR_NOT_ENOUGH_MEMORY; 1637 msiobj_release( &package->hdr ); 1638 } 1639 else 1640 MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 1641 1642 return ret; 1643 } 1644 1645 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) 1646 { 1647 return MsiOpenPackageExW( szPackage, 0, phPackage ); 1648 } 1649 1650 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1651 { 1652 LPWSTR szwPack = NULL; 1653 UINT ret; 1654 1655 if( szPackage ) 1656 { 1657 szwPack = strdupAtoW( szPackage ); 1658 if( !szwPack ) 1659 return ERROR_OUTOFMEMORY; 1660 } 1661 1662 ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); 1663 1664 msi_free( szwPack ); 1665 1666 return ret; 1667 } 1668 1669 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) 1670 { 1671 return MsiOpenPackageExA( szPackage, 0, phPackage ); 1672 } 1673 1674 MSIHANDLE WINAPI MsiGetActiveDatabase( MSIHANDLE hInstall ) 1675 { 1676 MSIPACKAGE *package; 1677 MSIHANDLE handle = 0; 1678 MSIHANDLE remote; 1679 1680 TRACE( "%lu\n", hInstall ); 1681 1682 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 1683 if( package) 1684 { 1685 handle = alloc_msihandle( &package->db->hdr ); 1686 msiobj_release( &package->hdr ); 1687 } 1688 else if ((remote = msi_get_remote(hInstall))) 1689 { 1690 __TRY 1691 { 1692 handle = remote_GetActiveDatabase(remote); 1693 handle = alloc_msi_remote_handle(handle); 1694 } 1695 __EXCEPT(rpc_filter) 1696 { 1697 handle = 0; 1698 } 1699 __ENDTRY 1700 } 1701 1702 return handle; 1703 } 1704 1705 static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message) 1706 { 1707 if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE) 1708 return 0; 1709 1710 /* todo: check if message needs additional styles (topmost/foreground/modality?) */ 1711 1712 switch (eMessageType & 0xff000000) 1713 { 1714 case INSTALLMESSAGE_FATALEXIT: 1715 case INSTALLMESSAGE_ERROR: 1716 case INSTALLMESSAGE_OUTOFDISKSPACE: 1717 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 1718 if (!(eMessageType & MB_ICONMASK)) 1719 eMessageType |= MB_ICONEXCLAMATION; 1720 return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff); 1721 case INSTALLMESSAGE_WARNING: 1722 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 1723 if (!(eMessageType & MB_ICONMASK)) 1724 eMessageType |= MB_ICONASTERISK; 1725 return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff); 1726 case INSTALLMESSAGE_USER: 1727 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 1728 if (!(eMessageType & MB_ICONMASK)) 1729 eMessageType |= MB_USERICON; 1730 return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff); 1731 case INSTALLMESSAGE_INFO: 1732 case INSTALLMESSAGE_INITIALIZE: 1733 case INSTALLMESSAGE_TERMINATE: 1734 case INSTALLMESSAGE_INSTALLSTART: 1735 case INSTALLMESSAGE_INSTALLEND: 1736 return 0; 1737 case INSTALLMESSAGE_SHOWDIALOG: 1738 { 1739 LPWSTR dialog = msi_dup_record_field(record, 0); 1740 INT rc = ACTION_DialogBox(package, dialog); 1741 msi_free(dialog); 1742 return rc; 1743 } 1744 case INSTALLMESSAGE_ACTIONSTART: 1745 { 1746 LPWSTR deformatted; 1747 MSIRECORD *uirow = MSI_CreateRecord(1); 1748 if (!uirow) return -1; 1749 deformat_string(package, MSI_RecordGetString(record, 2), &deformatted); 1750 MSI_RecordSetStringW(uirow, 1, deformatted); 1751 msi_event_fire(package, L"ActionText", uirow); 1752 1753 msi_free(deformatted); 1754 msiobj_release(&uirow->hdr); 1755 return 1; 1756 } 1757 case INSTALLMESSAGE_ACTIONDATA: 1758 { 1759 MSIRECORD *uirow = MSI_CreateRecord(1); 1760 if (!uirow) return -1; 1761 MSI_RecordSetStringW(uirow, 1, message); 1762 msi_event_fire(package, L"ActionData", uirow); 1763 msiobj_release(&uirow->hdr); 1764 1765 if (package->action_progress_increment) 1766 { 1767 uirow = MSI_CreateRecord(2); 1768 if (!uirow) return -1; 1769 MSI_RecordSetInteger(uirow, 1, 2); 1770 MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); 1771 msi_event_fire(package, L"SetProgress", uirow); 1772 msiobj_release(&uirow->hdr); 1773 } 1774 return 1; 1775 } 1776 case INSTALLMESSAGE_PROGRESS: 1777 msi_event_fire(package, L"SetProgress", record); 1778 return 1; 1779 case INSTALLMESSAGE_COMMONDATA: 1780 switch (MSI_RecordGetInteger(record, 1)) 1781 { 1782 case 0: 1783 case 1: 1784 /* do nothing */ 1785 return 0; 1786 default: 1787 /* fall through */ 1788 ; 1789 } 1790 default: 1791 FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level); 1792 return 0; 1793 } 1794 } 1795 1796 static const struct 1797 { 1798 int id; 1799 const WCHAR *text; 1800 } 1801 internal_errors[] = 1802 { 1803 {2726, L"DEBUG: Error [1]: Action not found: [2]"}, 1804 {0} 1805 }; 1806 1807 static LPCWSTR get_internal_error_message(int error) 1808 { 1809 int i = 0; 1810 1811 while (internal_errors[i].id != 0) 1812 { 1813 if (internal_errors[i].id == error) 1814 return internal_errors[i].text; 1815 i++; 1816 } 1817 1818 FIXME("missing error message %d\n", error); 1819 return NULL; 1820 } 1821 1822 /* Returned string must be freed */ 1823 LPWSTR msi_get_error_message(MSIDATABASE *db, int error) 1824 { 1825 MSIRECORD *record; 1826 LPWSTR ret = NULL; 1827 1828 if ((record = MSI_QueryGetRecord(db, L"SELECT `Message` FROM `Error` WHERE `Error` = %d", error))) 1829 { 1830 ret = msi_dup_record_field(record, 1); 1831 msiobj_release(&record->hdr); 1832 } 1833 else if (error < 2000) 1834 { 1835 int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0); 1836 if (len) 1837 { 1838 ret = msi_alloc((len + 1) * sizeof(WCHAR)); 1839 LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1); 1840 } 1841 else 1842 ret = NULL; 1843 } 1844 1845 return ret; 1846 } 1847 1848 INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record) 1849 { 1850 LPWSTR message = {0}; 1851 DWORD len; 1852 DWORD log_type = 1 << (eMessageType >> 24); 1853 UINT res; 1854 INT rc = 0; 1855 char *msg; 1856 1857 TRACE("%x\n", eMessageType); 1858 if (TRACE_ON(msi)) dump_record(record); 1859 1860 if (!package || !record) 1861 message = NULL; 1862 else { 1863 res = MSI_FormatRecordW(package, record, message, &len); 1864 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 1865 return res; 1866 len++; 1867 message = msi_alloc(len * sizeof(WCHAR)); 1868 if (!message) return ERROR_OUTOFMEMORY; 1869 MSI_FormatRecordW(package, record, message, &len); 1870 } 1871 1872 /* convert it to ANSI */ 1873 len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL ); 1874 msg = msi_alloc( len ); 1875 WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL ); 1876 1877 if (gUIHandlerRecord && (gUIFilterRecord & log_type)) 1878 { 1879 MSIHANDLE rec = alloc_msihandle(&record->hdr); 1880 TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, hRecord = %lu)\n", 1881 gUIHandlerRecord, gUIContextRecord, eMessageType, rec ); 1882 rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec ); 1883 MsiCloseHandle( rec ); 1884 } 1885 if (!rc && gUIHandlerW && (gUIFilter & log_type)) 1886 { 1887 TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n", 1888 gUIHandlerW, gUIContext, eMessageType, debugstr_w(message) ); 1889 rc = gUIHandlerW( gUIContext, eMessageType, message ); 1890 } 1891 else if (!rc && gUIHandlerA && (gUIFilter & log_type)) 1892 { 1893 TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n", 1894 gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg) ); 1895 rc = gUIHandlerA( gUIContext, eMessageType, msg ); 1896 } 1897 1898 if (!rc) 1899 rc = internal_ui_handler(package, eMessageType, record, message); 1900 1901 if (!rc && package && package->log_file != INVALID_HANDLE_VALUE && 1902 (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS) 1903 { 1904 DWORD written; 1905 WriteFile( package->log_file, msg, len - 1, &written, NULL ); 1906 WriteFile( package->log_file, "\n", 1, &written, NULL ); 1907 } 1908 msi_free( msg ); 1909 msi_free( message ); 1910 1911 return rc; 1912 } 1913 1914 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) 1915 { 1916 switch (eMessageType & 0xff000000) 1917 { 1918 case INSTALLMESSAGE_FATALEXIT: 1919 case INSTALLMESSAGE_ERROR: 1920 case INSTALLMESSAGE_WARNING: 1921 case INSTALLMESSAGE_USER: 1922 case INSTALLMESSAGE_INFO: 1923 case INSTALLMESSAGE_OUTOFDISKSPACE: 1924 if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER) 1925 { 1926 /* error message */ 1927 1928 LPWSTR template; 1929 LPWSTR template_rec = NULL, template_prefix = NULL; 1930 int error = MSI_RecordGetInteger(record, 1); 1931 1932 if (MSI_RecordIsNull(record, 0)) 1933 { 1934 if (error >= 32) 1935 { 1936 template_rec = msi_get_error_message(package->db, error); 1937 1938 if (!template_rec && error >= 2000) 1939 { 1940 /* internal error, not localized */ 1941 if ((template_rec = (LPWSTR) get_internal_error_message(error))) 1942 { 1943 MSI_RecordSetStringW(record, 0, template_rec); 1944 MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record); 1945 } 1946 template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR); 1947 MSI_RecordSetStringW(record, 0, template_rec); 1948 MSI_ProcessMessageVerbatim(package, eMessageType, record); 1949 msi_free(template_rec); 1950 return 0; 1951 } 1952 } 1953 } 1954 else 1955 template_rec = msi_dup_record_field(record, 0); 1956 1957 template_prefix = msi_get_error_message(package->db, eMessageType >> 24); 1958 if (!template_prefix) template_prefix = strdupW(L""); 1959 1960 if (!template_rec) 1961 { 1962 /* always returns 0 */ 1963 MSI_RecordSetStringW(record, 0, template_prefix); 1964 MSI_ProcessMessageVerbatim(package, eMessageType, record); 1965 msi_free(template_prefix); 1966 return 0; 1967 } 1968 1969 template = msi_alloc((lstrlenW(template_rec) + lstrlenW(template_prefix) + 1) * sizeof(WCHAR)); 1970 if (!template) return ERROR_OUTOFMEMORY; 1971 1972 lstrcpyW(template, template_prefix); 1973 lstrcatW(template, template_rec); 1974 MSI_RecordSetStringW(record, 0, template); 1975 1976 msi_free(template_prefix); 1977 msi_free(template_rec); 1978 msi_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 msi_free(template); 1986 1987 msi_free(package->LastAction); 1988 msi_free(package->LastActionTemplate); 1989 package->LastAction = msi_dup_record_field(record, 1); 1990 if (!package->LastAction) package->LastAction = strdupW(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 = msi_alloc(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 msi_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 msi_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 msi_free( szwName ); 2084 msi_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 msi_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 *msi_get_property_row( MSIDATABASE *db, LPCWSTR 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 = msi_alloc(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 msi_free(buffer); 2206 return NULL; 2207 } 2208 MSI_RecordSetStringW(row, 1, buffer); 2209 msi_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 = msi_alloc(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 msi_free(buffer); 2224 return NULL; 2225 } 2226 MSI_RecordSetStringW(row, 1, buffer); 2227 msi_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 = msi_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 = msi_alloc(sz * sizeof(WCHAR)); 2295 r = msi_get_property(db, prop, str, &sz); 2296 if (r != ERROR_SUCCESS) 2297 { 2298 msi_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 msi_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 = msi_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 = msi_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 = msi_alloc(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 = strdupW(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 = msi_alloc(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 = strdupW(volume_label); 2666 disk->disk_prompt = strdupW(disk_prompt); 2667 list_add_head(&package->sourcelist_media, &disk->entry); 2668 2669 return ERROR_SUCCESS; 2670 } 2671