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