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 DWORD localfile_attr; 1502 1503 r = msi_create_empty_local_file( localfile, dotmsi ); 1504 if (r != ERROR_SUCCESS) 1505 { 1506 msi_free ( base_url ); 1507 return r; 1508 } 1509 1510 if (!CopyFileW( file, localfile, FALSE )) 1511 { 1512 r = GetLastError(); 1513 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); 1514 DeleteFileW( localfile ); 1515 msi_free ( base_url ); 1516 return r; 1517 } 1518 delete_on_close = TRUE; 1519 1520 /* Remove read-only bit, we are opening it with write access in MSI_OpenDatabaseW below. */ 1521 localfile_attr = GetFileAttributesW( localfile ); 1522 if (localfile_attr & FILE_ATTRIBUTE_READONLY) 1523 SetFileAttributesW( localfile, localfile_attr & ~FILE_ATTRIBUTE_READONLY); 1524 } 1525 TRACE("opening package %s\n", debugstr_w( localfile )); 1526 r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); 1527 if (r != ERROR_SUCCESS) 1528 { 1529 msi_free ( base_url ); 1530 return r; 1531 } 1532 } 1533 package = MSI_CreatePackage( db, base_url ); 1534 msi_free( base_url ); 1535 msiobj_release( &db->hdr ); 1536 if (!package) return ERROR_INSTALL_PACKAGE_INVALID; 1537 package->localfile = strdupW( localfile ); 1538 package->delete_on_close = delete_on_close; 1539 1540 r = msi_get_suminfo( db->storage, 0, &si ); 1541 if (r != ERROR_SUCCESS) 1542 { 1543 r = msi_get_db_suminfo( db, 0, &si ); 1544 if (r != ERROR_SUCCESS) 1545 { 1546 WARN("failed to load summary info\n"); 1547 msiobj_release( &package->hdr ); 1548 return ERROR_INSTALL_PACKAGE_INVALID; 1549 } 1550 } 1551 r = parse_suminfo( si, package ); 1552 msiobj_release( &si->hdr ); 1553 if (r != ERROR_SUCCESS) 1554 { 1555 WARN("failed to parse summary info %u\n", r); 1556 msiobj_release( &package->hdr ); 1557 return r; 1558 } 1559 r = validate_package( package ); 1560 if (r != ERROR_SUCCESS) 1561 { 1562 msiobj_release( &package->hdr ); 1563 return r; 1564 } 1565 msi_set_property( package->db, szDatabase, db->path, -1 ); 1566 set_installed_prop( package ); 1567 msi_set_context( package ); 1568 1569 while (1) 1570 { 1571 WCHAR patch_code[GUID_SIZE]; 1572 r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context, 1573 MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL ); 1574 if (r != ERROR_SUCCESS) 1575 break; 1576 1577 TRACE("found registered patch %s\n", debugstr_w(patch_code)); 1578 1579 r = msi_apply_registered_patch( package, patch_code ); 1580 if (r != ERROR_SUCCESS) 1581 { 1582 ERR("registered patch failed to apply %u\n", r); 1583 msiobj_release( &package->hdr ); 1584 return r; 1585 } 1586 index++; 1587 } 1588 if (index) msi_adjust_privilege_properties( package ); 1589 1590 r = msi_set_original_database_property( package->db, szPackage ); 1591 if (r != ERROR_SUCCESS) 1592 { 1593 msiobj_release( &package->hdr ); 1594 return r; 1595 } 1596 if (gszLogFile) 1597 package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 1598 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 1599 1600 /* FIXME: when should these messages be sent? */ 1601 data_row = MSI_CreateRecord(3); 1602 if (!data_row) 1603 return ERROR_OUTOFMEMORY; 1604 MSI_RecordSetStringW(data_row, 0, NULL); 1605 MSI_RecordSetInteger(data_row, 1, 0); 1606 MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0); 1607 MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings)); 1608 MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row); 1609 1610 info_row = MSI_CreateRecord(0); 1611 if (!info_row) 1612 { 1613 msiobj_release(&data_row->hdr); 1614 return ERROR_OUTOFMEMORY; 1615 } 1616 info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART); 1617 MSI_RecordSetStringW(info_row, 0, info_template); 1618 msi_free(info_template); 1619 MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row); 1620 1621 MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 1622 1623 productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW); 1624 MSI_RecordSetInteger(data_row, 1, 1); 1625 MSI_RecordSetStringW(data_row, 2, productname); 1626 MSI_RecordSetStringW(data_row, 3, NULL); 1627 MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row); 1628 1629 msi_free(productname); 1630 msiobj_release(&info_row->hdr); 1631 msiobj_release(&data_row->hdr); 1632 1633 *pPackage = package; 1634 return ERROR_SUCCESS; 1635 } 1636 1637 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1638 { 1639 MSIPACKAGE *package = NULL; 1640 UINT ret; 1641 1642 TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage ); 1643 1644 if( !szPackage || !phPackage ) 1645 return ERROR_INVALID_PARAMETER; 1646 1647 if ( !*szPackage ) 1648 { 1649 FIXME("Should create an empty database and package\n"); 1650 return ERROR_FUNCTION_FAILED; 1651 } 1652 1653 if( dwOptions ) 1654 FIXME("dwOptions %08x not supported\n", dwOptions); 1655 1656 ret = MSI_OpenPackageW( szPackage, &package ); 1657 if( ret == ERROR_SUCCESS ) 1658 { 1659 *phPackage = alloc_msihandle( &package->hdr ); 1660 if (! *phPackage) 1661 ret = ERROR_NOT_ENOUGH_MEMORY; 1662 msiobj_release( &package->hdr ); 1663 } 1664 else 1665 MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0); 1666 1667 return ret; 1668 } 1669 1670 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage) 1671 { 1672 return MsiOpenPackageExW( szPackage, 0, phPackage ); 1673 } 1674 1675 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage) 1676 { 1677 LPWSTR szwPack = NULL; 1678 UINT ret; 1679 1680 if( szPackage ) 1681 { 1682 szwPack = strdupAtoW( szPackage ); 1683 if( !szwPack ) 1684 return ERROR_OUTOFMEMORY; 1685 } 1686 1687 ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage ); 1688 1689 msi_free( szwPack ); 1690 1691 return ret; 1692 } 1693 1694 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage) 1695 { 1696 return MsiOpenPackageExA( szPackage, 0, phPackage ); 1697 } 1698 1699 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall) 1700 { 1701 MSIPACKAGE *package; 1702 MSIHANDLE handle = 0; 1703 IUnknown *remote_unk; 1704 IWineMsiRemotePackage *remote_package; 1705 1706 TRACE("(%d)\n",hInstall); 1707 1708 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 1709 if( package) 1710 { 1711 handle = alloc_msihandle( &package->db->hdr ); 1712 msiobj_release( &package->hdr ); 1713 } 1714 else if ((remote_unk = msi_get_remote(hInstall))) 1715 { 1716 if (IUnknown_QueryInterface(remote_unk, &IID_IWineMsiRemotePackage, 1717 (LPVOID *)&remote_package) == S_OK) 1718 { 1719 IWineMsiRemotePackage_GetActiveDatabase(remote_package, &handle); 1720 IWineMsiRemotePackage_Release(remote_package); 1721 } 1722 else 1723 { 1724 WARN("remote handle %d is not a package\n", hInstall); 1725 } 1726 IUnknown_Release(remote_unk); 1727 } 1728 1729 return handle; 1730 } 1731 1732 static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message) 1733 { 1734 static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0}; 1735 static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0}; 1736 static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0}; 1737 static const WCHAR szWindows_Installer[] = 1738 {'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0}; 1739 1740 if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE) 1741 return 0; 1742 1743 /* todo: check if message needs additional styles (topmost/foreground/modality?) */ 1744 1745 switch (eMessageType & 0xff000000) 1746 { 1747 case INSTALLMESSAGE_FATALEXIT: 1748 case INSTALLMESSAGE_ERROR: 1749 case INSTALLMESSAGE_OUTOFDISKSPACE: 1750 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 1751 if (!(eMessageType & MB_ICONMASK)) 1752 eMessageType |= MB_ICONEXCLAMATION; 1753 return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 1754 case INSTALLMESSAGE_WARNING: 1755 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 1756 if (!(eMessageType & MB_ICONMASK)) 1757 eMessageType |= MB_ICONASTERISK; 1758 return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 1759 case INSTALLMESSAGE_USER: 1760 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0; 1761 if (!(eMessageType & MB_ICONMASK)) 1762 eMessageType |= MB_USERICON; 1763 return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff); 1764 case INSTALLMESSAGE_INFO: 1765 case INSTALLMESSAGE_INITIALIZE: 1766 case INSTALLMESSAGE_TERMINATE: 1767 case INSTALLMESSAGE_INSTALLSTART: 1768 case INSTALLMESSAGE_INSTALLEND: 1769 return 0; 1770 case INSTALLMESSAGE_SHOWDIALOG: 1771 { 1772 LPWSTR dialog = msi_dup_record_field(record, 0); 1773 INT rc = ACTION_DialogBox(package, dialog); 1774 msi_free(dialog); 1775 return rc; 1776 } 1777 case INSTALLMESSAGE_ACTIONSTART: 1778 { 1779 LPWSTR deformatted; 1780 MSIRECORD *uirow = MSI_CreateRecord(1); 1781 if (!uirow) return -1; 1782 deformat_string(package, MSI_RecordGetString(record, 2), &deformatted); 1783 MSI_RecordSetStringW(uirow, 1, deformatted); 1784 msi_event_fire(package, szActionText, uirow); 1785 1786 msi_free(deformatted); 1787 msiobj_release(&uirow->hdr); 1788 return 1; 1789 } 1790 case INSTALLMESSAGE_ACTIONDATA: 1791 { 1792 MSIRECORD *uirow = MSI_CreateRecord(1); 1793 if (!uirow) return -1; 1794 MSI_RecordSetStringW(uirow, 1, message); 1795 msi_event_fire(package, szActionData, uirow); 1796 msiobj_release(&uirow->hdr); 1797 1798 if (package->action_progress_increment) 1799 { 1800 uirow = MSI_CreateRecord(2); 1801 if (!uirow) return -1; 1802 MSI_RecordSetInteger(uirow, 1, 2); 1803 MSI_RecordSetInteger(uirow, 2, package->action_progress_increment); 1804 msi_event_fire(package, szSetProgress, uirow); 1805 msiobj_release(&uirow->hdr); 1806 } 1807 return 1; 1808 } 1809 case INSTALLMESSAGE_PROGRESS: 1810 msi_event_fire(package, szSetProgress, record); 1811 return 1; 1812 case INSTALLMESSAGE_COMMONDATA: 1813 switch (MSI_RecordGetInteger(record, 1)) 1814 { 1815 case 0: 1816 case 1: 1817 /* do nothing */ 1818 return 0; 1819 default: 1820 /* fall through */ 1821 ; 1822 } 1823 default: 1824 FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level); 1825 return 0; 1826 } 1827 } 1828 1829 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}; 1830 1831 static const struct 1832 { 1833 int id; 1834 const WCHAR *text; 1835 } 1836 internal_errors[] = 1837 { 1838 {2726, szActionNotFound}, 1839 {0} 1840 }; 1841 1842 static LPCWSTR get_internal_error_message(int error) 1843 { 1844 int i = 0; 1845 1846 while (internal_errors[i].id != 0) 1847 { 1848 if (internal_errors[i].id == error) 1849 return internal_errors[i].text; 1850 i++; 1851 } 1852 1853 FIXME("missing error message %d\n", error); 1854 return NULL; 1855 } 1856 1857 /* Returned string must be freed */ 1858 LPWSTR msi_get_error_message(MSIDATABASE *db, int error) 1859 { 1860 static const WCHAR query[] = 1861 {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ', 1862 'F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ', 1863 '`','E','r','r','o','r','`',' ','=',' ','%','i',0}; 1864 MSIRECORD *record; 1865 LPWSTR ret = NULL; 1866 1867 if ((record = MSI_QueryGetRecord(db, query, error))) 1868 { 1869 ret = msi_dup_record_field(record, 1); 1870 msiobj_release(&record->hdr); 1871 } 1872 else if (error < 2000) 1873 { 1874 int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0); 1875 if (len) 1876 { 1877 ret = msi_alloc((len + 1) * sizeof(WCHAR)); 1878 LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1); 1879 } 1880 else 1881 ret = NULL; 1882 } 1883 1884 return ret; 1885 } 1886 1887 INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record) 1888 { 1889 LPWSTR message = {0}; 1890 DWORD len; 1891 DWORD log_type = 1 << (eMessageType >> 24); 1892 UINT res; 1893 INT rc = 0; 1894 char *msg; 1895 1896 TRACE("%x\n", eMessageType); 1897 if (TRACE_ON(msi)) dump_record(record); 1898 1899 if (!package || !record) 1900 message = NULL; 1901 else { 1902 res = MSI_FormatRecordW(package, record, message, &len); 1903 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 1904 return res; 1905 len++; 1906 message = msi_alloc(len * sizeof(WCHAR)); 1907 if (!message) return ERROR_OUTOFMEMORY; 1908 MSI_FormatRecordW(package, record, message, &len); 1909 } 1910 1911 /* convert it to ASCII */ 1912 len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL ); 1913 msg = msi_alloc( len ); 1914 WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL ); 1915 1916 if (gUIHandlerRecord && (gUIFilterRecord & log_type)) 1917 { 1918 MSIHANDLE rec = alloc_msihandle(&record->hdr); 1919 TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, hRecord=%u)\n", 1920 gUIHandlerRecord, gUIContextRecord, eMessageType, rec); 1921 rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec ); 1922 MsiCloseHandle( rec ); 1923 } 1924 if (!rc && gUIHandlerW && (gUIFilter & log_type)) 1925 { 1926 TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n", 1927 gUIHandlerW, gUIContext, eMessageType, debugstr_w(message)); 1928 rc = gUIHandlerW( gUIContext, eMessageType, message ); 1929 } 1930 else if (!rc && gUIHandlerA && (gUIFilter & log_type)) 1931 { 1932 TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n", 1933 gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg)); 1934 rc = gUIHandlerA( gUIContext, eMessageType, msg ); 1935 } 1936 1937 if (!rc) 1938 rc = internal_ui_handler(package, eMessageType, record, message); 1939 1940 if (!rc && package && package->log_file != INVALID_HANDLE_VALUE && 1941 (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS) 1942 { 1943 DWORD written; 1944 WriteFile( package->log_file, msg, len - 1, &written, NULL ); 1945 WriteFile( package->log_file, "\n", 1, &written, NULL ); 1946 } 1947 msi_free( msg ); 1948 msi_free( message ); 1949 1950 return rc; 1951 } 1952 1953 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record ) 1954 { 1955 switch (eMessageType & 0xff000000) 1956 { 1957 case INSTALLMESSAGE_FATALEXIT: 1958 case INSTALLMESSAGE_ERROR: 1959 case INSTALLMESSAGE_WARNING: 1960 case INSTALLMESSAGE_USER: 1961 case INSTALLMESSAGE_INFO: 1962 case INSTALLMESSAGE_OUTOFDISKSPACE: 1963 if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER) 1964 { 1965 /* error message */ 1966 1967 LPWSTR template; 1968 LPWSTR template_rec = NULL, template_prefix = NULL; 1969 int error = MSI_RecordGetInteger(record, 1); 1970 1971 if (MSI_RecordIsNull(record, 0)) 1972 { 1973 if (error >= 32) 1974 { 1975 template_rec = msi_get_error_message(package->db, error); 1976 1977 if (!template_rec && error >= 2000) 1978 { 1979 /* internal error, not localized */ 1980 if ((template_rec = (LPWSTR) get_internal_error_message(error))) 1981 { 1982 MSI_RecordSetStringW(record, 0, template_rec); 1983 MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record); 1984 } 1985 template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR); 1986 MSI_RecordSetStringW(record, 0, template_rec); 1987 MSI_ProcessMessageVerbatim(package, eMessageType, record); 1988 msi_free(template_rec); 1989 return 0; 1990 } 1991 } 1992 } 1993 else 1994 template_rec = msi_dup_record_field(record, 0); 1995 1996 template_prefix = msi_get_error_message(package->db, eMessageType >> 24); 1997 if (!template_prefix) template_prefix = strdupW(szEmpty); 1998 1999 if (!template_rec) 2000 { 2001 /* always returns 0 */ 2002 MSI_RecordSetStringW(record, 0, template_prefix); 2003 MSI_ProcessMessageVerbatim(package, eMessageType, record); 2004 msi_free(template_prefix); 2005 return 0; 2006 } 2007 2008 template = msi_alloc((strlenW(template_rec) + strlenW(template_prefix) + 1) * sizeof(WCHAR)); 2009 if (!template) return ERROR_OUTOFMEMORY; 2010 2011 strcpyW(template, template_prefix); 2012 strcatW(template, template_rec); 2013 MSI_RecordSetStringW(record, 0, template); 2014 2015 msi_free(template_prefix); 2016 msi_free(template_rec); 2017 msi_free(template); 2018 } 2019 break; 2020 case INSTALLMESSAGE_ACTIONSTART: 2021 { 2022 WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART); 2023 MSI_RecordSetStringW(record, 0, template); 2024 msi_free(template); 2025 2026 msi_free(package->LastAction); 2027 msi_free(package->LastActionTemplate); 2028 package->LastAction = msi_dup_record_field(record, 1); 2029 if (!package->LastAction) package->LastAction = strdupW(szEmpty); 2030 package->LastActionTemplate = msi_dup_record_field(record, 3); 2031 break; 2032 } 2033 case INSTALLMESSAGE_ACTIONDATA: 2034 if (package->LastAction && package->LastActionTemplate) 2035 { 2036 static const WCHAR template_s[] = 2037 {'{','{','%','s',':',' ','}','}','%','s',0}; 2038 WCHAR *template; 2039 2040 template = msi_alloc((strlenW(package->LastAction) + strlenW(package->LastActionTemplate) + 7) * sizeof(WCHAR)); 2041 if (!template) return ERROR_OUTOFMEMORY; 2042 sprintfW(template, template_s, package->LastAction, package->LastActionTemplate); 2043 MSI_RecordSetStringW(record, 0, template); 2044 msi_free(template); 2045 } 2046 break; 2047 case INSTALLMESSAGE_COMMONDATA: 2048 { 2049 WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA); 2050 MSI_RecordSetStringW(record, 0, template); 2051 msi_free(template); 2052 } 2053 break; 2054 } 2055 2056 return MSI_ProcessMessageVerbatim(package, eMessageType, record); 2057 } 2058 2059 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, 2060 MSIHANDLE hRecord) 2061 { 2062 UINT ret = ERROR_INVALID_HANDLE; 2063 MSIPACKAGE *package = NULL; 2064 MSIRECORD *record = NULL; 2065 2066 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE || 2067 (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE) 2068 return -1; 2069 2070 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA && 2071 MsiRecordGetInteger(hRecord, 1) != 2) 2072 return -1; 2073 2074 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 2075 if( !package ) 2076 { 2077 HRESULT hr; 2078 IWineMsiRemotePackage *remote_package; 2079 2080 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 2081 if (!remote_package) 2082 return ERROR_INVALID_HANDLE; 2083 2084 hr = IWineMsiRemotePackage_ProcessMessage( remote_package, eMessageType, hRecord ); 2085 2086 IWineMsiRemotePackage_Release( remote_package ); 2087 2088 if (FAILED(hr)) 2089 { 2090 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 2091 return HRESULT_CODE(hr); 2092 2093 return ERROR_FUNCTION_FAILED; 2094 } 2095 2096 return ERROR_SUCCESS; 2097 } 2098 2099 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); 2100 if( !record ) 2101 goto out; 2102 2103 ret = MSI_ProcessMessage( package, eMessageType, record ); 2104 2105 out: 2106 msiobj_release( &package->hdr ); 2107 if( record ) 2108 msiobj_release( &record->hdr ); 2109 2110 return ret; 2111 } 2112 2113 /* property code */ 2114 2115 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue ) 2116 { 2117 LPWSTR szwName = NULL, szwValue = NULL; 2118 UINT r = ERROR_OUTOFMEMORY; 2119 2120 szwName = strdupAtoW( szName ); 2121 if( szName && !szwName ) 2122 goto end; 2123 2124 szwValue = strdupAtoW( szValue ); 2125 if( szValue && !szwValue ) 2126 goto end; 2127 2128 r = MsiSetPropertyW( hInstall, szwName, szwValue); 2129 2130 end: 2131 msi_free( szwName ); 2132 msi_free( szwValue ); 2133 2134 return r; 2135 } 2136 2137 void msi_reset_folders( MSIPACKAGE *package, BOOL source ) 2138 { 2139 MSIFOLDER *folder; 2140 2141 LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry ) 2142 { 2143 if ( source ) 2144 { 2145 msi_free( folder->ResolvedSource ); 2146 folder->ResolvedSource = NULL; 2147 } 2148 else 2149 { 2150 msi_free( folder->ResolvedTarget ); 2151 folder->ResolvedTarget = NULL; 2152 } 2153 } 2154 } 2155 2156 UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len ) 2157 { 2158 static const WCHAR insert_query[] = { 2159 'I','N','S','E','R','T',' ','I','N','T','O',' ', 2160 '`','_','P','r','o','p','e','r','t','y','`',' ', 2161 '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ', 2162 'V','A','L','U','E','S',' ','(','?',',','?',')',0}; 2163 static const WCHAR update_query[] = { 2164 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ', 2165 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ', 2166 '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 2167 static const WCHAR delete_query[] = { 2168 'D','E','L','E','T','E',' ','F','R','O','M',' ', 2169 '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ', 2170 '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0}; 2171 MSIQUERY *view; 2172 MSIRECORD *row = NULL; 2173 DWORD sz = 0; 2174 WCHAR query[1024]; 2175 UINT rc; 2176 2177 TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len); 2178 2179 if (!name) 2180 return ERROR_INVALID_PARAMETER; 2181 2182 /* this one is weird... */ 2183 if (!name[0]) 2184 return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS; 2185 2186 if (value && len < 0) len = strlenW( value ); 2187 2188 rc = msi_get_property( db, name, 0, &sz ); 2189 if (!value || (!*value && !len)) 2190 { 2191 sprintfW( query, delete_query, name ); 2192 } 2193 else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS) 2194 { 2195 sprintfW( query, update_query, name ); 2196 row = MSI_CreateRecord(1); 2197 msi_record_set_string( row, 1, value, len ); 2198 } 2199 else 2200 { 2201 strcpyW( query, insert_query ); 2202 row = MSI_CreateRecord(2); 2203 msi_record_set_string( row, 1, name, -1 ); 2204 msi_record_set_string( row, 2, value, len ); 2205 } 2206 2207 rc = MSI_DatabaseOpenViewW(db, query, &view); 2208 if (rc == ERROR_SUCCESS) 2209 { 2210 rc = MSI_ViewExecute(view, row); 2211 MSI_ViewClose(view); 2212 msiobj_release(&view->hdr); 2213 } 2214 if (row) msiobj_release(&row->hdr); 2215 return rc; 2216 } 2217 2218 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue) 2219 { 2220 MSIPACKAGE *package; 2221 UINT ret; 2222 2223 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE); 2224 if( !package ) 2225 { 2226 HRESULT hr; 2227 BSTR name = NULL, value = NULL; 2228 IWineMsiRemotePackage *remote_package; 2229 2230 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 2231 if (!remote_package) 2232 return ERROR_INVALID_HANDLE; 2233 2234 name = SysAllocString( szName ); 2235 value = SysAllocString( szValue ); 2236 if ((!name && szName) || (!value && szValue)) 2237 { 2238 SysFreeString( name ); 2239 SysFreeString( value ); 2240 IWineMsiRemotePackage_Release( remote_package ); 2241 return ERROR_OUTOFMEMORY; 2242 } 2243 2244 hr = IWineMsiRemotePackage_SetProperty( remote_package, name, value ); 2245 2246 SysFreeString( name ); 2247 SysFreeString( value ); 2248 IWineMsiRemotePackage_Release( remote_package ); 2249 2250 if (FAILED(hr)) 2251 { 2252 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 2253 return HRESULT_CODE(hr); 2254 2255 return ERROR_FUNCTION_FAILED; 2256 } 2257 2258 return ERROR_SUCCESS; 2259 } 2260 2261 ret = msi_set_property( package->db, szName, szValue, -1 ); 2262 if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir )) 2263 msi_reset_folders( package, TRUE ); 2264 2265 msiobj_release( &package->hdr ); 2266 return ret; 2267 } 2268 2269 static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name ) 2270 { 2271 static const WCHAR query[]= { 2272 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 2273 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ', 2274 'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0}; 2275 MSIRECORD *rec, *row = NULL; 2276 MSIQUERY *view; 2277 UINT r; 2278 2279 static const WCHAR szDate[] = {'D','a','t','e',0}; 2280 static const WCHAR szTime[] = {'T','i','m','e',0}; 2281 WCHAR *buffer; 2282 int length; 2283 2284 if (!name || !*name) 2285 return NULL; 2286 2287 if (!strcmpW(name, szDate)) 2288 { 2289 length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0); 2290 if (!length) 2291 return NULL; 2292 buffer = msi_alloc(length * sizeof(WCHAR)); 2293 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length); 2294 2295 row = MSI_CreateRecord(1); 2296 if (!row) 2297 { 2298 msi_free(buffer); 2299 return NULL; 2300 } 2301 MSI_RecordSetStringW(row, 1, buffer); 2302 msi_free(buffer); 2303 return row; 2304 } 2305 else if (!strcmpW(name, szTime)) 2306 { 2307 length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0); 2308 if (!length) 2309 return NULL; 2310 buffer = msi_alloc(length * sizeof(WCHAR)); 2311 GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length); 2312 2313 row = MSI_CreateRecord(1); 2314 if (!row) 2315 { 2316 msi_free(buffer); 2317 return NULL; 2318 } 2319 MSI_RecordSetStringW(row, 1, buffer); 2320 msi_free(buffer); 2321 return row; 2322 } 2323 2324 rec = MSI_CreateRecord(1); 2325 if (!rec) 2326 return NULL; 2327 2328 MSI_RecordSetStringW(rec, 1, name); 2329 2330 r = MSI_DatabaseOpenViewW(db, query, &view); 2331 if (r == ERROR_SUCCESS) 2332 { 2333 MSI_ViewExecute(view, rec); 2334 MSI_ViewFetch(view, &row); 2335 MSI_ViewClose(view); 2336 msiobj_release(&view->hdr); 2337 } 2338 msiobj_release(&rec->hdr); 2339 return row; 2340 } 2341 2342 /* internal function, not compatible with MsiGetPropertyW */ 2343 UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName, 2344 LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2345 { 2346 MSIRECORD *row; 2347 UINT rc = ERROR_FUNCTION_FAILED; 2348 2349 TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf); 2350 2351 row = msi_get_property_row( db, szName ); 2352 2353 if (*pchValueBuf > 0) 2354 szValueBuf[0] = 0; 2355 2356 if (row) 2357 { 2358 rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf); 2359 msiobj_release(&row->hdr); 2360 } 2361 2362 if (rc == ERROR_SUCCESS) 2363 TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf), 2364 debugstr_w(szName)); 2365 else if (rc == ERROR_MORE_DATA) 2366 TRACE("need %d sized buffer for %s\n", *pchValueBuf, 2367 debugstr_w(szName)); 2368 else 2369 { 2370 *pchValueBuf = 0; 2371 TRACE("property %s not found\n", debugstr_w(szName)); 2372 } 2373 2374 return rc; 2375 } 2376 2377 LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) 2378 { 2379 DWORD sz = 0; 2380 LPWSTR str; 2381 UINT r; 2382 2383 r = msi_get_property(db, prop, NULL, &sz); 2384 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2385 return NULL; 2386 2387 sz++; 2388 str = msi_alloc(sz * sizeof(WCHAR)); 2389 r = msi_get_property(db, prop, str, &sz); 2390 if (r != ERROR_SUCCESS) 2391 { 2392 msi_free(str); 2393 str = NULL; 2394 } 2395 2396 return str; 2397 } 2398 2399 int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def ) 2400 { 2401 LPWSTR str = msi_dup_property( db, prop ); 2402 int val = str ? atoiW(str) : def; 2403 msi_free(str); 2404 return val; 2405 } 2406 2407 static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name, 2408 awstring *szValueBuf, LPDWORD pchValueBuf ) 2409 { 2410 MSIPACKAGE *package; 2411 MSIRECORD *row = NULL; 2412 UINT r = ERROR_FUNCTION_FAILED; 2413 LPCWSTR val = NULL; 2414 DWORD len = 0; 2415 2416 TRACE("%u %s %p %p\n", handle, debugstr_w(name), 2417 szValueBuf->str.w, pchValueBuf ); 2418 2419 if (!name) 2420 return ERROR_INVALID_PARAMETER; 2421 2422 package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ); 2423 if (!package) 2424 { 2425 HRESULT hr; 2426 IWineMsiRemotePackage *remote_package; 2427 LPWSTR value = NULL; 2428 BSTR bname; 2429 2430 remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle ); 2431 if (!remote_package) 2432 return ERROR_INVALID_HANDLE; 2433 2434 bname = SysAllocString( name ); 2435 if (!bname) 2436 { 2437 IWineMsiRemotePackage_Release( remote_package ); 2438 return ERROR_OUTOFMEMORY; 2439 } 2440 2441 hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len ); 2442 if (FAILED(hr)) 2443 goto done; 2444 2445 len++; 2446 value = msi_alloc(len * sizeof(WCHAR)); 2447 if (!value) 2448 { 2449 r = ERROR_OUTOFMEMORY; 2450 goto done; 2451 } 2452 2453 hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, value, &len ); 2454 if (FAILED(hr)) 2455 goto done; 2456 2457 r = msi_strcpy_to_awstring( value, len, szValueBuf, pchValueBuf ); 2458 2459 /* Bug required by Adobe installers */ 2460 if (!szValueBuf->unicode && !szValueBuf->str.a) 2461 *pchValueBuf *= sizeof(WCHAR); 2462 2463 done: 2464 IWineMsiRemotePackage_Release(remote_package); 2465 SysFreeString(bname); 2466 msi_free(value); 2467 2468 if (FAILED(hr)) 2469 { 2470 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 2471 return HRESULT_CODE(hr); 2472 2473 return ERROR_FUNCTION_FAILED; 2474 } 2475 2476 return r; 2477 } 2478 2479 row = msi_get_property_row( package->db, name ); 2480 if (row) 2481 val = msi_record_get_string( row, 1, (int *)&len ); 2482 2483 if (!val) 2484 val = szEmpty; 2485 2486 r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf ); 2487 2488 if (row) 2489 msiobj_release( &row->hdr ); 2490 msiobj_release( &package->hdr ); 2491 2492 return r; 2493 } 2494 2495 UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName, 2496 LPSTR szValueBuf, LPDWORD pchValueBuf ) 2497 { 2498 awstring val; 2499 LPWSTR name; 2500 UINT r; 2501 2502 val.unicode = FALSE; 2503 val.str.a = szValueBuf; 2504 2505 name = strdupAtoW( szName ); 2506 if (szName && !name) 2507 return ERROR_OUTOFMEMORY; 2508 2509 r = MSI_GetProperty( hInstall, name, &val, pchValueBuf ); 2510 msi_free( name ); 2511 return r; 2512 } 2513 2514 UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, 2515 LPWSTR szValueBuf, LPDWORD pchValueBuf ) 2516 { 2517 awstring val; 2518 2519 val.unicode = TRUE; 2520 val.str.w = szValueBuf; 2521 2522 return MSI_GetProperty( hInstall, szName, &val, pchValueBuf ); 2523 } 2524 2525 typedef struct _msi_remote_package_impl { 2526 IWineMsiRemotePackage IWineMsiRemotePackage_iface; 2527 MSIHANDLE package; 2528 LONG refs; 2529 } msi_remote_package_impl; 2530 2531 static inline msi_remote_package_impl *impl_from_IWineMsiRemotePackage( IWineMsiRemotePackage *iface ) 2532 { 2533 return CONTAINING_RECORD(iface, msi_remote_package_impl, IWineMsiRemotePackage_iface); 2534 } 2535 2536 static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface, 2537 REFIID riid,LPVOID *ppobj) 2538 { 2539 if( IsEqualCLSID( riid, &IID_IUnknown ) || 2540 IsEqualCLSID( riid, &IID_IWineMsiRemotePackage ) ) 2541 { 2542 IWineMsiRemotePackage_AddRef( iface ); 2543 *ppobj = iface; 2544 return S_OK; 2545 } 2546 2547 return E_NOINTERFACE; 2548 } 2549 2550 static ULONG WINAPI mrp_AddRef( IWineMsiRemotePackage *iface ) 2551 { 2552 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2553 2554 return InterlockedIncrement( &This->refs ); 2555 } 2556 2557 static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface ) 2558 { 2559 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2560 ULONG r; 2561 2562 r = InterlockedDecrement( &This->refs ); 2563 if (r == 0) 2564 { 2565 MsiCloseHandle( This->package ); 2566 msi_free( This ); 2567 } 2568 return r; 2569 } 2570 2571 static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE handle ) 2572 { 2573 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2574 This->package = handle; 2575 return S_OK; 2576 } 2577 2578 static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle ) 2579 { 2580 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2581 IWineMsiRemoteDatabase *rdb = NULL; 2582 HRESULT hr; 2583 MSIHANDLE hdb; 2584 2585 hr = create_msi_remote_database( NULL, (LPVOID *)&rdb ); 2586 if (FAILED(hr) || !rdb) 2587 { 2588 ERR("Failed to create remote database\n"); 2589 return hr; 2590 } 2591 2592 hdb = MsiGetActiveDatabase(This->package); 2593 2594 hr = IWineMsiRemoteDatabase_SetMsiHandle( rdb, hdb ); 2595 if (FAILED(hr)) 2596 { 2597 ERR("Failed to set the database handle\n"); 2598 return hr; 2599 } 2600 2601 *handle = alloc_msi_remote_handle( (IUnknown *)rdb ); 2602 return S_OK; 2603 } 2604 2605 static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value, DWORD *size ) 2606 { 2607 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2608 UINT r = MsiGetPropertyW(This->package, property, value, size); 2609 if (r != ERROR_SUCCESS) return HRESULT_FROM_WIN32(r); 2610 return S_OK; 2611 } 2612 2613 static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value ) 2614 { 2615 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2616 UINT r = MsiSetPropertyW(This->package, property, value); 2617 return HRESULT_FROM_WIN32(r); 2618 } 2619 2620 static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record ) 2621 { 2622 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2623 UINT r = MsiProcessMessage(This->package, message, record); 2624 return HRESULT_FROM_WIN32(r); 2625 } 2626 2627 static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action ) 2628 { 2629 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2630 UINT r = MsiDoActionW(This->package, action); 2631 return HRESULT_FROM_WIN32(r); 2632 } 2633 2634 static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence ) 2635 { 2636 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2637 UINT r = MsiSequenceW(This->package, table, sequence); 2638 return HRESULT_FROM_WIN32(r); 2639 } 2640 2641 static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size ) 2642 { 2643 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2644 UINT r = MsiGetTargetPathW(This->package, folder, value, size); 2645 return HRESULT_FROM_WIN32(r); 2646 } 2647 2648 static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value) 2649 { 2650 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2651 UINT r = MsiSetTargetPathW(This->package, folder, value); 2652 return HRESULT_FROM_WIN32(r); 2653 } 2654 2655 static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size ) 2656 { 2657 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2658 UINT r = MsiGetSourcePathW(This->package, folder, value, size); 2659 return HRESULT_FROM_WIN32(r); 2660 } 2661 2662 static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret ) 2663 { 2664 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2665 *ret = MsiGetMode(This->package, mode); 2666 return S_OK; 2667 } 2668 2669 static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state ) 2670 { 2671 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2672 UINT r = MsiSetMode(This->package, mode, state); 2673 return HRESULT_FROM_WIN32(r); 2674 } 2675 2676 static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, 2677 INSTALLSTATE *installed, INSTALLSTATE *action ) 2678 { 2679 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2680 UINT r = MsiGetFeatureStateW(This->package, feature, installed, action); 2681 return HRESULT_FROM_WIN32(r); 2682 } 2683 2684 static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state ) 2685 { 2686 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2687 UINT r = MsiSetFeatureStateW(This->package, feature, state); 2688 return HRESULT_FROM_WIN32(r); 2689 } 2690 2691 static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component, 2692 INSTALLSTATE *installed, INSTALLSTATE *action ) 2693 { 2694 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2695 UINT r = MsiGetComponentStateW(This->package, component, installed, action); 2696 return HRESULT_FROM_WIN32(r); 2697 } 2698 2699 static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state ) 2700 { 2701 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2702 UINT r = MsiSetComponentStateW(This->package, component, state); 2703 return HRESULT_FROM_WIN32(r); 2704 } 2705 2706 static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language ) 2707 { 2708 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2709 *language = MsiGetLanguage(This->package); 2710 return S_OK; 2711 } 2712 2713 static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level ) 2714 { 2715 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2716 UINT r = MsiSetInstallLevel(This->package, level); 2717 return HRESULT_FROM_WIN32(r); 2718 } 2719 2720 static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record, 2721 BSTR *value) 2722 { 2723 DWORD size = 0; 2724 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2725 UINT r = MsiFormatRecordW(This->package, record, NULL, &size); 2726 if (r == ERROR_SUCCESS) 2727 { 2728 *value = SysAllocStringLen(NULL, size); 2729 if (!*value) 2730 return E_OUTOFMEMORY; 2731 size++; 2732 r = MsiFormatRecordW(This->package, record, *value, &size); 2733 } 2734 return HRESULT_FROM_WIN32(r); 2735 } 2736 2737 static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition ) 2738 { 2739 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2740 UINT r = MsiEvaluateConditionW(This->package, condition); 2741 return HRESULT_FROM_WIN32(r); 2742 } 2743 2744 static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature, 2745 INT cost_tree, INSTALLSTATE state, INT *cost ) 2746 { 2747 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2748 UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost); 2749 return HRESULT_FROM_WIN32(r); 2750 } 2751 2752 static HRESULT WINAPI mrp_EnumComponentCosts( IWineMsiRemotePackage *iface, BSTR component, 2753 DWORD index, INSTALLSTATE state, BSTR drive, 2754 DWORD *buflen, INT *cost, INT *temp ) 2755 { 2756 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface ); 2757 UINT r = MsiEnumComponentCostsW(This->package, component, index, state, drive, buflen, cost, temp); 2758 return HRESULT_FROM_WIN32(r); 2759 } 2760 2761 static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl = 2762 { 2763 mrp_QueryInterface, 2764 mrp_AddRef, 2765 mrp_Release, 2766 mrp_SetMsiHandle, 2767 mrp_GetActiveDatabase, 2768 mrp_GetProperty, 2769 mrp_SetProperty, 2770 mrp_ProcessMessage, 2771 mrp_DoAction, 2772 mrp_Sequence, 2773 mrp_GetTargetPath, 2774 mrp_SetTargetPath, 2775 mrp_GetSourcePath, 2776 mrp_GetMode, 2777 mrp_SetMode, 2778 mrp_GetFeatureState, 2779 mrp_SetFeatureState, 2780 mrp_GetComponentState, 2781 mrp_SetComponentState, 2782 mrp_GetLanguage, 2783 mrp_SetInstallLevel, 2784 mrp_FormatRecord, 2785 mrp_EvaluateCondition, 2786 mrp_GetFeatureCost, 2787 mrp_EnumComponentCosts 2788 }; 2789 2790 HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj ) 2791 { 2792 msi_remote_package_impl* This; 2793 2794 This = msi_alloc( sizeof *This ); 2795 if (!This) 2796 return E_OUTOFMEMORY; 2797 2798 This->IWineMsiRemotePackage_iface.lpVtbl = &msi_remote_package_vtbl; 2799 This->package = 0; 2800 This->refs = 1; 2801 2802 *ppObj = &This->IWineMsiRemotePackage_iface; 2803 2804 return S_OK; 2805 } 2806 2807 UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options, 2808 LPCWSTR property, LPWSTR value) 2809 { 2810 MSISOURCELISTINFO *info; 2811 2812 LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry ) 2813 { 2814 if (!strcmpW( info->value, value )) return ERROR_SUCCESS; 2815 } 2816 2817 info = msi_alloc(sizeof(MSISOURCELISTINFO)); 2818 if (!info) 2819 return ERROR_OUTOFMEMORY; 2820 2821 info->context = context; 2822 info->options = options; 2823 info->property = property; 2824 info->value = strdupW(value); 2825 list_add_head(&package->sourcelist_info, &info->entry); 2826 2827 return ERROR_SUCCESS; 2828 } 2829 2830 UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options, 2831 DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt) 2832 { 2833 MSIMEDIADISK *disk; 2834 2835 LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry ) 2836 { 2837 if (disk->disk_id == disk_id) return ERROR_SUCCESS; 2838 } 2839 2840 disk = msi_alloc(sizeof(MSIMEDIADISK)); 2841 if (!disk) 2842 return ERROR_OUTOFMEMORY; 2843 2844 disk->context = context; 2845 disk->options = options; 2846 disk->disk_id = disk_id; 2847 disk->volume_label = strdupW(volume_label); 2848 disk->disk_prompt = strdupW(disk_prompt); 2849 list_add_head(&package->sourcelist_media, &disk->entry); 2850 2851 return ERROR_SUCCESS; 2852 } 2853