1 /* 2 * Implementation of the Microsoft Installer (msi.dll) 3 * 4 * Copyright 2005 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 /* Msi top level apis directly related to installs */ 22 23 #define COBJMACROS 24 25 #include <stdarg.h> 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "winerror.h" 30 #include "wine/debug.h" 31 #include "msi.h" 32 #include "msidefs.h" 33 #include "objbase.h" 34 #include "oleauto.h" 35 36 #include "msipriv.h" 37 #include "msiserver.h" 38 #include "wine/unicode.h" 39 40 WINE_DEFAULT_DEBUG_CHANNEL(msi); 41 42 /*********************************************************************** 43 * MsiDoActionA (MSI.@) 44 */ 45 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction ) 46 { 47 LPWSTR szwAction; 48 UINT ret; 49 50 TRACE("%s\n", debugstr_a(szAction)); 51 52 szwAction = strdupAtoW(szAction); 53 if (szAction && !szwAction) 54 return ERROR_FUNCTION_FAILED; 55 56 ret = MsiDoActionW( hInstall, szwAction ); 57 msi_free( szwAction ); 58 return ret; 59 } 60 61 /*********************************************************************** 62 * MsiDoActionW (MSI.@) 63 */ 64 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction ) 65 { 66 MSIPACKAGE *package; 67 UINT ret; 68 69 TRACE("%s\n",debugstr_w(szAction)); 70 71 if (!szAction) 72 return ERROR_INVALID_PARAMETER; 73 74 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 75 if (!package) 76 { 77 HRESULT hr; 78 BSTR action; 79 IWineMsiRemotePackage *remote_package; 80 81 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 82 if (!remote_package) 83 return ERROR_INVALID_HANDLE; 84 85 action = SysAllocString( szAction ); 86 if (!action) 87 { 88 IWineMsiRemotePackage_Release( remote_package ); 89 return ERROR_OUTOFMEMORY; 90 } 91 92 hr = IWineMsiRemotePackage_DoAction( remote_package, action ); 93 94 SysFreeString( action ); 95 IWineMsiRemotePackage_Release( remote_package ); 96 97 if (FAILED(hr)) 98 { 99 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 100 return HRESULT_CODE(hr); 101 102 return ERROR_FUNCTION_FAILED; 103 } 104 105 return ERROR_SUCCESS; 106 } 107 108 ret = ACTION_PerformAction( package, szAction, SCRIPT_NONE ); 109 msiobj_release( &package->hdr ); 110 111 return ret; 112 } 113 114 /*********************************************************************** 115 * MsiSequenceA (MSI.@) 116 */ 117 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode ) 118 { 119 LPWSTR szwTable; 120 UINT ret; 121 122 TRACE("%s, %d\n", debugstr_a(szTable), iSequenceMode); 123 124 szwTable = strdupAtoW(szTable); 125 if (szTable && !szwTable) 126 return ERROR_FUNCTION_FAILED; 127 128 ret = MsiSequenceW( hInstall, szwTable, iSequenceMode ); 129 msi_free( szwTable ); 130 return ret; 131 } 132 133 /*********************************************************************** 134 * MsiSequenceW (MSI.@) 135 */ 136 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode ) 137 { 138 MSIPACKAGE *package; 139 UINT ret; 140 141 TRACE("%s, %d\n", debugstr_w(szTable), iSequenceMode); 142 143 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 144 if (!package) 145 { 146 HRESULT hr; 147 BSTR table; 148 IWineMsiRemotePackage *remote_package; 149 150 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 151 if (!remote_package) 152 return ERROR_INVALID_HANDLE; 153 154 table = SysAllocString( szTable ); 155 if (!table) 156 { 157 IWineMsiRemotePackage_Release( remote_package ); 158 return ERROR_OUTOFMEMORY; 159 } 160 161 hr = IWineMsiRemotePackage_Sequence( remote_package, table, iSequenceMode ); 162 163 SysFreeString( table ); 164 IWineMsiRemotePackage_Release( remote_package ); 165 166 if (FAILED(hr)) 167 { 168 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 169 return HRESULT_CODE(hr); 170 171 return ERROR_FUNCTION_FAILED; 172 } 173 174 return ERROR_SUCCESS; 175 } 176 ret = MSI_Sequence( package, szTable ); 177 msiobj_release( &package->hdr ); 178 return ret; 179 } 180 181 UINT msi_strcpy_to_awstring( const WCHAR *str, int len, awstring *awbuf, DWORD *sz ) 182 { 183 UINT r = ERROR_SUCCESS; 184 185 if (awbuf->str.w && !sz) 186 return ERROR_INVALID_PARAMETER; 187 if (!sz) 188 return ERROR_SUCCESS; 189 190 if (len < 0) len = strlenW( str ); 191 192 if (awbuf->unicode && awbuf->str.w) 193 memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) ); 194 else 195 { 196 int lenA = WideCharToMultiByte( CP_ACP, 0, str, len + 1, NULL, 0, NULL, NULL ); 197 if (lenA) lenA--; 198 WideCharToMultiByte( CP_ACP, 0, str, len + 1, awbuf->str.a, *sz, NULL, NULL ); 199 if (awbuf->str.a && *sz && lenA >= *sz) 200 awbuf->str.a[*sz - 1] = 0; 201 len = lenA; 202 } 203 if (awbuf->str.w && len >= *sz) 204 r = ERROR_MORE_DATA; 205 *sz = len; 206 return r; 207 } 208 209 const WCHAR *msi_get_target_folder( MSIPACKAGE *package, const WCHAR *name ) 210 { 211 MSIFOLDER *folder = msi_get_loaded_folder( package, name ); 212 213 if (!folder) return NULL; 214 if (!folder->ResolvedTarget) 215 { 216 MSIFOLDER *parent = folder; 217 while (parent->Parent && strcmpW( parent->Parent, parent->Directory )) 218 { 219 parent = msi_get_loaded_folder( package, parent->Parent ); 220 } 221 msi_resolve_target_folder( package, parent->Directory, TRUE ); 222 } 223 return folder->ResolvedTarget; 224 } 225 226 /*********************************************************************** 227 * MsiGetTargetPath (internal) 228 */ 229 static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder, 230 awstring *szPathBuf, LPDWORD pcchPathBuf ) 231 { 232 MSIPACKAGE *package; 233 const WCHAR *path; 234 UINT r = ERROR_FUNCTION_FAILED; 235 236 if (!szFolder) 237 return ERROR_INVALID_PARAMETER; 238 239 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 240 if (!package) 241 { 242 HRESULT hr; 243 IWineMsiRemotePackage *remote_package; 244 LPWSTR value = NULL; 245 BSTR folder; 246 DWORD len; 247 248 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 249 if (!remote_package) 250 return ERROR_INVALID_HANDLE; 251 252 folder = SysAllocString( szFolder ); 253 if (!folder) 254 { 255 IWineMsiRemotePackage_Release( remote_package ); 256 return ERROR_OUTOFMEMORY; 257 } 258 259 len = 0; 260 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder, NULL, &len ); 261 if (FAILED(hr)) 262 goto done; 263 264 len++; 265 value = msi_alloc(len * sizeof(WCHAR)); 266 if (!value) 267 { 268 r = ERROR_OUTOFMEMORY; 269 goto done; 270 } 271 272 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder, value, &len ); 273 if (FAILED(hr)) 274 goto done; 275 276 r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf ); 277 278 done: 279 IWineMsiRemotePackage_Release( remote_package ); 280 SysFreeString( folder ); 281 msi_free( value ); 282 283 if (FAILED(hr)) 284 { 285 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 286 return HRESULT_CODE(hr); 287 288 return ERROR_FUNCTION_FAILED; 289 } 290 291 return r; 292 } 293 294 path = msi_get_target_folder( package, szFolder ); 295 msiobj_release( &package->hdr ); 296 297 if (!path) 298 return ERROR_DIRECTORY; 299 300 return msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf ); 301 } 302 303 /*********************************************************************** 304 * MsiGetTargetPathA (MSI.@) 305 */ 306 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, 307 LPSTR szPathBuf, LPDWORD pcchPathBuf ) 308 { 309 LPWSTR szwFolder; 310 awstring path; 311 UINT r; 312 313 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf); 314 315 szwFolder = strdupAtoW(szFolder); 316 if (szFolder && !szwFolder) 317 return ERROR_FUNCTION_FAILED; 318 319 path.unicode = FALSE; 320 path.str.a = szPathBuf; 321 322 r = MSI_GetTargetPath( hInstall, szwFolder, &path, pcchPathBuf ); 323 324 msi_free( szwFolder ); 325 326 return r; 327 } 328 329 /*********************************************************************** 330 * MsiGetTargetPathW (MSI.@) 331 */ 332 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, 333 LPWSTR szPathBuf, LPDWORD pcchPathBuf ) 334 { 335 awstring path; 336 337 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf); 338 339 path.unicode = TRUE; 340 path.str.w = szPathBuf; 341 342 return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf ); 343 } 344 345 static WCHAR *get_source_root( MSIPACKAGE *package ) 346 { 347 msi_set_sourcedir_props( package, FALSE ); 348 return msi_dup_property( package->db, szSourceDir ); 349 } 350 351 WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder ) 352 { 353 MSIFOLDER *f; 354 LPWSTR p, path = NULL, parent; 355 356 TRACE("working to resolve %s\n", debugstr_w(name)); 357 358 if (!strcmpW( name, szSourceDir )) name = szTargetDir; 359 if (!(f = msi_get_loaded_folder( package, name ))) return NULL; 360 361 /* special resolving for root dir */ 362 if (!strcmpW( name, szTargetDir ) && !f->ResolvedSource) 363 { 364 f->ResolvedSource = get_source_root( package ); 365 } 366 if (folder) *folder = f; 367 if (f->ResolvedSource) 368 { 369 path = strdupW( f->ResolvedSource ); 370 TRACE(" already resolved to %s\n", debugstr_w(path)); 371 return path; 372 } 373 if (!f->Parent) return path; 374 parent = f->Parent; 375 TRACE(" ! parent is %s\n", debugstr_w(parent)); 376 377 p = msi_resolve_source_folder( package, parent, NULL ); 378 379 if (package->WordCount & msidbSumInfoSourceTypeCompressed) 380 path = get_source_root( package ); 381 else if (package->WordCount & msidbSumInfoSourceTypeSFN) 382 path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL ); 383 else 384 path = msi_build_directory_name( 3, p, f->SourceLongPath, NULL ); 385 386 TRACE("-> %s\n", debugstr_w(path)); 387 f->ResolvedSource = strdupW( path ); 388 msi_free( p ); 389 390 return path; 391 } 392 393 /*********************************************************************** 394 * MSI_GetSourcePath (internal) 395 */ 396 static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder, 397 awstring *szPathBuf, LPDWORD pcchPathBuf ) 398 { 399 MSIPACKAGE *package; 400 LPWSTR path; 401 UINT r = ERROR_FUNCTION_FAILED; 402 403 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf ); 404 405 if (!szFolder) 406 return ERROR_INVALID_PARAMETER; 407 408 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 409 if (!package) 410 { 411 HRESULT hr; 412 IWineMsiRemotePackage *remote_package; 413 LPWSTR value = NULL; 414 BSTR folder; 415 DWORD len; 416 417 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 418 if (!remote_package) 419 return ERROR_INVALID_HANDLE; 420 421 folder = SysAllocString( szFolder ); 422 if (!folder) 423 { 424 IWineMsiRemotePackage_Release( remote_package ); 425 return ERROR_OUTOFMEMORY; 426 } 427 428 len = 0; 429 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder, NULL, &len ); 430 if (FAILED(hr)) 431 goto done; 432 433 len++; 434 value = msi_alloc(len * sizeof(WCHAR)); 435 if (!value) 436 { 437 r = ERROR_OUTOFMEMORY; 438 goto done; 439 } 440 441 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder, value, &len ); 442 if (FAILED(hr)) 443 goto done; 444 445 r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf ); 446 447 done: 448 IWineMsiRemotePackage_Release( remote_package ); 449 SysFreeString( folder ); 450 msi_free( value ); 451 452 if (FAILED(hr)) 453 { 454 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 455 return HRESULT_CODE(hr); 456 457 return ERROR_FUNCTION_FAILED; 458 } 459 460 return r; 461 } 462 463 if (szPathBuf->str.w && !pcchPathBuf ) 464 { 465 msiobj_release( &package->hdr ); 466 return ERROR_INVALID_PARAMETER; 467 } 468 469 path = msi_resolve_source_folder( package, szFolder, NULL ); 470 msiobj_release( &package->hdr ); 471 472 TRACE("path = %s\n", debugstr_w(path)); 473 if (!path) 474 return ERROR_DIRECTORY; 475 476 r = msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf ); 477 msi_free( path ); 478 return r; 479 } 480 481 /*********************************************************************** 482 * MsiGetSourcePathA (MSI.@) 483 */ 484 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder, 485 LPSTR szPathBuf, LPDWORD pcchPathBuf ) 486 { 487 LPWSTR folder; 488 awstring str; 489 UINT r; 490 491 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf); 492 493 str.unicode = FALSE; 494 str.str.a = szPathBuf; 495 496 folder = strdupAtoW( szFolder ); 497 r = MSI_GetSourcePath( hInstall, folder, &str, pcchPathBuf ); 498 msi_free( folder ); 499 500 return r; 501 } 502 503 /*********************************************************************** 504 * MsiGetSourcePathW (MSI.@) 505 */ 506 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, 507 LPWSTR szPathBuf, LPDWORD pcchPathBuf ) 508 { 509 awstring str; 510 511 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf ); 512 513 str.unicode = TRUE; 514 str.str.w = szPathBuf; 515 516 return MSI_GetSourcePath( hInstall, szFolder, &str, pcchPathBuf ); 517 } 518 519 /*********************************************************************** 520 * MsiSetTargetPathA (MSI.@) 521 */ 522 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, 523 LPCSTR szFolderPath ) 524 { 525 LPWSTR szwFolder = NULL, szwFolderPath = NULL; 526 UINT rc = ERROR_OUTOFMEMORY; 527 528 if ( !szFolder || !szFolderPath ) 529 return ERROR_INVALID_PARAMETER; 530 531 szwFolder = strdupAtoW(szFolder); 532 szwFolderPath = strdupAtoW(szFolderPath); 533 if (!szwFolder || !szwFolderPath) 534 goto end; 535 536 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath ); 537 538 end: 539 msi_free(szwFolder); 540 msi_free(szwFolderPath); 541 542 return rc; 543 } 544 545 static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR *path ) 546 { 547 FolderList *fl; 548 MSIFOLDER *child; 549 WCHAR *target_path; 550 551 if (!(target_path = msi_normalize_path( path ))) return; 552 if (strcmpW( target_path, folder->ResolvedTarget )) 553 { 554 msi_free( folder->ResolvedTarget ); 555 folder->ResolvedTarget = target_path; 556 msi_set_property( package->db, folder->Directory, folder->ResolvedTarget, -1 ); 557 558 LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry ) 559 { 560 child = fl->folder; 561 msi_resolve_target_folder( package, child->Directory, FALSE ); 562 } 563 } 564 else msi_free( target_path ); 565 } 566 567 UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath ) 568 { 569 DWORD attrib; 570 MSIFOLDER *folder; 571 MSIFILE *file; 572 573 TRACE("%p %s %s\n", package, debugstr_w(szFolder), debugstr_w(szFolderPath)); 574 575 attrib = GetFileAttributesW(szFolderPath); 576 /* native MSI tests writeability by making temporary files at each drive */ 577 if (attrib != INVALID_FILE_ATTRIBUTES && 578 (attrib & FILE_ATTRIBUTE_OFFLINE || attrib & FILE_ATTRIBUTE_READONLY)) 579 { 580 return ERROR_FUNCTION_FAILED; 581 } 582 if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY; 583 584 set_target_path( package, folder, szFolderPath ); 585 586 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry ) 587 { 588 const WCHAR *dir; 589 MSICOMPONENT *comp = file->Component; 590 591 if (!comp->Enabled || msi_is_global_assembly( comp )) continue; 592 593 dir = msi_get_target_folder( package, comp->Directory ); 594 msi_free( file->TargetPath ); 595 file->TargetPath = msi_build_directory_name( 2, dir, file->FileName ); 596 } 597 return ERROR_SUCCESS; 598 } 599 600 /*********************************************************************** 601 * MsiSetTargetPathW (MSI.@) 602 */ 603 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder, 604 LPCWSTR szFolderPath) 605 { 606 MSIPACKAGE *package; 607 UINT ret; 608 609 TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath)); 610 611 if ( !szFolder || !szFolderPath ) 612 return ERROR_INVALID_PARAMETER; 613 614 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); 615 if (!package) 616 { 617 HRESULT hr; 618 BSTR folder, path; 619 IWineMsiRemotePackage *remote_package; 620 621 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 622 if (!remote_package) 623 return ERROR_INVALID_HANDLE; 624 625 folder = SysAllocString( szFolder ); 626 path = SysAllocString( szFolderPath ); 627 if (!folder || !path) 628 { 629 SysFreeString(folder); 630 SysFreeString(path); 631 IWineMsiRemotePackage_Release( remote_package ); 632 return ERROR_OUTOFMEMORY; 633 } 634 635 hr = IWineMsiRemotePackage_SetTargetPath( remote_package, folder, path ); 636 637 SysFreeString(folder); 638 SysFreeString(path); 639 IWineMsiRemotePackage_Release( remote_package ); 640 641 if (FAILED(hr)) 642 { 643 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 644 return HRESULT_CODE(hr); 645 646 return ERROR_FUNCTION_FAILED; 647 } 648 649 return ERROR_SUCCESS; 650 } 651 652 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath ); 653 msiobj_release( &package->hdr ); 654 return ret; 655 } 656 657 /*********************************************************************** 658 * MsiGetMode (MSI.@) 659 * 660 * Returns an internal installer state (if it is running in a mode iRunMode) 661 * 662 * PARAMS 663 * hInstall [I] Handle to the installation 664 * hRunMode [I] Checking run mode 665 * MSIRUNMODE_ADMIN Administrative mode 666 * MSIRUNMODE_ADVERTISE Advertisement mode 667 * MSIRUNMODE_MAINTENANCE Maintenance mode 668 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled 669 * MSIRUNMODE_LOGENABLED Log file is writing 670 * MSIRUNMODE_OPERATIONS Operations in progress?? 671 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed 672 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation 673 * MSIRUNMODE_CABINET Files from cabinet are installed 674 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed 675 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed 676 * MSIRUNMODE_RESERVED11 Reserved 677 * MSIRUNMODE_WINDOWS9X Running under Windows95/98 678 * MSIRUNMODE_ZAWENABLED Demand installation is supported 679 * MSIRUNMODE_RESERVED14 Reserved 680 * MSIRUNMODE_RESERVED15 Reserved 681 * MSIRUNMODE_SCHEDULED called from install script 682 * MSIRUNMODE_ROLLBACK called from rollback script 683 * MSIRUNMODE_COMMIT called from commit script 684 * 685 * RETURNS 686 * In the state: TRUE 687 * Not in the state: FALSE 688 * 689 */ 690 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode) 691 { 692 MSIPACKAGE *package; 693 BOOL r = FALSE; 694 695 TRACE("%d %d\n", hInstall, iRunMode); 696 697 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); 698 if (!package) 699 { 700 BOOL ret; 701 HRESULT hr; 702 IWineMsiRemotePackage *remote_package; 703 704 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall); 705 if (!remote_package) 706 return FALSE; 707 708 hr = IWineMsiRemotePackage_GetMode(remote_package, iRunMode, &ret); 709 IWineMsiRemotePackage_Release(remote_package); 710 711 if (hr == S_OK) 712 return ret; 713 714 return FALSE; 715 } 716 717 switch (iRunMode) 718 { 719 case MSIRUNMODE_ADMIN: 720 FIXME("no support for administrative installs\n"); 721 break; 722 723 case MSIRUNMODE_ADVERTISE: 724 FIXME("no support for advertised installs\n"); 725 break; 726 727 case MSIRUNMODE_WINDOWS9X: 728 if (GetVersion() & 0x80000000) 729 r = TRUE; 730 break; 731 732 case MSIRUNMODE_OPERATIONS: 733 case MSIRUNMODE_RESERVED11: 734 case MSIRUNMODE_RESERVED14: 735 case MSIRUNMODE_RESERVED15: 736 break; 737 738 case MSIRUNMODE_SCHEDULED: 739 r = package->scheduled_action_running; 740 break; 741 742 case MSIRUNMODE_ROLLBACK: 743 r = package->rollback_action_running; 744 break; 745 746 case MSIRUNMODE_COMMIT: 747 r = package->commit_action_running; 748 break; 749 750 case MSIRUNMODE_MAINTENANCE: 751 r = msi_get_property_int( package->db, szInstalled, 0 ) != 0; 752 break; 753 754 case MSIRUNMODE_ROLLBACKENABLED: 755 r = msi_get_property_int( package->db, szRollbackDisabled, 0 ) == 0; 756 break; 757 758 case MSIRUNMODE_REBOOTATEND: 759 r = package->need_reboot_at_end; 760 break; 761 762 case MSIRUNMODE_REBOOTNOW: 763 r = package->need_reboot_now; 764 break; 765 766 case MSIRUNMODE_LOGENABLED: 767 r = (package->log_file != INVALID_HANDLE_VALUE); 768 break; 769 770 default: 771 FIXME("unimplemented run mode: %d\n", iRunMode); 772 r = TRUE; 773 } 774 775 msiobj_release( &package->hdr ); 776 return r; 777 } 778 779 /*********************************************************************** 780 * MsiSetMode (MSI.@) 781 */ 782 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState) 783 { 784 MSIPACKAGE *package; 785 UINT r; 786 787 TRACE("%d %d %d\n", hInstall, iRunMode, fState); 788 789 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 790 if (!package) 791 { 792 HRESULT hr; 793 IWineMsiRemotePackage *remote_package; 794 795 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 796 if (!remote_package) 797 return FALSE; 798 799 hr = IWineMsiRemotePackage_SetMode( remote_package, iRunMode, fState ); 800 IWineMsiRemotePackage_Release( remote_package ); 801 802 if (FAILED(hr)) 803 { 804 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 805 return HRESULT_CODE(hr); 806 807 return ERROR_FUNCTION_FAILED; 808 } 809 810 return ERROR_SUCCESS; 811 } 812 813 switch (iRunMode) 814 { 815 case MSIRUNMODE_REBOOTATEND: 816 package->need_reboot_at_end = (fState != 0); 817 r = ERROR_SUCCESS; 818 break; 819 820 case MSIRUNMODE_REBOOTNOW: 821 package->need_reboot_now = (fState != 0); 822 r = ERROR_SUCCESS; 823 break; 824 825 default: 826 r = ERROR_ACCESS_DENIED; 827 } 828 829 msiobj_release( &package->hdr ); 830 return r; 831 } 832 833 /*********************************************************************** 834 * MsiSetFeatureStateA (MSI.@) 835 * 836 * According to the docs, when this is called it immediately recalculates 837 * all the component states as well 838 */ 839 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature, 840 INSTALLSTATE iState) 841 { 842 LPWSTR szwFeature = NULL; 843 UINT rc; 844 845 szwFeature = strdupAtoW(szFeature); 846 847 if (!szwFeature) 848 return ERROR_FUNCTION_FAILED; 849 850 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState); 851 852 msi_free(szwFeature); 853 854 return rc; 855 } 856 857 /* update component state based on a feature change */ 858 void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature ) 859 { 860 INSTALLSTATE newstate; 861 ComponentList *cl; 862 863 newstate = feature->ActionRequest; 864 if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN; 865 866 LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry) 867 { 868 MSICOMPONENT *component = cl->component; 869 870 if (!component->Enabled) continue; 871 872 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n", 873 newstate, debugstr_w(component->Component), component->Installed, 874 component->Action, component->ActionRequest); 875 876 if (newstate == INSTALLSTATE_LOCAL) 877 { 878 component->Action = INSTALLSTATE_LOCAL; 879 component->ActionRequest = INSTALLSTATE_LOCAL; 880 } 881 else 882 { 883 ComponentList *clist; 884 MSIFEATURE *f; 885 886 component->hasLocalFeature = FALSE; 887 888 component->Action = newstate; 889 component->ActionRequest = newstate; 890 /* if any other feature wants it local we need to set it local */ 891 LIST_FOR_EACH_ENTRY(f, &package->features, MSIFEATURE, entry) 892 { 893 if ( f->ActionRequest != INSTALLSTATE_LOCAL && 894 f->ActionRequest != INSTALLSTATE_SOURCE ) 895 { 896 continue; 897 } 898 LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry) 899 { 900 if (clist->component == component && 901 (f->ActionRequest == INSTALLSTATE_LOCAL || 902 f->ActionRequest == INSTALLSTATE_SOURCE)) 903 { 904 TRACE("Saved by %s\n", debugstr_w(f->Feature)); 905 component->hasLocalFeature = TRUE; 906 907 if (component->Attributes & msidbComponentAttributesOptional) 908 { 909 if (f->Attributes & msidbFeatureAttributesFavorSource) 910 { 911 component->Action = INSTALLSTATE_SOURCE; 912 component->ActionRequest = INSTALLSTATE_SOURCE; 913 } 914 else 915 { 916 component->Action = INSTALLSTATE_LOCAL; 917 component->ActionRequest = INSTALLSTATE_LOCAL; 918 } 919 } 920 else if (component->Attributes & msidbComponentAttributesSourceOnly) 921 { 922 component->Action = INSTALLSTATE_SOURCE; 923 component->ActionRequest = INSTALLSTATE_SOURCE; 924 } 925 else 926 { 927 component->Action = INSTALLSTATE_LOCAL; 928 component->ActionRequest = INSTALLSTATE_LOCAL; 929 } 930 } 931 } 932 } 933 } 934 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n", 935 newstate, debugstr_w(component->Component), component->Installed, 936 component->Action, component->ActionRequest); 937 } 938 } 939 940 UINT MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState ) 941 { 942 UINT rc = ERROR_SUCCESS; 943 MSIFEATURE *feature, *child; 944 945 TRACE("%s %i\n", debugstr_w(szFeature), iState); 946 947 feature = msi_get_loaded_feature( package, szFeature ); 948 if (!feature) 949 return ERROR_UNKNOWN_FEATURE; 950 951 if (iState == INSTALLSTATE_ADVERTISED && 952 feature->Attributes & msidbFeatureAttributesDisallowAdvertise) 953 return ERROR_FUNCTION_FAILED; 954 955 feature->ActionRequest = iState; 956 957 ACTION_UpdateComponentStates( package, feature ); 958 959 /* update all the features that are children of this feature */ 960 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry ) 961 { 962 if (child->Feature_Parent && !strcmpW( szFeature, child->Feature_Parent )) 963 MSI_SetFeatureStateW(package, child->Feature, iState); 964 } 965 966 return rc; 967 } 968 969 /*********************************************************************** 970 * MsiSetFeatureStateW (MSI.@) 971 */ 972 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature, 973 INSTALLSTATE iState) 974 { 975 MSIPACKAGE* package; 976 UINT rc = ERROR_SUCCESS; 977 978 TRACE("%s %i\n",debugstr_w(szFeature), iState); 979 980 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); 981 if (!package) 982 { 983 HRESULT hr; 984 BSTR feature; 985 IWineMsiRemotePackage *remote_package; 986 987 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall); 988 if (!remote_package) 989 return ERROR_INVALID_HANDLE; 990 991 feature = SysAllocString(szFeature); 992 if (!feature) 993 { 994 IWineMsiRemotePackage_Release(remote_package); 995 return ERROR_OUTOFMEMORY; 996 } 997 998 hr = IWineMsiRemotePackage_SetFeatureState(remote_package, feature, iState); 999 1000 SysFreeString(feature); 1001 IWineMsiRemotePackage_Release(remote_package); 1002 1003 if (FAILED(hr)) 1004 { 1005 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 1006 return HRESULT_CODE(hr); 1007 1008 return ERROR_FUNCTION_FAILED; 1009 } 1010 1011 return ERROR_SUCCESS; 1012 } 1013 1014 rc = MSI_SetFeatureStateW(package,szFeature,iState); 1015 1016 msiobj_release( &package->hdr ); 1017 return rc; 1018 } 1019 1020 /*********************************************************************** 1021 * MsiSetFeatureAttributesA (MSI.@) 1022 */ 1023 UINT WINAPI MsiSetFeatureAttributesA( MSIHANDLE handle, LPCSTR feature, DWORD attrs ) 1024 { 1025 UINT r; 1026 WCHAR *featureW = NULL; 1027 1028 TRACE("%u, %s, 0x%08x\n", handle, debugstr_a(feature), attrs); 1029 1030 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY; 1031 1032 r = MsiSetFeatureAttributesW( handle, featureW, attrs ); 1033 msi_free( featureW ); 1034 return r; 1035 } 1036 1037 static DWORD unmap_feature_attributes( DWORD attrs ) 1038 { 1039 DWORD ret = 0; 1040 1041 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORLOCAL) ret = msidbFeatureAttributesFavorLocal; 1042 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORSOURCE) ret |= msidbFeatureAttributesFavorSource; 1043 if (attrs & INSTALLFEATUREATTRIBUTE_FOLLOWPARENT) ret |= msidbFeatureAttributesFollowParent; 1044 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORADVERTISE) ret |= msidbFeatureAttributesFavorAdvertise; 1045 if (attrs & INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE) ret |= msidbFeatureAttributesDisallowAdvertise; 1046 if (attrs & INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE) ret |= msidbFeatureAttributesNoUnsupportedAdvertise; 1047 return ret; 1048 } 1049 1050 /*********************************************************************** 1051 * MsiSetFeatureAttributesW (MSI.@) 1052 */ 1053 UINT WINAPI MsiSetFeatureAttributesW( MSIHANDLE handle, LPCWSTR name, DWORD attrs ) 1054 { 1055 MSIPACKAGE *package; 1056 MSIFEATURE *feature; 1057 WCHAR *costing; 1058 1059 TRACE("%u, %s, 0x%08x\n", handle, debugstr_w(name), attrs); 1060 1061 if (!name || !name[0]) return ERROR_UNKNOWN_FEATURE; 1062 1063 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ))) 1064 return ERROR_INVALID_HANDLE; 1065 1066 costing = msi_dup_property( package->db, szCostingComplete ); 1067 if (!costing || !strcmpW( costing, szOne )) 1068 { 1069 msi_free( costing ); 1070 msiobj_release( &package->hdr ); 1071 return ERROR_FUNCTION_FAILED; 1072 } 1073 msi_free( costing ); 1074 if (!(feature = msi_get_loaded_feature( package, name ))) 1075 { 1076 msiobj_release( &package->hdr ); 1077 return ERROR_UNKNOWN_FEATURE; 1078 } 1079 feature->Attributes = unmap_feature_attributes( attrs ); 1080 msiobj_release( &package->hdr ); 1081 return ERROR_SUCCESS; 1082 } 1083 1084 /*********************************************************************** 1085 * MsiGetFeatureStateA (MSI.@) 1086 */ 1087 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature, 1088 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) 1089 { 1090 LPWSTR szwFeature = NULL; 1091 UINT rc; 1092 1093 if (szFeature && !(szwFeature = strdupAtoW(szFeature))) return ERROR_OUTOFMEMORY; 1094 1095 rc = MsiGetFeatureStateW(hInstall, szwFeature, piInstalled, piAction); 1096 msi_free( szwFeature); 1097 return rc; 1098 } 1099 1100 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature, 1101 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) 1102 { 1103 MSIFEATURE *feature; 1104 1105 feature = msi_get_loaded_feature(package,szFeature); 1106 if (!feature) 1107 return ERROR_UNKNOWN_FEATURE; 1108 1109 if (piInstalled) 1110 *piInstalled = feature->Installed; 1111 1112 if (piAction) 1113 *piAction = feature->ActionRequest; 1114 1115 TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest); 1116 1117 return ERROR_SUCCESS; 1118 } 1119 1120 /*********************************************************************** 1121 * MsiGetFeatureStateW (MSI.@) 1122 */ 1123 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature, 1124 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) 1125 { 1126 MSIPACKAGE* package; 1127 UINT ret; 1128 1129 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction); 1130 1131 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); 1132 if (!package) 1133 { 1134 HRESULT hr; 1135 BSTR feature; 1136 IWineMsiRemotePackage *remote_package; 1137 1138 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall); 1139 if (!remote_package) 1140 return ERROR_INVALID_HANDLE; 1141 1142 feature = SysAllocString(szFeature); 1143 if (!feature) 1144 { 1145 IWineMsiRemotePackage_Release(remote_package); 1146 return ERROR_OUTOFMEMORY; 1147 } 1148 1149 hr = IWineMsiRemotePackage_GetFeatureState(remote_package, feature, 1150 piInstalled, piAction); 1151 1152 SysFreeString(feature); 1153 IWineMsiRemotePackage_Release(remote_package); 1154 1155 if (FAILED(hr)) 1156 { 1157 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 1158 return HRESULT_CODE(hr); 1159 1160 return ERROR_FUNCTION_FAILED; 1161 } 1162 1163 return ERROR_SUCCESS; 1164 } 1165 1166 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction); 1167 msiobj_release( &package->hdr ); 1168 return ret; 1169 } 1170 1171 /*********************************************************************** 1172 * MsiGetFeatureCostA (MSI.@) 1173 */ 1174 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature, 1175 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost) 1176 { 1177 LPWSTR szwFeature = NULL; 1178 UINT rc; 1179 1180 szwFeature = strdupAtoW(szFeature); 1181 1182 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost); 1183 1184 msi_free(szwFeature); 1185 1186 return rc; 1187 } 1188 1189 static INT feature_cost( MSIFEATURE *feature ) 1190 { 1191 INT cost = 0; 1192 ComponentList *cl; 1193 1194 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry ) 1195 { 1196 cost += cl->component->Cost; 1197 } 1198 return cost; 1199 } 1200 1201 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree, 1202 INSTALLSTATE state, LPINT cost ) 1203 { 1204 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost); 1205 1206 *cost = 0; 1207 switch (tree) 1208 { 1209 case MSICOSTTREE_CHILDREN: 1210 { 1211 MSIFEATURE *child; 1212 1213 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry ) 1214 { 1215 if (child->ActionRequest == state) 1216 *cost += feature_cost( child ); 1217 } 1218 break; 1219 } 1220 case MSICOSTTREE_PARENTS: 1221 { 1222 const WCHAR *feature_parent = feature->Feature_Parent; 1223 for (;;) 1224 { 1225 MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent ); 1226 if (!parent) 1227 break; 1228 1229 if (parent->ActionRequest == state) 1230 *cost += feature_cost( parent ); 1231 1232 feature_parent = parent->Feature_Parent; 1233 } 1234 break; 1235 } 1236 case MSICOSTTREE_SELFONLY: 1237 if (feature->ActionRequest == state) 1238 *cost = feature_cost( feature ); 1239 break; 1240 1241 default: 1242 WARN("unhandled cost tree %u\n", tree); 1243 break; 1244 } 1245 1246 *cost /= 512; 1247 return ERROR_SUCCESS; 1248 } 1249 1250 /*********************************************************************** 1251 * MsiGetFeatureCostW (MSI.@) 1252 */ 1253 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature, 1254 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost) 1255 { 1256 MSIPACKAGE *package; 1257 MSIFEATURE *feature; 1258 UINT ret; 1259 1260 TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature), 1261 iCostTree, iState, piCost); 1262 1263 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); 1264 if (!package) 1265 { 1266 HRESULT hr; 1267 BSTR feature; 1268 IWineMsiRemotePackage *remote_package; 1269 1270 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall); 1271 if (!remote_package) 1272 return ERROR_INVALID_HANDLE; 1273 1274 feature = SysAllocString(szFeature); 1275 if (!feature) 1276 { 1277 IWineMsiRemotePackage_Release(remote_package); 1278 return ERROR_OUTOFMEMORY; 1279 } 1280 1281 hr = IWineMsiRemotePackage_GetFeatureCost(remote_package, feature, 1282 iCostTree, iState, piCost); 1283 1284 SysFreeString(feature); 1285 IWineMsiRemotePackage_Release(remote_package); 1286 1287 if (FAILED(hr)) 1288 { 1289 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 1290 return HRESULT_CODE(hr); 1291 1292 return ERROR_FUNCTION_FAILED; 1293 } 1294 1295 return ERROR_SUCCESS; 1296 } 1297 1298 feature = msi_get_loaded_feature(package, szFeature); 1299 1300 if (feature) 1301 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost); 1302 else 1303 ret = ERROR_UNKNOWN_FEATURE; 1304 1305 msiobj_release( &package->hdr ); 1306 return ret; 1307 } 1308 1309 /*********************************************************************** 1310 * MsiGetFeatureInfoA (MSI.@) 1311 */ 1312 UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, LPCSTR feature, LPDWORD attrs, 1313 LPSTR title, LPDWORD title_len, LPSTR help, LPDWORD help_len ) 1314 { 1315 UINT r; 1316 WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL; 1317 1318 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title, 1319 title_len, help, help_len); 1320 1321 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY; 1322 1323 if (title && title_len && !(titleW = msi_alloc( *title_len * sizeof(WCHAR) ))) 1324 { 1325 msi_free( featureW ); 1326 return ERROR_OUTOFMEMORY; 1327 } 1328 if (help && help_len && !(helpW = msi_alloc( *help_len * sizeof(WCHAR) ))) 1329 { 1330 msi_free( featureW ); 1331 msi_free( titleW ); 1332 return ERROR_OUTOFMEMORY; 1333 } 1334 r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len ); 1335 if (r == ERROR_SUCCESS) 1336 { 1337 if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL ); 1338 if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL ); 1339 } 1340 msi_free( titleW ); 1341 msi_free( helpW ); 1342 msi_free( featureW ); 1343 return r; 1344 } 1345 1346 static DWORD map_feature_attributes( DWORD attrs ) 1347 { 1348 DWORD ret = 0; 1349 1350 if (attrs == msidbFeatureAttributesFavorLocal) ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL; 1351 if (attrs & msidbFeatureAttributesFavorSource) ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE; 1352 if (attrs & msidbFeatureAttributesFollowParent) ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT; 1353 if (attrs & msidbFeatureAttributesFavorAdvertise) ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE; 1354 if (attrs & msidbFeatureAttributesDisallowAdvertise) ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE; 1355 if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE; 1356 return ret; 1357 } 1358 1359 static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs, 1360 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len ) 1361 { 1362 UINT r = ERROR_SUCCESS; 1363 MSIFEATURE *feature = msi_get_loaded_feature( package, name ); 1364 int len; 1365 1366 if (!feature) return ERROR_UNKNOWN_FEATURE; 1367 if (attrs) *attrs = map_feature_attributes( feature->Attributes ); 1368 if (title_len) 1369 { 1370 if (feature->Title) len = strlenW( feature->Title ); 1371 else len = 0; 1372 if (*title_len <= len) 1373 { 1374 *title_len = len; 1375 if (title) r = ERROR_MORE_DATA; 1376 } 1377 else if (title) 1378 { 1379 if (feature->Title) strcpyW( title, feature->Title ); 1380 else *title = 0; 1381 *title_len = len; 1382 } 1383 } 1384 if (help_len) 1385 { 1386 if (feature->Description) len = strlenW( feature->Description ); 1387 else len = 0; 1388 if (*help_len <= len) 1389 { 1390 *help_len = len; 1391 if (help) r = ERROR_MORE_DATA; 1392 } 1393 else if (help) 1394 { 1395 if (feature->Description) strcpyW( help, feature->Description ); 1396 else *help = 0; 1397 *help_len = len; 1398 } 1399 } 1400 return r; 1401 } 1402 1403 /*********************************************************************** 1404 * MsiGetFeatureInfoW (MSI.@) 1405 */ 1406 UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, LPCWSTR feature, LPDWORD attrs, 1407 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len ) 1408 { 1409 UINT r; 1410 MSIPACKAGE *package; 1411 1412 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title, 1413 title_len, help, help_len); 1414 1415 if (!feature) return ERROR_INVALID_PARAMETER; 1416 1417 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ))) 1418 return ERROR_INVALID_HANDLE; 1419 1420 /* features may not have been loaded yet */ 1421 msi_load_all_components( package ); 1422 msi_load_all_features( package ); 1423 1424 r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len ); 1425 msiobj_release( &package->hdr ); 1426 return r; 1427 } 1428 1429 /*********************************************************************** 1430 * MsiSetComponentStateA (MSI.@) 1431 */ 1432 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent, 1433 INSTALLSTATE iState) 1434 { 1435 UINT rc; 1436 LPWSTR szwComponent = strdupAtoW(szComponent); 1437 1438 rc = MsiSetComponentStateW(hInstall, szwComponent, iState); 1439 1440 msi_free(szwComponent); 1441 1442 return rc; 1443 } 1444 1445 /*********************************************************************** 1446 * MsiGetComponentStateA (MSI.@) 1447 */ 1448 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent, 1449 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) 1450 { 1451 LPWSTR szwComponent= NULL; 1452 UINT rc; 1453 1454 szwComponent= strdupAtoW(szComponent); 1455 1456 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction); 1457 1458 msi_free( szwComponent); 1459 1460 return rc; 1461 } 1462 1463 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent, 1464 INSTALLSTATE iState) 1465 { 1466 MSICOMPONENT *comp; 1467 1468 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState); 1469 1470 comp = msi_get_loaded_component(package, szComponent); 1471 if (!comp) 1472 return ERROR_UNKNOWN_COMPONENT; 1473 1474 if (comp->Enabled) 1475 comp->Action = iState; 1476 1477 return ERROR_SUCCESS; 1478 } 1479 1480 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent, 1481 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) 1482 { 1483 MSICOMPONENT *comp; 1484 1485 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent), 1486 piInstalled, piAction); 1487 1488 comp = msi_get_loaded_component(package,szComponent); 1489 if (!comp) 1490 return ERROR_UNKNOWN_COMPONENT; 1491 1492 if (piInstalled) 1493 { 1494 if (comp->Enabled) 1495 *piInstalled = comp->Installed; 1496 else 1497 *piInstalled = INSTALLSTATE_UNKNOWN; 1498 } 1499 1500 if (piAction) 1501 { 1502 if (comp->Enabled) 1503 *piAction = comp->Action; 1504 else 1505 *piAction = INSTALLSTATE_UNKNOWN; 1506 } 1507 1508 TRACE("states (%i, %i)\n", comp->Installed, comp->Action ); 1509 return ERROR_SUCCESS; 1510 } 1511 1512 /*********************************************************************** 1513 * MsiSetComponentStateW (MSI.@) 1514 */ 1515 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent, 1516 INSTALLSTATE iState) 1517 { 1518 MSIPACKAGE* package; 1519 UINT ret; 1520 1521 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); 1522 if (!package) 1523 { 1524 HRESULT hr; 1525 BSTR component; 1526 IWineMsiRemotePackage *remote_package; 1527 1528 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall); 1529 if (!remote_package) 1530 return ERROR_INVALID_HANDLE; 1531 1532 component = SysAllocString(szComponent); 1533 if (!component) 1534 { 1535 IWineMsiRemotePackage_Release(remote_package); 1536 return ERROR_OUTOFMEMORY; 1537 } 1538 1539 hr = IWineMsiRemotePackage_SetComponentState(remote_package, component, iState); 1540 1541 SysFreeString(component); 1542 IWineMsiRemotePackage_Release(remote_package); 1543 1544 if (FAILED(hr)) 1545 { 1546 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 1547 return HRESULT_CODE(hr); 1548 1549 return ERROR_FUNCTION_FAILED; 1550 } 1551 1552 return ERROR_SUCCESS; 1553 } 1554 1555 ret = MSI_SetComponentStateW(package, szComponent, iState); 1556 msiobj_release(&package->hdr); 1557 return ret; 1558 } 1559 1560 /*********************************************************************** 1561 * MsiGetComponentStateW (MSI.@) 1562 */ 1563 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent, 1564 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) 1565 { 1566 MSIPACKAGE* package; 1567 UINT ret; 1568 1569 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent), 1570 piInstalled, piAction); 1571 1572 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); 1573 if (!package) 1574 { 1575 HRESULT hr; 1576 BSTR component; 1577 IWineMsiRemotePackage *remote_package; 1578 1579 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall); 1580 if (!remote_package) 1581 return ERROR_INVALID_HANDLE; 1582 1583 component = SysAllocString(szComponent); 1584 if (!component) 1585 { 1586 IWineMsiRemotePackage_Release(remote_package); 1587 return ERROR_OUTOFMEMORY; 1588 } 1589 1590 hr = IWineMsiRemotePackage_GetComponentState(remote_package, component, 1591 piInstalled, piAction); 1592 1593 SysFreeString(component); 1594 IWineMsiRemotePackage_Release(remote_package); 1595 1596 if (FAILED(hr)) 1597 { 1598 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 1599 return HRESULT_CODE(hr); 1600 1601 return ERROR_FUNCTION_FAILED; 1602 } 1603 1604 return ERROR_SUCCESS; 1605 } 1606 1607 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction); 1608 msiobj_release( &package->hdr ); 1609 return ret; 1610 } 1611 1612 /*********************************************************************** 1613 * MsiGetLanguage (MSI.@) 1614 */ 1615 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall) 1616 { 1617 MSIPACKAGE* package; 1618 LANGID langid; 1619 1620 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); 1621 if (!package) 1622 { 1623 HRESULT hr; 1624 LANGID lang; 1625 IWineMsiRemotePackage *remote_package; 1626 1627 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall); 1628 if (!remote_package) 1629 return ERROR_INVALID_HANDLE; 1630 1631 hr = IWineMsiRemotePackage_GetLanguage(remote_package, &lang); 1632 1633 if (SUCCEEDED(hr)) 1634 return lang; 1635 1636 return 0; 1637 } 1638 1639 langid = msi_get_property_int( package->db, szProductLanguage, 0 ); 1640 msiobj_release( &package->hdr ); 1641 return langid; 1642 } 1643 1644 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel ) 1645 { 1646 static const WCHAR fmt[] = { '%','d',0 }; 1647 WCHAR level[6]; 1648 int len; 1649 UINT r; 1650 1651 TRACE("%p %i\n", package, iInstallLevel); 1652 1653 if (iInstallLevel > 32767) 1654 return ERROR_INVALID_PARAMETER; 1655 1656 if (iInstallLevel < 1) 1657 return MSI_SetFeatureStates( package ); 1658 1659 len = sprintfW( level, fmt, iInstallLevel ); 1660 r = msi_set_property( package->db, szInstallLevel, level, len ); 1661 if ( r == ERROR_SUCCESS ) 1662 r = MSI_SetFeatureStates( package ); 1663 1664 return r; 1665 } 1666 1667 /*********************************************************************** 1668 * MsiSetInstallLevel (MSI.@) 1669 */ 1670 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel) 1671 { 1672 MSIPACKAGE* package; 1673 UINT r; 1674 1675 TRACE("%d %i\n", hInstall, iInstallLevel); 1676 1677 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); 1678 if (!package) 1679 { 1680 HRESULT hr; 1681 IWineMsiRemotePackage *remote_package; 1682 1683 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall); 1684 if (!remote_package) 1685 return ERROR_INVALID_HANDLE; 1686 1687 hr = IWineMsiRemotePackage_SetInstallLevel(remote_package, iInstallLevel); 1688 1689 IWineMsiRemotePackage_Release(remote_package); 1690 1691 if (FAILED(hr)) 1692 { 1693 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 1694 return HRESULT_CODE(hr); 1695 1696 return ERROR_FUNCTION_FAILED; 1697 } 1698 1699 return ERROR_SUCCESS; 1700 } 1701 1702 r = MSI_SetInstallLevel( package, iInstallLevel ); 1703 1704 msiobj_release( &package->hdr ); 1705 1706 return r; 1707 } 1708 1709 /*********************************************************************** 1710 * MsiGetFeatureValidStatesW (MSI.@) 1711 */ 1712 UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature, 1713 LPDWORD pInstallState) 1714 { 1715 if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL; 1716 FIXME("%d %s %p stub returning %d\n", 1717 hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0); 1718 1719 return ERROR_SUCCESS; 1720 } 1721 1722 /*********************************************************************** 1723 * MsiGetFeatureValidStatesA (MSI.@) 1724 */ 1725 UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature, 1726 LPDWORD pInstallState) 1727 { 1728 UINT ret; 1729 LPWSTR szwFeature = strdupAtoW(szFeature); 1730 1731 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState); 1732 1733 msi_free(szwFeature); 1734 1735 return ret; 1736 } 1737