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