1 /* 2 * Implementation of the Microsoft Installer (msi.dll) 3 * 4 * Copyright 2002,2003,2004,2005 Mike McCormack 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 #include <stdarg.h> 22 23 #define COBJMACROS 24 #define NONAMELESSUNION 25 26 #include "windef.h" 27 #include "winbase.h" 28 #include "winreg.h" 29 #include "winnls.h" 30 #include "shlwapi.h" 31 #include "msi.h" 32 #include "msidefs.h" 33 #include "msiquery.h" 34 #include "wincrypt.h" 35 #include "winver.h" 36 #include "winuser.h" 37 #include "shlobj.h" 38 #include "shobjidl.h" 39 #include "objidl.h" 40 #include "wintrust.h" 41 #include "softpub.h" 42 43 #include "msipriv.h" 44 #include "winemsi_s.h" 45 46 #include "initguid.h" 47 #include "msxml2.h" 48 49 #include "wine/debug.h" 50 #include "wine/exception.h" 51 52 WINE_DEFAULT_DEBUG_CHANNEL(msi); 53 54 BOOL is_wow64; 55 56 UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context) 57 { 58 HKEY hkey = NULL; 59 60 *context = MSIINSTALLCONTEXT_NONE; 61 if (!szProduct) return ERROR_UNKNOWN_PRODUCT; 62 63 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, 64 &hkey, FALSE) == ERROR_SUCCESS) 65 *context = MSIINSTALLCONTEXT_USERMANAGED; 66 else if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, 67 &hkey, FALSE) == ERROR_SUCCESS) 68 *context = MSIINSTALLCONTEXT_MACHINE; 69 else if (MSIREG_OpenProductKey(szProduct, NULL, 70 MSIINSTALLCONTEXT_USERUNMANAGED, 71 &hkey, FALSE) == ERROR_SUCCESS) 72 *context = MSIINSTALLCONTEXT_USERUNMANAGED; 73 74 RegCloseKey(hkey); 75 76 if (*context == MSIINSTALLCONTEXT_NONE) 77 return ERROR_UNKNOWN_PRODUCT; 78 79 return ERROR_SUCCESS; 80 } 81 82 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct) 83 { 84 UINT r; 85 LPWSTR szwProd = NULL; 86 87 TRACE("%s %p\n",debugstr_a(szProduct), phProduct); 88 89 if( szProduct ) 90 { 91 szwProd = strdupAtoW( szProduct ); 92 if( !szwProd ) 93 return ERROR_OUTOFMEMORY; 94 } 95 96 r = MsiOpenProductW( szwProd, phProduct ); 97 98 msi_free( szwProd ); 99 100 return r; 101 } 102 103 static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package) 104 { 105 UINT r; 106 HKEY props; 107 LPWSTR path; 108 MSIINSTALLCONTEXT context; 109 110 TRACE("%s %p\n", debugstr_w(szProduct), package); 111 112 r = msi_locate_product(szProduct, &context); 113 if (r != ERROR_SUCCESS) 114 return r; 115 116 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &props, FALSE); 117 if (r != ERROR_SUCCESS) 118 return ERROR_UNKNOWN_PRODUCT; 119 120 if (context == MSIINSTALLCONTEXT_USERMANAGED) 121 path = msi_reg_get_val_str(props, L"ManagedLocalPackage"); 122 else 123 path = msi_reg_get_val_str(props, L"LocalPackage"); 124 125 r = ERROR_UNKNOWN_PRODUCT; 126 127 if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES) 128 goto done; 129 130 if (PathIsRelativeW(path)) 131 { 132 r = ERROR_INSTALL_PACKAGE_OPEN_FAILED; 133 goto done; 134 } 135 136 r = MSI_OpenPackageW(path, 0, package); 137 138 done: 139 RegCloseKey(props); 140 msi_free(path); 141 return r; 142 } 143 144 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct) 145 { 146 MSIPACKAGE *package = NULL; 147 WCHAR squashed_pc[SQUASHED_GUID_SIZE]; 148 UINT r; 149 150 if (!szProduct || !squash_guid( szProduct, squashed_pc )) 151 return ERROR_INVALID_PARAMETER; 152 153 if (!phProduct) 154 return ERROR_INVALID_PARAMETER; 155 156 r = MSI_OpenProductW(szProduct, &package); 157 if (r != ERROR_SUCCESS) 158 return r; 159 160 *phProduct = alloc_msihandle(&package->hdr); 161 if (!*phProduct) 162 r = ERROR_NOT_ENOUGH_MEMORY; 163 164 msiobj_release(&package->hdr); 165 return r; 166 } 167 168 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, 169 LPCSTR szTransforms, LANGID lgidLanguage) 170 { 171 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath), 172 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage); 173 return ERROR_CALL_NOT_IMPLEMENTED; 174 } 175 176 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, 177 LPCWSTR szTransforms, LANGID lgidLanguage) 178 { 179 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath), 180 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage); 181 return ERROR_CALL_NOT_IMPLEMENTED; 182 } 183 184 UINT WINAPI MsiAdvertiseProductExA( const char *szPackagePath, const char *szScriptfilePath, 185 const char *szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions ) 186 { 187 FIXME( "%s, %s, %s, %#x, %#lx, %#lx\n", debugstr_a(szPackagePath), debugstr_a(szScriptfilePath), 188 debugstr_a(szTransforms), lgidLanguage, dwPlatform, dwOptions ); 189 return ERROR_CALL_NOT_IMPLEMENTED; 190 } 191 192 UINT WINAPI MsiAdvertiseProductExW( const WCHAR *szPackagePath, const WCHAR *szScriptfilePath, 193 const WCHAR *szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions ) 194 { 195 FIXME( "%s, %s, %s, %#x %#lx %#lx\n", debugstr_w(szPackagePath), debugstr_w(szScriptfilePath), 196 debugstr_w(szTransforms), lgidLanguage, dwPlatform, dwOptions ); 197 return ERROR_CALL_NOT_IMPLEMENTED; 198 } 199 200 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine) 201 { 202 LPWSTR szwPath = NULL, szwCommand = NULL; 203 UINT r = ERROR_OUTOFMEMORY; 204 205 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine)); 206 207 if( szPackagePath ) 208 { 209 szwPath = strdupAtoW( szPackagePath ); 210 if( !szwPath ) 211 goto end; 212 } 213 214 if( szCommandLine ) 215 { 216 szwCommand = strdupAtoW( szCommandLine ); 217 if( !szwCommand ) 218 goto end; 219 } 220 221 r = MsiInstallProductW( szwPath, szwCommand ); 222 223 end: 224 msi_free( szwPath ); 225 msi_free( szwCommand ); 226 227 return r; 228 } 229 230 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine) 231 { 232 MSIPACKAGE *package = NULL; 233 const WCHAR *reinstallmode; 234 DWORD options = 0; 235 UINT r, len; 236 237 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine)); 238 239 if (!szPackagePath) 240 return ERROR_INVALID_PARAMETER; 241 242 if (!*szPackagePath) 243 return ERROR_PATH_NOT_FOUND; 244 245 reinstallmode = msi_get_command_line_option(szCommandLine, L"REINSTALLMODE", &len); 246 if (reinstallmode) 247 { 248 while (len > 0) 249 { 250 if (reinstallmode[--len] == 'v' || reinstallmode[len] == 'V') 251 { 252 options |= WINE_OPENPACKAGEFLAGS_RECACHE; 253 break; 254 } 255 } 256 } 257 258 r = MSI_OpenPackageW( szPackagePath, options, &package ); 259 if (r == ERROR_SUCCESS) 260 { 261 r = MSI_InstallPackage( package, szPackagePath, szCommandLine ); 262 msiobj_release( &package->hdr ); 263 } 264 265 return r; 266 } 267 268 UINT WINAPI MsiReinstallProductA( const char *szProduct, DWORD dwReinstallMode ) 269 { 270 WCHAR *wszProduct; 271 UINT rc; 272 273 TRACE( "%s, %#lx\n", debugstr_a(szProduct), dwReinstallMode ); 274 275 wszProduct = strdupAtoW(szProduct); 276 rc = MsiReinstallProductW(wszProduct, dwReinstallMode); 277 msi_free(wszProduct); 278 return rc; 279 } 280 281 UINT WINAPI MsiReinstallProductW( const WCHAR *szProduct, DWORD dwReinstallMode ) 282 { 283 TRACE( "%s, %#lx\n", debugstr_w(szProduct), dwReinstallMode ); 284 285 return MsiReinstallFeatureW(szProduct, L"ALL", dwReinstallMode); 286 } 287 288 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage, 289 INSTALLTYPE eInstallType, LPCSTR szCommandLine) 290 { 291 LPWSTR patch_package = NULL; 292 LPWSTR install_package = NULL; 293 LPWSTR command_line = NULL; 294 UINT r = ERROR_OUTOFMEMORY; 295 296 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage), 297 eInstallType, debugstr_a(szCommandLine)); 298 299 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage))) 300 goto done; 301 302 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage))) 303 goto done; 304 305 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine))) 306 goto done; 307 308 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line); 309 310 done: 311 msi_free(patch_package); 312 msi_free(install_package); 313 msi_free(command_line); 314 315 return r; 316 } 317 318 static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes ) 319 { 320 MSIHANDLE patch, info = 0; 321 UINT r, type; 322 DWORD size; 323 static WCHAR empty[] = L""; 324 WCHAR *codes = NULL; 325 326 r = MsiOpenDatabaseW( szPatchPackage, MSIDBOPEN_READONLY, &patch ); 327 if (r != ERROR_SUCCESS) 328 return r; 329 330 r = MsiGetSummaryInformationW( patch, NULL, 0, &info ); 331 if (r != ERROR_SUCCESS) 332 goto done; 333 334 size = 0; 335 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, empty, &size ); 336 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR) 337 { 338 ERR("Failed to read product codes from patch\n"); 339 r = ERROR_FUNCTION_FAILED; 340 goto done; 341 } 342 343 codes = msi_alloc( ++size * sizeof(WCHAR) ); 344 if (!codes) 345 { 346 r = ERROR_OUTOFMEMORY; 347 goto done; 348 } 349 350 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, codes, &size ); 351 if (r == ERROR_SUCCESS) 352 *product_codes = msi_split_string( codes, ';' ); 353 354 done: 355 MsiCloseHandle( info ); 356 MsiCloseHandle( patch ); 357 msi_free( codes ); 358 return r; 359 } 360 361 static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine) 362 { 363 UINT i, r = ERROR_FUNCTION_FAILED; 364 DWORD size; 365 LPCWSTR cmd_ptr = szCommandLine; 366 LPWSTR cmd, *codes = NULL; 367 BOOL succeeded = FALSE; 368 369 if (!szPatchPackage || !szPatchPackage[0]) 370 return ERROR_INVALID_PARAMETER; 371 372 if (!szProductCode && (r = get_patch_product_codes( szPatchPackage, &codes ))) 373 return r; 374 375 if (!szCommandLine) 376 cmd_ptr = L""; 377 378 size = lstrlenW(cmd_ptr) + lstrlenW(L"%s PATCH=\"%s\"") + lstrlenW(szPatchPackage) + 1; 379 cmd = msi_alloc(size * sizeof(WCHAR)); 380 if (!cmd) 381 { 382 msi_free(codes); 383 return ERROR_OUTOFMEMORY; 384 } 385 swprintf(cmd, size, L"%s PATCH=\"%s\"", cmd_ptr, szPatchPackage); 386 387 if (szProductCode) 388 r = MsiConfigureProductExW(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd); 389 else 390 { 391 for (i = 0; codes[i]; i++) 392 { 393 r = MsiConfigureProductExW(codes[i], INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd); 394 if (r == ERROR_SUCCESS) 395 { 396 TRACE("patch applied\n"); 397 succeeded = TRUE; 398 } 399 } 400 401 if (succeeded) 402 r = ERROR_SUCCESS; 403 } 404 405 msi_free(cmd); 406 msi_free(codes); 407 return r; 408 } 409 410 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage, 411 INSTALLTYPE eInstallType, LPCWSTR szCommandLine) 412 { 413 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage), 414 eInstallType, debugstr_w(szCommandLine)); 415 416 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE || 417 eInstallType == INSTALLTYPE_SINGLE_INSTANCE) 418 { 419 FIXME("Only reading target products from patch\n"); 420 return ERROR_CALL_NOT_IMPLEMENTED; 421 } 422 423 return MSI_ApplyPatchW(szPatchPackage, NULL, szCommandLine); 424 } 425 426 UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR szPatchPackages, 427 LPCSTR szProductCode, LPCSTR szPropertiesList) 428 { 429 LPWSTR patch_packages = NULL; 430 LPWSTR product_code = NULL; 431 LPWSTR properties_list = NULL; 432 UINT r = ERROR_OUTOFMEMORY; 433 434 TRACE("%s %s %s\n", debugstr_a(szPatchPackages), debugstr_a(szProductCode), 435 debugstr_a(szPropertiesList)); 436 437 if (!szPatchPackages || !szPatchPackages[0]) 438 return ERROR_INVALID_PARAMETER; 439 440 if (!(patch_packages = strdupAtoW(szPatchPackages))) 441 return ERROR_OUTOFMEMORY; 442 443 if (szProductCode && !(product_code = strdupAtoW(szProductCode))) 444 goto done; 445 446 if (szPropertiesList && !(properties_list = strdupAtoW(szPropertiesList))) 447 goto done; 448 449 r = MsiApplyMultiplePatchesW(patch_packages, product_code, properties_list); 450 451 done: 452 msi_free(patch_packages); 453 msi_free(product_code); 454 msi_free(properties_list); 455 456 return r; 457 } 458 459 UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages, 460 LPCWSTR szProductCode, LPCWSTR szPropertiesList) 461 { 462 UINT r = ERROR_SUCCESS; 463 LPCWSTR beg, end; 464 465 TRACE("%s %s %s\n", debugstr_w(szPatchPackages), debugstr_w(szProductCode), 466 debugstr_w(szPropertiesList)); 467 468 if (!szPatchPackages || !szPatchPackages[0]) 469 return ERROR_INVALID_PARAMETER; 470 471 beg = end = szPatchPackages; 472 while (*beg) 473 { 474 DWORD len; 475 LPWSTR patch; 476 477 while (*beg == ' ') beg++; 478 while (*end && *end != ';') end++; 479 480 len = end - beg; 481 while (len && beg[len - 1] == ' ') len--; 482 483 if (!len) return ERROR_INVALID_NAME; 484 485 patch = msi_alloc((len + 1) * sizeof(WCHAR)); 486 if (!patch) 487 return ERROR_OUTOFMEMORY; 488 489 memcpy(patch, beg, len * sizeof(WCHAR)); 490 patch[len] = '\0'; 491 492 r = MSI_ApplyPatchW(patch, szProductCode, szPropertiesList); 493 msi_free(patch); 494 495 if (r != ERROR_SUCCESS || !*end) 496 break; 497 498 beg = ++end; 499 } 500 return r; 501 } 502 503 static void free_patchinfo( DWORD count, MSIPATCHSEQUENCEINFOW *info ) 504 { 505 DWORD i; 506 for (i = 0; i < count; i++) msi_free( (WCHAR *)info[i].szPatchData ); 507 msi_free( info ); 508 } 509 510 static MSIPATCHSEQUENCEINFOW *patchinfoAtoW( DWORD count, const MSIPATCHSEQUENCEINFOA *info ) 511 { 512 DWORD i; 513 MSIPATCHSEQUENCEINFOW *ret; 514 515 if (!(ret = msi_alloc( count * sizeof(MSIPATCHSEQUENCEINFOW) ))) return NULL; 516 for (i = 0; i < count; i++) 517 { 518 if (info[i].szPatchData && !(ret[i].szPatchData = strdupAtoW( info[i].szPatchData ))) 519 { 520 free_patchinfo( i, ret ); 521 return NULL; 522 } 523 ret[i].ePatchDataType = info[i].ePatchDataType; 524 ret[i].dwOrder = info[i].dwOrder; 525 ret[i].uStatus = info[i].uStatus; 526 } 527 return ret; 528 } 529 530 UINT WINAPI MsiDetermineApplicablePatchesA( const char *szProductPackagePath, DWORD cPatchInfo, 531 MSIPATCHSEQUENCEINFOA *pPatchInfo ) 532 { 533 UINT i, r; 534 WCHAR *package_path = NULL; 535 MSIPATCHSEQUENCEINFOW *psi; 536 537 TRACE( "%s, %lu, %p\n", debugstr_a(szProductPackagePath), cPatchInfo, pPatchInfo ); 538 539 if (szProductPackagePath && !(package_path = strdupAtoW( szProductPackagePath ))) 540 return ERROR_OUTOFMEMORY; 541 542 if (!(psi = patchinfoAtoW( cPatchInfo, pPatchInfo ))) 543 { 544 msi_free( package_path ); 545 return ERROR_OUTOFMEMORY; 546 } 547 r = MsiDetermineApplicablePatchesW( package_path, cPatchInfo, psi ); 548 if (r == ERROR_SUCCESS) 549 { 550 for (i = 0; i < cPatchInfo; i++) 551 { 552 pPatchInfo[i].dwOrder = psi[i].dwOrder; 553 pPatchInfo[i].uStatus = psi[i].uStatus; 554 } 555 } 556 msi_free( package_path ); 557 free_patchinfo( cPatchInfo, psi ); 558 return r; 559 } 560 561 static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch ) 562 { 563 MSISUMMARYINFO *si; 564 MSIDATABASE *patch_db; 565 UINT r; 566 567 r = MSI_OpenDatabaseW( patch, MSIDBOPEN_READONLY, &patch_db ); 568 if (r != ERROR_SUCCESS) 569 { 570 WARN("failed to open patch file %s\n", debugstr_w(patch)); 571 return r; 572 } 573 574 r = msi_get_suminfo( patch_db->storage, 0, &si ); 575 if (r != ERROR_SUCCESS) 576 { 577 msiobj_release( &patch_db->hdr ); 578 return ERROR_FUNCTION_FAILED; 579 } 580 581 r = msi_check_patch_applicable( package, si ); 582 if (r != ERROR_SUCCESS) 583 TRACE("patch not applicable\n"); 584 585 msiobj_release( &patch_db->hdr ); 586 msiobj_release( &si->hdr ); 587 return r; 588 } 589 590 /* IXMLDOMDocument should be set to XPath mode already */ 591 static UINT MSI_ApplicablePatchXML( MSIPACKAGE *package, IXMLDOMDocument *desc ) 592 { 593 UINT r = ERROR_FUNCTION_FAILED; 594 IXMLDOMNodeList *list; 595 LPWSTR product_code; 596 IXMLDOMNode *node; 597 HRESULT hr; 598 BSTR s; 599 600 product_code = msi_dup_property( package->db, L"ProductCode" ); 601 if (!product_code) 602 { 603 /* FIXME: the property ProductCode should be written into the DB somewhere */ 604 ERR("no product code to check\n"); 605 return ERROR_SUCCESS; 606 } 607 608 s = SysAllocString( L"MsiPatch/TargetProduct/TargetProductCode" ); 609 hr = IXMLDOMDocument_selectNodes( desc, s, &list ); 610 SysFreeString(s); 611 if (hr != S_OK) 612 return ERROR_INVALID_PATCH_XML; 613 614 while (IXMLDOMNodeList_nextNode( list, &node ) == S_OK && r != ERROR_SUCCESS) 615 { 616 hr = IXMLDOMNode_get_text( node, &s ); 617 IXMLDOMNode_Release( node ); 618 if (hr == S_OK) 619 { 620 if (!wcscmp( s, product_code )) r = ERROR_SUCCESS; 621 SysFreeString( s ); 622 } 623 } 624 IXMLDOMNodeList_Release( list ); 625 626 if (r != ERROR_SUCCESS) 627 TRACE("patch not applicable\n"); 628 629 msi_free( product_code ); 630 return r; 631 } 632 633 static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCHSEQUENCEINFOW *info ) 634 { 635 IXMLDOMDocument *desc = NULL; 636 DWORD i; 637 638 if (count > 1) 639 FIXME("patch ordering not supported\n"); 640 641 for (i = 0; i < count; i++) 642 { 643 switch (info[i].ePatchDataType) 644 { 645 case MSIPATCH_DATATYPE_PATCHFILE: 646 { 647 if (MSI_ApplicablePatchW( package, info[i].szPatchData ) != ERROR_SUCCESS) 648 { 649 info[i].dwOrder = ~0u; 650 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND; 651 } 652 else 653 { 654 info[i].dwOrder = i; 655 info[i].uStatus = ERROR_SUCCESS; 656 } 657 break; 658 } 659 case MSIPATCH_DATATYPE_XMLPATH: 660 case MSIPATCH_DATATYPE_XMLBLOB: 661 { 662 VARIANT_BOOL b; 663 HRESULT hr; 664 BSTR s; 665 666 if (!desc) 667 { 668 hr = CoCreateInstance( &CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER, 669 &IID_IXMLDOMDocument, (void**)&desc ); 670 if (hr != S_OK) 671 { 672 ERR( "failed to create DOMDocument30 instance, %#lx\n", hr ); 673 return ERROR_FUNCTION_FAILED; 674 } 675 } 676 677 s = SysAllocString( info[i].szPatchData ); 678 if (info[i].ePatchDataType == MSIPATCH_DATATYPE_XMLPATH) 679 { 680 VARIANT src; 681 682 V_VT(&src) = VT_BSTR; 683 V_BSTR(&src) = s; 684 hr = IXMLDOMDocument_load( desc, src, &b ); 685 } 686 else 687 hr = IXMLDOMDocument_loadXML( desc, s, &b ); 688 SysFreeString( s ); 689 if ( hr != S_OK ) 690 { 691 ERR("failed to parse patch description\n"); 692 IXMLDOMDocument_Release( desc ); 693 break; 694 } 695 696 if (MSI_ApplicablePatchXML( package, desc ) != ERROR_SUCCESS) 697 { 698 info[i].dwOrder = ~0u; 699 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND; 700 } 701 else 702 { 703 info[i].dwOrder = i; 704 info[i].uStatus = ERROR_SUCCESS; 705 } 706 break; 707 } 708 default: 709 { 710 FIXME("unknown patch data type %u\n", info[i].ePatchDataType); 711 info[i].dwOrder = i; 712 info[i].uStatus = ERROR_SUCCESS; 713 break; 714 } 715 } 716 717 TRACE("szPatchData: %s\n", debugstr_w(info[i].szPatchData)); 718 TRACE("ePatchDataType: %u\n", info[i].ePatchDataType); 719 TRACE("dwOrder: %lu\n", info[i].dwOrder); 720 TRACE("uStatus: %u\n", info[i].uStatus); 721 } 722 723 if (desc) IXMLDOMDocument_Release( desc ); 724 725 return ERROR_SUCCESS; 726 } 727 728 UINT WINAPI MsiDetermineApplicablePatchesW( const WCHAR *szProductPackagePath, DWORD cPatchInfo, 729 MSIPATCHSEQUENCEINFOW *pPatchInfo ) 730 { 731 UINT r; 732 MSIPACKAGE *package; 733 734 TRACE( "%s, %lu, %p\n", debugstr_w(szProductPackagePath), cPatchInfo, pPatchInfo ); 735 736 r = MSI_OpenPackageW( szProductPackagePath, 0, &package ); 737 if (r != ERROR_SUCCESS) 738 { 739 ERR("failed to open package %u\n", r); 740 return r; 741 } 742 r = determine_patch_sequence( package, cPatchInfo, pPatchInfo ); 743 msiobj_release( &package->hdr ); 744 return r; 745 } 746 747 UINT WINAPI MsiDeterminePatchSequenceA( const char *product, const char *usersid, MSIINSTALLCONTEXT context, 748 DWORD count, MSIPATCHSEQUENCEINFOA *patchinfo ) 749 { 750 UINT i, r; 751 WCHAR *productW, *usersidW = NULL; 752 MSIPATCHSEQUENCEINFOW *patchinfoW; 753 754 TRACE( "%s, %s, %d, %lu, %p\n", debugstr_a(product), debugstr_a(usersid), context, count, patchinfo ); 755 756 if (!product) return ERROR_INVALID_PARAMETER; 757 if (!(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY; 758 if (usersid && !(usersidW = strdupAtoW( usersid ))) 759 { 760 msi_free( productW ); 761 return ERROR_OUTOFMEMORY; 762 } 763 if (!(patchinfoW = patchinfoAtoW( count, patchinfo ))) 764 { 765 msi_free( productW ); 766 msi_free( usersidW ); 767 return ERROR_OUTOFMEMORY; 768 } 769 r = MsiDeterminePatchSequenceW( productW, usersidW, context, count, patchinfoW ); 770 if (r == ERROR_SUCCESS) 771 { 772 for (i = 0; i < count; i++) 773 { 774 patchinfo[i].dwOrder = patchinfoW[i].dwOrder; 775 patchinfo[i].uStatus = patchinfoW[i].uStatus; 776 } 777 } 778 msi_free( productW ); 779 msi_free( usersidW ); 780 free_patchinfo( count, patchinfoW ); 781 return r; 782 } 783 784 static UINT open_package( const WCHAR *product, const WCHAR *usersid, 785 MSIINSTALLCONTEXT context, MSIPACKAGE **package ) 786 { 787 UINT r; 788 HKEY props; 789 WCHAR *localpath, sourcepath[MAX_PATH], filename[MAX_PATH]; 790 791 r = MSIREG_OpenInstallProps( product, context, usersid, &props, FALSE ); 792 if (r != ERROR_SUCCESS) return ERROR_BAD_CONFIGURATION; 793 794 if ((localpath = msi_reg_get_val_str( props, L"LocalPackage" ))) 795 { 796 lstrcpyW( sourcepath, localpath ); 797 msi_free( localpath ); 798 } 799 RegCloseKey( props ); 800 if (!localpath || GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES) 801 { 802 DWORD sz = sizeof(sourcepath); 803 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT, 804 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz ); 805 sz = sizeof(filename); 806 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT, 807 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz ); 808 lstrcatW( sourcepath, filename ); 809 } 810 if (GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES) 811 return ERROR_INSTALL_SOURCE_ABSENT; 812 813 return MSI_OpenPackageW( sourcepath, 0, package ); 814 } 815 816 UINT WINAPI MsiDeterminePatchSequenceW( const WCHAR *product, const WCHAR *usersid, MSIINSTALLCONTEXT context, 817 DWORD count, MSIPATCHSEQUENCEINFOW *patchinfo ) 818 { 819 UINT r; 820 MSIPACKAGE *package; 821 822 TRACE( "%s, %s, %d, %lu, %p\n", debugstr_w(product), debugstr_w(usersid), context, count, patchinfo ); 823 824 if (!product) return ERROR_INVALID_PARAMETER; 825 r = open_package( product, usersid, context, &package ); 826 if (r != ERROR_SUCCESS) return r; 827 828 r = determine_patch_sequence( package, count, patchinfo ); 829 msiobj_release( &package->hdr ); 830 return r; 831 } 832 833 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, 834 INSTALLSTATE eInstallState, LPCWSTR szCommandLine) 835 { 836 MSIPACKAGE* package = NULL; 837 MSIINSTALLCONTEXT context; 838 UINT r; 839 DWORD sz; 840 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH]; 841 LPWSTR commandline; 842 843 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState, 844 debugstr_w(szCommandLine)); 845 846 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1) 847 return ERROR_INVALID_PARAMETER; 848 849 if (eInstallState == INSTALLSTATE_ADVERTISED || 850 eInstallState == INSTALLSTATE_SOURCE) 851 { 852 FIXME("State %d not implemented\n", eInstallState); 853 return ERROR_CALL_NOT_IMPLEMENTED; 854 } 855 856 r = msi_locate_product(szProduct, &context); 857 if (r != ERROR_SUCCESS) 858 return r; 859 860 r = open_package(szProduct, NULL, context, &package); 861 if (r != ERROR_SUCCESS) 862 return r; 863 864 sz = lstrlenW(L" Installed=1") + 1; 865 866 if (szCommandLine) 867 sz += lstrlenW(szCommandLine); 868 869 if (eInstallState != INSTALLSTATE_DEFAULT) 870 sz += lstrlenW(L" INSTALLLEVEL=32767"); 871 872 if (eInstallState == INSTALLSTATE_ABSENT) 873 sz += lstrlenW(L" REMOVE=ALL"); 874 875 if (context == MSIINSTALLCONTEXT_MACHINE) 876 sz += lstrlenW(L" ALLUSERS=1"); 877 878 commandline = msi_alloc(sz * sizeof(WCHAR)); 879 if (!commandline) 880 { 881 r = ERROR_OUTOFMEMORY; 882 goto end; 883 } 884 885 commandline[0] = 0; 886 if (szCommandLine) 887 lstrcpyW(commandline, szCommandLine); 888 889 if (eInstallState != INSTALLSTATE_DEFAULT) 890 lstrcatW(commandline, L" INSTALLLEVEL=32767"); 891 892 if (eInstallState == INSTALLSTATE_ABSENT) 893 lstrcatW(commandline, L" REMOVE=ALL"); 894 895 if (context == MSIINSTALLCONTEXT_MACHINE) 896 lstrcatW(commandline, L" ALLUSERS=1"); 897 898 sz = sizeof(sourcepath); 899 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT, 900 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); 901 902 sz = sizeof(filename); 903 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT, 904 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); 905 906 lstrcatW(sourcepath, filename); 907 908 r = MSI_InstallPackage( package, sourcepath, commandline ); 909 910 msi_free(commandline); 911 912 end: 913 msiobj_release( &package->hdr ); 914 915 return r; 916 } 917 918 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel, 919 INSTALLSTATE eInstallState, LPCSTR szCommandLine) 920 { 921 LPWSTR szwProduct = NULL; 922 LPWSTR szwCommandLine = NULL; 923 UINT r = ERROR_OUTOFMEMORY; 924 925 if( szProduct ) 926 { 927 szwProduct = strdupAtoW( szProduct ); 928 if( !szwProduct ) 929 goto end; 930 } 931 932 if( szCommandLine) 933 { 934 szwCommandLine = strdupAtoW( szCommandLine ); 935 if( !szwCommandLine) 936 goto end; 937 } 938 939 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState, 940 szwCommandLine ); 941 end: 942 msi_free( szwProduct ); 943 msi_free( szwCommandLine); 944 945 return r; 946 } 947 948 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, 949 INSTALLSTATE eInstallState) 950 { 951 LPWSTR szwProduct = NULL; 952 UINT r; 953 954 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState); 955 956 if( szProduct ) 957 { 958 szwProduct = strdupAtoW( szProduct ); 959 if( !szwProduct ) 960 return ERROR_OUTOFMEMORY; 961 } 962 963 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState ); 964 msi_free( szwProduct ); 965 966 return r; 967 } 968 969 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, 970 INSTALLSTATE eInstallState) 971 { 972 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL); 973 } 974 975 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer) 976 { 977 LPWSTR szwComponent = NULL; 978 UINT r; 979 WCHAR szwBuffer[GUID_SIZE]; 980 981 TRACE("%s %p\n", debugstr_a(szComponent), szBuffer); 982 983 if( szComponent ) 984 { 985 szwComponent = strdupAtoW( szComponent ); 986 if( !szwComponent ) 987 return ERROR_OUTOFMEMORY; 988 } 989 990 *szwBuffer = '\0'; 991 r = MsiGetProductCodeW( szwComponent, szwBuffer ); 992 993 if(*szwBuffer) 994 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL); 995 996 msi_free( szwComponent ); 997 998 return r; 999 } 1000 1001 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer) 1002 { 1003 UINT rc, index; 1004 HKEY compkey, prodkey; 1005 WCHAR squashed_comp[SQUASHED_GUID_SIZE], squashed_prod[SQUASHED_GUID_SIZE]; 1006 DWORD sz = ARRAY_SIZE(squashed_prod); 1007 1008 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer); 1009 1010 if (!szComponent || !*szComponent) 1011 return ERROR_INVALID_PARAMETER; 1012 1013 if (!squash_guid( szComponent, squashed_comp )) 1014 return ERROR_INVALID_PARAMETER; 1015 1016 if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &compkey, FALSE) != ERROR_SUCCESS && 1017 MSIREG_OpenUserDataComponentKey(szComponent, L"S-1-5-18", &compkey, FALSE) != ERROR_SUCCESS) 1018 { 1019 return ERROR_UNKNOWN_COMPONENT; 1020 } 1021 1022 rc = RegEnumValueW( compkey, 0, squashed_prod, &sz, NULL, NULL, NULL, NULL ); 1023 if (rc != ERROR_SUCCESS) 1024 { 1025 RegCloseKey(compkey); 1026 return ERROR_UNKNOWN_COMPONENT; 1027 } 1028 1029 /* check simple case, only one product */ 1030 rc = RegEnumValueW( compkey, 1, squashed_prod, &sz, NULL, NULL, NULL, NULL ); 1031 if (rc == ERROR_NO_MORE_ITEMS) 1032 { 1033 rc = ERROR_SUCCESS; 1034 goto done; 1035 } 1036 1037 index = 0; 1038 while ((rc = RegEnumValueW( compkey, index, squashed_prod, &sz, NULL, NULL, NULL, NULL )) != 1039 ERROR_NO_MORE_ITEMS) 1040 { 1041 index++; 1042 sz = GUID_SIZE; 1043 unsquash_guid( squashed_prod, szBuffer ); 1044 1045 if (MSIREG_OpenProductKey(szBuffer, NULL, 1046 MSIINSTALLCONTEXT_USERMANAGED, 1047 &prodkey, FALSE) == ERROR_SUCCESS || 1048 MSIREG_OpenProductKey(szBuffer, NULL, 1049 MSIINSTALLCONTEXT_USERUNMANAGED, 1050 &prodkey, FALSE) == ERROR_SUCCESS || 1051 MSIREG_OpenProductKey(szBuffer, NULL, 1052 MSIINSTALLCONTEXT_MACHINE, 1053 &prodkey, FALSE) == ERROR_SUCCESS) 1054 { 1055 RegCloseKey(prodkey); 1056 rc = ERROR_SUCCESS; 1057 goto done; 1058 } 1059 } 1060 1061 rc = ERROR_INSTALL_FAILURE; 1062 1063 done: 1064 RegCloseKey(compkey); 1065 unsquash_guid( squashed_prod, szBuffer ); 1066 return rc; 1067 } 1068 1069 static WCHAR *reg_get_value( HKEY hkey, const WCHAR *name, DWORD *type ) 1070 { 1071 LONG res; 1072 1073 if ((res = RegQueryValueExW( hkey, name, NULL, type, NULL, NULL )) != ERROR_SUCCESS) return NULL; 1074 1075 if (*type == REG_SZ) return msi_reg_get_val_str( hkey, name ); 1076 if (*type == REG_DWORD) 1077 { 1078 WCHAR temp[11]; 1079 DWORD val; 1080 1081 if (!msi_reg_get_val_dword( hkey, name, &val )) return NULL; 1082 swprintf( temp, ARRAY_SIZE(temp), L"%u", val ); 1083 return strdupW( temp ); 1084 } 1085 1086 ERR( "unhandled value type %lu\n", *type ); 1087 return NULL; 1088 } 1089 1090 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, 1091 awstring *szValue, LPDWORD pcchValueBuf) 1092 { 1093 static WCHAR empty[] = L""; 1094 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED; 1095 UINT r = ERROR_UNKNOWN_PROPERTY; 1096 HKEY prodkey, userdata, source; 1097 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE], packagecode[GUID_SIZE]; 1098 BOOL badconfig = FALSE; 1099 LONG res; 1100 DWORD type = REG_NONE; 1101 1102 TRACE("%s %s %p %p\n", debugstr_w(szProduct), 1103 debugstr_w(szAttribute), szValue, pcchValueBuf); 1104 1105 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute) 1106 return ERROR_INVALID_PARAMETER; 1107 1108 if (!squash_guid( szProduct, squashed_pc )) 1109 return ERROR_INVALID_PARAMETER; 1110 1111 if ((r = MSIREG_OpenProductKey(szProduct, NULL, 1112 MSIINSTALLCONTEXT_USERMANAGED, 1113 &prodkey, FALSE)) != ERROR_SUCCESS && 1114 (r = MSIREG_OpenProductKey(szProduct, NULL, 1115 MSIINSTALLCONTEXT_USERUNMANAGED, 1116 &prodkey, FALSE)) != ERROR_SUCCESS && 1117 (r = MSIREG_OpenProductKey(szProduct, NULL, 1118 MSIINSTALLCONTEXT_MACHINE, 1119 &prodkey, FALSE)) == ERROR_SUCCESS) 1120 { 1121 context = MSIINSTALLCONTEXT_MACHINE; 1122 } 1123 1124 if (!wcscmp( szAttribute, INSTALLPROPERTY_HELPLINKW ) || 1125 !wcscmp( szAttribute, INSTALLPROPERTY_HELPTELEPHONEW ) || 1126 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLDATEW ) || 1127 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) || 1128 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW ) || 1129 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLSOURCEW ) || 1130 !wcscmp( szAttribute, INSTALLPROPERTY_LOCALPACKAGEW ) || 1131 !wcscmp( szAttribute, INSTALLPROPERTY_PUBLISHERW ) || 1132 !wcscmp( szAttribute, INSTALLPROPERTY_URLINFOABOUTW ) || 1133 !wcscmp( szAttribute, INSTALLPROPERTY_URLUPDATEINFOW ) || 1134 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONMINORW ) || 1135 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONMAJORW ) || 1136 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ) || 1137 !wcscmp( szAttribute, INSTALLPROPERTY_PRODUCTIDW ) || 1138 !wcscmp( szAttribute, INSTALLPROPERTY_REGCOMPANYW ) || 1139 !wcscmp( szAttribute, INSTALLPROPERTY_REGOWNERW )) 1140 { 1141 if (!prodkey) 1142 { 1143 r = ERROR_UNKNOWN_PRODUCT; 1144 goto done; 1145 } 1146 if (MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE)) 1147 { 1148 r = ERROR_UNKNOWN_PROPERTY; 1149 goto done; 1150 } 1151 1152 if (!wcscmp( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW )) 1153 szAttribute = L"DisplayName"; 1154 else if (!wcscmp( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW )) 1155 szAttribute = L"DisplayVersion"; 1156 1157 val = reg_get_value(userdata, szAttribute, &type); 1158 if (!val) 1159 val = empty; 1160 RegCloseKey(userdata); 1161 } 1162 else if (!wcscmp( szAttribute, INSTALLPROPERTY_INSTANCETYPEW ) || 1163 !wcscmp( szAttribute, INSTALLPROPERTY_TRANSFORMSW ) || 1164 !wcscmp( szAttribute, INSTALLPROPERTY_LANGUAGEW ) || 1165 !wcscmp( szAttribute, INSTALLPROPERTY_PRODUCTNAMEW ) || 1166 !wcscmp( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ) || 1167 !wcscmp( szAttribute, INSTALLPROPERTY_PACKAGECODEW ) || 1168 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONW ) || 1169 !wcscmp( szAttribute, INSTALLPROPERTY_PRODUCTICONW ) || 1170 !wcscmp( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ) || 1171 !wcscmp( szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW )) 1172 { 1173 if (!prodkey) 1174 { 1175 r = ERROR_UNKNOWN_PRODUCT; 1176 goto done; 1177 } 1178 1179 if (!wcscmp( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW )) 1180 szAttribute = L"Assignment"; 1181 1182 if (!wcscmp( szAttribute, INSTALLPROPERTY_PACKAGENAMEW )) 1183 { 1184 res = RegOpenKeyW(prodkey, L"SourceList", &source); 1185 if (res != ERROR_SUCCESS) 1186 { 1187 r = ERROR_UNKNOWN_PRODUCT; 1188 goto done; 1189 } 1190 1191 val = reg_get_value(source, szAttribute, &type); 1192 if (!val) 1193 val = empty; 1194 1195 RegCloseKey(source); 1196 } 1197 else 1198 { 1199 val = reg_get_value(prodkey, szAttribute, &type); 1200 if (!val) 1201 val = empty; 1202 } 1203 1204 if (val != empty && type != REG_DWORD && 1205 !wcscmp( szAttribute, INSTALLPROPERTY_PACKAGECODEW )) 1206 { 1207 if (lstrlenW( val ) != SQUASHED_GUID_SIZE - 1) 1208 badconfig = TRUE; 1209 else 1210 { 1211 unsquash_guid(val, packagecode); 1212 msi_free(val); 1213 val = strdupW(packagecode); 1214 } 1215 } 1216 } 1217 1218 if (!val) 1219 { 1220 r = ERROR_UNKNOWN_PROPERTY; 1221 goto done; 1222 } 1223 1224 if (pcchValueBuf) 1225 { 1226 int len = lstrlenW( val ); 1227 1228 /* If szBuffer (szValue->str) is NULL, there's no need to copy the value 1229 * out. Also, *pcchValueBuf may be uninitialized in this case, so we 1230 * can't rely on its value. 1231 */ 1232 if (szValue->str.a || szValue->str.w) 1233 { 1234 DWORD size = *pcchValueBuf; 1235 if (len < size) 1236 r = msi_strcpy_to_awstring( val, len, szValue, &size ); 1237 else 1238 r = ERROR_MORE_DATA; 1239 } 1240 1241 if (!badconfig) 1242 *pcchValueBuf = len; 1243 } 1244 1245 if (badconfig) 1246 r = ERROR_BAD_CONFIGURATION; 1247 1248 if (val != empty) 1249 msi_free(val); 1250 1251 done: 1252 RegCloseKey(prodkey); 1253 return r; 1254 } 1255 1256 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, 1257 LPSTR szBuffer, LPDWORD pcchValueBuf) 1258 { 1259 LPWSTR szwProduct, szwAttribute = NULL; 1260 UINT r = ERROR_OUTOFMEMORY; 1261 awstring buffer; 1262 1263 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute), 1264 szBuffer, pcchValueBuf); 1265 1266 szwProduct = strdupAtoW( szProduct ); 1267 if( szProduct && !szwProduct ) 1268 goto end; 1269 1270 szwAttribute = strdupAtoW( szAttribute ); 1271 if( szAttribute && !szwAttribute ) 1272 goto end; 1273 1274 buffer.unicode = FALSE; 1275 buffer.str.a = szBuffer; 1276 1277 r = MSI_GetProductInfo( szwProduct, szwAttribute, 1278 &buffer, pcchValueBuf ); 1279 1280 end: 1281 msi_free( szwProduct ); 1282 msi_free( szwAttribute ); 1283 1284 return r; 1285 } 1286 1287 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, 1288 LPWSTR szBuffer, LPDWORD pcchValueBuf) 1289 { 1290 awstring buffer; 1291 1292 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute), 1293 szBuffer, pcchValueBuf); 1294 1295 buffer.unicode = TRUE; 1296 buffer.str.w = szBuffer; 1297 1298 return MSI_GetProductInfo( szProduct, szAttribute, 1299 &buffer, pcchValueBuf ); 1300 } 1301 1302 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid, 1303 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty, 1304 LPSTR szValue, LPDWORD pcchValue) 1305 { 1306 LPWSTR product = NULL; 1307 LPWSTR usersid = NULL; 1308 LPWSTR property = NULL; 1309 LPWSTR value = NULL; 1310 DWORD len = 0; 1311 UINT r; 1312 1313 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode), 1314 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty), 1315 szValue, pcchValue); 1316 1317 if (szValue && !pcchValue) 1318 return ERROR_INVALID_PARAMETER; 1319 1320 if (szProductCode) product = strdupAtoW(szProductCode); 1321 if (szUserSid) usersid = strdupAtoW(szUserSid); 1322 if (szProperty) property = strdupAtoW(szProperty); 1323 1324 r = MsiGetProductInfoExW(product, usersid, dwContext, property, 1325 NULL, &len); 1326 if (r != ERROR_SUCCESS) 1327 goto done; 1328 1329 value = msi_alloc(++len * sizeof(WCHAR)); 1330 if (!value) 1331 { 1332 r = ERROR_OUTOFMEMORY; 1333 goto done; 1334 } 1335 1336 r = MsiGetProductInfoExW(product, usersid, dwContext, property, 1337 value, &len); 1338 if (r != ERROR_SUCCESS) 1339 goto done; 1340 1341 if (!pcchValue) 1342 goto done; 1343 1344 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL); 1345 if (*pcchValue >= len) 1346 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL); 1347 else if (szValue) 1348 { 1349 r = ERROR_MORE_DATA; 1350 if (*pcchValue > 0) 1351 *szValue = '\0'; 1352 } 1353 1354 if (*pcchValue <= len || !szValue) 1355 len = len * sizeof(WCHAR) - 1; 1356 1357 *pcchValue = len - 1; 1358 1359 done: 1360 msi_free(product); 1361 msi_free(usersid); 1362 msi_free(property); 1363 msi_free(value); 1364 1365 return r; 1366 } 1367 1368 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size) 1369 { 1370 UINT r = ERROR_SUCCESS; 1371 1372 if (!val) 1373 return ERROR_UNKNOWN_PROPERTY; 1374 1375 if (out) 1376 { 1377 if (lstrlenW(val) >= *size) 1378 { 1379 r = ERROR_MORE_DATA; 1380 if (*size > 0) 1381 *out = '\0'; 1382 } 1383 else 1384 lstrcpyW(out, val); 1385 } 1386 1387 if (size) 1388 *size = lstrlenW(val); 1389 1390 return r; 1391 } 1392 1393 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid, 1394 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty, 1395 LPWSTR szValue, LPDWORD pcchValue) 1396 { 1397 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE]; 1398 LPCWSTR package = NULL; 1399 HKEY props = NULL, prod, classes = NULL, managed, hkey = NULL; 1400 DWORD type; 1401 UINT r = ERROR_UNKNOWN_PRODUCT; 1402 1403 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode), 1404 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty), 1405 szValue, pcchValue); 1406 1407 if (!szProductCode || !squash_guid( szProductCode, squashed_pc )) 1408 return ERROR_INVALID_PARAMETER; 1409 1410 if (szValue && !pcchValue) 1411 return ERROR_INVALID_PARAMETER; 1412 1413 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED && 1414 dwContext != MSIINSTALLCONTEXT_USERMANAGED && 1415 dwContext != MSIINSTALLCONTEXT_MACHINE) 1416 return ERROR_INVALID_PARAMETER; 1417 1418 if (!szProperty || !*szProperty) 1419 return ERROR_INVALID_PARAMETER; 1420 1421 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid) 1422 return ERROR_INVALID_PARAMETER; 1423 1424 /* FIXME: dwContext is provided, no need to search for it */ 1425 MSIREG_OpenProductKey(szProductCode, NULL,MSIINSTALLCONTEXT_USERMANAGED, 1426 &managed, FALSE); 1427 MSIREG_OpenProductKey(szProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 1428 &prod, FALSE); 1429 1430 MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE); 1431 1432 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED) 1433 { 1434 package = INSTALLPROPERTY_LOCALPACKAGEW; 1435 1436 if (!props && !prod) 1437 goto done; 1438 } 1439 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED) 1440 { 1441 package = L"ManagedLocalPackage"; 1442 1443 if (!props && !managed) 1444 goto done; 1445 } 1446 else if (dwContext == MSIINSTALLCONTEXT_MACHINE) 1447 { 1448 package = INSTALLPROPERTY_LOCALPACKAGEW; 1449 MSIREG_OpenProductKey(szProductCode, NULL, dwContext, &classes, FALSE); 1450 1451 if (!props && !classes) 1452 goto done; 1453 } 1454 1455 if (!wcscmp( szProperty, INSTALLPROPERTY_HELPLINKW ) || 1456 !wcscmp( szProperty, INSTALLPROPERTY_HELPTELEPHONEW ) || 1457 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLDATEW ) || 1458 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) || 1459 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLLOCATIONW ) || 1460 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLSOURCEW ) || 1461 !wcscmp( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ) || 1462 !wcscmp( szProperty, INSTALLPROPERTY_PUBLISHERW ) || 1463 !wcscmp( szProperty, INSTALLPROPERTY_URLINFOABOUTW ) || 1464 !wcscmp( szProperty, INSTALLPROPERTY_URLUPDATEINFOW ) || 1465 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONMINORW ) || 1466 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONMAJORW ) || 1467 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ) || 1468 !wcscmp( szProperty, INSTALLPROPERTY_PRODUCTIDW ) || 1469 !wcscmp( szProperty, INSTALLPROPERTY_REGCOMPANYW ) || 1470 !wcscmp( szProperty, INSTALLPROPERTY_REGOWNERW ) || 1471 !wcscmp( szProperty, INSTALLPROPERTY_INSTANCETYPEW )) 1472 { 1473 val = reg_get_value(props, package, &type); 1474 if (!val) 1475 { 1476 if (prod || classes) 1477 r = ERROR_UNKNOWN_PROPERTY; 1478 1479 goto done; 1480 } 1481 1482 msi_free(val); 1483 1484 if (!wcscmp( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW )) 1485 szProperty = L"DisplayName"; 1486 else if (!wcscmp( szProperty, INSTALLPROPERTY_VERSIONSTRINGW )) 1487 szProperty = L"DisplayVersion"; 1488 1489 val = reg_get_value(props, szProperty, &type); 1490 if (!val) 1491 val = strdupW(L""); 1492 1493 r = msi_copy_outval(val, szValue, pcchValue); 1494 } 1495 else if (!wcscmp( szProperty, INSTALLPROPERTY_TRANSFORMSW ) || 1496 !wcscmp( szProperty, INSTALLPROPERTY_LANGUAGEW ) || 1497 !wcscmp( szProperty, INSTALLPROPERTY_PRODUCTNAMEW ) || 1498 !wcscmp( szProperty, INSTALLPROPERTY_PACKAGECODEW ) || 1499 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONW ) || 1500 !wcscmp( szProperty, INSTALLPROPERTY_PRODUCTICONW ) || 1501 !wcscmp( szProperty, INSTALLPROPERTY_PACKAGENAMEW ) || 1502 !wcscmp( szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW )) 1503 { 1504 if (!prod && !classes) 1505 goto done; 1506 1507 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED) 1508 hkey = prod; 1509 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED) 1510 hkey = managed; 1511 else if (dwContext == MSIINSTALLCONTEXT_MACHINE) 1512 hkey = classes; 1513 1514 val = reg_get_value(hkey, szProperty, &type); 1515 if (!val) 1516 val = strdupW(L""); 1517 1518 r = msi_copy_outval(val, szValue, pcchValue); 1519 } 1520 else if (!wcscmp( szProperty, INSTALLPROPERTY_PRODUCTSTATEW )) 1521 { 1522 if (dwContext == MSIINSTALLCONTEXT_MACHINE) 1523 { 1524 if (props) 1525 { 1526 val = reg_get_value(props, package, &type); 1527 if (!val) 1528 goto done; 1529 1530 msi_free(val); 1531 val = strdupW(L"5"); 1532 } 1533 else 1534 val = strdupW(L"1"); 1535 1536 r = msi_copy_outval(val, szValue, pcchValue); 1537 goto done; 1538 } 1539 else if (props && (val = reg_get_value(props, package, &type))) 1540 { 1541 msi_free(val); 1542 val = strdupW(L"5"); 1543 r = msi_copy_outval(val, szValue, pcchValue); 1544 goto done; 1545 } 1546 1547 if (prod || managed) 1548 val = strdupW(L"1"); 1549 else 1550 goto done; 1551 1552 r = msi_copy_outval(val, szValue, pcchValue); 1553 } 1554 else if (!wcscmp( szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW )) 1555 { 1556 if (!prod && !classes) 1557 goto done; 1558 1559 /* FIXME */ 1560 val = strdupW(L""); 1561 r = msi_copy_outval(val, szValue, pcchValue); 1562 } 1563 else 1564 r = ERROR_UNKNOWN_PROPERTY; 1565 1566 done: 1567 RegCloseKey(props); 1568 RegCloseKey(prod); 1569 RegCloseKey(managed); 1570 RegCloseKey(classes); 1571 msi_free(val); 1572 1573 return r; 1574 } 1575 1576 UINT WINAPI MsiGetPatchFileListA(LPCSTR szProductCode, LPCSTR szPatchList, 1577 LPDWORD pcFiles, MSIHANDLE **pphFileRecords) 1578 { 1579 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_a(szProductCode), 1580 debugstr_a(szPatchList), pcFiles, pphFileRecords); 1581 return ERROR_FUNCTION_FAILED; 1582 } 1583 1584 UINT WINAPI MsiGetPatchFileListW(LPCWSTR szProductCode, LPCWSTR szPatchList, 1585 LPDWORD pcFiles, MSIHANDLE **pphFileRecords) 1586 { 1587 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_w(szProductCode), 1588 debugstr_w(szPatchList), pcFiles, pphFileRecords); 1589 return ERROR_FUNCTION_FAILED; 1590 } 1591 1592 UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode, 1593 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, 1594 LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue) 1595 { 1596 LPWSTR patch = NULL, product = NULL, usersid = NULL; 1597 LPWSTR property = NULL, val = NULL; 1598 DWORD len; 1599 UINT r; 1600 1601 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode), 1602 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext, 1603 debugstr_a(szProperty), lpValue, pcchValue); 1604 1605 if (lpValue && !pcchValue) 1606 return ERROR_INVALID_PARAMETER; 1607 1608 if (szPatchCode) patch = strdupAtoW(szPatchCode); 1609 if (szProductCode) product = strdupAtoW(szProductCode); 1610 if (szUserSid) usersid = strdupAtoW(szUserSid); 1611 if (szProperty) property = strdupAtoW(szProperty); 1612 1613 len = 0; 1614 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property, 1615 NULL, &len); 1616 if (r != ERROR_SUCCESS) 1617 goto done; 1618 1619 val = msi_alloc(++len * sizeof(WCHAR)); 1620 if (!val) 1621 { 1622 r = ERROR_OUTOFMEMORY; 1623 goto done; 1624 } 1625 1626 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property, 1627 val, &len); 1628 if (r != ERROR_SUCCESS || !pcchValue) 1629 goto done; 1630 1631 if (lpValue) 1632 WideCharToMultiByte(CP_ACP, 0, val, -1, lpValue, 1633 *pcchValue - 1, NULL, NULL); 1634 1635 len = lstrlenW(val); 1636 if ((*val && *pcchValue < len + 1) || !lpValue) 1637 { 1638 if (lpValue) 1639 { 1640 r = ERROR_MORE_DATA; 1641 lpValue[*pcchValue - 1] = '\0'; 1642 } 1643 1644 *pcchValue = len * sizeof(WCHAR); 1645 } 1646 else 1647 *pcchValue = len; 1648 1649 done: 1650 msi_free(val); 1651 msi_free(patch); 1652 msi_free(product); 1653 msi_free(usersid); 1654 msi_free(property); 1655 1656 return r; 1657 } 1658 1659 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode, 1660 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext, 1661 LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue) 1662 { 1663 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE], squashed_patch[SQUASHED_GUID_SIZE]; 1664 HKEY udprod = 0, prod = 0, props = 0; 1665 HKEY patch = 0, patches = 0; 1666 HKEY udpatch = 0, datakey = 0; 1667 HKEY prodpatches = 0; 1668 UINT r = ERROR_UNKNOWN_PRODUCT; 1669 DWORD len, type; 1670 LONG res; 1671 1672 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode), 1673 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext, 1674 debugstr_w(szProperty), lpValue, pcchValue); 1675 1676 if (!szProductCode || !squash_guid( szProductCode, squashed_pc )) 1677 return ERROR_INVALID_PARAMETER; 1678 1679 if (!szPatchCode || !squash_guid( szPatchCode, squashed_patch )) 1680 return ERROR_INVALID_PARAMETER; 1681 1682 if (!szProperty) 1683 return ERROR_INVALID_PARAMETER; 1684 1685 if (lpValue && !pcchValue) 1686 return ERROR_INVALID_PARAMETER; 1687 1688 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED && 1689 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED && 1690 dwContext != MSIINSTALLCONTEXT_MACHINE) 1691 return ERROR_INVALID_PARAMETER; 1692 1693 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid) 1694 return ERROR_INVALID_PARAMETER; 1695 1696 if (szUserSid && !wcscmp( szUserSid, L"S-1-5-18" )) 1697 return ERROR_INVALID_PARAMETER; 1698 1699 if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL, 1700 &udprod, FALSE) != ERROR_SUCCESS) 1701 goto done; 1702 1703 if (MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, 1704 &props, FALSE) != ERROR_SUCCESS) 1705 goto done; 1706 1707 r = ERROR_UNKNOWN_PATCH; 1708 1709 res = RegOpenKeyExW(udprod, L"Patches", 0, KEY_READ, &patches); 1710 if (res != ERROR_SUCCESS) 1711 goto done; 1712 1713 res = RegOpenKeyExW( patches, squashed_patch, 0, KEY_READ, &patch ); 1714 if (res != ERROR_SUCCESS) 1715 goto done; 1716 1717 if (!wcscmp( szProperty, INSTALLPROPERTY_TRANSFORMSW )) 1718 { 1719 if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext, 1720 &prod, FALSE) != ERROR_SUCCESS) 1721 goto done; 1722 1723 res = RegOpenKeyExW(prod, L"Patches", 0, KEY_ALL_ACCESS, &prodpatches); 1724 if (res != ERROR_SUCCESS) 1725 goto done; 1726 1727 datakey = prodpatches; 1728 szProperty = squashed_patch; 1729 } 1730 else 1731 { 1732 if (MSIREG_OpenUserDataPatchKey(szPatchCode, dwContext, 1733 &udpatch, FALSE) != ERROR_SUCCESS) 1734 goto done; 1735 1736 if (!wcscmp( szProperty, INSTALLPROPERTY_LOCALPACKAGEW )) 1737 { 1738 if (dwContext == MSIINSTALLCONTEXT_USERMANAGED) 1739 szProperty = L"ManagedLocalPackage"; 1740 datakey = udpatch; 1741 } 1742 else if (!wcscmp( szProperty, INSTALLPROPERTY_INSTALLDATEW )) 1743 { 1744 datakey = patch; 1745 szProperty = L"Installed"; 1746 } 1747 else if (!wcscmp( szProperty, INSTALLPROPERTY_UNINSTALLABLEW ) || 1748 !wcscmp( szProperty, INSTALLPROPERTY_PATCHSTATEW ) || 1749 !wcscmp( szProperty, INSTALLPROPERTY_DISPLAYNAMEW ) || 1750 !wcscmp( szProperty, INSTALLPROPERTY_MOREINFOURLW )) 1751 { 1752 datakey = patch; 1753 } 1754 else 1755 { 1756 r = ERROR_UNKNOWN_PROPERTY; 1757 goto done; 1758 } 1759 } 1760 1761 val = reg_get_value(datakey, szProperty, &type); 1762 if (!val) 1763 val = strdupW(L""); 1764 1765 r = ERROR_SUCCESS; 1766 1767 if (!pcchValue) 1768 goto done; 1769 1770 if (lpValue) 1771 lstrcpynW(lpValue, val, *pcchValue); 1772 1773 len = lstrlenW(val); 1774 if ((*val && *pcchValue < len + 1) || !lpValue) 1775 { 1776 if (lpValue) 1777 r = ERROR_MORE_DATA; 1778 1779 *pcchValue = len * sizeof(WCHAR); 1780 } 1781 1782 *pcchValue = len; 1783 1784 done: 1785 msi_free(val); 1786 RegCloseKey(prodpatches); 1787 RegCloseKey(prod); 1788 RegCloseKey(patch); 1789 RegCloseKey(patches); 1790 RegCloseKey(udpatch); 1791 RegCloseKey(props); 1792 RegCloseKey(udprod); 1793 1794 return r; 1795 } 1796 1797 UINT WINAPI MsiGetPatchInfoA( LPCSTR patch, LPCSTR attr, LPSTR buffer, LPDWORD buflen ) 1798 { 1799 UINT r = ERROR_OUTOFMEMORY; 1800 DWORD size; 1801 LPWSTR patchW = NULL, attrW = NULL, bufferW = NULL; 1802 1803 TRACE("%s %s %p %p\n", debugstr_a(patch), debugstr_a(attr), buffer, buflen); 1804 1805 if (!patch || !attr) 1806 return ERROR_INVALID_PARAMETER; 1807 1808 if (!(patchW = strdupAtoW( patch ))) 1809 goto done; 1810 1811 if (!(attrW = strdupAtoW( attr ))) 1812 goto done; 1813 1814 size = 0; 1815 r = MsiGetPatchInfoW( patchW, attrW, NULL, &size ); 1816 if (r != ERROR_SUCCESS) 1817 goto done; 1818 1819 size++; 1820 if (!(bufferW = msi_alloc( size * sizeof(WCHAR) ))) 1821 { 1822 r = ERROR_OUTOFMEMORY; 1823 goto done; 1824 } 1825 1826 r = MsiGetPatchInfoW( patchW, attrW, bufferW, &size ); 1827 if (r == ERROR_SUCCESS) 1828 { 1829 int len = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL ); 1830 if (len > *buflen) 1831 r = ERROR_MORE_DATA; 1832 else if (buffer) 1833 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL ); 1834 1835 *buflen = len - 1; 1836 } 1837 1838 done: 1839 msi_free( patchW ); 1840 msi_free( attrW ); 1841 msi_free( bufferW ); 1842 return r; 1843 } 1844 1845 UINT WINAPI MsiGetPatchInfoW( LPCWSTR patch, LPCWSTR attr, LPWSTR buffer, LPDWORD buflen ) 1846 { 1847 UINT r; 1848 WCHAR product[GUID_SIZE]; 1849 DWORD index; 1850 1851 TRACE("%s %s %p %p\n", debugstr_w(patch), debugstr_w(attr), buffer, buflen); 1852 1853 if (!patch || !attr) 1854 return ERROR_INVALID_PARAMETER; 1855 1856 if (wcscmp( INSTALLPROPERTY_LOCALPACKAGEW, attr )) 1857 return ERROR_UNKNOWN_PROPERTY; 1858 1859 index = 0; 1860 while (1) 1861 { 1862 r = MsiEnumProductsW( index, product ); 1863 if (r != ERROR_SUCCESS) 1864 break; 1865 1866 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERMANAGED, attr, buffer, buflen ); 1867 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA) 1868 return r; 1869 1870 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, attr, buffer, buflen ); 1871 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA) 1872 return r; 1873 1874 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_MACHINE, attr, buffer, buflen ); 1875 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA) 1876 return r; 1877 1878 index++; 1879 } 1880 1881 return ERROR_UNKNOWN_PRODUCT; 1882 } 1883 1884 UINT WINAPI MsiEnableLogA( DWORD dwLogMode, const char *szLogFile, DWORD attributes ) 1885 { 1886 LPWSTR szwLogFile = NULL; 1887 UINT r; 1888 1889 TRACE( "%#lx, %s, %#lx\n", dwLogMode, debugstr_a(szLogFile), attributes ); 1890 1891 if( szLogFile ) 1892 { 1893 szwLogFile = strdupAtoW( szLogFile ); 1894 if( !szwLogFile ) 1895 return ERROR_OUTOFMEMORY; 1896 } 1897 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes ); 1898 msi_free( szwLogFile ); 1899 return r; 1900 } 1901 1902 UINT WINAPI MsiEnableLogW( DWORD dwLogMode, const WCHAR *szLogFile, DWORD attributes ) 1903 { 1904 TRACE( "%#lx, %s, %#lx\n", dwLogMode, debugstr_w(szLogFile), attributes ); 1905 1906 msi_free(gszLogFile); 1907 gszLogFile = NULL; 1908 if (szLogFile) 1909 { 1910 HANDLE file; 1911 1912 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND)) 1913 DeleteFileW(szLogFile); 1914 file = CreateFileW(szLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 1915 FILE_ATTRIBUTE_NORMAL, NULL); 1916 if (file != INVALID_HANDLE_VALUE) 1917 { 1918 gszLogFile = strdupW(szLogFile); 1919 CloseHandle(file); 1920 } 1921 else ERR( "unable to enable log %s (%lu)\n", debugstr_w(szLogFile), GetLastError() ); 1922 } 1923 1924 return ERROR_SUCCESS; 1925 } 1926 1927 UINT WINAPI MsiEnumComponentCostsA( MSIHANDLE handle, const char *component, DWORD index, INSTALLSTATE state, 1928 char *drive, DWORD *buflen, int *cost, int *temp ) 1929 { 1930 UINT r; 1931 DWORD len; 1932 WCHAR *driveW, *componentW = NULL; 1933 1934 TRACE( "%lu, %s, %lu, %d, %p, %p, %p, %p\n", handle, debugstr_a(component), index, state, drive, buflen, cost, 1935 temp ); 1936 1937 if (!drive || !buflen) return ERROR_INVALID_PARAMETER; 1938 if (component && !(componentW = strdupAtoW( component ))) return ERROR_OUTOFMEMORY; 1939 1940 len = *buflen; 1941 if (!(driveW = msi_alloc( len * sizeof(WCHAR) ))) 1942 { 1943 msi_free( componentW ); 1944 return ERROR_OUTOFMEMORY; 1945 } 1946 r = MsiEnumComponentCostsW( handle, componentW, index, state, driveW, buflen, cost, temp ); 1947 if (!r) 1948 { 1949 WideCharToMultiByte( CP_ACP, 0, driveW, -1, drive, len, NULL, NULL ); 1950 } 1951 msi_free( componentW ); 1952 msi_free( driveW ); 1953 return r; 1954 } 1955 1956 static UINT set_drive( WCHAR *buffer, WCHAR letter ) 1957 { 1958 buffer[0] = letter; 1959 buffer[1] = ':'; 1960 buffer[2] = 0; 1961 return 2; 1962 } 1963 1964 UINT WINAPI MsiEnumComponentCostsW( MSIHANDLE handle, const WCHAR *component, DWORD index, INSTALLSTATE state, 1965 WCHAR *drive, DWORD *buflen, int *cost, int *temp ) 1966 { 1967 UINT r = ERROR_NO_MORE_ITEMS; 1968 MSICOMPONENT *comp = NULL; 1969 MSIPACKAGE *package; 1970 MSIFILE *file; 1971 STATSTG stat = {0}; 1972 WCHAR path[MAX_PATH]; 1973 1974 TRACE( "%lu, %s, %lu, %d, %p, %p, %p, %p\n", handle, debugstr_w(component), index, state, drive, buflen, cost, 1975 temp ); 1976 1977 if (!drive || !buflen || !cost || !temp) return ERROR_INVALID_PARAMETER; 1978 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ))) 1979 { 1980 WCHAR buffer[3]; 1981 MSIHANDLE remote; 1982 1983 if (!(remote = msi_get_remote(handle))) 1984 return ERROR_INVALID_HANDLE; 1985 1986 __TRY 1987 { 1988 r = remote_EnumComponentCosts(remote, component, index, state, buffer, cost, temp); 1989 } 1990 __EXCEPT(rpc_filter) 1991 { 1992 r = GetExceptionCode(); 1993 } 1994 __ENDTRY 1995 1996 if (r == ERROR_SUCCESS) 1997 { 1998 lstrcpynW(drive, buffer, *buflen); 1999 if (*buflen < 3) 2000 r = ERROR_MORE_DATA; 2001 *buflen = 2; 2002 } 2003 return r; 2004 } 2005 2006 if (!msi_get_property_int( package->db, L"CostingComplete", 0 )) 2007 { 2008 msiobj_release( &package->hdr ); 2009 return ERROR_FUNCTION_NOT_CALLED; 2010 } 2011 if (component && component[0] && !(comp = msi_get_loaded_component( package, component ))) 2012 { 2013 msiobj_release( &package->hdr ); 2014 return ERROR_UNKNOWN_COMPONENT; 2015 } 2016 if (*buflen < 3) 2017 { 2018 *buflen = 2; 2019 msiobj_release( &package->hdr ); 2020 return ERROR_MORE_DATA; 2021 } 2022 if (index) 2023 { 2024 msiobj_release( &package->hdr ); 2025 return ERROR_NO_MORE_ITEMS; 2026 } 2027 2028 drive[0] = 0; 2029 *cost = *temp = 0; 2030 GetWindowsDirectoryW( path, MAX_PATH ); 2031 if (component && component[0]) 2032 { 2033 if (msi_is_global_assembly( comp )) *temp = comp->Cost; 2034 if (!comp->Enabled || !comp->KeyPath) 2035 { 2036 *cost = 0; 2037 *buflen = set_drive( drive, path[0] ); 2038 r = ERROR_SUCCESS; 2039 } 2040 else if ((file = msi_get_loaded_file( package, comp->KeyPath ))) 2041 { 2042 *cost = max( 8, comp->Cost / 512 ); 2043 *buflen = set_drive( drive, file->TargetPath[0] ); 2044 r = ERROR_SUCCESS; 2045 } 2046 } 2047 else if (IStorage_Stat( package->db->storage, &stat, STATFLAG_NONAME ) == S_OK) 2048 { 2049 *temp = max( 8, stat.cbSize.QuadPart / 512 ); 2050 *buflen = set_drive( drive, path[0] ); 2051 r = ERROR_SUCCESS; 2052 } 2053 msiobj_release( &package->hdr ); 2054 return r; 2055 } 2056 2057 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode, 2058 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, 2059 LPCSTR szComponent, INSTALLSTATE *pdwState) 2060 { 2061 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL; 2062 UINT r; 2063 2064 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode), 2065 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState); 2066 2067 if (szProductCode && !(prodcode = strdupAtoW(szProductCode))) 2068 return ERROR_OUTOFMEMORY; 2069 2070 if (szUserSid && !(usersid = strdupAtoW(szUserSid))) 2071 return ERROR_OUTOFMEMORY; 2072 2073 if (szComponent && !(comp = strdupAtoW(szComponent))) 2074 return ERROR_OUTOFMEMORY; 2075 2076 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState); 2077 2078 msi_free(prodcode); 2079 msi_free(usersid); 2080 msi_free(comp); 2081 2082 return r; 2083 } 2084 2085 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context) 2086 { 2087 UINT r; 2088 HKEY hkey = NULL; 2089 2090 r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE); 2091 RegCloseKey(hkey); 2092 return (r == ERROR_SUCCESS); 2093 } 2094 2095 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context) 2096 { 2097 LPCWSTR package; 2098 HKEY hkey; 2099 DWORD sz; 2100 LONG res; 2101 UINT r; 2102 2103 r = MSIREG_OpenInstallProps(prodcode, context, NULL, &hkey, FALSE); 2104 if (r != ERROR_SUCCESS) 2105 return FALSE; 2106 2107 if (context == MSIINSTALLCONTEXT_USERMANAGED) 2108 package = L"ManagedLocalPackage"; 2109 else 2110 package = L"LocalPackage"; 2111 2112 sz = 0; 2113 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz); 2114 RegCloseKey(hkey); 2115 2116 return (res == ERROR_SUCCESS); 2117 } 2118 2119 static UINT msi_comp_find_prodcode(WCHAR *squashed_pc, 2120 MSIINSTALLCONTEXT context, 2121 LPCWSTR comp, LPWSTR val, DWORD *sz) 2122 { 2123 HKEY hkey; 2124 LONG res; 2125 UINT r; 2126 2127 if (context == MSIINSTALLCONTEXT_MACHINE) 2128 r = MSIREG_OpenUserDataComponentKey(comp, L"S-1-5-18", &hkey, FALSE); 2129 else 2130 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE); 2131 2132 if (r != ERROR_SUCCESS) 2133 return r; 2134 2135 res = RegQueryValueExW( hkey, squashed_pc, NULL, NULL, (BYTE *)val, sz ); 2136 if (res != ERROR_SUCCESS) 2137 return res; 2138 2139 RegCloseKey(hkey); 2140 return res; 2141 } 2142 2143 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode, 2144 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext, 2145 LPCWSTR szComponent, INSTALLSTATE *pdwState) 2146 { 2147 WCHAR squashed_pc[SQUASHED_GUID_SIZE]; 2148 BOOL found; 2149 DWORD sz; 2150 2151 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode), 2152 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState); 2153 2154 if (!pdwState || !szComponent) 2155 return ERROR_INVALID_PARAMETER; 2156 2157 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1) 2158 return ERROR_INVALID_PARAMETER; 2159 2160 if (!squash_guid( szProductCode, squashed_pc )) 2161 return ERROR_INVALID_PARAMETER; 2162 2163 found = msi_comp_find_prod_key(szProductCode, dwContext); 2164 2165 if (!msi_comp_find_package(szProductCode, dwContext)) 2166 { 2167 if (found) 2168 { 2169 *pdwState = INSTALLSTATE_UNKNOWN; 2170 return ERROR_UNKNOWN_COMPONENT; 2171 } 2172 2173 return ERROR_UNKNOWN_PRODUCT; 2174 } 2175 2176 *pdwState = INSTALLSTATE_UNKNOWN; 2177 2178 sz = 0; 2179 if (msi_comp_find_prodcode( squashed_pc, dwContext, szComponent, NULL, &sz )) 2180 return ERROR_UNKNOWN_COMPONENT; 2181 2182 if (sz == 0) 2183 *pdwState = INSTALLSTATE_NOTUSED; 2184 else 2185 { 2186 WCHAR *val; 2187 UINT r; 2188 2189 if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY; 2190 if ((r = msi_comp_find_prodcode( squashed_pc, dwContext, szComponent, val, &sz ))) 2191 { 2192 msi_free(val); 2193 return r; 2194 } 2195 2196 if (lstrlenW(val) > 2 && 2197 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && val[2] != ':') 2198 { 2199 *pdwState = INSTALLSTATE_SOURCE; 2200 } 2201 else 2202 *pdwState = INSTALLSTATE_LOCAL; 2203 msi_free( val ); 2204 } 2205 2206 TRACE("-> %d\n", *pdwState); 2207 return ERROR_SUCCESS; 2208 } 2209 2210 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct) 2211 { 2212 LPWSTR szwProduct = NULL; 2213 INSTALLSTATE r; 2214 2215 if( szProduct ) 2216 { 2217 szwProduct = strdupAtoW( szProduct ); 2218 if( !szwProduct ) 2219 return ERROR_OUTOFMEMORY; 2220 } 2221 r = MsiQueryProductStateW( szwProduct ); 2222 msi_free( szwProduct ); 2223 return r; 2224 } 2225 2226 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct) 2227 { 2228 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED; 2229 INSTALLSTATE state = INSTALLSTATE_ADVERTISED; 2230 HKEY prodkey = 0, userdata = 0; 2231 DWORD val; 2232 UINT r; 2233 2234 TRACE("%s\n", debugstr_w(szProduct)); 2235 2236 if (!szProduct || !*szProduct) 2237 return INSTALLSTATE_INVALIDARG; 2238 2239 if (lstrlenW(szProduct) != GUID_SIZE - 1) 2240 return INSTALLSTATE_INVALIDARG; 2241 2242 if (szProduct[0] != '{' || szProduct[37] != '}') 2243 return INSTALLSTATE_UNKNOWN; 2244 2245 SetLastError( ERROR_SUCCESS ); 2246 2247 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, 2248 &prodkey, FALSE) != ERROR_SUCCESS && 2249 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 2250 &prodkey, FALSE) != ERROR_SUCCESS && 2251 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, 2252 &prodkey, FALSE) == ERROR_SUCCESS) 2253 { 2254 context = MSIINSTALLCONTEXT_MACHINE; 2255 } 2256 2257 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE); 2258 if (r != ERROR_SUCCESS) 2259 goto done; 2260 2261 if (!msi_reg_get_val_dword(userdata, L"WindowsInstaller", &val)) 2262 goto done; 2263 2264 if (val) 2265 state = INSTALLSTATE_DEFAULT; 2266 else 2267 state = INSTALLSTATE_UNKNOWN; 2268 2269 done: 2270 if (!prodkey) 2271 { 2272 state = INSTALLSTATE_UNKNOWN; 2273 2274 if (userdata) 2275 state = INSTALLSTATE_ABSENT; 2276 } 2277 2278 RegCloseKey(prodkey); 2279 RegCloseKey(userdata); 2280 TRACE("-> %d\n", state); 2281 return state; 2282 } 2283 2284 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd) 2285 { 2286 INSTALLUILEVEL old = gUILevel; 2287 HWND oldwnd = gUIhwnd; 2288 2289 TRACE("%08x %p\n", dwUILevel, phWnd); 2290 2291 if (dwUILevel & ~(INSTALLUILEVEL_MASK|INSTALLUILEVEL_HIDECANCEL|INSTALLUILEVEL_PROGRESSONLY| 2292 INSTALLUILEVEL_ENDDIALOG|INSTALLUILEVEL_SOURCERESONLY)) 2293 { 2294 FIXME("Unrecognized flags %08x\n", dwUILevel); 2295 return INSTALLUILEVEL_NOCHANGE; 2296 } 2297 2298 if (dwUILevel != INSTALLUILEVEL_NOCHANGE) 2299 gUILevel = dwUILevel; 2300 2301 if (phWnd) 2302 { 2303 gUIhwnd = *phWnd; 2304 *phWnd = oldwnd; 2305 } 2306 return old; 2307 } 2308 2309 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA( INSTALLUI_HANDLERA puiHandler, DWORD dwMessageFilter, void *pvContext ) 2310 { 2311 INSTALLUI_HANDLERA prev = gUIHandlerA; 2312 2313 TRACE( "%p, %#lx, %p\n", puiHandler, dwMessageFilter, pvContext ); 2314 2315 gUIHandlerA = puiHandler; 2316 gUIHandlerW = NULL; 2317 gUIFilter = dwMessageFilter; 2318 gUIContext = pvContext; 2319 2320 return prev; 2321 } 2322 2323 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW( INSTALLUI_HANDLERW puiHandler, DWORD dwMessageFilter, void *pvContext ) 2324 { 2325 INSTALLUI_HANDLERW prev = gUIHandlerW; 2326 2327 TRACE( "%p, %#lx, %p\n", puiHandler, dwMessageFilter, pvContext ); 2328 2329 gUIHandlerA = NULL; 2330 gUIHandlerW = puiHandler; 2331 gUIFilter = dwMessageFilter; 2332 gUIContext = pvContext; 2333 2334 return prev; 2335 } 2336 2337 /****************************************************************** 2338 * MsiLoadStringW [MSI.@] 2339 * 2340 * Loads a string from MSI's string resources. 2341 * 2342 * PARAMS 2343 * 2344 * handle [I] only -1 is handled currently 2345 * id [I] id of the string to be loaded 2346 * lpBuffer [O] buffer for the string to be written to 2347 * nBufferMax [I] maximum size of the buffer in characters 2348 * lang [I] the preferred language for the string 2349 * 2350 * RETURNS 2351 * 2352 * If successful, this function returns the language id of the string loaded 2353 * If the function fails, the function returns zero. 2354 * 2355 * NOTES 2356 * 2357 * The type of the first parameter is unknown. LoadString's prototype 2358 * suggests that it might be a module handle. I have made it an MSI handle 2359 * for starters, as -1 is an invalid MSI handle, but not an invalid module 2360 * handle. Maybe strings can be stored in an MSI database somehow. 2361 */ 2362 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, WCHAR *lpBuffer, int nBufferMax, LANGID lang ) 2363 { 2364 HRSRC hres; 2365 HGLOBAL hResData; 2366 LPWSTR p; 2367 DWORD i, len; 2368 2369 TRACE( "%lu, %u, %p, %d, %#x\n", handle, id, lpBuffer, nBufferMax, lang ); 2370 2371 if( handle != -1 ) 2372 FIXME( "don't know how to deal with handle = %lu\n", handle ); 2373 2374 if( !lang ) 2375 lang = GetUserDefaultLangID(); 2376 2377 hres = FindResourceExW( msi_hInstance, (const WCHAR *)RT_STRING, (WCHAR *)1, lang ); 2378 if( !hres ) 2379 return 0; 2380 hResData = LoadResource( msi_hInstance, hres ); 2381 if( !hResData ) 2382 return 0; 2383 p = LockResource( hResData ); 2384 if( !p ) 2385 return 0; 2386 2387 for (i = 0; i < (id & 0xf); i++) p += *p + 1; 2388 len = *p; 2389 2390 if( nBufferMax <= len ) 2391 return 0; 2392 2393 memcpy( lpBuffer, p+1, len * sizeof(WCHAR)); 2394 lpBuffer[ len ] = 0; 2395 2396 TRACE("found -> %s\n", debugstr_w(lpBuffer)); 2397 return lang; 2398 } 2399 2400 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer, 2401 int nBufferMax, LANGID lang ) 2402 { 2403 LPWSTR bufW; 2404 LANGID r; 2405 INT len; 2406 2407 bufW = msi_alloc(nBufferMax*sizeof(WCHAR)); 2408 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang); 2409 if( r ) 2410 { 2411 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL ); 2412 if( len <= nBufferMax ) 2413 WideCharToMultiByte( CP_ACP, 0, bufW, -1, 2414 lpBuffer, nBufferMax, NULL, NULL ); 2415 else 2416 r = 0; 2417 } 2418 msi_free(bufW); 2419 return r; 2420 } 2421 2422 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf, 2423 LPDWORD pcchBuf) 2424 { 2425 char szProduct[GUID_SIZE]; 2426 2427 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf); 2428 2429 if (!szComponent || !pcchBuf) 2430 return INSTALLSTATE_INVALIDARG; 2431 2432 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS) 2433 return INSTALLSTATE_UNKNOWN; 2434 2435 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf ); 2436 } 2437 2438 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf, 2439 LPDWORD pcchBuf) 2440 { 2441 WCHAR szProduct[GUID_SIZE]; 2442 2443 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf); 2444 2445 if (!szComponent || !pcchBuf) 2446 return INSTALLSTATE_INVALIDARG; 2447 2448 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS) 2449 return INSTALLSTATE_UNKNOWN; 2450 2451 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf ); 2452 } 2453 2454 UINT WINAPI MsiMessageBoxA( HWND hWnd, const char *lpText, const char *lpCaption, UINT uType, WORD wLanguageId, 2455 DWORD f ) 2456 { 2457 FIXME( "%p, %s, %s, %u, %#x, %#lx\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption), uType, wLanguageId, f ); 2458 return MessageBoxExA( hWnd, lpText, lpCaption, uType, wLanguageId ); 2459 } 2460 2461 UINT WINAPI MsiMessageBoxW( HWND hWnd, const WCHAR *lpText, const WCHAR *lpCaption, UINT uType, WORD wLanguageId, 2462 DWORD f ) 2463 { 2464 FIXME( "%p, %s, %s, %u, %#x %#lx\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption), uType, wLanguageId, f ); 2465 return MessageBoxExW( hWnd, lpText, lpCaption, uType, wLanguageId ); 2466 } 2467 2468 UINT WINAPI MsiMessageBoxExA( HWND hWnd, const char *lpText, const char *lpCaption, UINT uType, DWORD unknown, 2469 WORD wLanguageId, DWORD f ) 2470 { 2471 FIXME( "%p, %s, %s, %u, %#lx, %#x, %#lx): semi-stub\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption), uType, 2472 unknown, wLanguageId, f ); 2473 return MessageBoxExA( hWnd, lpText, lpCaption, uType, wLanguageId ); 2474 } 2475 2476 UINT WINAPI MsiMessageBoxExW( HWND hWnd, const WCHAR *lpText, const WCHAR *lpCaption, UINT uType, DWORD unknown, 2477 WORD wLanguageId, DWORD f ) 2478 { 2479 FIXME( "%p, %s, %s, %u, %#lx, %#x, %#lx): semi-stub\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption), uType, 2480 unknown, wLanguageId, f ); 2481 return MessageBoxExW( hWnd, lpText, lpCaption, uType, wLanguageId ); 2482 } 2483 2484 UINT WINAPI MsiProvideAssemblyA( const char *szAssemblyName, const char *szAppContext, DWORD dwInstallMode, 2485 DWORD dwAssemblyInfo, char *lpPathBuf, DWORD *pcchPathBuf ) 2486 { 2487 FIXME( "%s, %s, %#lx, %#lx, %p, %p\n", debugstr_a(szAssemblyName), debugstr_a(szAppContext), dwInstallMode, 2488 dwAssemblyInfo, lpPathBuf, pcchPathBuf ); 2489 return ERROR_CALL_NOT_IMPLEMENTED; 2490 } 2491 2492 UINT WINAPI MsiProvideAssemblyW( const WCHAR *szAssemblyName, const WCHAR *szAppContext, DWORD dwInstallMode, 2493 DWORD dwAssemblyInfo, WCHAR *lpPathBuf, DWORD *pcchPathBuf ) 2494 { 2495 FIXME( "%s, %s, %#lx, %#lx, %p, %p\n", debugstr_w(szAssemblyName), debugstr_w(szAppContext), dwInstallMode, 2496 dwAssemblyInfo, lpPathBuf, pcchPathBuf ); 2497 return ERROR_CALL_NOT_IMPLEMENTED; 2498 } 2499 2500 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, 2501 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs ) 2502 { 2503 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs ); 2504 return ERROR_CALL_NOT_IMPLEMENTED; 2505 } 2506 2507 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, 2508 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs ) 2509 { 2510 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs ); 2511 return ERROR_CALL_NOT_IMPLEMENTED; 2512 } 2513 2514 HRESULT WINAPI MsiGetFileSignatureInformationA( const char *path, DWORD flags, PCCERT_CONTEXT *cert, BYTE *hash, 2515 DWORD *hashlen ) 2516 { 2517 UINT r; 2518 WCHAR *pathW = NULL; 2519 2520 TRACE( "%s, %#lx, %p, %p, %p\n", debugstr_a(path), flags, cert, hash, hashlen ); 2521 2522 if (path && !(pathW = strdupAtoW( path ))) return E_OUTOFMEMORY; 2523 r = MsiGetFileSignatureInformationW( pathW, flags, cert, hash, hashlen ); 2524 msi_free( pathW ); 2525 return r; 2526 } 2527 2528 HRESULT WINAPI MsiGetFileSignatureInformationW( const WCHAR *path, DWORD flags, PCCERT_CONTEXT *cert, BYTE *hash, 2529 DWORD *hashlen ) 2530 { 2531 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2; 2532 HRESULT hr; 2533 WINTRUST_DATA data; 2534 WINTRUST_FILE_INFO info; 2535 CRYPT_PROVIDER_SGNR *signer; 2536 CRYPT_PROVIDER_CERT *provider; 2537 2538 TRACE( "%s, %#lx, %p, %p, %p\n", debugstr_w(path), flags, cert, hash, hashlen ); 2539 2540 if (!path || !cert) return E_INVALIDARG; 2541 2542 info.cbStruct = sizeof(info); 2543 info.pcwszFilePath = path; 2544 info.hFile = NULL; 2545 info.pgKnownSubject = NULL; 2546 2547 data.cbStruct = sizeof(data); 2548 data.pPolicyCallbackData = NULL; 2549 data.pSIPClientData = NULL; 2550 data.dwUIChoice = WTD_UI_NONE; 2551 data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN; 2552 data.dwUnionChoice = WTD_CHOICE_FILE; 2553 data.u.pFile = &info; 2554 data.dwStateAction = WTD_STATEACTION_VERIFY; 2555 data.hWVTStateData = NULL; 2556 data.pwszURLReference = NULL; 2557 data.dwProvFlags = 0; 2558 data.dwUIContext = WTD_UICONTEXT_INSTALL; 2559 hr = WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data ); 2560 *cert = NULL; 2561 if (FAILED(hr)) goto done; 2562 2563 if (!(signer = WTHelperGetProvSignerFromChain( data.hWVTStateData, 0, FALSE, 0 ))) 2564 { 2565 hr = TRUST_E_NOSIGNATURE; 2566 goto done; 2567 } 2568 if (hash) 2569 { 2570 DWORD len = signer->psSigner->EncryptedHash.cbData; 2571 if (*hashlen < len) 2572 { 2573 *hashlen = len; 2574 hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA); 2575 goto done; 2576 } 2577 memcpy( hash, signer->psSigner->EncryptedHash.pbData, len ); 2578 *hashlen = len; 2579 } 2580 if (!(provider = WTHelperGetProvCertFromChain( signer, 0 ))) 2581 { 2582 hr = TRUST_E_PROVIDER_UNKNOWN; 2583 goto done; 2584 } 2585 *cert = CertDuplicateCertificateContext( provider->pCert ); 2586 2587 done: 2588 data.dwStateAction = WTD_STATEACTION_CLOSE; 2589 WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data ); 2590 return hr; 2591 } 2592 2593 /****************************************************************** 2594 * MsiGetProductPropertyA [MSI.@] 2595 */ 2596 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, const char *szProperty, char *szValue, DWORD *pccbValue ) 2597 { 2598 LPWSTR prop = NULL, val = NULL; 2599 DWORD len; 2600 UINT r; 2601 2602 TRACE( "%lu, %s, %p, %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue ); 2603 2604 if (szValue && !pccbValue) 2605 return ERROR_INVALID_PARAMETER; 2606 2607 if (szProperty) prop = strdupAtoW(szProperty); 2608 2609 len = 0; 2610 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len); 2611 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2612 goto done; 2613 2614 if (r == ERROR_SUCCESS) 2615 { 2616 if (szValue) *szValue = '\0'; 2617 if (pccbValue) *pccbValue = 0; 2618 goto done; 2619 } 2620 2621 val = msi_alloc(++len * sizeof(WCHAR)); 2622 if (!val) 2623 { 2624 r = ERROR_OUTOFMEMORY; 2625 goto done; 2626 } 2627 2628 r = MsiGetProductPropertyW(hProduct, prop, val, &len); 2629 if (r != ERROR_SUCCESS) 2630 goto done; 2631 2632 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL); 2633 2634 if (szValue) 2635 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue, 2636 *pccbValue, NULL, NULL); 2637 2638 if (pccbValue) 2639 { 2640 if (len > *pccbValue) 2641 r = ERROR_MORE_DATA; 2642 2643 *pccbValue = len - 1; 2644 } 2645 2646 done: 2647 msi_free(prop); 2648 msi_free(val); 2649 2650 return r; 2651 } 2652 2653 /****************************************************************** 2654 * MsiGetProductPropertyW [MSI.@] 2655 */ 2656 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, const WCHAR *szProperty, WCHAR *szValue, DWORD *pccbValue ) 2657 { 2658 MSIPACKAGE *package; 2659 MSIQUERY *view = NULL; 2660 MSIRECORD *rec = NULL; 2661 LPCWSTR val; 2662 UINT r; 2663 2664 TRACE( "%lu, %s, %p, %p)\n", hProduct, debugstr_w(szProperty), szValue, pccbValue ); 2665 2666 if (!szProperty) 2667 return ERROR_INVALID_PARAMETER; 2668 2669 if (szValue && !pccbValue) 2670 return ERROR_INVALID_PARAMETER; 2671 2672 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE); 2673 if (!package) 2674 return ERROR_INVALID_HANDLE; 2675 2676 r = MSI_OpenQuery(package->db, &view, L"SELECT * FROM `Property` WHERE `Property` = '%s'", szProperty); 2677 if (r != ERROR_SUCCESS) 2678 goto done; 2679 2680 r = MSI_ViewExecute(view, 0); 2681 if (r != ERROR_SUCCESS) 2682 goto done; 2683 2684 r = MSI_ViewFetch(view, &rec); 2685 if (r != ERROR_SUCCESS) 2686 goto done; 2687 2688 val = MSI_RecordGetString(rec, 2); 2689 if (!val) 2690 goto done; 2691 2692 if (lstrlenW(val) >= *pccbValue) 2693 { 2694 if (szValue) lstrcpynW(szValue, val, *pccbValue); 2695 r = ERROR_MORE_DATA; 2696 } 2697 else 2698 { 2699 if (szValue) lstrcpyW(szValue, val); 2700 r = ERROR_SUCCESS; 2701 } 2702 2703 *pccbValue = lstrlenW(val); 2704 2705 done: 2706 if (view) 2707 { 2708 MSI_ViewClose(view); 2709 msiobj_release(&view->hdr); 2710 if (rec) msiobj_release(&rec->hdr); 2711 } 2712 2713 if (!rec) 2714 { 2715 if (szValue) *szValue = '\0'; 2716 if (pccbValue) *pccbValue = 0; 2717 r = ERROR_SUCCESS; 2718 } 2719 2720 msiobj_release(&package->hdr); 2721 return r; 2722 } 2723 2724 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage ) 2725 { 2726 UINT r; 2727 LPWSTR szPack = NULL; 2728 2729 TRACE("%s\n", debugstr_a(szPackage) ); 2730 2731 if( szPackage ) 2732 { 2733 szPack = strdupAtoW( szPackage ); 2734 if( !szPack ) 2735 return ERROR_OUTOFMEMORY; 2736 } 2737 2738 r = MsiVerifyPackageW( szPack ); 2739 2740 msi_free( szPack ); 2741 2742 return r; 2743 } 2744 2745 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage ) 2746 { 2747 MSIHANDLE handle; 2748 UINT r; 2749 2750 TRACE("%s\n", debugstr_w(szPackage) ); 2751 2752 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle ); 2753 MsiCloseHandle( handle ); 2754 2755 return r; 2756 } 2757 2758 static BOOL open_userdata_comp_key( const WCHAR *comp, const WCHAR *usersid, MSIINSTALLCONTEXT ctx, 2759 HKEY *hkey ) 2760 { 2761 if (ctx & MSIINSTALLCONTEXT_MACHINE) 2762 { 2763 if (!MSIREG_OpenUserDataComponentKey( comp, L"S-1-5-18", hkey, FALSE )) return TRUE; 2764 } 2765 if (ctx & (MSIINSTALLCONTEXT_USERMANAGED|MSIINSTALLCONTEXT_USERUNMANAGED)) 2766 { 2767 if (usersid && !wcsicmp( usersid, L"S-1-1-0" )) 2768 { 2769 FIXME( "only looking at the current user\n" ); 2770 usersid = NULL; 2771 } 2772 if (!MSIREG_OpenUserDataComponentKey( comp, usersid, hkey, FALSE )) return TRUE; 2773 } 2774 return FALSE; 2775 } 2776 2777 static INSTALLSTATE MSI_GetComponentPath( const WCHAR *szProduct, const WCHAR *szComponent, 2778 const WCHAR *szUserSid, MSIINSTALLCONTEXT ctx, 2779 awstring *lpPathBuf, DWORD *pcchBuf ) 2780 { 2781 WCHAR *path = NULL, squashed_pc[SQUASHED_GUID_SIZE], squashed_comp[SQUASHED_GUID_SIZE]; 2782 HKEY hkey; 2783 INSTALLSTATE state; 2784 DWORD version; 2785 2786 if (!szProduct || !szComponent) 2787 return INSTALLSTATE_INVALIDARG; 2788 2789 if (lpPathBuf->str.w && !pcchBuf) 2790 return INSTALLSTATE_INVALIDARG; 2791 2792 if (!squash_guid( szProduct, squashed_pc ) || !squash_guid( szComponent, squashed_comp )) 2793 return INSTALLSTATE_INVALIDARG; 2794 2795 if (szUserSid && ctx == MSIINSTALLCONTEXT_MACHINE) 2796 return INSTALLSTATE_INVALIDARG; 2797 2798 state = INSTALLSTATE_UNKNOWN; 2799 2800 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey )) 2801 { 2802 path = msi_reg_get_val_str( hkey, squashed_pc ); 2803 RegCloseKey(hkey); 2804 2805 state = INSTALLSTATE_ABSENT; 2806 2807 if ((!MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, &hkey, FALSE) || 2808 !MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, NULL, &hkey, FALSE)) && 2809 msi_reg_get_val_dword(hkey, L"WindowsInstaller", &version) && 2810 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) 2811 { 2812 RegCloseKey(hkey); 2813 state = INSTALLSTATE_LOCAL; 2814 } 2815 } 2816 2817 if (state != INSTALLSTATE_LOCAL && 2818 (!MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, &hkey, FALSE) || 2819 !MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, &hkey, FALSE))) 2820 { 2821 RegCloseKey(hkey); 2822 2823 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey )) 2824 { 2825 msi_free(path); 2826 path = msi_reg_get_val_str( hkey, squashed_pc ); 2827 RegCloseKey(hkey); 2828 2829 state = INSTALLSTATE_ABSENT; 2830 2831 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) 2832 state = INSTALLSTATE_LOCAL; 2833 } 2834 } 2835 2836 if (!path) 2837 return INSTALLSTATE_UNKNOWN; 2838 2839 if (state == INSTALLSTATE_LOCAL && !*path) 2840 state = INSTALLSTATE_NOTUSED; 2841 2842 if (msi_strcpy_to_awstring(path, -1, lpPathBuf, pcchBuf) == ERROR_MORE_DATA) 2843 state = INSTALLSTATE_MOREDATA; 2844 2845 msi_free(path); 2846 return state; 2847 } 2848 2849 /****************************************************************** 2850 * MsiGetComponentPathExW [MSI.@] 2851 */ 2852 INSTALLSTATE WINAPI MsiGetComponentPathExW( LPCWSTR product, LPCWSTR comp, LPCWSTR usersid, 2853 MSIINSTALLCONTEXT ctx, LPWSTR buf, LPDWORD buflen ) 2854 { 2855 awstring path; 2856 2857 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_w(product), debugstr_w(comp), debugstr_w(usersid), 2858 ctx, buf, buflen ); 2859 2860 path.unicode = TRUE; 2861 path.str.w = buf; 2862 2863 return MSI_GetComponentPath( product, comp, usersid, ctx, &path, buflen ); 2864 } 2865 2866 INSTALLSTATE WINAPI MsiGetComponentPathExA( LPCSTR product, LPCSTR comp, LPCSTR usersid, 2867 MSIINSTALLCONTEXT ctx, LPSTR buf, LPDWORD buflen ) 2868 { 2869 WCHAR *productW = NULL, *compW = NULL, *usersidW = NULL; 2870 INSTALLSTATE r = INSTALLSTATE_UNKNOWN; 2871 awstring path; 2872 2873 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_a(product), debugstr_a(comp), debugstr_a(usersid), 2874 ctx, buf, buflen ); 2875 2876 if (product && !(productW = strdupAtoW( product ))) return INSTALLSTATE_UNKNOWN; 2877 if (comp && !(compW = strdupAtoW( comp ))) goto end; 2878 if (usersid && !(usersidW = strdupAtoW( usersid ))) goto end; 2879 2880 path.unicode = FALSE; 2881 path.str.a = buf; 2882 2883 r = MSI_GetComponentPath( productW, compW, usersidW, ctx, &path, buflen ); 2884 2885 end: 2886 msi_free( productW ); 2887 msi_free( compW ); 2888 msi_free( usersidW ); 2889 2890 return r; 2891 } 2892 2893 /****************************************************************** 2894 * MsiGetComponentPathW [MSI.@] 2895 */ 2896 INSTALLSTATE WINAPI MsiGetComponentPathW( LPCWSTR product, LPCWSTR comp, LPWSTR buf, LPDWORD buflen ) 2897 { 2898 return MsiGetComponentPathExW( product, comp, L"S-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen ); 2899 } 2900 2901 /****************************************************************** 2902 * MsiGetComponentPathA [MSI.@] 2903 */ 2904 INSTALLSTATE WINAPI MsiGetComponentPathA( LPCSTR product, LPCSTR comp, LPSTR buf, LPDWORD buflen ) 2905 { 2906 return MsiGetComponentPathExA( product, comp, "s-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen ); 2907 } 2908 2909 static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid, 2910 MSIINSTALLCONTEXT ctx, const WCHAR *feature, INSTALLSTATE *state ) 2911 { 2912 UINT r; 2913 HKEY hkey; 2914 WCHAR *parent, *components, *path; 2915 const WCHAR *p; 2916 BOOL missing = FALSE, source = FALSE; 2917 WCHAR comp[GUID_SIZE]; 2918 GUID guid; 2919 2920 if (ctx != MSIINSTALLCONTEXT_MACHINE) SetLastError( ERROR_SUCCESS ); 2921 2922 if (MSIREG_OpenFeaturesKey( product, usersid, ctx, &hkey, FALSE )) return ERROR_UNKNOWN_PRODUCT; 2923 2924 parent = msi_reg_get_val_str( hkey, feature ); 2925 RegCloseKey( hkey ); 2926 if (!parent) return ERROR_UNKNOWN_FEATURE; 2927 2928 *state = (parent[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL; 2929 msi_free( parent ); 2930 if (*state == INSTALLSTATE_ABSENT) 2931 return ERROR_SUCCESS; 2932 2933 r = MSIREG_OpenUserDataFeaturesKey( product, usersid, ctx, &hkey, FALSE ); 2934 if (r != ERROR_SUCCESS) 2935 { 2936 *state = INSTALLSTATE_ADVERTISED; 2937 return ERROR_SUCCESS; 2938 } 2939 components = msi_reg_get_val_str( hkey, feature ); 2940 RegCloseKey( hkey ); 2941 2942 TRACE("buffer = %s\n", debugstr_w(components)); 2943 2944 if (!components) 2945 { 2946 *state = INSTALLSTATE_ADVERTISED; 2947 return ERROR_SUCCESS; 2948 } 2949 for (p = components; *p && *p != 2 ; p += 20) 2950 { 2951 if (!decode_base85_guid( p, &guid )) 2952 { 2953 if (p != components) break; 2954 msi_free( components ); 2955 *state = INSTALLSTATE_BADCONFIG; 2956 return ERROR_BAD_CONFIGURATION; 2957 } 2958 StringFromGUID2( &guid, comp, GUID_SIZE ); 2959 if (ctx == MSIINSTALLCONTEXT_MACHINE) 2960 r = MSIREG_OpenUserDataComponentKey( comp, L"S-1-5-18", &hkey, FALSE ); 2961 else 2962 r = MSIREG_OpenUserDataComponentKey( comp, usersid, &hkey, FALSE ); 2963 2964 if (r != ERROR_SUCCESS) 2965 { 2966 msi_free( components ); 2967 *state = INSTALLSTATE_ADVERTISED; 2968 return ERROR_SUCCESS; 2969 } 2970 path = msi_reg_get_val_str( hkey, squashed ); 2971 if (!path) missing = TRUE; 2972 else if (lstrlenW( path ) > 2 && 2973 path[0] >= '0' && path[0] <= '9' && 2974 path[1] >= '0' && path[1] <= '9') 2975 { 2976 source = TRUE; 2977 } 2978 msi_free( path ); 2979 } 2980 msi_free( components ); 2981 2982 if (missing) 2983 *state = INSTALLSTATE_ADVERTISED; 2984 else if (source) 2985 *state = INSTALLSTATE_SOURCE; 2986 else 2987 *state = INSTALLSTATE_LOCAL; 2988 2989 TRACE("returning state %d\n", *state); 2990 return ERROR_SUCCESS; 2991 } 2992 2993 UINT WINAPI MsiQueryFeatureStateExA( LPCSTR product, LPCSTR usersid, MSIINSTALLCONTEXT ctx, 2994 LPCSTR feature, INSTALLSTATE *state ) 2995 { 2996 UINT r; 2997 WCHAR *productW = NULL, *usersidW = NULL, *featureW = NULL; 2998 2999 if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY; 3000 if (usersid && !(usersidW = strdupAtoW( usersid ))) 3001 { 3002 msi_free( productW ); 3003 return ERROR_OUTOFMEMORY; 3004 } 3005 if (feature && !(featureW = strdupAtoW( feature ))) 3006 { 3007 msi_free( productW ); 3008 msi_free( usersidW ); 3009 return ERROR_OUTOFMEMORY; 3010 } 3011 r = MsiQueryFeatureStateExW( productW, usersidW, ctx, featureW, state ); 3012 msi_free( productW ); 3013 msi_free( usersidW ); 3014 msi_free( featureW ); 3015 return r; 3016 } 3017 3018 UINT WINAPI MsiQueryFeatureStateExW( LPCWSTR product, LPCWSTR usersid, MSIINSTALLCONTEXT ctx, 3019 LPCWSTR feature, INSTALLSTATE *state ) 3020 { 3021 WCHAR squashed[33]; 3022 if (!squash_guid( product, squashed )) return ERROR_INVALID_PARAMETER; 3023 return query_feature_state( product, squashed, usersid, ctx, feature, state ); 3024 } 3025 3026 /****************************************************************** 3027 * MsiQueryFeatureStateA [MSI.@] 3028 */ 3029 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature) 3030 { 3031 LPWSTR szwProduct = NULL, szwFeature= NULL; 3032 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN; 3033 3034 szwProduct = strdupAtoW( szProduct ); 3035 if ( szProduct && !szwProduct ) 3036 goto end; 3037 3038 szwFeature = strdupAtoW( szFeature ); 3039 if ( szFeature && !szwFeature ) 3040 goto end; 3041 3042 rc = MsiQueryFeatureStateW(szwProduct, szwFeature); 3043 3044 end: 3045 msi_free( szwProduct); 3046 msi_free( szwFeature); 3047 3048 return rc; 3049 } 3050 3051 /****************************************************************** 3052 * MsiQueryFeatureStateW [MSI.@] 3053 * 3054 * Checks the state of a feature 3055 * 3056 * PARAMS 3057 * szProduct [I] Product's GUID string 3058 * szFeature [I] Feature's GUID string 3059 * 3060 * RETURNS 3061 * INSTALLSTATE_LOCAL Feature is installed and usable 3062 * INSTALLSTATE_ABSENT Feature is absent 3063 * INSTALLSTATE_ADVERTISED Feature should be installed on demand 3064 * INSTALLSTATE_UNKNOWN An error occurred 3065 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid 3066 * 3067 */ 3068 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) 3069 { 3070 UINT r; 3071 INSTALLSTATE state; 3072 WCHAR squashed[33]; 3073 3074 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); 3075 3076 if (!szProduct || !szFeature || !squash_guid( szProduct, squashed )) 3077 return INSTALLSTATE_INVALIDARG; 3078 3079 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERMANAGED, szFeature, &state ); 3080 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; 3081 3082 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, szFeature, &state ); 3083 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; 3084 3085 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_MACHINE, szFeature, &state ); 3086 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; 3087 3088 return INSTALLSTATE_UNKNOWN; 3089 } 3090 3091 /****************************************************************** 3092 * MsiGetFileVersionA [MSI.@] 3093 */ 3094 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, 3095 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf) 3096 { 3097 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL; 3098 UINT ret = ERROR_OUTOFMEMORY; 3099 3100 if ((lpVersionBuf && !pcchVersionBuf) || 3101 (lpLangBuf && !pcchLangBuf)) 3102 return ERROR_INVALID_PARAMETER; 3103 3104 if( szFilePath ) 3105 { 3106 szwFilePath = strdupAtoW( szFilePath ); 3107 if( !szwFilePath ) 3108 goto end; 3109 } 3110 3111 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf ) 3112 { 3113 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR)); 3114 if( !lpwVersionBuff ) 3115 goto end; 3116 } 3117 3118 if( lpLangBuf && pcchLangBuf && *pcchLangBuf ) 3119 { 3120 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR)); 3121 if( !lpwLangBuff ) 3122 goto end; 3123 } 3124 3125 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf, 3126 lpwLangBuff, pcchLangBuf); 3127 3128 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff ) 3129 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1, 3130 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL); 3131 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff ) 3132 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1, 3133 lpLangBuf, *pcchLangBuf + 1, NULL, NULL); 3134 3135 end: 3136 msi_free(szwFilePath); 3137 msi_free(lpwVersionBuff); 3138 msi_free(lpwLangBuff); 3139 3140 return ret; 3141 } 3142 3143 static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, 3144 WCHAR *langbuf, DWORD *langlen ) 3145 { 3146 UINT ret = ERROR_MORE_DATA; 3147 UINT len; 3148 DWORD error; 3149 LPVOID version; 3150 VS_FIXEDFILEINFO *ffi; 3151 USHORT *lang; 3152 WCHAR tmp[32]; 3153 3154 if (!(len = GetFileVersionInfoSizeW( path, NULL ))) 3155 { 3156 error = GetLastError(); 3157 if (error == ERROR_BAD_PATHNAME) return ERROR_FILE_NOT_FOUND; 3158 if (error == ERROR_RESOURCE_DATA_NOT_FOUND) return ERROR_FILE_INVALID; 3159 return error; 3160 } 3161 if (!(version = msi_alloc( len ))) return ERROR_OUTOFMEMORY; 3162 if (!GetFileVersionInfoW( path, 0, len, version )) 3163 { 3164 msi_free( version ); 3165 return GetLastError(); 3166 } 3167 if (!verbuf && !verlen && !langbuf && !langlen) 3168 { 3169 msi_free( version ); 3170 return ERROR_SUCCESS; 3171 } 3172 if (verlen) 3173 { 3174 if (VerQueryValueW( version, L"\\", (LPVOID *)&ffi, &len ) && len > 0) 3175 { 3176 swprintf( tmp, ARRAY_SIZE(tmp), L"%d.%d.%d.%d", 3177 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), 3178 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS) ); 3179 if (verbuf) lstrcpynW( verbuf, tmp, *verlen ); 3180 len = lstrlenW( tmp ); 3181 if (*verlen > len) ret = ERROR_SUCCESS; 3182 *verlen = len; 3183 } 3184 else 3185 { 3186 if (verbuf) *verbuf = 0; 3187 *verlen = 0; 3188 } 3189 } 3190 if (langlen) 3191 { 3192 if (VerQueryValueW( version, L"\\VarFileInfo\\Translation", (LPVOID *)&lang, &len ) && len > 0) 3193 { 3194 swprintf( tmp, ARRAY_SIZE(tmp), L"%d", *lang ); 3195 if (langbuf) lstrcpynW( langbuf, tmp, *langlen ); 3196 len = lstrlenW( tmp ); 3197 if (*langlen > len) ret = ERROR_SUCCESS; 3198 *langlen = len; 3199 } 3200 else 3201 { 3202 if (langbuf) *langbuf = 0; 3203 *langlen = 0; 3204 } 3205 } 3206 msi_free( version ); 3207 return ret; 3208 } 3209 3210 3211 /****************************************************************** 3212 * MsiGetFileVersionW [MSI.@] 3213 */ 3214 UINT WINAPI MsiGetFileVersionW( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, WCHAR *langbuf, DWORD *langlen ) 3215 { 3216 UINT ret; 3217 3218 TRACE( "%s, %p(%lu), %p(%lu)\n", debugstr_w(path), verbuf, verlen ? *verlen : 0, langbuf, langlen ? *langlen : 0 ); 3219 3220 if ((verbuf && !verlen) || (langbuf && !langlen)) 3221 return ERROR_INVALID_PARAMETER; 3222 3223 ret = get_file_version( path, verbuf, verlen, langbuf, langlen ); 3224 if (ret == ERROR_RESOURCE_DATA_NOT_FOUND && verlen) 3225 { 3226 int len; 3227 WCHAR *version = msi_get_font_file_version( NULL, path ); 3228 if (!version) return ERROR_FILE_INVALID; 3229 len = lstrlenW( version ); 3230 if (len >= *verlen) ret = ERROR_MORE_DATA; 3231 else if (verbuf) 3232 { 3233 lstrcpyW( verbuf, version ); 3234 ret = ERROR_SUCCESS; 3235 } 3236 *verlen = len; 3237 msi_free( version ); 3238 } 3239 return ret; 3240 } 3241 3242 /*********************************************************************** 3243 * MsiGetFeatureUsageW [MSI.@] 3244 */ 3245 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature, 3246 LPDWORD pdwUseCount, LPWORD pwDateUsed ) 3247 { 3248 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature), 3249 pdwUseCount, pwDateUsed); 3250 return ERROR_CALL_NOT_IMPLEMENTED; 3251 } 3252 3253 /*********************************************************************** 3254 * MsiGetFeatureUsageA [MSI.@] 3255 */ 3256 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature, 3257 LPDWORD pdwUseCount, LPWORD pwDateUsed ) 3258 { 3259 LPWSTR prod = NULL, feat = NULL; 3260 UINT ret = ERROR_OUTOFMEMORY; 3261 3262 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature), 3263 pdwUseCount, pwDateUsed); 3264 3265 prod = strdupAtoW( szProduct ); 3266 if (szProduct && !prod) 3267 goto end; 3268 3269 feat = strdupAtoW( szFeature ); 3270 if (szFeature && !feat) 3271 goto end; 3272 3273 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed ); 3274 3275 end: 3276 msi_free( prod ); 3277 msi_free( feat ); 3278 3279 return ret; 3280 } 3281 3282 /*********************************************************************** 3283 * MsiUseFeatureExW [MSI.@] 3284 */ 3285 INSTALLSTATE WINAPI MsiUseFeatureExW( const WCHAR *szProduct, const WCHAR *szFeature, DWORD dwInstallMode, 3286 DWORD dwReserved ) 3287 { 3288 INSTALLSTATE state; 3289 3290 TRACE( "%s, %s, %lu %#lx\n", debugstr_w(szProduct), debugstr_w(szFeature), dwInstallMode, dwReserved ); 3291 3292 state = MsiQueryFeatureStateW( szProduct, szFeature ); 3293 3294 if (dwReserved) 3295 return INSTALLSTATE_INVALIDARG; 3296 3297 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION) 3298 { 3299 FIXME("mark product %s feature %s as used\n", 3300 debugstr_w(szProduct), debugstr_w(szFeature) ); 3301 } 3302 3303 return state; 3304 } 3305 3306 /*********************************************************************** 3307 * MsiUseFeatureExA [MSI.@] 3308 */ 3309 INSTALLSTATE WINAPI MsiUseFeatureExA( const char *szProduct, const char *szFeature, DWORD dwInstallMode, 3310 DWORD dwReserved ) 3311 { 3312 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN; 3313 WCHAR *prod = NULL, *feat = NULL; 3314 3315 TRACE( "%s, %s, %lu, %#lx\n", debugstr_a(szProduct), debugstr_a(szFeature), dwInstallMode, dwReserved ); 3316 3317 prod = strdupAtoW( szProduct ); 3318 if (szProduct && !prod) 3319 goto end; 3320 3321 feat = strdupAtoW( szFeature ); 3322 if (szFeature && !feat) 3323 goto end; 3324 3325 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved ); 3326 3327 end: 3328 msi_free( prod ); 3329 msi_free( feat ); 3330 3331 return ret; 3332 } 3333 3334 /*********************************************************************** 3335 * MsiUseFeatureW [MSI.@] 3336 */ 3337 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature ) 3338 { 3339 return MsiUseFeatureExW(szProduct, szFeature, 0, 0); 3340 } 3341 3342 /*********************************************************************** 3343 * MsiUseFeatureA [MSI.@] 3344 */ 3345 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature ) 3346 { 3347 return MsiUseFeatureExA(szProduct, szFeature, 0, 0); 3348 } 3349 3350 static WCHAR *reg_get_multisz( HKEY hkey, const WCHAR *name ) 3351 { 3352 WCHAR *ret; 3353 DWORD len, type; 3354 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_MULTI_SZ) return NULL; 3355 if ((ret = msi_alloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len ); 3356 return ret; 3357 } 3358 3359 static WCHAR *reg_get_sz( HKEY hkey, const WCHAR *name ) 3360 { 3361 WCHAR *ret; 3362 DWORD len, type; 3363 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_SZ) return NULL; 3364 if ((ret = msi_alloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len ); 3365 return ret; 3366 } 3367 3368 #define BASE85_SIZE 20 3369 3370 /*********************************************************************** 3371 * MSI_ProvideQualifiedComponentEx [internal] 3372 */ 3373 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent, 3374 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct, 3375 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf, 3376 LPDWORD pcchPathBuf) 3377 { 3378 WCHAR product[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1]; 3379 WCHAR *desc; 3380 HKEY hkey; 3381 DWORD size; 3382 UINT ret; 3383 INSTALLSTATE state; 3384 3385 if (MSIREG_OpenUserComponentsKey( szComponent, &hkey, FALSE )) return ERROR_UNKNOWN_COMPONENT; 3386 3387 desc = reg_get_multisz( hkey, szQualifier ); 3388 RegCloseKey(hkey); 3389 if (!desc) return ERROR_INDEX_ABSENT; 3390 3391 /* FIXME: handle multiple descriptors */ 3392 ret = MsiDecomposeDescriptorW( desc, product, feature, comp, &size ); 3393 msi_free( desc ); 3394 if (ret != ERROR_SUCCESS) return ret; 3395 3396 if (!szProduct) szProduct = product; 3397 if (!comp[0]) 3398 { 3399 MSIINSTALLCONTEXT ctx; 3400 WCHAR *components; 3401 GUID guid; 3402 3403 /* use the first component of the feature if the descriptor component is empty */ 3404 if ((ret = msi_locate_product( szProduct, &ctx ))) return ret; 3405 if ((ret = MSIREG_OpenUserDataFeaturesKey( szProduct, NULL, ctx, &hkey, FALSE ))) 3406 { 3407 return ERROR_FILE_NOT_FOUND; 3408 } 3409 components = reg_get_sz( hkey, feature ); 3410 RegCloseKey( hkey ); 3411 if (!components) return ERROR_FILE_NOT_FOUND; 3412 3413 if (lstrlenW( components ) < BASE85_SIZE || !decode_base85_guid( components, &guid )) 3414 { 3415 msi_free( components ); 3416 return ERROR_FILE_NOT_FOUND; 3417 } 3418 msi_free( components ); 3419 StringFromGUID2( &guid, comp, ARRAY_SIZE( comp )); 3420 } 3421 3422 state = MSI_GetComponentPath( szProduct, comp, L"S-1-1-0", MSIINSTALLCONTEXT_ALL, lpPathBuf, pcchPathBuf ); 3423 3424 if (state == INSTALLSTATE_MOREDATA) return ERROR_MORE_DATA; 3425 if (state != INSTALLSTATE_LOCAL) return ERROR_FILE_NOT_FOUND; 3426 return ERROR_SUCCESS; 3427 } 3428 3429 /*********************************************************************** 3430 * MsiProvideQualifiedComponentExW [MSI.@] 3431 */ 3432 UINT WINAPI MsiProvideQualifiedComponentExW( const WCHAR *szComponent, const WCHAR *szQualifier, DWORD dwInstallMode, 3433 const WCHAR *szProduct, DWORD Unused1, DWORD Unused2, WCHAR *lpPathBuf, 3434 DWORD *pcchPathBuf ) 3435 { 3436 awstring path; 3437 3438 TRACE( "%s, %s, %lu, %s, %#lx, %#lx, %p, %p\n", debugstr_w(szComponent), debugstr_w(szQualifier), dwInstallMode, 3439 debugstr_w(szProduct), Unused1, Unused2, lpPathBuf, pcchPathBuf ); 3440 3441 path.unicode = TRUE; 3442 path.str.w = lpPathBuf; 3443 3444 return MSI_ProvideQualifiedComponentEx( szComponent, szQualifier, dwInstallMode, szProduct, Unused1, Unused2, 3445 &path, pcchPathBuf ); 3446 } 3447 3448 /*********************************************************************** 3449 * MsiProvideQualifiedComponentExA [MSI.@] 3450 */ 3451 UINT WINAPI MsiProvideQualifiedComponentExA( const char *szComponent, const char *szQualifier, DWORD dwInstallMode, 3452 const char *szProduct, DWORD Unused1, DWORD Unused2, char *lpPathBuf, 3453 DWORD *pcchPathBuf ) 3454 { 3455 WCHAR *szwComponent, *szwQualifier = NULL, *szwProduct = NULL; 3456 UINT r = ERROR_OUTOFMEMORY; 3457 awstring path; 3458 3459 TRACE( "%s, %s, %lu, %s, %#lx, %#lx, %p, %p\n", debugstr_a(szComponent), debugstr_a(szQualifier), dwInstallMode, 3460 debugstr_a(szProduct), Unused1, Unused2, lpPathBuf, pcchPathBuf ); 3461 3462 szwComponent = strdupAtoW( szComponent ); 3463 if (szComponent && !szwComponent) 3464 goto end; 3465 3466 szwQualifier = strdupAtoW( szQualifier ); 3467 if (szQualifier && !szwQualifier) 3468 goto end; 3469 3470 szwProduct = strdupAtoW( szProduct ); 3471 if (szProduct && !szwProduct) 3472 goto end; 3473 3474 path.unicode = FALSE; 3475 path.str.a = lpPathBuf; 3476 3477 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier, 3478 dwInstallMode, szwProduct, Unused1, 3479 Unused2, &path, pcchPathBuf); 3480 end: 3481 msi_free(szwProduct); 3482 msi_free(szwComponent); 3483 msi_free(szwQualifier); 3484 3485 return r; 3486 } 3487 3488 /*********************************************************************** 3489 * MsiProvideQualifiedComponentW [MSI.@] 3490 */ 3491 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent, 3492 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf, 3493 LPDWORD pcchPathBuf) 3494 { 3495 return MsiProvideQualifiedComponentExW(szComponent, szQualifier, 3496 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf); 3497 } 3498 3499 /*********************************************************************** 3500 * MsiProvideQualifiedComponentA [MSI.@] 3501 */ 3502 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent, 3503 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf, 3504 LPDWORD pcchPathBuf) 3505 { 3506 return MsiProvideQualifiedComponentExA(szComponent, szQualifier, 3507 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf); 3508 } 3509 3510 /*********************************************************************** 3511 * MSI_GetUserInfo [internal] 3512 */ 3513 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct, 3514 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf, 3515 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf, 3516 awstring *lpSerialBuf, LPDWORD pcchSerialBuf) 3517 { 3518 WCHAR *user, *org, *serial, squashed_pc[SQUASHED_GUID_SIZE]; 3519 USERINFOSTATE state; 3520 HKEY hkey, props; 3521 LPCWSTR orgptr; 3522 UINT r; 3523 3524 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf, 3525 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf, 3526 pcchSerialBuf); 3527 3528 if (!szProduct || !squash_guid( szProduct, squashed_pc )) 3529 return USERINFOSTATE_INVALIDARG; 3530 3531 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, 3532 &hkey, FALSE) != ERROR_SUCCESS && 3533 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 3534 &hkey, FALSE) != ERROR_SUCCESS && 3535 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, 3536 &hkey, FALSE) != ERROR_SUCCESS) 3537 { 3538 return USERINFOSTATE_UNKNOWN; 3539 } 3540 3541 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, 3542 NULL, &props, FALSE) != ERROR_SUCCESS && 3543 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, 3544 NULL, &props, FALSE) != ERROR_SUCCESS) 3545 { 3546 RegCloseKey(hkey); 3547 return USERINFOSTATE_ABSENT; 3548 } 3549 3550 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW); 3551 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW); 3552 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW); 3553 state = USERINFOSTATE_ABSENT; 3554 3555 RegCloseKey(hkey); 3556 RegCloseKey(props); 3557 3558 if (user && serial) 3559 state = USERINFOSTATE_PRESENT; 3560 3561 if (pcchUserNameBuf) 3562 { 3563 if (lpUserNameBuf && !user) 3564 { 3565 (*pcchUserNameBuf)--; 3566 goto done; 3567 } 3568 3569 r = msi_strcpy_to_awstring(user, -1, lpUserNameBuf, pcchUserNameBuf); 3570 if (r == ERROR_MORE_DATA) 3571 { 3572 state = USERINFOSTATE_MOREDATA; 3573 goto done; 3574 } 3575 } 3576 3577 if (pcchOrgNameBuf) 3578 { 3579 orgptr = org; 3580 if (!orgptr) orgptr = L""; 3581 3582 r = msi_strcpy_to_awstring(orgptr, -1, lpOrgNameBuf, pcchOrgNameBuf); 3583 if (r == ERROR_MORE_DATA) 3584 { 3585 state = USERINFOSTATE_MOREDATA; 3586 goto done; 3587 } 3588 } 3589 3590 if (pcchSerialBuf) 3591 { 3592 if (!serial) 3593 { 3594 (*pcchSerialBuf)--; 3595 goto done; 3596 } 3597 3598 r = msi_strcpy_to_awstring(serial, -1, lpSerialBuf, pcchSerialBuf); 3599 if (r == ERROR_MORE_DATA) 3600 state = USERINFOSTATE_MOREDATA; 3601 } 3602 3603 done: 3604 msi_free(user); 3605 msi_free(org); 3606 msi_free(serial); 3607 3608 return state; 3609 } 3610 3611 /*********************************************************************** 3612 * MsiGetUserInfoW [MSI.@] 3613 */ 3614 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, 3615 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf, 3616 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf, 3617 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf) 3618 { 3619 awstring user, org, serial; 3620 3621 if ((lpUserNameBuf && !pcchUserNameBuf) || 3622 (lpOrgNameBuf && !pcchOrgNameBuf) || 3623 (lpSerialBuf && !pcchSerialBuf)) 3624 return USERINFOSTATE_INVALIDARG; 3625 3626 user.unicode = TRUE; 3627 user.str.w = lpUserNameBuf; 3628 org.unicode = TRUE; 3629 org.str.w = lpOrgNameBuf; 3630 serial.unicode = TRUE; 3631 serial.str.w = lpSerialBuf; 3632 3633 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf, 3634 &org, pcchOrgNameBuf, 3635 &serial, pcchSerialBuf ); 3636 } 3637 3638 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, 3639 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf, 3640 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf, 3641 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf) 3642 { 3643 awstring user, org, serial; 3644 LPWSTR prod; 3645 UINT r; 3646 3647 if ((lpUserNameBuf && !pcchUserNameBuf) || 3648 (lpOrgNameBuf && !pcchOrgNameBuf) || 3649 (lpSerialBuf && !pcchSerialBuf)) 3650 return USERINFOSTATE_INVALIDARG; 3651 3652 prod = strdupAtoW( szProduct ); 3653 if (szProduct && !prod) 3654 return ERROR_OUTOFMEMORY; 3655 3656 user.unicode = FALSE; 3657 user.str.a = lpUserNameBuf; 3658 org.unicode = FALSE; 3659 org.str.a = lpOrgNameBuf; 3660 serial.unicode = FALSE; 3661 serial.str.a = lpSerialBuf; 3662 3663 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf, 3664 &org, pcchOrgNameBuf, 3665 &serial, pcchSerialBuf ); 3666 3667 msi_free( prod ); 3668 3669 return r; 3670 } 3671 3672 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct) 3673 { 3674 MSIHANDLE handle; 3675 UINT rc; 3676 MSIPACKAGE *package; 3677 3678 TRACE("(%s)\n",debugstr_w(szProduct)); 3679 3680 rc = MsiOpenProductW(szProduct,&handle); 3681 if (rc != ERROR_SUCCESS) 3682 return ERROR_INVALID_PARAMETER; 3683 3684 /* MsiCollectUserInfo cannot be called from a custom action. */ 3685 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE); 3686 if (!package) 3687 return ERROR_CALL_NOT_IMPLEMENTED; 3688 3689 rc = ACTION_PerformAction(package, L"FirstRun"); 3690 msiobj_release( &package->hdr ); 3691 3692 MsiCloseHandle(handle); 3693 3694 return rc; 3695 } 3696 3697 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct) 3698 { 3699 MSIHANDLE handle; 3700 UINT rc; 3701 MSIPACKAGE *package; 3702 3703 TRACE("(%s)\n",debugstr_a(szProduct)); 3704 3705 rc = MsiOpenProductA(szProduct,&handle); 3706 if (rc != ERROR_SUCCESS) 3707 return ERROR_INVALID_PARAMETER; 3708 3709 /* MsiCollectUserInfo cannot be called from a custom action. */ 3710 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE); 3711 if (!package) 3712 return ERROR_CALL_NOT_IMPLEMENTED; 3713 3714 rc = ACTION_PerformAction(package, L"FirstRun"); 3715 msiobj_release( &package->hdr ); 3716 3717 MsiCloseHandle(handle); 3718 3719 return rc; 3720 } 3721 3722 /*********************************************************************** 3723 * MsiConfigureFeatureA [MSI.@] 3724 */ 3725 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState) 3726 { 3727 LPWSTR prod, feat = NULL; 3728 UINT r = ERROR_OUTOFMEMORY; 3729 3730 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState); 3731 3732 prod = strdupAtoW( szProduct ); 3733 if (szProduct && !prod) 3734 goto end; 3735 3736 feat = strdupAtoW( szFeature ); 3737 if (szFeature && !feat) 3738 goto end; 3739 3740 r = MsiConfigureFeatureW(prod, feat, eInstallState); 3741 3742 end: 3743 msi_free(feat); 3744 msi_free(prod); 3745 3746 return r; 3747 } 3748 3749 /*********************************************************************** 3750 * MsiConfigureFeatureW [MSI.@] 3751 */ 3752 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState) 3753 { 3754 MSIPACKAGE *package = NULL; 3755 UINT r; 3756 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH]; 3757 DWORD sz; 3758 3759 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState); 3760 3761 if (!szProduct || !szFeature) 3762 return ERROR_INVALID_PARAMETER; 3763 3764 switch (eInstallState) 3765 { 3766 case INSTALLSTATE_DEFAULT: 3767 /* FIXME: how do we figure out the default location? */ 3768 eInstallState = INSTALLSTATE_LOCAL; 3769 break; 3770 case INSTALLSTATE_LOCAL: 3771 case INSTALLSTATE_SOURCE: 3772 case INSTALLSTATE_ABSENT: 3773 case INSTALLSTATE_ADVERTISED: 3774 break; 3775 default: 3776 return ERROR_INVALID_PARAMETER; 3777 } 3778 3779 r = MSI_OpenProductW( szProduct, &package ); 3780 if (r != ERROR_SUCCESS) 3781 return r; 3782 3783 sz = sizeof(sourcepath); 3784 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 3785 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); 3786 3787 sz = sizeof(filename); 3788 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 3789 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); 3790 3791 lstrcatW( sourcepath, filename ); 3792 3793 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL ); 3794 3795 r = ACTION_PerformAction(package, L"CostInitialize"); 3796 if (r != ERROR_SUCCESS) 3797 goto end; 3798 3799 r = MSI_SetFeatureStateW( package, szFeature, eInstallState); 3800 if (r != ERROR_SUCCESS) 3801 goto end; 3802 3803 r = MSI_InstallPackage( package, sourcepath, NULL ); 3804 3805 end: 3806 msiobj_release( &package->hdr ); 3807 3808 return r; 3809 } 3810 3811 /*********************************************************************** 3812 * MsiCreateAndVerifyInstallerDirectory [MSI.@] 3813 * 3814 * Notes: undocumented 3815 */ 3816 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved) 3817 { 3818 WCHAR path[MAX_PATH]; 3819 3820 TRACE( "%#lx\n", dwReserved ); 3821 3822 if (dwReserved) 3823 { 3824 FIXME( "dwReserved = %#lx\n", dwReserved ); 3825 return ERROR_INVALID_PARAMETER; 3826 } 3827 3828 if (!GetWindowsDirectoryW(path, MAX_PATH)) 3829 return ERROR_FUNCTION_FAILED; 3830 3831 lstrcatW(path, L"\\Installer"); 3832 3833 if (!CreateDirectoryW(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) 3834 return ERROR_FUNCTION_FAILED; 3835 3836 return ERROR_SUCCESS; 3837 } 3838 3839 /*********************************************************************** 3840 * MsiGetShortcutTargetA [MSI.@] 3841 */ 3842 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget, 3843 LPSTR szProductCode, LPSTR szFeatureId, 3844 LPSTR szComponentCode ) 3845 { 3846 LPWSTR target; 3847 const int len = MAX_FEATURE_CHARS+1; 3848 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1]; 3849 UINT r; 3850 3851 target = strdupAtoW( szShortcutTarget ); 3852 if (szShortcutTarget && !target ) 3853 return ERROR_OUTOFMEMORY; 3854 product[0] = 0; 3855 feature[0] = 0; 3856 component[0] = 0; 3857 r = MsiGetShortcutTargetW( target, product, feature, component ); 3858 msi_free( target ); 3859 if (r == ERROR_SUCCESS) 3860 { 3861 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL ); 3862 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL ); 3863 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL ); 3864 } 3865 return r; 3866 } 3867 3868 /*********************************************************************** 3869 * MsiGetShortcutTargetW [MSI.@] 3870 */ 3871 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget, 3872 LPWSTR szProductCode, LPWSTR szFeatureId, 3873 LPWSTR szComponentCode ) 3874 { 3875 IShellLinkDataList *dl = NULL; 3876 IPersistFile *pf = NULL; 3877 LPEXP_DARWIN_LINK darwin = NULL; 3878 HRESULT r, init; 3879 3880 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget), 3881 szProductCode, szFeatureId, szComponentCode ); 3882 3883 init = CoInitialize(NULL); 3884 3885 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 3886 &IID_IPersistFile, (LPVOID*) &pf ); 3887 if( SUCCEEDED( r ) ) 3888 { 3889 r = IPersistFile_Load( pf, szShortcutTarget, 3890 STGM_READ | STGM_SHARE_DENY_WRITE ); 3891 if( SUCCEEDED( r ) ) 3892 { 3893 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList, 3894 (LPVOID*) &dl ); 3895 if( SUCCEEDED( r ) ) 3896 { 3897 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG, 3898 (LPVOID) &darwin ); 3899 IShellLinkDataList_Release( dl ); 3900 } 3901 } 3902 IPersistFile_Release( pf ); 3903 } 3904 3905 if (SUCCEEDED(init)) 3906 CoUninitialize(); 3907 3908 TRACE("darwin = %p\n", darwin); 3909 3910 if (darwin) 3911 { 3912 DWORD sz; 3913 UINT ret; 3914 3915 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID, 3916 szProductCode, szFeatureId, szComponentCode, &sz ); 3917 LocalFree( darwin ); 3918 return ret; 3919 } 3920 3921 return ERROR_FUNCTION_FAILED; 3922 } 3923 3924 UINT WINAPI MsiReinstallFeatureW( const WCHAR *szProduct, const WCHAR *szFeature, DWORD dwReinstallMode ) 3925 { 3926 MSIPACKAGE *package; 3927 MSIINSTALLCONTEXT context; 3928 UINT r; 3929 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH], reinstallmode[11]; 3930 WCHAR *ptr, *cmdline; 3931 DWORD sz; 3932 3933 TRACE( "%s, %s, %#lx\n", debugstr_w(szProduct), debugstr_w(szFeature), dwReinstallMode ); 3934 3935 r = msi_locate_product( szProduct, &context ); 3936 if (r != ERROR_SUCCESS) 3937 return r; 3938 3939 ptr = reinstallmode; 3940 3941 if (dwReinstallMode & REINSTALLMODE_FILEMISSING) 3942 *ptr++ = 'p'; 3943 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION) 3944 *ptr++ = 'o'; 3945 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION) 3946 *ptr++ = 'w'; 3947 if (dwReinstallMode & REINSTALLMODE_FILEEXACT) 3948 *ptr++ = 'd'; 3949 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY) 3950 *ptr++ = 'c'; 3951 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE) 3952 *ptr++ = 'a'; 3953 if (dwReinstallMode & REINSTALLMODE_USERDATA) 3954 *ptr++ = 'u'; 3955 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA) 3956 *ptr++ = 'm'; 3957 if (dwReinstallMode & REINSTALLMODE_SHORTCUT) 3958 *ptr++ = 's'; 3959 if (dwReinstallMode & REINSTALLMODE_PACKAGE) 3960 *ptr++ = 'v'; 3961 *ptr = 0; 3962 3963 sz = sizeof(sourcepath); 3964 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT, 3965 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz ); 3966 sz = sizeof(filename); 3967 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT, 3968 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz ); 3969 lstrcatW( sourcepath, filename ); 3970 3971 if (dwReinstallMode & REINSTALLMODE_PACKAGE) 3972 r = MSI_OpenPackageW( sourcepath, 0, &package ); 3973 else 3974 r = MSI_OpenProductW( szProduct, &package ); 3975 3976 if (r != ERROR_SUCCESS) 3977 return r; 3978 3979 sz = (lstrlenW( L"%s=%s %s=%s" ) + lstrlenW( L"REINSTALLMODE" ) + lstrlenW( reinstallmode )) * sizeof(WCHAR); 3980 sz += (lstrlenW( L"REINSTALL" ) + lstrlenW( szFeature )) * sizeof(WCHAR); 3981 if (!(cmdline = msi_alloc( sz ))) 3982 { 3983 msiobj_release( &package->hdr ); 3984 return ERROR_OUTOFMEMORY; 3985 } 3986 swprintf( cmdline, sz / sizeof(WCHAR), L"%s=%s %s=%s", L"REINSTALLMODE", reinstallmode, L"REINSTALL", szFeature ); 3987 3988 r = MSI_InstallPackage( package, sourcepath, cmdline ); 3989 msiobj_release( &package->hdr ); 3990 msi_free( cmdline ); 3991 3992 return r; 3993 } 3994 3995 UINT WINAPI MsiReinstallFeatureA( const char *szProduct, const char *szFeature, DWORD dwReinstallMode ) 3996 { 3997 WCHAR *wszProduct, *wszFeature; 3998 UINT rc; 3999 4000 TRACE( "%s, %s, %lu\n", debugstr_a(szProduct), debugstr_a(szFeature), dwReinstallMode ); 4001 4002 wszProduct = strdupAtoW(szProduct); 4003 wszFeature = strdupAtoW(szFeature); 4004 4005 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode); 4006 4007 msi_free(wszProduct); 4008 msi_free(wszFeature); 4009 return rc; 4010 } 4011 4012 typedef struct 4013 { 4014 unsigned int i[2]; 4015 unsigned int buf[4]; 4016 unsigned char in[64]; 4017 unsigned char digest[16]; 4018 } MD5_CTX; 4019 4020 extern VOID WINAPI MD5Init( MD5_CTX *); 4021 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int ); 4022 extern VOID WINAPI MD5Final( MD5_CTX *); 4023 4024 UINT msi_get_filehash( MSIPACKAGE *package, const WCHAR *path, MSIFILEHASHINFO *hash ) 4025 { 4026 HANDLE handle, mapping; 4027 void *p; 4028 DWORD length; 4029 UINT r = ERROR_FUNCTION_FAILED; 4030 4031 if (package) 4032 handle = msi_create_file( package, path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, OPEN_EXISTING, 0 ); 4033 else 4034 handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL ); 4035 if (handle == INVALID_HANDLE_VALUE) 4036 { 4037 WARN( "can't open file %lu\n", GetLastError() ); 4038 return ERROR_FILE_NOT_FOUND; 4039 } 4040 if ((length = GetFileSize( handle, NULL ))) 4041 { 4042 if ((mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL ))) 4043 { 4044 if ((p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length ))) 4045 { 4046 MD5_CTX ctx; 4047 4048 MD5Init( &ctx ); 4049 MD5Update( &ctx, p, length ); 4050 MD5Final( &ctx ); 4051 UnmapViewOfFile( p ); 4052 4053 memcpy( hash->dwData, ctx.digest, sizeof(hash->dwData) ); 4054 r = ERROR_SUCCESS; 4055 } 4056 CloseHandle( mapping ); 4057 } 4058 } 4059 else 4060 { 4061 /* Empty file -> set hash to 0 */ 4062 memset( hash->dwData, 0, sizeof(hash->dwData) ); 4063 r = ERROR_SUCCESS; 4064 } 4065 4066 CloseHandle( handle ); 4067 return r; 4068 } 4069 4070 /*********************************************************************** 4071 * MsiGetFileHashW [MSI.@] 4072 */ 4073 UINT WINAPI MsiGetFileHashW( const WCHAR *szFilePath, DWORD dwOptions, MSIFILEHASHINFO *pHash ) 4074 { 4075 TRACE( "%s, %#lx, %p\n", debugstr_w(szFilePath), dwOptions, pHash ); 4076 4077 if (!szFilePath) 4078 return ERROR_INVALID_PARAMETER; 4079 4080 if (!*szFilePath) 4081 return ERROR_PATH_NOT_FOUND; 4082 4083 if (dwOptions) 4084 return ERROR_INVALID_PARAMETER; 4085 if (!pHash) 4086 return ERROR_INVALID_PARAMETER; 4087 if (pHash->dwFileHashInfoSize < sizeof *pHash) 4088 return ERROR_INVALID_PARAMETER; 4089 4090 return msi_get_filehash( NULL, szFilePath, pHash ); 4091 } 4092 4093 /*********************************************************************** 4094 * MsiGetFileHashA [MSI.@] 4095 */ 4096 UINT WINAPI MsiGetFileHashA( const char *szFilePath, DWORD dwOptions, MSIFILEHASHINFO *pHash ) 4097 { 4098 LPWSTR file; 4099 UINT r; 4100 4101 TRACE( "%s, %#lx, %p\n", debugstr_a(szFilePath), dwOptions, pHash ); 4102 4103 file = strdupAtoW( szFilePath ); 4104 if (szFilePath && !file) 4105 return ERROR_OUTOFMEMORY; 4106 4107 r = MsiGetFileHashW( file, dwOptions, pHash ); 4108 msi_free( file ); 4109 return r; 4110 } 4111 4112 /*********************************************************************** 4113 * MsiAdvertiseScriptW [MSI.@] 4114 */ 4115 UINT WINAPI MsiAdvertiseScriptW( const WCHAR *szScriptFile, DWORD dwFlags, HKEY *phRegData, BOOL fRemoveItems ) 4116 { 4117 FIXME( "%s, %#lx, %p, %d\n", debugstr_w(szScriptFile), dwFlags, phRegData, fRemoveItems ); 4118 return ERROR_CALL_NOT_IMPLEMENTED; 4119 } 4120 4121 /*********************************************************************** 4122 * MsiAdvertiseScriptA [MSI.@] 4123 */ 4124 UINT WINAPI MsiAdvertiseScriptA( const char *szScriptFile, DWORD dwFlags, HKEY *phRegData, BOOL fRemoveItems ) 4125 { 4126 FIXME( "%s, %#lx, %p, %d\n", debugstr_a(szScriptFile), dwFlags, phRegData, fRemoveItems ); 4127 return ERROR_CALL_NOT_IMPLEMENTED; 4128 } 4129 4130 /*********************************************************************** 4131 * MsiIsProductElevatedW [MSI.@] 4132 */ 4133 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated ) 4134 { 4135 FIXME("%s %p - stub\n", 4136 debugstr_w( szProduct ), pfElevated ); 4137 *pfElevated = TRUE; 4138 return ERROR_SUCCESS; 4139 } 4140 4141 /*********************************************************************** 4142 * MsiIsProductElevatedA [MSI.@] 4143 */ 4144 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated ) 4145 { 4146 FIXME("%s %p - stub\n", 4147 debugstr_a( szProduct ), pfElevated ); 4148 *pfElevated = TRUE; 4149 return ERROR_SUCCESS; 4150 } 4151 4152 /*********************************************************************** 4153 * MsiSetExternalUIRecord [MSI.@] 4154 */ 4155 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler, DWORD filter, void *context, 4156 INSTALLUI_HANDLER_RECORD *prev ) 4157 { 4158 TRACE( "%p, %#lx, %p, %p\n", handler, filter, context, prev ); 4159 4160 if (prev) 4161 *prev = gUIHandlerRecord; 4162 4163 gUIHandlerRecord = handler; 4164 gUIFilterRecord = filter; 4165 gUIContextRecord = context; 4166 4167 return ERROR_SUCCESS; 4168 } 4169 4170 /*********************************************************************** 4171 * MsiInstallMissingComponentA [MSI.@] 4172 */ 4173 UINT WINAPI MsiInstallMissingComponentA( LPCSTR product, LPCSTR component, INSTALLSTATE state ) 4174 { 4175 UINT r; 4176 WCHAR *productW = NULL, *componentW = NULL; 4177 4178 TRACE("%s, %s, %d\n", debugstr_a(product), debugstr_a(component), state); 4179 4180 if (product && !(productW = strdupAtoW( product ))) 4181 return ERROR_OUTOFMEMORY; 4182 4183 if (component && !(componentW = strdupAtoW( component ))) 4184 { 4185 msi_free( productW ); 4186 return ERROR_OUTOFMEMORY; 4187 } 4188 4189 r = MsiInstallMissingComponentW( productW, componentW, state ); 4190 msi_free( productW ); 4191 msi_free( componentW ); 4192 return r; 4193 } 4194 4195 /*********************************************************************** 4196 * MsiInstallMissingComponentW [MSI.@] 4197 */ 4198 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState) 4199 { 4200 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState); 4201 return ERROR_SUCCESS; 4202 } 4203 4204 UINT WINAPI MsiProvideComponentA( const char *product, const char *feature, const char *component, DWORD mode, 4205 char *buf, DWORD *buflen ) 4206 { 4207 WCHAR *productW = NULL, *componentW = NULL, *featureW = NULL, *bufW = NULL; 4208 UINT r = ERROR_OUTOFMEMORY; 4209 DWORD lenW = 0; 4210 int len; 4211 4212 TRACE( "%s, %s, %s, %#lx, %p, %p\n", debugstr_a(product), debugstr_a(component), debugstr_a(feature), mode, 4213 buf, buflen ); 4214 4215 if (product && !(productW = strdupAtoW( product ))) goto done; 4216 if (feature && !(featureW = strdupAtoW( feature ))) goto done; 4217 if (component && !(componentW = strdupAtoW( component ))) goto done; 4218 4219 r = MsiProvideComponentW( productW, featureW, componentW, mode, NULL, &lenW ); 4220 if (r != ERROR_SUCCESS) 4221 goto done; 4222 4223 if (!(bufW = msi_alloc( ++lenW * sizeof(WCHAR) ))) 4224 { 4225 r = ERROR_OUTOFMEMORY; 4226 goto done; 4227 } 4228 4229 r = MsiProvideComponentW( productW, featureW, componentW, mode, bufW, &lenW ); 4230 if (r != ERROR_SUCCESS) 4231 goto done; 4232 4233 len = WideCharToMultiByte( CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL ); 4234 if (buf) 4235 { 4236 if (len > *buflen) 4237 r = ERROR_MORE_DATA; 4238 else 4239 WideCharToMultiByte( CP_ACP, 0, bufW, -1, buf, *buflen, NULL, NULL ); 4240 } 4241 4242 *buflen = len - 1; 4243 4244 done: 4245 msi_free( productW ); 4246 msi_free( featureW ); 4247 msi_free( componentW ); 4248 msi_free( bufW ); 4249 return r; 4250 } 4251 4252 UINT WINAPI MsiProvideComponentW( const WCHAR *product, const WCHAR *feature, const WCHAR *component, DWORD mode, 4253 WCHAR *buf, DWORD *buflen ) 4254 { 4255 INSTALLSTATE state; 4256 4257 TRACE( "%s, %s, %s, %#lx, %p, %p\n", debugstr_w(product), debugstr_w(component), debugstr_w(feature), mode, 4258 buf, buflen); 4259 4260 state = MsiQueryFeatureStateW( product, feature ); 4261 TRACE("feature state: %d\n", state); 4262 switch (mode) 4263 { 4264 case INSTALLMODE_NODETECTION: 4265 break; 4266 4267 default: 4268 FIXME( "mode %#lx not implemented\n", mode ); 4269 return ERROR_INSTALL_FAILURE; 4270 } 4271 4272 state = MsiGetComponentPathW( product, component, buf, buflen ); 4273 TRACE("component state: %d\n", state); 4274 switch (state) 4275 { 4276 case INSTALLSTATE_INVALIDARG: 4277 return ERROR_INVALID_PARAMETER; 4278 4279 case INSTALLSTATE_MOREDATA: 4280 return ERROR_MORE_DATA; 4281 4282 case INSTALLSTATE_ADVERTISED: 4283 case INSTALLSTATE_LOCAL: 4284 case INSTALLSTATE_SOURCE: 4285 MsiUseFeatureW( product, feature ); 4286 return ERROR_SUCCESS; 4287 4288 default: 4289 TRACE("MsiGetComponentPathW returned %d\n", state); 4290 return ERROR_INSTALL_FAILURE; 4291 } 4292 } 4293 4294 /*********************************************************************** 4295 * MsiBeginTransactionA [MSI.@] 4296 */ 4297 UINT WINAPI MsiBeginTransactionA( const char *name, DWORD attrs, MSIHANDLE *id, HANDLE *event ) 4298 { 4299 WCHAR *nameW; 4300 UINT r; 4301 4302 FIXME( "%s, %#lx, %p, %p\n", debugstr_a(name), attrs, id, event ); 4303 4304 nameW = strdupAtoW( name ); 4305 if (name && !nameW) 4306 return ERROR_OUTOFMEMORY; 4307 4308 r = MsiBeginTransactionW( nameW, attrs, id, event ); 4309 msi_free( nameW ); 4310 return r; 4311 } 4312 4313 /*********************************************************************** 4314 * MsiBeginTransactionW [MSI.@] 4315 */ 4316 UINT WINAPI MsiBeginTransactionW( const WCHAR *name, DWORD attrs, MSIHANDLE *id, HANDLE *event ) 4317 { 4318 FIXME( "%s, %#lx, %p, %p\n", debugstr_w(name), attrs, id, event ); 4319 4320 *id = (MSIHANDLE)0xdeadbeef; 4321 *event = (HANDLE)0xdeadbeef; 4322 4323 return ERROR_SUCCESS; 4324 } 4325 4326 /*********************************************************************** 4327 * MsiJoinTransaction [MSI.@] 4328 */ 4329 UINT WINAPI MsiJoinTransaction( MSIHANDLE handle, DWORD attrs, HANDLE *event ) 4330 { 4331 FIXME( "%lu, %#lx, %p\n", handle, attrs, event ); 4332 4333 *event = (HANDLE)0xdeadbeef; 4334 return ERROR_SUCCESS; 4335 } 4336 4337 /*********************************************************************** 4338 * MsiEndTransaction [MSI.@] 4339 */ 4340 UINT WINAPI MsiEndTransaction( DWORD state ) 4341 { 4342 FIXME( "%#lx\n", state ); 4343 return ERROR_SUCCESS; 4344 } 4345 4346 UINT WINAPI Migrate10CachedPackagesW( void *a, void *b, void *c, DWORD d ) 4347 { 4348 FIXME( "%p, %p, %p, %#lx\n", a, b, c, d ); 4349 return ERROR_SUCCESS; 4350 } 4351 4352 /*********************************************************************** 4353 * MsiRemovePatchesA [MSI.@] 4354 */ 4355 UINT WINAPI MsiRemovePatchesA(LPCSTR patchlist, LPCSTR product, INSTALLTYPE type, LPCSTR propertylist) 4356 { 4357 FIXME("(%s %s %d %s\n", debugstr_a(patchlist), debugstr_a(product), type, debugstr_a(propertylist)); 4358 return ERROR_SUCCESS; 4359 } 4360 4361 /*********************************************************************** 4362 * MsiRemovePatchesW [MSI.@] 4363 */ 4364 UINT WINAPI MsiRemovePatchesW(LPCWSTR patchlist, LPCWSTR product, INSTALLTYPE type, LPCWSTR propertylist) 4365 { 4366 FIXME("(%s %s %d %s\n", debugstr_w(patchlist), debugstr_w(product), type, debugstr_w(propertylist)); 4367 return ERROR_SUCCESS; 4368 } 4369