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