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