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 gUILevel = dwUILevel; 2297 if (phWnd) 2298 { 2299 gUIhwnd = *phWnd; 2300 *phWnd = oldwnd; 2301 } 2302 return old; 2303 } 2304 2305 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler, 2306 DWORD dwMessageFilter, LPVOID pvContext) 2307 { 2308 INSTALLUI_HANDLERA prev = gUIHandlerA; 2309 2310 TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext); 2311 2312 gUIHandlerA = puiHandler; 2313 gUIHandlerW = NULL; 2314 gUIFilter = dwMessageFilter; 2315 gUIContext = pvContext; 2316 2317 return prev; 2318 } 2319 2320 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler, 2321 DWORD dwMessageFilter, LPVOID pvContext) 2322 { 2323 INSTALLUI_HANDLERW prev = gUIHandlerW; 2324 2325 TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext); 2326 2327 gUIHandlerA = NULL; 2328 gUIHandlerW = puiHandler; 2329 gUIFilter = dwMessageFilter; 2330 gUIContext = pvContext; 2331 2332 return prev; 2333 } 2334 2335 /****************************************************************** 2336 * MsiLoadStringW [MSI.@] 2337 * 2338 * Loads a string from MSI's string resources. 2339 * 2340 * PARAMS 2341 * 2342 * handle [I] only -1 is handled currently 2343 * id [I] id of the string to be loaded 2344 * lpBuffer [O] buffer for the string to be written to 2345 * nBufferMax [I] maximum size of the buffer in characters 2346 * lang [I] the preferred language for the string 2347 * 2348 * RETURNS 2349 * 2350 * If successful, this function returns the language id of the string loaded 2351 * If the function fails, the function returns zero. 2352 * 2353 * NOTES 2354 * 2355 * The type of the first parameter is unknown. LoadString's prototype 2356 * suggests that it might be a module handle. I have made it an MSI handle 2357 * for starters, as -1 is an invalid MSI handle, but not an invalid module 2358 * handle. Maybe strings can be stored in an MSI database somehow. 2359 */ 2360 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer, 2361 int nBufferMax, LANGID lang ) 2362 { 2363 HRSRC hres; 2364 HGLOBAL hResData; 2365 LPWSTR p; 2366 DWORD i, len; 2367 2368 TRACE("%d %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang); 2369 2370 if( handle != -1 ) 2371 FIXME("don't know how to deal with handle = %08x\n", handle); 2372 2373 if( !lang ) 2374 lang = GetUserDefaultLangID(); 2375 2376 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING, 2377 (LPWSTR)1, lang ); 2378 if( !hres ) 2379 return 0; 2380 hResData = LoadResource( msi_hInstance, hres ); 2381 if( !hResData ) 2382 return 0; 2383 p = LockResource( hResData ); 2384 if( !p ) 2385 return 0; 2386 2387 for (i = 0; i < (id & 0xf); i++) p += *p + 1; 2388 len = *p; 2389 2390 if( nBufferMax <= len ) 2391 return 0; 2392 2393 memcpy( lpBuffer, p+1, len * sizeof(WCHAR)); 2394 lpBuffer[ len ] = 0; 2395 2396 TRACE("found -> %s\n", debugstr_w(lpBuffer)); 2397 return lang; 2398 } 2399 2400 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer, 2401 int nBufferMax, LANGID lang ) 2402 { 2403 LPWSTR bufW; 2404 LANGID r; 2405 INT len; 2406 2407 bufW = msi_alloc(nBufferMax*sizeof(WCHAR)); 2408 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang); 2409 if( r ) 2410 { 2411 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL ); 2412 if( len <= nBufferMax ) 2413 WideCharToMultiByte( CP_ACP, 0, bufW, -1, 2414 lpBuffer, nBufferMax, NULL, NULL ); 2415 else 2416 r = 0; 2417 } 2418 msi_free(bufW); 2419 return r; 2420 } 2421 2422 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf, 2423 LPDWORD pcchBuf) 2424 { 2425 char szProduct[GUID_SIZE]; 2426 2427 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf); 2428 2429 if (!szComponent || !pcchBuf) 2430 return INSTALLSTATE_INVALIDARG; 2431 2432 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS) 2433 return INSTALLSTATE_UNKNOWN; 2434 2435 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf ); 2436 } 2437 2438 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf, 2439 LPDWORD pcchBuf) 2440 { 2441 WCHAR szProduct[GUID_SIZE]; 2442 2443 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf); 2444 2445 if (!szComponent || !pcchBuf) 2446 return INSTALLSTATE_INVALIDARG; 2447 2448 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS) 2449 return INSTALLSTATE_UNKNOWN; 2450 2451 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf ); 2452 } 2453 2454 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, 2455 WORD wLanguageId, DWORD f) 2456 { 2457 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption), 2458 uType, wLanguageId, f); 2459 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId); 2460 } 2461 2462 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, 2463 WORD wLanguageId, DWORD f) 2464 { 2465 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption), 2466 uType, wLanguageId, f); 2467 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId); 2468 } 2469 2470 UINT WINAPI MsiMessageBoxExA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, 2471 DWORD unknown, WORD wLanguageId, DWORD f) 2472 { 2473 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_a(lpText), 2474 debugstr_a(lpCaption), uType, unknown, wLanguageId, f); 2475 return MessageBoxExA(hWnd, lpText, lpCaption, uType, wLanguageId); 2476 } 2477 2478 UINT WINAPI MsiMessageBoxExW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, 2479 DWORD unknown, WORD wLanguageId, DWORD f) 2480 { 2481 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_w(lpText), 2482 debugstr_w(lpCaption), uType, unknown, wLanguageId, f); 2483 return MessageBoxExW(hWnd, lpText, lpCaption, uType, wLanguageId); 2484 } 2485 2486 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext, 2487 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, 2488 LPDWORD pcchPathBuf ) 2489 { 2490 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName), 2491 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, 2492 pcchPathBuf); 2493 return ERROR_CALL_NOT_IMPLEMENTED; 2494 } 2495 2496 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext, 2497 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, 2498 LPDWORD pcchPathBuf ) 2499 { 2500 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName), 2501 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, 2502 pcchPathBuf); 2503 return ERROR_CALL_NOT_IMPLEMENTED; 2504 } 2505 2506 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, 2507 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs ) 2508 { 2509 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs ); 2510 return ERROR_CALL_NOT_IMPLEMENTED; 2511 } 2512 2513 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, 2514 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs ) 2515 { 2516 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs ); 2517 return ERROR_CALL_NOT_IMPLEMENTED; 2518 } 2519 2520 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR path, DWORD flags, PCCERT_CONTEXT *cert, 2521 LPBYTE hash, LPDWORD hashlen ) 2522 { 2523 UINT r; 2524 WCHAR *pathW = NULL; 2525 2526 TRACE("%s %08x %p %p %p\n", debugstr_a(path), flags, cert, hash, hashlen); 2527 2528 if (path && !(pathW = strdupAtoW( path ))) return E_OUTOFMEMORY; 2529 r = MsiGetFileSignatureInformationW( pathW, flags, cert, hash, hashlen ); 2530 msi_free( pathW ); 2531 return r; 2532 } 2533 2534 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR path, DWORD flags, PCCERT_CONTEXT *cert, 2535 LPBYTE hash, LPDWORD hashlen ) 2536 { 2537 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2; 2538 HRESULT hr; 2539 WINTRUST_DATA data; 2540 WINTRUST_FILE_INFO info; 2541 CRYPT_PROVIDER_SGNR *signer; 2542 CRYPT_PROVIDER_CERT *provider; 2543 2544 TRACE("%s %08x %p %p %p\n", debugstr_w(path), flags, cert, hash, hashlen); 2545 2546 if (!path || !cert) return E_INVALIDARG; 2547 2548 info.cbStruct = sizeof(info); 2549 info.pcwszFilePath = path; 2550 info.hFile = NULL; 2551 info.pgKnownSubject = NULL; 2552 2553 data.cbStruct = sizeof(data); 2554 data.pPolicyCallbackData = NULL; 2555 data.pSIPClientData = NULL; 2556 data.dwUIChoice = WTD_UI_NONE; 2557 data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN; 2558 data.dwUnionChoice = WTD_CHOICE_FILE; 2559 data.u.pFile = &info; 2560 data.dwStateAction = WTD_STATEACTION_VERIFY; 2561 data.hWVTStateData = NULL; 2562 data.pwszURLReference = NULL; 2563 data.dwProvFlags = 0; 2564 data.dwUIContext = WTD_UICONTEXT_INSTALL; 2565 hr = WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data ); 2566 *cert = NULL; 2567 if (FAILED(hr)) goto done; 2568 2569 if (!(signer = WTHelperGetProvSignerFromChain( data.hWVTStateData, 0, FALSE, 0 ))) 2570 { 2571 hr = TRUST_E_NOSIGNATURE; 2572 goto done; 2573 } 2574 if (hash) 2575 { 2576 DWORD len = signer->psSigner->EncryptedHash.cbData; 2577 if (*hashlen < len) 2578 { 2579 *hashlen = len; 2580 hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA); 2581 goto done; 2582 } 2583 memcpy( hash, signer->psSigner->EncryptedHash.pbData, len ); 2584 *hashlen = len; 2585 } 2586 if (!(provider = WTHelperGetProvCertFromChain( signer, 0 ))) 2587 { 2588 hr = TRUST_E_PROVIDER_UNKNOWN; 2589 goto done; 2590 } 2591 *cert = CertDuplicateCertificateContext( provider->pCert ); 2592 2593 done: 2594 data.dwStateAction = WTD_STATEACTION_CLOSE; 2595 WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data ); 2596 return hr; 2597 } 2598 2599 /****************************************************************** 2600 * MsiGetProductPropertyA [MSI.@] 2601 */ 2602 UINT WINAPI MsiGetProductPropertyA(MSIHANDLE hProduct, LPCSTR szProperty, 2603 LPSTR szValue, LPDWORD pccbValue) 2604 { 2605 LPWSTR prop = NULL, val = NULL; 2606 DWORD len; 2607 UINT r; 2608 2609 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_a(szProperty), 2610 szValue, pccbValue); 2611 2612 if (szValue && !pccbValue) 2613 return ERROR_INVALID_PARAMETER; 2614 2615 if (szProperty) prop = strdupAtoW(szProperty); 2616 2617 len = 0; 2618 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len); 2619 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 2620 goto done; 2621 2622 if (r == ERROR_SUCCESS) 2623 { 2624 if (szValue) *szValue = '\0'; 2625 if (pccbValue) *pccbValue = 0; 2626 goto done; 2627 } 2628 2629 val = msi_alloc(++len * sizeof(WCHAR)); 2630 if (!val) 2631 { 2632 r = ERROR_OUTOFMEMORY; 2633 goto done; 2634 } 2635 2636 r = MsiGetProductPropertyW(hProduct, prop, val, &len); 2637 if (r != ERROR_SUCCESS) 2638 goto done; 2639 2640 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL); 2641 2642 if (szValue) 2643 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue, 2644 *pccbValue, NULL, NULL); 2645 2646 if (pccbValue) 2647 { 2648 if (len > *pccbValue) 2649 r = ERROR_MORE_DATA; 2650 2651 *pccbValue = len - 1; 2652 } 2653 2654 done: 2655 msi_free(prop); 2656 msi_free(val); 2657 2658 return r; 2659 } 2660 2661 /****************************************************************** 2662 * MsiGetProductPropertyW [MSI.@] 2663 */ 2664 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE hProduct, LPCWSTR szProperty, 2665 LPWSTR szValue, LPDWORD pccbValue) 2666 { 2667 MSIPACKAGE *package; 2668 MSIQUERY *view = NULL; 2669 MSIRECORD *rec = NULL; 2670 LPCWSTR val; 2671 UINT r; 2672 2673 static const WCHAR query[] = { 2674 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 2675 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ', 2676 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0}; 2677 2678 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_w(szProperty), 2679 szValue, pccbValue); 2680 2681 if (!szProperty) 2682 return ERROR_INVALID_PARAMETER; 2683 2684 if (szValue && !pccbValue) 2685 return ERROR_INVALID_PARAMETER; 2686 2687 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE); 2688 if (!package) 2689 return ERROR_INVALID_HANDLE; 2690 2691 r = MSI_OpenQuery(package->db, &view, query, szProperty); 2692 if (r != ERROR_SUCCESS) 2693 goto done; 2694 2695 r = MSI_ViewExecute(view, 0); 2696 if (r != ERROR_SUCCESS) 2697 goto done; 2698 2699 r = MSI_ViewFetch(view, &rec); 2700 if (r != ERROR_SUCCESS) 2701 goto done; 2702 2703 val = MSI_RecordGetString(rec, 2); 2704 if (!val) 2705 goto done; 2706 2707 if (lstrlenW(val) >= *pccbValue) 2708 { 2709 if (szValue) lstrcpynW(szValue, val, *pccbValue); 2710 r = ERROR_MORE_DATA; 2711 } 2712 else 2713 { 2714 if (szValue) lstrcpyW(szValue, val); 2715 r = ERROR_SUCCESS; 2716 } 2717 2718 *pccbValue = lstrlenW(val); 2719 2720 done: 2721 if (view) 2722 { 2723 MSI_ViewClose(view); 2724 msiobj_release(&view->hdr); 2725 if (rec) msiobj_release(&rec->hdr); 2726 } 2727 2728 if (!rec) 2729 { 2730 if (szValue) *szValue = '\0'; 2731 if (pccbValue) *pccbValue = 0; 2732 r = ERROR_SUCCESS; 2733 } 2734 2735 msiobj_release(&package->hdr); 2736 return r; 2737 } 2738 2739 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage ) 2740 { 2741 UINT r; 2742 LPWSTR szPack = NULL; 2743 2744 TRACE("%s\n", debugstr_a(szPackage) ); 2745 2746 if( szPackage ) 2747 { 2748 szPack = strdupAtoW( szPackage ); 2749 if( !szPack ) 2750 return ERROR_OUTOFMEMORY; 2751 } 2752 2753 r = MsiVerifyPackageW( szPack ); 2754 2755 msi_free( szPack ); 2756 2757 return r; 2758 } 2759 2760 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage ) 2761 { 2762 MSIHANDLE handle; 2763 UINT r; 2764 2765 TRACE("%s\n", debugstr_w(szPackage) ); 2766 2767 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle ); 2768 MsiCloseHandle( handle ); 2769 2770 return r; 2771 } 2772 2773 static BOOL open_userdata_comp_key( const WCHAR *comp, const WCHAR *usersid, MSIINSTALLCONTEXT ctx, 2774 HKEY *hkey ) 2775 { 2776 if (ctx & MSIINSTALLCONTEXT_MACHINE) 2777 { 2778 if (!MSIREG_OpenUserDataComponentKey( comp, szLocalSid, hkey, FALSE )) return TRUE; 2779 } 2780 if (ctx & (MSIINSTALLCONTEXT_USERMANAGED|MSIINSTALLCONTEXT_USERUNMANAGED)) 2781 { 2782 if (usersid && !strcmpiW( usersid, szAllSid )) 2783 { 2784 FIXME( "only looking at the current user\n" ); 2785 usersid = NULL; 2786 } 2787 if (!MSIREG_OpenUserDataComponentKey( comp, usersid, hkey, FALSE )) return TRUE; 2788 } 2789 return FALSE; 2790 } 2791 2792 static INSTALLSTATE MSI_GetComponentPath( const WCHAR *szProduct, const WCHAR *szComponent, 2793 const WCHAR *szUserSid, MSIINSTALLCONTEXT ctx, 2794 awstring *lpPathBuf, DWORD *pcchBuf ) 2795 { 2796 static const WCHAR wininstaller[] = 2797 {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0}; 2798 WCHAR *path = NULL, squashed_pc[SQUASHED_GUID_SIZE], squashed_comp[SQUASHED_GUID_SIZE]; 2799 HKEY hkey; 2800 INSTALLSTATE state; 2801 DWORD version; 2802 2803 if (!szProduct || !szComponent) 2804 return INSTALLSTATE_INVALIDARG; 2805 2806 if (lpPathBuf->str.w && !pcchBuf) 2807 return INSTALLSTATE_INVALIDARG; 2808 2809 if (!squash_guid( szProduct, squashed_pc ) || !squash_guid( szComponent, squashed_comp )) 2810 return INSTALLSTATE_INVALIDARG; 2811 2812 if (szUserSid && ctx == MSIINSTALLCONTEXT_MACHINE) 2813 return INSTALLSTATE_INVALIDARG; 2814 2815 state = INSTALLSTATE_UNKNOWN; 2816 2817 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey )) 2818 { 2819 path = msi_reg_get_val_str( hkey, squashed_pc ); 2820 RegCloseKey(hkey); 2821 2822 state = INSTALLSTATE_ABSENT; 2823 2824 if ((!MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, &hkey, FALSE) || 2825 !MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, NULL, &hkey, FALSE)) && 2826 msi_reg_get_val_dword(hkey, wininstaller, &version) && 2827 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) 2828 { 2829 RegCloseKey(hkey); 2830 state = INSTALLSTATE_LOCAL; 2831 } 2832 } 2833 2834 if (state != INSTALLSTATE_LOCAL && 2835 (!MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, &hkey, FALSE) || 2836 !MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, &hkey, FALSE))) 2837 { 2838 RegCloseKey(hkey); 2839 2840 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey )) 2841 { 2842 msi_free(path); 2843 path = msi_reg_get_val_str( hkey, squashed_pc ); 2844 RegCloseKey(hkey); 2845 2846 state = INSTALLSTATE_ABSENT; 2847 2848 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) 2849 state = INSTALLSTATE_LOCAL; 2850 } 2851 } 2852 2853 if (!path) 2854 return INSTALLSTATE_UNKNOWN; 2855 2856 if (state == INSTALLSTATE_LOCAL && !*path) 2857 state = INSTALLSTATE_NOTUSED; 2858 2859 if (msi_strcpy_to_awstring(path, -1, lpPathBuf, pcchBuf) == ERROR_MORE_DATA) 2860 state = INSTALLSTATE_MOREDATA; 2861 2862 msi_free(path); 2863 return state; 2864 } 2865 2866 /****************************************************************** 2867 * MsiGetComponentPathExW [MSI.@] 2868 */ 2869 INSTALLSTATE WINAPI MsiGetComponentPathExW( LPCWSTR product, LPCWSTR comp, LPCWSTR usersid, 2870 MSIINSTALLCONTEXT ctx, LPWSTR buf, LPDWORD buflen ) 2871 { 2872 awstring path; 2873 2874 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_w(product), debugstr_w(comp), debugstr_w(usersid), 2875 ctx, buf, buflen ); 2876 2877 path.unicode = TRUE; 2878 path.str.w = buf; 2879 2880 return MSI_GetComponentPath( product, comp, usersid, ctx, &path, buflen ); 2881 } 2882 2883 INSTALLSTATE WINAPI MsiGetComponentPathExA( LPCSTR product, LPCSTR comp, LPCSTR usersid, 2884 MSIINSTALLCONTEXT ctx, LPSTR buf, LPDWORD buflen ) 2885 { 2886 WCHAR *productW = NULL, *compW = NULL, *usersidW = NULL; 2887 INSTALLSTATE r = INSTALLSTATE_UNKNOWN; 2888 awstring path; 2889 2890 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_a(product), debugstr_a(comp), debugstr_a(usersid), 2891 ctx, buf, buflen ); 2892 2893 if (product && !(productW = strdupAtoW( product ))) return INSTALLSTATE_UNKNOWN; 2894 if (comp && !(compW = strdupAtoW( comp ))) goto end; 2895 if (usersid && !(usersidW = strdupAtoW( usersid ))) goto end; 2896 2897 path.unicode = FALSE; 2898 path.str.a = buf; 2899 2900 r = MSI_GetComponentPath( productW, compW, usersidW, ctx, &path, buflen ); 2901 2902 end: 2903 msi_free( productW ); 2904 msi_free( compW ); 2905 msi_free( usersidW ); 2906 2907 return r; 2908 } 2909 2910 /****************************************************************** 2911 * MsiGetComponentPathW [MSI.@] 2912 */ 2913 INSTALLSTATE WINAPI MsiGetComponentPathW( LPCWSTR product, LPCWSTR comp, LPWSTR buf, LPDWORD buflen ) 2914 { 2915 return MsiGetComponentPathExW( product, comp, szAllSid, MSIINSTALLCONTEXT_ALL, buf, buflen ); 2916 } 2917 2918 /****************************************************************** 2919 * MsiGetComponentPathA [MSI.@] 2920 */ 2921 INSTALLSTATE WINAPI MsiGetComponentPathA( LPCSTR product, LPCSTR comp, LPSTR buf, LPDWORD buflen ) 2922 { 2923 return MsiGetComponentPathExA( product, comp, "s-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen ); 2924 } 2925 2926 static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid, 2927 MSIINSTALLCONTEXT ctx, const WCHAR *feature, INSTALLSTATE *state ) 2928 { 2929 UINT r; 2930 HKEY hkey; 2931 WCHAR *parent, *components, *path; 2932 const WCHAR *p; 2933 BOOL missing = FALSE, source = FALSE; 2934 WCHAR comp[GUID_SIZE]; 2935 GUID guid; 2936 2937 if (ctx != MSIINSTALLCONTEXT_MACHINE) SetLastError( ERROR_SUCCESS ); 2938 2939 if (MSIREG_OpenFeaturesKey( product, usersid, ctx, &hkey, FALSE )) return ERROR_UNKNOWN_PRODUCT; 2940 2941 parent = msi_reg_get_val_str( hkey, feature ); 2942 RegCloseKey( hkey ); 2943 if (!parent) return ERROR_UNKNOWN_FEATURE; 2944 2945 *state = (parent[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL; 2946 msi_free( parent ); 2947 if (*state == INSTALLSTATE_ABSENT) 2948 return ERROR_SUCCESS; 2949 2950 r = MSIREG_OpenUserDataFeaturesKey( product, usersid, ctx, &hkey, FALSE ); 2951 if (r != ERROR_SUCCESS) 2952 { 2953 *state = INSTALLSTATE_ADVERTISED; 2954 return ERROR_SUCCESS; 2955 } 2956 components = msi_reg_get_val_str( hkey, feature ); 2957 RegCloseKey( hkey ); 2958 2959 TRACE("buffer = %s\n", debugstr_w(components)); 2960 2961 if (!components) 2962 { 2963 *state = INSTALLSTATE_ADVERTISED; 2964 return ERROR_SUCCESS; 2965 } 2966 for (p = components; *p && *p != 2 ; p += 20) 2967 { 2968 if (!decode_base85_guid( p, &guid )) 2969 { 2970 if (p != components) break; 2971 msi_free( components ); 2972 *state = INSTALLSTATE_BADCONFIG; 2973 return ERROR_BAD_CONFIGURATION; 2974 } 2975 StringFromGUID2( &guid, comp, GUID_SIZE ); 2976 if (ctx == MSIINSTALLCONTEXT_MACHINE) 2977 r = MSIREG_OpenUserDataComponentKey( comp, szLocalSid, &hkey, FALSE ); 2978 else 2979 r = MSIREG_OpenUserDataComponentKey( comp, usersid, &hkey, FALSE ); 2980 2981 if (r != ERROR_SUCCESS) 2982 { 2983 msi_free( components ); 2984 *state = INSTALLSTATE_ADVERTISED; 2985 return ERROR_SUCCESS; 2986 } 2987 path = msi_reg_get_val_str( hkey, squashed ); 2988 if (!path) missing = TRUE; 2989 else if (strlenW( path ) > 2 && 2990 path[0] >= '0' && path[0] <= '9' && 2991 path[1] >= '0' && path[1] <= '9') 2992 { 2993 source = TRUE; 2994 } 2995 msi_free( path ); 2996 } 2997 msi_free( components ); 2998 2999 if (missing) 3000 *state = INSTALLSTATE_ADVERTISED; 3001 else if (source) 3002 *state = INSTALLSTATE_SOURCE; 3003 else 3004 *state = INSTALLSTATE_LOCAL; 3005 3006 TRACE("returning state %d\n", *state); 3007 return ERROR_SUCCESS; 3008 } 3009 3010 UINT WINAPI MsiQueryFeatureStateExA( LPCSTR product, LPCSTR usersid, MSIINSTALLCONTEXT ctx, 3011 LPCSTR feature, INSTALLSTATE *state ) 3012 { 3013 UINT r; 3014 WCHAR *productW = NULL, *usersidW = NULL, *featureW = NULL; 3015 3016 if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY; 3017 if (usersid && !(usersidW = strdupAtoW( usersid ))) 3018 { 3019 msi_free( productW ); 3020 return ERROR_OUTOFMEMORY; 3021 } 3022 if (feature && !(featureW = strdupAtoW( feature ))) 3023 { 3024 msi_free( productW ); 3025 msi_free( usersidW ); 3026 return ERROR_OUTOFMEMORY; 3027 } 3028 r = MsiQueryFeatureStateExW( productW, usersidW, ctx, featureW, state ); 3029 msi_free( productW ); 3030 msi_free( usersidW ); 3031 msi_free( featureW ); 3032 return r; 3033 } 3034 3035 UINT WINAPI MsiQueryFeatureStateExW( LPCWSTR product, LPCWSTR usersid, MSIINSTALLCONTEXT ctx, 3036 LPCWSTR feature, INSTALLSTATE *state ) 3037 { 3038 WCHAR squashed[33]; 3039 if (!squash_guid( product, squashed )) return ERROR_INVALID_PARAMETER; 3040 return query_feature_state( product, squashed, usersid, ctx, feature, state ); 3041 } 3042 3043 /****************************************************************** 3044 * MsiQueryFeatureStateA [MSI.@] 3045 */ 3046 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature) 3047 { 3048 LPWSTR szwProduct = NULL, szwFeature= NULL; 3049 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN; 3050 3051 szwProduct = strdupAtoW( szProduct ); 3052 if ( szProduct && !szwProduct ) 3053 goto end; 3054 3055 szwFeature = strdupAtoW( szFeature ); 3056 if ( szFeature && !szwFeature ) 3057 goto end; 3058 3059 rc = MsiQueryFeatureStateW(szwProduct, szwFeature); 3060 3061 end: 3062 msi_free( szwProduct); 3063 msi_free( szwFeature); 3064 3065 return rc; 3066 } 3067 3068 /****************************************************************** 3069 * MsiQueryFeatureStateW [MSI.@] 3070 * 3071 * Checks the state of a feature 3072 * 3073 * PARAMS 3074 * szProduct [I] Product's GUID string 3075 * szFeature [I] Feature's GUID string 3076 * 3077 * RETURNS 3078 * INSTALLSTATE_LOCAL Feature is installed and usable 3079 * INSTALLSTATE_ABSENT Feature is absent 3080 * INSTALLSTATE_ADVERTISED Feature should be installed on demand 3081 * INSTALLSTATE_UNKNOWN An error occurred 3082 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid 3083 * 3084 */ 3085 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) 3086 { 3087 UINT r; 3088 INSTALLSTATE state; 3089 WCHAR squashed[33]; 3090 3091 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); 3092 3093 if (!szProduct || !szFeature || !squash_guid( szProduct, squashed )) 3094 return INSTALLSTATE_INVALIDARG; 3095 3096 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERMANAGED, szFeature, &state ); 3097 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; 3098 3099 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, szFeature, &state ); 3100 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; 3101 3102 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_MACHINE, szFeature, &state ); 3103 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state; 3104 3105 return INSTALLSTATE_UNKNOWN; 3106 } 3107 3108 /****************************************************************** 3109 * MsiGetFileVersionA [MSI.@] 3110 */ 3111 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, 3112 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf) 3113 { 3114 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL; 3115 UINT ret = ERROR_OUTOFMEMORY; 3116 3117 if ((lpVersionBuf && !pcchVersionBuf) || 3118 (lpLangBuf && !pcchLangBuf)) 3119 return ERROR_INVALID_PARAMETER; 3120 3121 if( szFilePath ) 3122 { 3123 szwFilePath = strdupAtoW( szFilePath ); 3124 if( !szwFilePath ) 3125 goto end; 3126 } 3127 3128 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf ) 3129 { 3130 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR)); 3131 if( !lpwVersionBuff ) 3132 goto end; 3133 } 3134 3135 if( lpLangBuf && pcchLangBuf && *pcchLangBuf ) 3136 { 3137 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR)); 3138 if( !lpwLangBuff ) 3139 goto end; 3140 } 3141 3142 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf, 3143 lpwLangBuff, pcchLangBuf); 3144 3145 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff ) 3146 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1, 3147 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL); 3148 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff ) 3149 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1, 3150 lpLangBuf, *pcchLangBuf + 1, NULL, NULL); 3151 3152 end: 3153 msi_free(szwFilePath); 3154 msi_free(lpwVersionBuff); 3155 msi_free(lpwLangBuff); 3156 3157 return ret; 3158 } 3159 3160 static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, 3161 WCHAR *langbuf, DWORD *langlen ) 3162 { 3163 static const WCHAR szVersionResource[] = {'\\',0}; 3164 static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0}; 3165 static const WCHAR szLangFormat[] = {'%','d',0}; 3166 UINT ret = ERROR_MORE_DATA; 3167 DWORD len, error; 3168 LPVOID version; 3169 VS_FIXEDFILEINFO *ffi; 3170 USHORT *lang; 3171 WCHAR tmp[32]; 3172 3173 if (!(len = GetFileVersionInfoSizeW( path, NULL ))) 3174 { 3175 error = GetLastError(); 3176 if (error == ERROR_BAD_PATHNAME) return ERROR_FILE_NOT_FOUND; 3177 if (error == ERROR_RESOURCE_DATA_NOT_FOUND) return ERROR_FILE_INVALID; 3178 return error; 3179 } 3180 if (!(version = msi_alloc( len ))) return ERROR_OUTOFMEMORY; 3181 if (!GetFileVersionInfoW( path, 0, len, version )) 3182 { 3183 msi_free( version ); 3184 return GetLastError(); 3185 } 3186 if (!verbuf && !verlen && !langbuf && !langlen) 3187 { 3188 msi_free( version ); 3189 return ERROR_SUCCESS; 3190 } 3191 if (verlen) 3192 { 3193 if (VerQueryValueW( version, szVersionResource, (LPVOID *)&ffi, &len ) && len > 0) 3194 { 3195 sprintfW( tmp, szVersionFormat, 3196 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), 3197 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS) ); 3198 if (verbuf) lstrcpynW( verbuf, tmp, *verlen ); 3199 len = strlenW( tmp ); 3200 if (*verlen > len) ret = ERROR_SUCCESS; 3201 *verlen = len; 3202 } 3203 else 3204 { 3205 if (verbuf) *verbuf = 0; 3206 *verlen = 0; 3207 } 3208 } 3209 if (langlen) 3210 { 3211 if (VerQueryValueW( version, szLangResource, (LPVOID *)&lang, &len ) && len > 0) 3212 { 3213 sprintfW( tmp, szLangFormat, *lang ); 3214 if (langbuf) lstrcpynW( langbuf, tmp, *langlen ); 3215 len = strlenW( tmp ); 3216 if (*langlen > len) ret = ERROR_SUCCESS; 3217 *langlen = len; 3218 } 3219 else 3220 { 3221 if (langbuf) *langbuf = 0; 3222 *langlen = 0; 3223 } 3224 } 3225 msi_free( version ); 3226 return ret; 3227 } 3228 3229 3230 /****************************************************************** 3231 * MsiGetFileVersionW [MSI.@] 3232 */ 3233 UINT WINAPI MsiGetFileVersionW( LPCWSTR path, LPWSTR verbuf, LPDWORD verlen, 3234 LPWSTR langbuf, LPDWORD langlen ) 3235 { 3236 UINT ret; 3237 3238 TRACE("%s %p %u %p %u\n", debugstr_w(path), verbuf, verlen ? *verlen : 0, 3239 langbuf, langlen ? *langlen : 0); 3240 3241 if ((verbuf && !verlen) || (langbuf && !langlen)) 3242 return ERROR_INVALID_PARAMETER; 3243 3244 ret = get_file_version( path, verbuf, verlen, langbuf, langlen ); 3245 if (ret == ERROR_RESOURCE_DATA_NOT_FOUND && verlen) 3246 { 3247 int len; 3248 WCHAR *version = msi_font_version_from_file( path ); 3249 if (!version) return ERROR_FILE_INVALID; 3250 len = strlenW( version ); 3251 if (len >= *verlen) ret = ERROR_MORE_DATA; 3252 else if (verbuf) 3253 { 3254 strcpyW( verbuf, version ); 3255 ret = ERROR_SUCCESS; 3256 } 3257 *verlen = len; 3258 msi_free( version ); 3259 } 3260 return ret; 3261 } 3262 3263 /*********************************************************************** 3264 * MsiGetFeatureUsageW [MSI.@] 3265 */ 3266 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature, 3267 LPDWORD pdwUseCount, LPWORD pwDateUsed ) 3268 { 3269 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature), 3270 pdwUseCount, pwDateUsed); 3271 return ERROR_CALL_NOT_IMPLEMENTED; 3272 } 3273 3274 /*********************************************************************** 3275 * MsiGetFeatureUsageA [MSI.@] 3276 */ 3277 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature, 3278 LPDWORD pdwUseCount, LPWORD pwDateUsed ) 3279 { 3280 LPWSTR prod = NULL, feat = NULL; 3281 UINT ret = ERROR_OUTOFMEMORY; 3282 3283 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature), 3284 pdwUseCount, pwDateUsed); 3285 3286 prod = strdupAtoW( szProduct ); 3287 if (szProduct && !prod) 3288 goto end; 3289 3290 feat = strdupAtoW( szFeature ); 3291 if (szFeature && !feat) 3292 goto end; 3293 3294 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed ); 3295 3296 end: 3297 msi_free( prod ); 3298 msi_free( feat ); 3299 3300 return ret; 3301 } 3302 3303 /*********************************************************************** 3304 * MsiUseFeatureExW [MSI.@] 3305 */ 3306 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature, 3307 DWORD dwInstallMode, DWORD dwReserved ) 3308 { 3309 INSTALLSTATE state; 3310 3311 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature), 3312 dwInstallMode, dwReserved); 3313 3314 state = MsiQueryFeatureStateW( szProduct, szFeature ); 3315 3316 if (dwReserved) 3317 return INSTALLSTATE_INVALIDARG; 3318 3319 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION) 3320 { 3321 FIXME("mark product %s feature %s as used\n", 3322 debugstr_w(szProduct), debugstr_w(szFeature) ); 3323 } 3324 3325 return state; 3326 } 3327 3328 /*********************************************************************** 3329 * MsiUseFeatureExA [MSI.@] 3330 */ 3331 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature, 3332 DWORD dwInstallMode, DWORD dwReserved ) 3333 { 3334 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN; 3335 LPWSTR prod = NULL, feat = NULL; 3336 3337 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature), 3338 dwInstallMode, dwReserved); 3339 3340 prod = strdupAtoW( szProduct ); 3341 if (szProduct && !prod) 3342 goto end; 3343 3344 feat = strdupAtoW( szFeature ); 3345 if (szFeature && !feat) 3346 goto end; 3347 3348 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved ); 3349 3350 end: 3351 msi_free( prod ); 3352 msi_free( feat ); 3353 3354 return ret; 3355 } 3356 3357 /*********************************************************************** 3358 * MsiUseFeatureW [MSI.@] 3359 */ 3360 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature ) 3361 { 3362 return MsiUseFeatureExW(szProduct, szFeature, 0, 0); 3363 } 3364 3365 /*********************************************************************** 3366 * MsiUseFeatureA [MSI.@] 3367 */ 3368 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature ) 3369 { 3370 return MsiUseFeatureExA(szProduct, szFeature, 0, 0); 3371 } 3372 3373 static WCHAR *reg_get_multisz( HKEY hkey, const WCHAR *name ) 3374 { 3375 WCHAR *ret; 3376 DWORD len, type; 3377 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_MULTI_SZ) return NULL; 3378 if ((ret = msi_alloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len ); 3379 return ret; 3380 } 3381 3382 static WCHAR *reg_get_sz( HKEY hkey, const WCHAR *name ) 3383 { 3384 WCHAR *ret; 3385 DWORD len, type; 3386 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_SZ) return NULL; 3387 if ((ret = msi_alloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len ); 3388 return ret; 3389 } 3390 3391 #define BASE85_SIZE 20 3392 3393 /*********************************************************************** 3394 * MSI_ProvideQualifiedComponentEx [internal] 3395 */ 3396 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent, 3397 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct, 3398 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf, 3399 LPDWORD pcchPathBuf) 3400 { 3401 WCHAR product[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1]; 3402 WCHAR *desc; 3403 HKEY hkey; 3404 DWORD size; 3405 UINT ret; 3406 INSTALLSTATE state; 3407 3408 if (MSIREG_OpenUserComponentsKey( szComponent, &hkey, FALSE )) return ERROR_UNKNOWN_COMPONENT; 3409 3410 desc = reg_get_multisz( hkey, szQualifier ); 3411 RegCloseKey(hkey); 3412 if (!desc) return ERROR_INDEX_ABSENT; 3413 3414 /* FIXME: handle multiple descriptors */ 3415 ret = MsiDecomposeDescriptorW( desc, product, feature, comp, &size ); 3416 msi_free( desc ); 3417 if (ret != ERROR_SUCCESS) return ret; 3418 3419 if (!szProduct) szProduct = product; 3420 if (!comp[0]) 3421 { 3422 MSIINSTALLCONTEXT ctx; 3423 WCHAR *components; 3424 GUID guid; 3425 3426 /* use the first component of the feature if the descriptor component is empty */ 3427 if ((ret = msi_locate_product( szProduct, &ctx ))) return ret; 3428 if ((ret = MSIREG_OpenUserDataFeaturesKey( szProduct, NULL, ctx, &hkey, FALSE ))) 3429 { 3430 return ERROR_FILE_NOT_FOUND; 3431 } 3432 components = reg_get_sz( hkey, feature ); 3433 RegCloseKey( hkey ); 3434 if (!components) return ERROR_FILE_NOT_FOUND; 3435 3436 if (strlenW( components ) < BASE85_SIZE || !decode_base85_guid( components, &guid )) 3437 { 3438 msi_free( components ); 3439 return ERROR_FILE_NOT_FOUND; 3440 } 3441 msi_free( components ); 3442 StringFromGUID2( &guid, comp, sizeof(comp)/sizeof(comp[0]) ); 3443 } 3444 3445 state = MSI_GetComponentPath( szProduct, comp, szAllSid, MSIINSTALLCONTEXT_ALL, lpPathBuf, pcchPathBuf ); 3446 3447 if (state == INSTALLSTATE_MOREDATA) return ERROR_MORE_DATA; 3448 if (state != INSTALLSTATE_LOCAL) return ERROR_FILE_NOT_FOUND; 3449 return ERROR_SUCCESS; 3450 } 3451 3452 /*********************************************************************** 3453 * MsiProvideQualifiedComponentExW [MSI.@] 3454 */ 3455 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent, 3456 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct, 3457 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf, 3458 LPDWORD pcchPathBuf) 3459 { 3460 awstring path; 3461 3462 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_w(szComponent), 3463 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct), 3464 Unused1, Unused2, lpPathBuf, pcchPathBuf); 3465 3466 path.unicode = TRUE; 3467 path.str.w = lpPathBuf; 3468 3469 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier, 3470 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf); 3471 } 3472 3473 /*********************************************************************** 3474 * MsiProvideQualifiedComponentExA [MSI.@] 3475 */ 3476 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent, 3477 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct, 3478 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf, 3479 LPDWORD pcchPathBuf) 3480 { 3481 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL; 3482 UINT r = ERROR_OUTOFMEMORY; 3483 awstring path; 3484 3485 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent), 3486 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct), 3487 Unused1, Unused2, lpPathBuf, pcchPathBuf); 3488 3489 szwComponent = strdupAtoW( szComponent ); 3490 if (szComponent && !szwComponent) 3491 goto end; 3492 3493 szwQualifier = strdupAtoW( szQualifier ); 3494 if (szQualifier && !szwQualifier) 3495 goto end; 3496 3497 szwProduct = strdupAtoW( szProduct ); 3498 if (szProduct && !szwProduct) 3499 goto end; 3500 3501 path.unicode = FALSE; 3502 path.str.a = lpPathBuf; 3503 3504 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier, 3505 dwInstallMode, szwProduct, Unused1, 3506 Unused2, &path, pcchPathBuf); 3507 end: 3508 msi_free(szwProduct); 3509 msi_free(szwComponent); 3510 msi_free(szwQualifier); 3511 3512 return r; 3513 } 3514 3515 /*********************************************************************** 3516 * MsiProvideQualifiedComponentW [MSI.@] 3517 */ 3518 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent, 3519 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf, 3520 LPDWORD pcchPathBuf) 3521 { 3522 return MsiProvideQualifiedComponentExW(szComponent, szQualifier, 3523 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf); 3524 } 3525 3526 /*********************************************************************** 3527 * MsiProvideQualifiedComponentA [MSI.@] 3528 */ 3529 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent, 3530 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf, 3531 LPDWORD pcchPathBuf) 3532 { 3533 return MsiProvideQualifiedComponentExA(szComponent, szQualifier, 3534 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf); 3535 } 3536 3537 /*********************************************************************** 3538 * MSI_GetUserInfo [internal] 3539 */ 3540 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct, 3541 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf, 3542 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf, 3543 awstring *lpSerialBuf, LPDWORD pcchSerialBuf) 3544 { 3545 WCHAR *user, *org, *serial, squashed_pc[SQUASHED_GUID_SIZE]; 3546 USERINFOSTATE state; 3547 HKEY hkey, props; 3548 LPCWSTR orgptr; 3549 UINT r; 3550 3551 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf, 3552 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf, 3553 pcchSerialBuf); 3554 3555 if (!szProduct || !squash_guid( szProduct, squashed_pc )) 3556 return USERINFOSTATE_INVALIDARG; 3557 3558 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, 3559 &hkey, FALSE) != ERROR_SUCCESS && 3560 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 3561 &hkey, FALSE) != ERROR_SUCCESS && 3562 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, 3563 &hkey, FALSE) != ERROR_SUCCESS) 3564 { 3565 return USERINFOSTATE_UNKNOWN; 3566 } 3567 3568 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, 3569 NULL, &props, FALSE) != ERROR_SUCCESS && 3570 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, 3571 NULL, &props, FALSE) != ERROR_SUCCESS) 3572 { 3573 RegCloseKey(hkey); 3574 return USERINFOSTATE_ABSENT; 3575 } 3576 3577 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW); 3578 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW); 3579 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW); 3580 state = USERINFOSTATE_ABSENT; 3581 3582 RegCloseKey(hkey); 3583 RegCloseKey(props); 3584 3585 if (user && serial) 3586 state = USERINFOSTATE_PRESENT; 3587 3588 if (pcchUserNameBuf) 3589 { 3590 if (lpUserNameBuf && !user) 3591 { 3592 (*pcchUserNameBuf)--; 3593 goto done; 3594 } 3595 3596 r = msi_strcpy_to_awstring(user, -1, lpUserNameBuf, pcchUserNameBuf); 3597 if (r == ERROR_MORE_DATA) 3598 { 3599 state = USERINFOSTATE_MOREDATA; 3600 goto done; 3601 } 3602 } 3603 3604 if (pcchOrgNameBuf) 3605 { 3606 orgptr = org; 3607 if (!orgptr) orgptr = szEmpty; 3608 3609 r = msi_strcpy_to_awstring(orgptr, -1, lpOrgNameBuf, pcchOrgNameBuf); 3610 if (r == ERROR_MORE_DATA) 3611 { 3612 state = USERINFOSTATE_MOREDATA; 3613 goto done; 3614 } 3615 } 3616 3617 if (pcchSerialBuf) 3618 { 3619 if (!serial) 3620 { 3621 (*pcchSerialBuf)--; 3622 goto done; 3623 } 3624 3625 r = msi_strcpy_to_awstring(serial, -1, lpSerialBuf, pcchSerialBuf); 3626 if (r == ERROR_MORE_DATA) 3627 state = USERINFOSTATE_MOREDATA; 3628 } 3629 3630 done: 3631 msi_free(user); 3632 msi_free(org); 3633 msi_free(serial); 3634 3635 return state; 3636 } 3637 3638 /*********************************************************************** 3639 * MsiGetUserInfoW [MSI.@] 3640 */ 3641 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, 3642 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf, 3643 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf, 3644 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf) 3645 { 3646 awstring user, org, serial; 3647 3648 if ((lpUserNameBuf && !pcchUserNameBuf) || 3649 (lpOrgNameBuf && !pcchOrgNameBuf) || 3650 (lpSerialBuf && !pcchSerialBuf)) 3651 return USERINFOSTATE_INVALIDARG; 3652 3653 user.unicode = TRUE; 3654 user.str.w = lpUserNameBuf; 3655 org.unicode = TRUE; 3656 org.str.w = lpOrgNameBuf; 3657 serial.unicode = TRUE; 3658 serial.str.w = lpSerialBuf; 3659 3660 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf, 3661 &org, pcchOrgNameBuf, 3662 &serial, pcchSerialBuf ); 3663 } 3664 3665 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, 3666 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf, 3667 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf, 3668 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf) 3669 { 3670 awstring user, org, serial; 3671 LPWSTR prod; 3672 UINT r; 3673 3674 if ((lpUserNameBuf && !pcchUserNameBuf) || 3675 (lpOrgNameBuf && !pcchOrgNameBuf) || 3676 (lpSerialBuf && !pcchSerialBuf)) 3677 return USERINFOSTATE_INVALIDARG; 3678 3679 prod = strdupAtoW( szProduct ); 3680 if (szProduct && !prod) 3681 return ERROR_OUTOFMEMORY; 3682 3683 user.unicode = FALSE; 3684 user.str.a = lpUserNameBuf; 3685 org.unicode = FALSE; 3686 org.str.a = lpOrgNameBuf; 3687 serial.unicode = FALSE; 3688 serial.str.a = lpSerialBuf; 3689 3690 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf, 3691 &org, pcchOrgNameBuf, 3692 &serial, pcchSerialBuf ); 3693 3694 msi_free( prod ); 3695 3696 return r; 3697 } 3698 3699 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct) 3700 { 3701 MSIHANDLE handle; 3702 UINT rc; 3703 MSIPACKAGE *package; 3704 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0}; 3705 3706 TRACE("(%s)\n",debugstr_w(szProduct)); 3707 3708 rc = MsiOpenProductW(szProduct,&handle); 3709 if (rc != ERROR_SUCCESS) 3710 return ERROR_INVALID_PARAMETER; 3711 3712 /* MsiCollectUserInfo cannot be called from a custom action. */ 3713 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE); 3714 if (!package) 3715 return ERROR_CALL_NOT_IMPLEMENTED; 3716 3717 rc = ACTION_PerformUIAction(package, szFirstRun, SCRIPT_NONE); 3718 msiobj_release( &package->hdr ); 3719 3720 MsiCloseHandle(handle); 3721 3722 return rc; 3723 } 3724 3725 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct) 3726 { 3727 MSIHANDLE handle; 3728 UINT rc; 3729 MSIPACKAGE *package; 3730 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0}; 3731 3732 TRACE("(%s)\n",debugstr_a(szProduct)); 3733 3734 rc = MsiOpenProductA(szProduct,&handle); 3735 if (rc != ERROR_SUCCESS) 3736 return ERROR_INVALID_PARAMETER; 3737 3738 /* MsiCollectUserInfo cannot be called from a custom action. */ 3739 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE); 3740 if (!package) 3741 return ERROR_CALL_NOT_IMPLEMENTED; 3742 3743 rc = ACTION_PerformUIAction(package, szFirstRun, SCRIPT_NONE); 3744 msiobj_release( &package->hdr ); 3745 3746 MsiCloseHandle(handle); 3747 3748 return rc; 3749 } 3750 3751 /*********************************************************************** 3752 * MsiConfigureFeatureA [MSI.@] 3753 */ 3754 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState) 3755 { 3756 LPWSTR prod, feat = NULL; 3757 UINT r = ERROR_OUTOFMEMORY; 3758 3759 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState); 3760 3761 prod = strdupAtoW( szProduct ); 3762 if (szProduct && !prod) 3763 goto end; 3764 3765 feat = strdupAtoW( szFeature ); 3766 if (szFeature && !feat) 3767 goto end; 3768 3769 r = MsiConfigureFeatureW(prod, feat, eInstallState); 3770 3771 end: 3772 msi_free(feat); 3773 msi_free(prod); 3774 3775 return r; 3776 } 3777 3778 /*********************************************************************** 3779 * MsiConfigureFeatureW [MSI.@] 3780 */ 3781 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState) 3782 { 3783 MSIPACKAGE *package = NULL; 3784 UINT r; 3785 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH]; 3786 DWORD sz; 3787 3788 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState); 3789 3790 if (!szProduct || !szFeature) 3791 return ERROR_INVALID_PARAMETER; 3792 3793 switch (eInstallState) 3794 { 3795 case INSTALLSTATE_DEFAULT: 3796 /* FIXME: how do we figure out the default location? */ 3797 eInstallState = INSTALLSTATE_LOCAL; 3798 break; 3799 case INSTALLSTATE_LOCAL: 3800 case INSTALLSTATE_SOURCE: 3801 case INSTALLSTATE_ABSENT: 3802 case INSTALLSTATE_ADVERTISED: 3803 break; 3804 default: 3805 return ERROR_INVALID_PARAMETER; 3806 } 3807 3808 r = MSI_OpenProductW( szProduct, &package ); 3809 if (r != ERROR_SUCCESS) 3810 return r; 3811 3812 sz = sizeof(sourcepath); 3813 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 3814 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); 3815 3816 sz = sizeof(filename); 3817 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 3818 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); 3819 3820 lstrcatW( sourcepath, filename ); 3821 3822 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL ); 3823 3824 r = ACTION_PerformUIAction( package, szCostInitialize, SCRIPT_NONE ); 3825 if (r != ERROR_SUCCESS) 3826 goto end; 3827 3828 r = MSI_SetFeatureStateW( package, szFeature, eInstallState); 3829 if (r != ERROR_SUCCESS) 3830 goto end; 3831 3832 r = MSI_InstallPackage( package, sourcepath, NULL ); 3833 3834 end: 3835 msiobj_release( &package->hdr ); 3836 3837 return r; 3838 } 3839 3840 /*********************************************************************** 3841 * MsiCreateAndVerifyInstallerDirectory [MSI.@] 3842 * 3843 * Notes: undocumented 3844 */ 3845 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved) 3846 { 3847 WCHAR path[MAX_PATH]; 3848 3849 TRACE("%d\n", dwReserved); 3850 3851 if (dwReserved) 3852 { 3853 FIXME("dwReserved=%d\n", dwReserved); 3854 return ERROR_INVALID_PARAMETER; 3855 } 3856 3857 if (!GetWindowsDirectoryW(path, MAX_PATH)) 3858 return ERROR_FUNCTION_FAILED; 3859 3860 lstrcatW(path, installerW); 3861 3862 if (!CreateDirectoryW(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) 3863 return ERROR_FUNCTION_FAILED; 3864 3865 return ERROR_SUCCESS; 3866 } 3867 3868 /*********************************************************************** 3869 * MsiGetShortcutTargetA [MSI.@] 3870 */ 3871 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget, 3872 LPSTR szProductCode, LPSTR szFeatureId, 3873 LPSTR szComponentCode ) 3874 { 3875 LPWSTR target; 3876 const int len = MAX_FEATURE_CHARS+1; 3877 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1]; 3878 UINT r; 3879 3880 target = strdupAtoW( szShortcutTarget ); 3881 if (szShortcutTarget && !target ) 3882 return ERROR_OUTOFMEMORY; 3883 product[0] = 0; 3884 feature[0] = 0; 3885 component[0] = 0; 3886 r = MsiGetShortcutTargetW( target, product, feature, component ); 3887 msi_free( target ); 3888 if (r == ERROR_SUCCESS) 3889 { 3890 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL ); 3891 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL ); 3892 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL ); 3893 } 3894 return r; 3895 } 3896 3897 /*********************************************************************** 3898 * MsiGetShortcutTargetW [MSI.@] 3899 */ 3900 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget, 3901 LPWSTR szProductCode, LPWSTR szFeatureId, 3902 LPWSTR szComponentCode ) 3903 { 3904 IShellLinkDataList *dl = NULL; 3905 IPersistFile *pf = NULL; 3906 LPEXP_DARWIN_LINK darwin = NULL; 3907 HRESULT r, init; 3908 3909 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget), 3910 szProductCode, szFeatureId, szComponentCode ); 3911 3912 init = CoInitialize(NULL); 3913 3914 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 3915 &IID_IPersistFile, (LPVOID*) &pf ); 3916 if( SUCCEEDED( r ) ) 3917 { 3918 r = IPersistFile_Load( pf, szShortcutTarget, 3919 STGM_READ | STGM_SHARE_DENY_WRITE ); 3920 if( SUCCEEDED( r ) ) 3921 { 3922 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList, 3923 (LPVOID*) &dl ); 3924 if( SUCCEEDED( r ) ) 3925 { 3926 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG, 3927 (LPVOID) &darwin ); 3928 IShellLinkDataList_Release( dl ); 3929 } 3930 } 3931 IPersistFile_Release( pf ); 3932 } 3933 3934 if (SUCCEEDED(init)) 3935 CoUninitialize(); 3936 3937 TRACE("darwin = %p\n", darwin); 3938 3939 if (darwin) 3940 { 3941 DWORD sz; 3942 UINT ret; 3943 3944 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID, 3945 szProductCode, szFeatureId, szComponentCode, &sz ); 3946 LocalFree( darwin ); 3947 return ret; 3948 } 3949 3950 return ERROR_FUNCTION_FAILED; 3951 } 3952 3953 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature, DWORD dwReinstallMode ) 3954 { 3955 static const WCHAR fmtW[] = {'%','s','=','%','s',' ','%','s','=','%','s',0}; 3956 MSIPACKAGE *package; 3957 MSIINSTALLCONTEXT context; 3958 UINT r; 3959 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH], reinstallmode[11]; 3960 WCHAR *ptr, *cmdline; 3961 DWORD sz; 3962 3963 TRACE("%s, %s, 0x%08x\n", debugstr_w(szProduct), debugstr_w(szFeature), dwReinstallMode); 3964 3965 r = msi_locate_product( szProduct, &context ); 3966 if (r != ERROR_SUCCESS) 3967 return r; 3968 3969 ptr = reinstallmode; 3970 3971 if (dwReinstallMode & REINSTALLMODE_FILEMISSING) 3972 *ptr++ = 'p'; 3973 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION) 3974 *ptr++ = 'o'; 3975 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION) 3976 *ptr++ = 'w'; 3977 if (dwReinstallMode & REINSTALLMODE_FILEEXACT) 3978 *ptr++ = 'd'; 3979 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY) 3980 *ptr++ = 'c'; 3981 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE) 3982 *ptr++ = 'a'; 3983 if (dwReinstallMode & REINSTALLMODE_USERDATA) 3984 *ptr++ = 'u'; 3985 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA) 3986 *ptr++ = 'm'; 3987 if (dwReinstallMode & REINSTALLMODE_SHORTCUT) 3988 *ptr++ = 's'; 3989 if (dwReinstallMode & REINSTALLMODE_PACKAGE) 3990 *ptr++ = 'v'; 3991 *ptr = 0; 3992 3993 sz = sizeof(sourcepath); 3994 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT, 3995 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz ); 3996 sz = sizeof(filename); 3997 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT, 3998 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz ); 3999 strcatW( sourcepath, filename ); 4000 4001 if (dwReinstallMode & REINSTALLMODE_PACKAGE) 4002 r = MSI_OpenPackageW( sourcepath, &package ); 4003 else 4004 r = MSI_OpenProductW( szProduct, &package ); 4005 4006 if (r != ERROR_SUCCESS) 4007 return r; 4008 4009 sz = (strlenW( fmtW ) + strlenW( szReinstallMode ) + strlenW( reinstallmode )) * sizeof(WCHAR); 4010 sz += (strlenW( szReinstall ) + strlenW( szFeature )) * sizeof(WCHAR); 4011 if (!(cmdline = msi_alloc( sz ))) 4012 { 4013 msiobj_release( &package->hdr ); 4014 return ERROR_OUTOFMEMORY; 4015 } 4016 sprintfW( cmdline, fmtW, szReinstallMode, reinstallmode, szReinstall, szFeature ); 4017 4018 r = MSI_InstallPackage( package, sourcepath, cmdline ); 4019 msiobj_release( &package->hdr ); 4020 msi_free( cmdline ); 4021 4022 return r; 4023 } 4024 4025 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature, 4026 DWORD dwReinstallMode ) 4027 { 4028 LPWSTR wszProduct; 4029 LPWSTR wszFeature; 4030 UINT rc; 4031 4032 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), 4033 dwReinstallMode); 4034 4035 wszProduct = strdupAtoW(szProduct); 4036 wszFeature = strdupAtoW(szFeature); 4037 4038 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode); 4039 4040 msi_free(wszProduct); 4041 msi_free(wszFeature); 4042 return rc; 4043 } 4044 4045 typedef struct 4046 { 4047 unsigned int i[2]; 4048 unsigned int buf[4]; 4049 unsigned char in[64]; 4050 unsigned char digest[16]; 4051 } MD5_CTX; 4052 4053 extern VOID WINAPI MD5Init( MD5_CTX *); 4054 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int ); 4055 extern VOID WINAPI MD5Final( MD5_CTX *); 4056 4057 UINT msi_get_filehash( const WCHAR *path, MSIFILEHASHINFO *hash ) 4058 { 4059 HANDLE handle, mapping; 4060 void *p; 4061 DWORD length; 4062 UINT r = ERROR_FUNCTION_FAILED; 4063 4064 handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL ); 4065 if (handle == INVALID_HANDLE_VALUE) 4066 { 4067 WARN("can't open file %u\n", GetLastError()); 4068 return ERROR_FILE_NOT_FOUND; 4069 } 4070 if ((length = GetFileSize( handle, NULL ))) 4071 { 4072 if ((mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL ))) 4073 { 4074 if ((p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length ))) 4075 { 4076 MD5_CTX ctx; 4077 4078 MD5Init( &ctx ); 4079 MD5Update( &ctx, p, length ); 4080 MD5Final( &ctx ); 4081 UnmapViewOfFile( p ); 4082 4083 memcpy( hash->dwData, ctx.digest, sizeof(hash->dwData) ); 4084 r = ERROR_SUCCESS; 4085 } 4086 CloseHandle( mapping ); 4087 } 4088 } 4089 else 4090 { 4091 /* Empty file -> set hash to 0 */ 4092 memset( hash->dwData, 0, sizeof(hash->dwData) ); 4093 r = ERROR_SUCCESS; 4094 } 4095 4096 CloseHandle( handle ); 4097 return r; 4098 } 4099 4100 /*********************************************************************** 4101 * MsiGetFileHashW [MSI.@] 4102 */ 4103 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions, 4104 PMSIFILEHASHINFO pHash ) 4105 { 4106 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash ); 4107 4108 if (!szFilePath) 4109 return ERROR_INVALID_PARAMETER; 4110 4111 if (!*szFilePath) 4112 return ERROR_PATH_NOT_FOUND; 4113 4114 if (dwOptions) 4115 return ERROR_INVALID_PARAMETER; 4116 if (!pHash) 4117 return ERROR_INVALID_PARAMETER; 4118 if (pHash->dwFileHashInfoSize < sizeof *pHash) 4119 return ERROR_INVALID_PARAMETER; 4120 4121 return msi_get_filehash( szFilePath, pHash ); 4122 } 4123 4124 /*********************************************************************** 4125 * MsiGetFileHashA [MSI.@] 4126 */ 4127 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions, 4128 PMSIFILEHASHINFO pHash ) 4129 { 4130 LPWSTR file; 4131 UINT r; 4132 4133 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash ); 4134 4135 file = strdupAtoW( szFilePath ); 4136 if (szFilePath && !file) 4137 return ERROR_OUTOFMEMORY; 4138 4139 r = MsiGetFileHashW( file, dwOptions, pHash ); 4140 msi_free( file ); 4141 return r; 4142 } 4143 4144 /*********************************************************************** 4145 * MsiAdvertiseScriptW [MSI.@] 4146 */ 4147 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags, 4148 PHKEY phRegData, BOOL fRemoveItems ) 4149 { 4150 FIXME("%s %08x %p %d\n", 4151 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems ); 4152 return ERROR_CALL_NOT_IMPLEMENTED; 4153 } 4154 4155 /*********************************************************************** 4156 * MsiAdvertiseScriptA [MSI.@] 4157 */ 4158 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags, 4159 PHKEY phRegData, BOOL fRemoveItems ) 4160 { 4161 FIXME("%s %08x %p %d\n", 4162 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems ); 4163 return ERROR_CALL_NOT_IMPLEMENTED; 4164 } 4165 4166 /*********************************************************************** 4167 * MsiIsProductElevatedW [MSI.@] 4168 */ 4169 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated ) 4170 { 4171 FIXME("%s %p - stub\n", 4172 debugstr_w( szProduct ), pfElevated ); 4173 *pfElevated = TRUE; 4174 return ERROR_SUCCESS; 4175 } 4176 4177 /*********************************************************************** 4178 * MsiIsProductElevatedA [MSI.@] 4179 */ 4180 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated ) 4181 { 4182 FIXME("%s %p - stub\n", 4183 debugstr_a( szProduct ), pfElevated ); 4184 *pfElevated = TRUE; 4185 return ERROR_SUCCESS; 4186 } 4187 4188 /*********************************************************************** 4189 * MsiSetExternalUIRecord [MSI.@] 4190 */ 4191 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler, 4192 DWORD filter, LPVOID context, 4193 PINSTALLUI_HANDLER_RECORD prev ) 4194 { 4195 TRACE("%p %08x %p %p\n", handler, filter, context, prev); 4196 4197 if (prev) 4198 *prev = gUIHandlerRecord; 4199 4200 gUIHandlerRecord = handler; 4201 gUIFilter = filter; 4202 gUIContext = context; 4203 4204 return ERROR_SUCCESS; 4205 } 4206 4207 /*********************************************************************** 4208 * MsiInstallMissingComponentA [MSI.@] 4209 */ 4210 UINT WINAPI MsiInstallMissingComponentA( LPCSTR product, LPCSTR component, INSTALLSTATE state ) 4211 { 4212 UINT r; 4213 WCHAR *productW = NULL, *componentW = NULL; 4214 4215 TRACE("%s, %s, %d\n", debugstr_a(product), debugstr_a(component), state); 4216 4217 if (product && !(productW = strdupAtoW( product ))) 4218 return ERROR_OUTOFMEMORY; 4219 4220 if (component && !(componentW = strdupAtoW( component ))) 4221 { 4222 msi_free( productW ); 4223 return ERROR_OUTOFMEMORY; 4224 } 4225 4226 r = MsiInstallMissingComponentW( productW, componentW, state ); 4227 msi_free( productW ); 4228 msi_free( componentW ); 4229 return r; 4230 } 4231 4232 /*********************************************************************** 4233 * MsiInstallMissingComponentW [MSI.@] 4234 */ 4235 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState) 4236 { 4237 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState); 4238 return ERROR_SUCCESS; 4239 } 4240 4241 UINT WINAPI MsiProvideComponentA( LPCSTR product, LPCSTR feature, LPCSTR component, DWORD mode, LPSTR buf, LPDWORD buflen ) 4242 { 4243 WCHAR *productW = NULL, *componentW = NULL, *featureW = NULL, *bufW = NULL; 4244 UINT r = ERROR_OUTOFMEMORY; 4245 DWORD lenW = 0; 4246 int len; 4247 4248 TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_a(product), debugstr_a(component), debugstr_a(feature), mode, buf, buflen); 4249 4250 if (product && !(productW = strdupAtoW( product ))) goto done; 4251 if (feature && !(featureW = strdupAtoW( feature ))) goto done; 4252 if (component && !(componentW = strdupAtoW( component ))) goto done; 4253 4254 r = MsiProvideComponentW( productW, featureW, componentW, mode, NULL, &lenW ); 4255 if (r != ERROR_SUCCESS) 4256 goto done; 4257 4258 if (!(bufW = msi_alloc( ++lenW * sizeof(WCHAR) ))) 4259 { 4260 r = ERROR_OUTOFMEMORY; 4261 goto done; 4262 } 4263 4264 r = MsiProvideComponentW( productW, featureW, componentW, mode, bufW, &lenW ); 4265 if (r != ERROR_SUCCESS) 4266 goto done; 4267 4268 len = WideCharToMultiByte( CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL ); 4269 if (buf) 4270 { 4271 if (len > *buflen) 4272 r = ERROR_MORE_DATA; 4273 else 4274 WideCharToMultiByte( CP_ACP, 0, bufW, -1, buf, *buflen, NULL, NULL ); 4275 } 4276 4277 *buflen = len - 1; 4278 4279 done: 4280 msi_free( productW ); 4281 msi_free( featureW ); 4282 msi_free( componentW ); 4283 msi_free( bufW ); 4284 return r; 4285 } 4286 4287 UINT WINAPI MsiProvideComponentW( LPCWSTR product, LPCWSTR feature, LPCWSTR component, DWORD mode, LPWSTR buf, LPDWORD buflen ) 4288 { 4289 INSTALLSTATE state; 4290 4291 TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_w(product), debugstr_w(component), debugstr_w(feature), mode, buf, buflen); 4292 4293 state = MsiQueryFeatureStateW( product, feature ); 4294 TRACE("feature state: %d\n", state); 4295 switch (mode) 4296 { 4297 case INSTALLMODE_NODETECTION: 4298 break; 4299 4300 default: 4301 FIXME("mode %x not implemented\n", mode); 4302 return ERROR_INSTALL_FAILURE; 4303 } 4304 4305 state = MsiGetComponentPathW( product, component, buf, buflen ); 4306 TRACE("component state: %d\n", state); 4307 switch (state) 4308 { 4309 case INSTALLSTATE_INVALIDARG: 4310 return ERROR_INVALID_PARAMETER; 4311 4312 case INSTALLSTATE_MOREDATA: 4313 return ERROR_MORE_DATA; 4314 4315 case INSTALLSTATE_ADVERTISED: 4316 case INSTALLSTATE_LOCAL: 4317 case INSTALLSTATE_SOURCE: 4318 MsiUseFeatureW( product, feature ); 4319 return ERROR_SUCCESS; 4320 4321 default: 4322 TRACE("MsiGetComponentPathW returned %d\n", state); 4323 return ERROR_INSTALL_FAILURE; 4324 } 4325 } 4326 4327 /*********************************************************************** 4328 * MsiBeginTransactionA [MSI.@] 4329 */ 4330 UINT WINAPI MsiBeginTransactionA( LPCSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event ) 4331 { 4332 WCHAR *nameW; 4333 UINT r; 4334 4335 FIXME("%s %u %p %p\n", debugstr_a(name), attrs, id, event); 4336 4337 nameW = strdupAtoW( name ); 4338 if (name && !nameW) 4339 return ERROR_OUTOFMEMORY; 4340 4341 r = MsiBeginTransactionW( nameW, attrs, id, event ); 4342 msi_free( nameW ); 4343 return r; 4344 } 4345 4346 /*********************************************************************** 4347 * MsiBeginTransactionW [MSI.@] 4348 */ 4349 UINT WINAPI MsiBeginTransactionW( LPCWSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event ) 4350 { 4351 FIXME("%s %u %p %p\n", debugstr_w(name), attrs, id, event); 4352 4353 *id = (MSIHANDLE)0xdeadbeef; 4354 *event = (HANDLE)0xdeadbeef; 4355 4356 return ERROR_SUCCESS; 4357 } 4358 4359 /*********************************************************************** 4360 * MsiJoinTransaction [MSI.@] 4361 */ 4362 UINT WINAPI MsiJoinTransaction( MSIHANDLE handle, DWORD attrs, HANDLE *event ) 4363 { 4364 FIXME("%u %08x %p\n", handle, attrs, event); 4365 4366 *event = (HANDLE)0xdeadbeef; 4367 return ERROR_SUCCESS; 4368 } 4369 4370 /*********************************************************************** 4371 * MsiEndTransaction [MSI.@] 4372 */ 4373 UINT WINAPI MsiEndTransaction( DWORD state ) 4374 { 4375 FIXME("%u\n", state); 4376 return ERROR_SUCCESS; 4377 } 4378 4379 UINT WINAPI Migrate10CachedPackagesW(void* a, void* b, void* c, DWORD d) 4380 { 4381 FIXME("%p,%p,%p,%08x\n", a, b, c, d); 4382 return ERROR_SUCCESS; 4383 } 4384 4385 /*********************************************************************** 4386 * MsiRemovePatchesA [MSI.@] 4387 */ 4388 UINT WINAPI MsiRemovePatchesA(LPCSTR patchlist, LPCSTR product, INSTALLTYPE type, LPCSTR propertylist) 4389 { 4390 FIXME("(%s %s %d %s\n", debugstr_a(patchlist), debugstr_a(product), type, debugstr_a(propertylist)); 4391 return ERROR_SUCCESS; 4392 } 4393 4394 /*********************************************************************** 4395 * MsiRemovePatchesW [MSI.@] 4396 */ 4397 UINT WINAPI MsiRemovePatchesW(LPCWSTR patchlist, LPCWSTR product, INSTALLTYPE type, LPCWSTR propertylist) 4398 { 4399 FIXME("(%s %s %d %s\n", debugstr_w(patchlist), debugstr_w(product), type, debugstr_w(propertylist)); 4400 return ERROR_SUCCESS; 4401 } 4402