Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmsi.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of the Microsoft Installer (msi.dll) 00003 * 00004 * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <stdarg.h> 00022 00023 #define COBJMACROS 00024 #define NONAMELESSUNION 00025 00026 #include "windef.h" 00027 #include "winbase.h" 00028 #include "winreg.h" 00029 #include "winnls.h" 00030 #include "shlwapi.h" 00031 #include "msi.h" 00032 #include "msidefs.h" 00033 #include "msiquery.h" 00034 #include "msipriv.h" 00035 #include "msiserver.h" 00036 #include "wincrypt.h" 00037 #include "winver.h" 00038 #include "winuser.h" 00039 #include "shlobj.h" 00040 #include "shobjidl.h" 00041 #include "objidl.h" 00042 #include "wintrust.h" 00043 #include "softpub.h" 00044 00045 #include "initguid.h" 00046 #include "msxml2.h" 00047 00048 #include "wine/debug.h" 00049 #include "wine/unicode.h" 00050 00051 WINE_DEFAULT_DEBUG_CHANNEL(msi); 00052 00053 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0}; 00054 00055 UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context) 00056 { 00057 HKEY hkey = NULL; 00058 00059 *context = MSIINSTALLCONTEXT_NONE; 00060 if (!szProduct) return ERROR_UNKNOWN_PRODUCT; 00061 00062 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, 00063 &hkey, FALSE) == ERROR_SUCCESS) 00064 *context = MSIINSTALLCONTEXT_USERMANAGED; 00065 else if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, 00066 &hkey, FALSE) == ERROR_SUCCESS) 00067 *context = MSIINSTALLCONTEXT_MACHINE; 00068 else if (MSIREG_OpenProductKey(szProduct, NULL, 00069 MSIINSTALLCONTEXT_USERUNMANAGED, 00070 &hkey, FALSE) == ERROR_SUCCESS) 00071 *context = MSIINSTALLCONTEXT_USERUNMANAGED; 00072 00073 RegCloseKey(hkey); 00074 00075 if (*context == MSIINSTALLCONTEXT_NONE) 00076 return ERROR_UNKNOWN_PRODUCT; 00077 00078 return ERROR_SUCCESS; 00079 } 00080 00081 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct) 00082 { 00083 UINT r; 00084 LPWSTR szwProd = NULL; 00085 00086 TRACE("%s %p\n",debugstr_a(szProduct), phProduct); 00087 00088 if( szProduct ) 00089 { 00090 szwProd = strdupAtoW( szProduct ); 00091 if( !szwProd ) 00092 return ERROR_OUTOFMEMORY; 00093 } 00094 00095 r = MsiOpenProductW( szwProd, phProduct ); 00096 00097 msi_free( szwProd ); 00098 00099 return r; 00100 } 00101 00102 static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package) 00103 { 00104 UINT r; 00105 HKEY props; 00106 LPWSTR path; 00107 MSIINSTALLCONTEXT context; 00108 00109 static const WCHAR managed[] = { 00110 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0}; 00111 static const WCHAR local[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0}; 00112 00113 TRACE("%s %p\n", debugstr_w(szProduct), package); 00114 00115 r = msi_locate_product(szProduct, &context); 00116 if (r != ERROR_SUCCESS) 00117 return r; 00118 00119 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &props, FALSE); 00120 if (r != ERROR_SUCCESS) 00121 return ERROR_UNKNOWN_PRODUCT; 00122 00123 if (context == MSIINSTALLCONTEXT_USERMANAGED) 00124 path = msi_reg_get_val_str(props, managed); 00125 else 00126 path = msi_reg_get_val_str(props, local); 00127 00128 r = ERROR_UNKNOWN_PRODUCT; 00129 00130 if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES) 00131 goto done; 00132 00133 if (PathIsRelativeW(path)) 00134 { 00135 r = ERROR_INSTALL_PACKAGE_OPEN_FAILED; 00136 goto done; 00137 } 00138 00139 r = MSI_OpenPackageW(path, package); 00140 00141 done: 00142 RegCloseKey(props); 00143 msi_free(path); 00144 return r; 00145 } 00146 00147 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct) 00148 { 00149 MSIPACKAGE *package = NULL; 00150 WCHAR squished_pc[GUID_SIZE]; 00151 UINT r; 00152 00153 if (!szProduct || !squash_guid(szProduct, squished_pc)) 00154 return ERROR_INVALID_PARAMETER; 00155 00156 if (!phProduct) 00157 return ERROR_INVALID_PARAMETER; 00158 00159 r = MSI_OpenProductW(szProduct, &package); 00160 if (r != ERROR_SUCCESS) 00161 return r; 00162 00163 *phProduct = alloc_msihandle(&package->hdr); 00164 if (!*phProduct) 00165 r = ERROR_NOT_ENOUGH_MEMORY; 00166 00167 msiobj_release(&package->hdr); 00168 return r; 00169 } 00170 00171 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, 00172 LPCSTR szTransforms, LANGID lgidLanguage) 00173 { 00174 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath), 00175 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage); 00176 return ERROR_CALL_NOT_IMPLEMENTED; 00177 } 00178 00179 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, 00180 LPCWSTR szTransforms, LANGID lgidLanguage) 00181 { 00182 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath), 00183 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage); 00184 return ERROR_CALL_NOT_IMPLEMENTED; 00185 } 00186 00187 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, 00188 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions) 00189 { 00190 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath), 00191 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), 00192 lgidLanguage, dwPlatform, dwOptions); 00193 return ERROR_CALL_NOT_IMPLEMENTED; 00194 } 00195 00196 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath, 00197 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions) 00198 { 00199 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath), 00200 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), 00201 lgidLanguage, dwPlatform, dwOptions); 00202 return ERROR_CALL_NOT_IMPLEMENTED; 00203 } 00204 00205 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine) 00206 { 00207 LPWSTR szwPath = NULL, szwCommand = NULL; 00208 UINT r = ERROR_OUTOFMEMORY; 00209 00210 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine)); 00211 00212 if( szPackagePath ) 00213 { 00214 szwPath = strdupAtoW( szPackagePath ); 00215 if( !szwPath ) 00216 goto end; 00217 } 00218 00219 if( szCommandLine ) 00220 { 00221 szwCommand = strdupAtoW( szCommandLine ); 00222 if( !szwCommand ) 00223 goto end; 00224 } 00225 00226 r = MsiInstallProductW( szwPath, szwCommand ); 00227 00228 end: 00229 msi_free( szwPath ); 00230 msi_free( szwCommand ); 00231 00232 return r; 00233 } 00234 00235 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine) 00236 { 00237 MSIPACKAGE *package = NULL; 00238 UINT r; 00239 00240 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine)); 00241 00242 if (!szPackagePath) 00243 return ERROR_INVALID_PARAMETER; 00244 00245 if (!*szPackagePath) 00246 return ERROR_PATH_NOT_FOUND; 00247 00248 r = MSI_OpenPackageW( szPackagePath, &package ); 00249 if (r == ERROR_SUCCESS) 00250 { 00251 r = MSI_InstallPackage( package, szPackagePath, szCommandLine ); 00252 msiobj_release( &package->hdr ); 00253 } 00254 00255 return r; 00256 } 00257 00258 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode) 00259 { 00260 LPWSTR wszProduct; 00261 UINT rc; 00262 00263 TRACE("%s %08x\n", debugstr_a(szProduct), dwReinstallMode); 00264 00265 wszProduct = strdupAtoW(szProduct); 00266 00267 rc = MsiReinstallProductW(wszProduct, dwReinstallMode); 00268 00269 msi_free(wszProduct); 00270 return rc; 00271 } 00272 00273 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode) 00274 { 00275 TRACE("%s %08x\n", debugstr_w(szProduct), dwReinstallMode); 00276 00277 return MsiReinstallFeatureW(szProduct, szAll, dwReinstallMode); 00278 } 00279 00280 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage, 00281 INSTALLTYPE eInstallType, LPCSTR szCommandLine) 00282 { 00283 LPWSTR patch_package = NULL; 00284 LPWSTR install_package = NULL; 00285 LPWSTR command_line = NULL; 00286 UINT r = ERROR_OUTOFMEMORY; 00287 00288 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage), 00289 eInstallType, debugstr_a(szCommandLine)); 00290 00291 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage))) 00292 goto done; 00293 00294 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage))) 00295 goto done; 00296 00297 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine))) 00298 goto done; 00299 00300 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line); 00301 00302 done: 00303 msi_free(patch_package); 00304 msi_free(install_package); 00305 msi_free(command_line); 00306 00307 return r; 00308 } 00309 00310 static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes ) 00311 { 00312 MSIHANDLE patch, info = 0; 00313 UINT r, type; 00314 DWORD size; 00315 static WCHAR empty[] = {0}; 00316 WCHAR *codes = NULL; 00317 00318 r = MsiOpenDatabaseW( szPatchPackage, MSIDBOPEN_READONLY, &patch ); 00319 if (r != ERROR_SUCCESS) 00320 return r; 00321 00322 r = MsiGetSummaryInformationW( patch, NULL, 0, &info ); 00323 if (r != ERROR_SUCCESS) 00324 goto done; 00325 00326 size = 0; 00327 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, empty, &size ); 00328 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR) 00329 { 00330 ERR("Failed to read product codes from patch\n"); 00331 r = ERROR_FUNCTION_FAILED; 00332 goto done; 00333 } 00334 00335 codes = msi_alloc( ++size * sizeof(WCHAR) ); 00336 if (!codes) 00337 { 00338 r = ERROR_OUTOFMEMORY; 00339 goto done; 00340 } 00341 00342 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, codes, &size ); 00343 if (r == ERROR_SUCCESS) 00344 *product_codes = msi_split_string( codes, ';' ); 00345 00346 done: 00347 MsiCloseHandle( info ); 00348 MsiCloseHandle( patch ); 00349 msi_free( codes ); 00350 return r; 00351 } 00352 00353 static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine) 00354 { 00355 UINT i, r = ERROR_FUNCTION_FAILED; 00356 DWORD size; 00357 LPCWSTR cmd_ptr = szCommandLine; 00358 LPWSTR cmd, *codes = NULL; 00359 BOOL succeeded = FALSE; 00360 00361 static const WCHAR fmt[] = {'%','s',' ','P','A','T','C','H','=','"','%','s','"',0}; 00362 static WCHAR empty[] = {0}; 00363 00364 if (!szPatchPackage || !szPatchPackage[0]) 00365 return ERROR_INVALID_PARAMETER; 00366 00367 if (!szProductCode && (r = get_patch_product_codes( szPatchPackage, &codes ))) 00368 return r; 00369 00370 if (!szCommandLine) 00371 cmd_ptr = empty; 00372 00373 size = strlenW(cmd_ptr) + strlenW(fmt) + strlenW(szPatchPackage) + 1; 00374 cmd = msi_alloc(size * sizeof(WCHAR)); 00375 if (!cmd) 00376 { 00377 msi_free(codes); 00378 return ERROR_OUTOFMEMORY; 00379 } 00380 sprintfW(cmd, fmt, cmd_ptr, szPatchPackage); 00381 00382 if (szProductCode) 00383 r = MsiConfigureProductExW(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd); 00384 else 00385 { 00386 for (i = 0; codes[i]; i++) 00387 { 00388 r = MsiConfigureProductExW(codes[i], INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd); 00389 if (r == ERROR_SUCCESS) 00390 { 00391 TRACE("patch applied\n"); 00392 succeeded = TRUE; 00393 } 00394 } 00395 00396 if (succeeded) 00397 r = ERROR_SUCCESS; 00398 } 00399 00400 msi_free(cmd); 00401 msi_free(codes); 00402 return r; 00403 } 00404 00405 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage, 00406 INSTALLTYPE eInstallType, LPCWSTR szCommandLine) 00407 { 00408 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage), 00409 eInstallType, debugstr_w(szCommandLine)); 00410 00411 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE || 00412 eInstallType == INSTALLTYPE_SINGLE_INSTANCE) 00413 { 00414 FIXME("Only reading target products from patch\n"); 00415 return ERROR_CALL_NOT_IMPLEMENTED; 00416 } 00417 00418 return MSI_ApplyPatchW(szPatchPackage, NULL, szCommandLine); 00419 } 00420 00421 UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR szPatchPackages, 00422 LPCSTR szProductCode, LPCSTR szPropertiesList) 00423 { 00424 LPWSTR patch_packages = NULL; 00425 LPWSTR product_code = NULL; 00426 LPWSTR properties_list = NULL; 00427 UINT r = ERROR_OUTOFMEMORY; 00428 00429 TRACE("%s %s %s\n", debugstr_a(szPatchPackages), debugstr_a(szProductCode), 00430 debugstr_a(szPropertiesList)); 00431 00432 if (!szPatchPackages || !szPatchPackages[0]) 00433 return ERROR_INVALID_PARAMETER; 00434 00435 if (!(patch_packages = strdupAtoW(szPatchPackages))) 00436 return ERROR_OUTOFMEMORY; 00437 00438 if (szProductCode && !(product_code = strdupAtoW(szProductCode))) 00439 goto done; 00440 00441 if (szPropertiesList && !(properties_list = strdupAtoW(szPropertiesList))) 00442 goto done; 00443 00444 r = MsiApplyMultiplePatchesW(patch_packages, product_code, properties_list); 00445 00446 done: 00447 msi_free(patch_packages); 00448 msi_free(product_code); 00449 msi_free(properties_list); 00450 00451 return r; 00452 } 00453 00454 UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages, 00455 LPCWSTR szProductCode, LPCWSTR szPropertiesList) 00456 { 00457 UINT r = ERROR_SUCCESS; 00458 LPCWSTR beg, end; 00459 00460 TRACE("%s %s %s\n", debugstr_w(szPatchPackages), debugstr_w(szProductCode), 00461 debugstr_w(szPropertiesList)); 00462 00463 if (!szPatchPackages || !szPatchPackages[0]) 00464 return ERROR_INVALID_PARAMETER; 00465 00466 beg = end = szPatchPackages; 00467 while (*beg) 00468 { 00469 DWORD len; 00470 LPWSTR patch; 00471 00472 while (*beg == ' ') beg++; 00473 while (*end && *end != ';') end++; 00474 00475 len = end - beg; 00476 while (len && beg[len - 1] == ' ') len--; 00477 00478 if (!len) return ERROR_INVALID_NAME; 00479 00480 patch = msi_alloc((len + 1) * sizeof(WCHAR)); 00481 if (!patch) 00482 return ERROR_OUTOFMEMORY; 00483 00484 memcpy(patch, beg, len * sizeof(WCHAR)); 00485 patch[len] = '\0'; 00486 00487 r = MSI_ApplyPatchW(patch, szProductCode, szPropertiesList); 00488 msi_free(patch); 00489 00490 if (r != ERROR_SUCCESS) 00491 break; 00492 00493 beg = ++end; 00494 } 00495 return r; 00496 } 00497 00498 static void free_patchinfo( DWORD count, MSIPATCHSEQUENCEINFOW *info ) 00499 { 00500 DWORD i; 00501 for (i = 0; i < count; i++) msi_free( (WCHAR *)info[i].szPatchData ); 00502 msi_free( info ); 00503 } 00504 00505 static MSIPATCHSEQUENCEINFOW *patchinfoAtoW( DWORD count, const MSIPATCHSEQUENCEINFOA *info ) 00506 { 00507 DWORD i; 00508 MSIPATCHSEQUENCEINFOW *ret; 00509 00510 if (!(ret = msi_alloc( count * sizeof(MSIPATCHSEQUENCEINFOW) ))) return NULL; 00511 for (i = 0; i < count; i++) 00512 { 00513 if (info[i].szPatchData && !(ret[i].szPatchData = strdupAtoW( info[i].szPatchData ))) 00514 { 00515 free_patchinfo( i, ret ); 00516 return NULL; 00517 } 00518 ret[i].ePatchDataType = info[i].ePatchDataType; 00519 ret[i].dwOrder = info[i].dwOrder; 00520 ret[i].uStatus = info[i].uStatus; 00521 } 00522 return ret; 00523 } 00524 00525 UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath, 00526 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo) 00527 { 00528 UINT i, r; 00529 WCHAR *package_path = NULL; 00530 MSIPATCHSEQUENCEINFOW *psi; 00531 00532 TRACE("%s, %u, %p\n", debugstr_a(szProductPackagePath), cPatchInfo, pPatchInfo); 00533 00534 if (szProductPackagePath && !(package_path = strdupAtoW( szProductPackagePath ))) 00535 return ERROR_OUTOFMEMORY; 00536 00537 if (!(psi = patchinfoAtoW( cPatchInfo, pPatchInfo ))) 00538 { 00539 msi_free( package_path ); 00540 return ERROR_OUTOFMEMORY; 00541 } 00542 r = MsiDetermineApplicablePatchesW( package_path, cPatchInfo, psi ); 00543 if (r == ERROR_SUCCESS) 00544 { 00545 for (i = 0; i < cPatchInfo; i++) 00546 { 00547 pPatchInfo[i].dwOrder = psi[i].dwOrder; 00548 pPatchInfo[i].uStatus = psi[i].uStatus; 00549 } 00550 } 00551 msi_free( package_path ); 00552 free_patchinfo( cPatchInfo, psi ); 00553 return r; 00554 } 00555 00556 static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch ) 00557 { 00558 MSISUMMARYINFO *si; 00559 MSIDATABASE *patch_db; 00560 UINT r = ERROR_SUCCESS; 00561 00562 r = MSI_OpenDatabaseW( patch, MSIDBOPEN_READONLY, &patch_db ); 00563 if (r != ERROR_SUCCESS) 00564 { 00565 WARN("failed to open patch file %s\n", debugstr_w(patch)); 00566 return r; 00567 } 00568 00569 si = MSI_GetSummaryInformationW( patch_db->storage, 0 ); 00570 if (!si) 00571 { 00572 msiobj_release( &patch_db->hdr ); 00573 return ERROR_FUNCTION_FAILED; 00574 } 00575 00576 r = msi_check_patch_applicable( package, si ); 00577 if (r != ERROR_SUCCESS) 00578 TRACE("patch not applicable\n"); 00579 00580 msiobj_release( &patch_db->hdr ); 00581 msiobj_release( &si->hdr ); 00582 return r; 00583 } 00584 00585 /* IXMLDOMDocument should be set to XPath mode already */ 00586 static UINT MSI_ApplicablePatchXML( MSIPACKAGE *package, IXMLDOMDocument *desc ) 00587 { 00588 static const WCHAR queryW[] = {'M','s','i','P','a','t','c','h','/', 00589 'T','a','r','g','e','t','P','r','o','d','u','c','t','/', 00590 'T','a','r','g','e','t','P','r','o','d','u','c','t','C','o','d','e',0}; 00591 UINT r = ERROR_FUNCTION_FAILED; 00592 IXMLDOMNodeList *list; 00593 LPWSTR product_code; 00594 IXMLDOMNode *node; 00595 HRESULT hr; 00596 BSTR s; 00597 00598 product_code = msi_dup_property( package->db, szProductCode ); 00599 if (!product_code) 00600 { 00601 /* FIXME: the property ProductCode should be written into the DB somewhere */ 00602 ERR("no product code to check\n"); 00603 return ERROR_SUCCESS; 00604 } 00605 00606 s = SysAllocString(queryW); 00607 hr = IXMLDOMDocument_selectNodes( desc, s, &list ); 00608 SysFreeString(s); 00609 if (hr != S_OK) 00610 return ERROR_INVALID_PATCH_XML; 00611 00612 while (IXMLDOMNodeList_nextNode( list, &node ) == S_OK && r != ERROR_SUCCESS) 00613 { 00614 hr = IXMLDOMNode_get_text( node, &s ); 00615 IXMLDOMNode_Release( node ); 00616 if (hr == S_OK) 00617 { 00618 if (!strcmpW( s, product_code )) r = ERROR_SUCCESS; 00619 SysFreeString( s ); 00620 } 00621 } 00622 IXMLDOMNodeList_Release( list ); 00623 00624 if (r != ERROR_SUCCESS) 00625 TRACE("patch not applicable\n"); 00626 00627 msi_free( product_code ); 00628 return r; 00629 } 00630 00631 static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCHSEQUENCEINFOW *info ) 00632 { 00633 IXMLDOMDocument *desc = NULL; 00634 DWORD i; 00635 00636 if (count > 1) 00637 FIXME("patch ordering not supported\n"); 00638 00639 for (i = 0; i < count; i++) 00640 { 00641 switch (info[i].ePatchDataType) 00642 { 00643 case MSIPATCH_DATATYPE_PATCHFILE: 00644 { 00645 if (MSI_ApplicablePatchW( package, info[i].szPatchData ) != ERROR_SUCCESS) 00646 { 00647 info[i].dwOrder = ~0u; 00648 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND; 00649 } 00650 else 00651 { 00652 info[i].dwOrder = i; 00653 info[i].uStatus = ERROR_SUCCESS; 00654 } 00655 break; 00656 } 00657 case MSIPATCH_DATATYPE_XMLPATH: 00658 case MSIPATCH_DATATYPE_XMLBLOB: 00659 { 00660 VARIANT_BOOL b; 00661 HRESULT hr; 00662 BSTR s; 00663 00664 if (!desc) 00665 { 00666 hr = CoCreateInstance( &CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER, 00667 &IID_IXMLDOMDocument, (void**)&desc ); 00668 if (hr != S_OK) 00669 { 00670 ERR("failed to create DOMDocument30 instance, 0x%08x\n", hr); 00671 return ERROR_FUNCTION_FAILED; 00672 } 00673 } 00674 00675 s = SysAllocString( info[i].szPatchData ); 00676 if (info[i].ePatchDataType == MSIPATCH_DATATYPE_XMLPATH) 00677 { 00678 VARIANT src; 00679 00680 V_VT(&src) = VT_BSTR; 00681 V_BSTR(&src) = s; 00682 hr = IXMLDOMDocument_load( desc, src, &b ); 00683 } 00684 else 00685 hr = IXMLDOMDocument_loadXML( desc, s, &b ); 00686 SysFreeString( s ); 00687 if ( hr != S_OK ) 00688 { 00689 ERR("failed to parse patch description\n"); 00690 IXMLDOMDocument_Release( desc ); 00691 break; 00692 } 00693 00694 if (MSI_ApplicablePatchXML( package, desc ) != ERROR_SUCCESS) 00695 { 00696 info[i].dwOrder = ~0u; 00697 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND; 00698 } 00699 else 00700 { 00701 info[i].dwOrder = i; 00702 info[i].uStatus = ERROR_SUCCESS; 00703 } 00704 break; 00705 } 00706 default: 00707 { 00708 FIXME("unknown patch data type %u\n", info[i].ePatchDataType); 00709 info[i].dwOrder = i; 00710 info[i].uStatus = ERROR_SUCCESS; 00711 break; 00712 } 00713 } 00714 00715 TRACE("szPatchData: %s\n", debugstr_w(info[i].szPatchData)); 00716 TRACE("ePatchDataType: %u\n", info[i].ePatchDataType); 00717 TRACE("dwOrder: %u\n", info[i].dwOrder); 00718 TRACE("uStatus: %u\n", info[i].uStatus); 00719 } 00720 00721 if (desc) IXMLDOMDocument_Release( desc ); 00722 00723 return ERROR_SUCCESS; 00724 } 00725 00726 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath, 00727 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo) 00728 { 00729 UINT r; 00730 MSIPACKAGE *package; 00731 00732 TRACE("%s, %u, %p\n", debugstr_w(szProductPackagePath), cPatchInfo, pPatchInfo); 00733 00734 r = MSI_OpenPackageW( szProductPackagePath, &package ); 00735 if (r != ERROR_SUCCESS) 00736 { 00737 ERR("failed to open package %u\n", r); 00738 return r; 00739 } 00740 r = determine_patch_sequence( package, cPatchInfo, pPatchInfo ); 00741 msiobj_release( &package->hdr ); 00742 return r; 00743 } 00744 00745 UINT WINAPI MsiDeterminePatchSequenceA( LPCSTR product, LPCSTR usersid, 00746 MSIINSTALLCONTEXT context, DWORD count, PMSIPATCHSEQUENCEINFOA patchinfo ) 00747 { 00748 UINT i, r; 00749 WCHAR *productW, *usersidW = NULL; 00750 MSIPATCHSEQUENCEINFOW *patchinfoW; 00751 00752 TRACE("%s, %s, %d, %d, %p\n", debugstr_a(product), debugstr_a(usersid), 00753 context, count, patchinfo); 00754 00755 if (!product) return ERROR_INVALID_PARAMETER; 00756 if (!(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY; 00757 if (usersid && !(usersidW = strdupAtoW( usersid ))) 00758 { 00759 msi_free( productW ); 00760 return ERROR_OUTOFMEMORY; 00761 } 00762 if (!(patchinfoW = patchinfoAtoW( count, patchinfo ))) 00763 { 00764 msi_free( productW ); 00765 msi_free( usersidW ); 00766 return ERROR_OUTOFMEMORY; 00767 } 00768 r = MsiDeterminePatchSequenceW( productW, usersidW, context, count, patchinfoW ); 00769 if (r == ERROR_SUCCESS) 00770 { 00771 for (i = 0; i < count; i++) 00772 { 00773 patchinfo[i].dwOrder = patchinfoW[i].dwOrder; 00774 patchinfo[i].uStatus = patchinfoW[i].uStatus; 00775 } 00776 } 00777 msi_free( productW ); 00778 msi_free( usersidW ); 00779 free_patchinfo( count, patchinfoW ); 00780 return r; 00781 } 00782 00783 static UINT open_package( const WCHAR *product, const WCHAR *usersid, 00784 MSIINSTALLCONTEXT context, MSIPACKAGE **package ) 00785 { 00786 UINT r; 00787 HKEY props; 00788 WCHAR *localpath, sourcepath[MAX_PATH], filename[MAX_PATH]; 00789 00790 r = MSIREG_OpenInstallProps( product, context, usersid, &props, FALSE ); 00791 if (r != ERROR_SUCCESS) return ERROR_BAD_CONFIGURATION; 00792 00793 if ((localpath = msi_reg_get_val_str( props, szLocalPackage ))) 00794 { 00795 strcpyW( sourcepath, localpath ); 00796 msi_free( localpath ); 00797 } 00798 RegCloseKey( props ); 00799 if (!localpath || GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES) 00800 { 00801 DWORD sz = sizeof(sourcepath); 00802 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT, 00803 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz ); 00804 sz = sizeof(filename); 00805 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT, 00806 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz ); 00807 strcatW( sourcepath, filename ); 00808 } 00809 if (GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES) 00810 return ERROR_INSTALL_SOURCE_ABSENT; 00811 00812 return MSI_OpenPackageW( sourcepath, package ); 00813 } 00814 00815 UINT WINAPI MsiDeterminePatchSequenceW( LPCWSTR product, LPCWSTR usersid, 00816 MSIINSTALLCONTEXT context, DWORD count, PMSIPATCHSEQUENCEINFOW patchinfo ) 00817 { 00818 UINT r; 00819 MSIPACKAGE *package; 00820 00821 TRACE("%s, %s, %d, %d, %p\n", debugstr_w(product), debugstr_w(usersid), 00822 context, count, patchinfo); 00823 00824 if (!product) return ERROR_INVALID_PARAMETER; 00825 r = open_package( product, usersid, context, &package ); 00826 if (r != ERROR_SUCCESS) return r; 00827 00828 r = determine_patch_sequence( package, count, patchinfo ); 00829 msiobj_release( &package->hdr ); 00830 return r; 00831 } 00832 00833 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, 00834 INSTALLSTATE eInstallState, LPCWSTR szCommandLine) 00835 { 00836 MSIPACKAGE* package = NULL; 00837 MSIINSTALLCONTEXT context; 00838 UINT r; 00839 DWORD sz; 00840 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH]; 00841 LPWSTR commandline; 00842 00843 static const WCHAR szInstalled[] = { 00844 ' ','I','n','s','t','a','l','l','e','d','=','1',0}; 00845 static const WCHAR szMaxInstallLevel[] = { 00846 ' ','I','N','S','T','A','L','L','L','E','V','E','L','=','3','2','7','6','7',0}; 00847 static const WCHAR szRemoveAll[] = { 00848 ' ','R','E','M','O','V','E','=','A','L','L',0}; 00849 static const WCHAR szMachine[] = { 00850 ' ','A','L','L','U','S','E','R','S','=','1',0}; 00851 00852 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState, 00853 debugstr_w(szCommandLine)); 00854 00855 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1) 00856 return ERROR_INVALID_PARAMETER; 00857 00858 if (eInstallState == INSTALLSTATE_ADVERTISED || 00859 eInstallState == INSTALLSTATE_SOURCE) 00860 { 00861 FIXME("State %d not implemented\n", eInstallState); 00862 return ERROR_CALL_NOT_IMPLEMENTED; 00863 } 00864 00865 r = msi_locate_product(szProduct, &context); 00866 if (r != ERROR_SUCCESS) 00867 return r; 00868 00869 r = open_package(szProduct, NULL, context, &package); 00870 if (r != ERROR_SUCCESS) 00871 return r; 00872 00873 sz = lstrlenW(szInstalled) + 1; 00874 00875 if (szCommandLine) 00876 sz += lstrlenW(szCommandLine); 00877 00878 if (eInstallState != INSTALLSTATE_DEFAULT) 00879 sz += lstrlenW(szMaxInstallLevel); 00880 00881 if (eInstallState == INSTALLSTATE_ABSENT) 00882 sz += lstrlenW(szRemoveAll); 00883 00884 if (context == MSIINSTALLCONTEXT_MACHINE) 00885 sz += lstrlenW(szMachine); 00886 00887 commandline = msi_alloc(sz * sizeof(WCHAR)); 00888 if (!commandline) 00889 { 00890 r = ERROR_OUTOFMEMORY; 00891 goto end; 00892 } 00893 00894 commandline[0] = 0; 00895 if (szCommandLine) 00896 lstrcpyW(commandline,szCommandLine); 00897 00898 if (eInstallState != INSTALLSTATE_DEFAULT) 00899 lstrcatW(commandline, szMaxInstallLevel); 00900 00901 if (eInstallState == INSTALLSTATE_ABSENT) 00902 lstrcatW(commandline, szRemoveAll); 00903 00904 if (context == MSIINSTALLCONTEXT_MACHINE) 00905 lstrcatW(commandline, szMachine); 00906 00907 sz = sizeof(sourcepath); 00908 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT, 00909 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); 00910 00911 sz = sizeof(filename); 00912 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT, 00913 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); 00914 00915 strcatW(sourcepath, filename); 00916 00917 r = MSI_InstallPackage( package, sourcepath, commandline ); 00918 00919 msi_free(commandline); 00920 00921 end: 00922 msiobj_release( &package->hdr ); 00923 00924 return r; 00925 } 00926 00927 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel, 00928 INSTALLSTATE eInstallState, LPCSTR szCommandLine) 00929 { 00930 LPWSTR szwProduct = NULL; 00931 LPWSTR szwCommandLine = NULL; 00932 UINT r = ERROR_OUTOFMEMORY; 00933 00934 if( szProduct ) 00935 { 00936 szwProduct = strdupAtoW( szProduct ); 00937 if( !szwProduct ) 00938 goto end; 00939 } 00940 00941 if( szCommandLine) 00942 { 00943 szwCommandLine = strdupAtoW( szCommandLine ); 00944 if( !szwCommandLine) 00945 goto end; 00946 } 00947 00948 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState, 00949 szwCommandLine ); 00950 end: 00951 msi_free( szwProduct ); 00952 msi_free( szwCommandLine); 00953 00954 return r; 00955 } 00956 00957 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, 00958 INSTALLSTATE eInstallState) 00959 { 00960 LPWSTR szwProduct = NULL; 00961 UINT r; 00962 00963 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState); 00964 00965 if( szProduct ) 00966 { 00967 szwProduct = strdupAtoW( szProduct ); 00968 if( !szwProduct ) 00969 return ERROR_OUTOFMEMORY; 00970 } 00971 00972 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState ); 00973 msi_free( szwProduct ); 00974 00975 return r; 00976 } 00977 00978 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel, 00979 INSTALLSTATE eInstallState) 00980 { 00981 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL); 00982 } 00983 00984 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer) 00985 { 00986 LPWSTR szwComponent = NULL; 00987 UINT r; 00988 WCHAR szwBuffer[GUID_SIZE]; 00989 00990 TRACE("%s %p\n", debugstr_a(szComponent), szBuffer); 00991 00992 if( szComponent ) 00993 { 00994 szwComponent = strdupAtoW( szComponent ); 00995 if( !szwComponent ) 00996 return ERROR_OUTOFMEMORY; 00997 } 00998 00999 *szwBuffer = '\0'; 01000 r = MsiGetProductCodeW( szwComponent, szwBuffer ); 01001 01002 if(*szwBuffer) 01003 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL); 01004 01005 msi_free( szwComponent ); 01006 01007 return r; 01008 } 01009 01010 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer) 01011 { 01012 UINT rc, index; 01013 HKEY compkey, prodkey; 01014 WCHAR squished_comp[GUID_SIZE]; 01015 WCHAR squished_prod[GUID_SIZE]; 01016 DWORD sz = GUID_SIZE; 01017 01018 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer); 01019 01020 if (!szComponent || !*szComponent) 01021 return ERROR_INVALID_PARAMETER; 01022 01023 if (!squash_guid(szComponent, squished_comp)) 01024 return ERROR_INVALID_PARAMETER; 01025 01026 if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &compkey, FALSE) != ERROR_SUCCESS && 01027 MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &compkey, FALSE) != ERROR_SUCCESS) 01028 { 01029 return ERROR_UNKNOWN_COMPONENT; 01030 } 01031 01032 rc = RegEnumValueW(compkey, 0, squished_prod, &sz, NULL, NULL, NULL, NULL); 01033 if (rc != ERROR_SUCCESS) 01034 { 01035 RegCloseKey(compkey); 01036 return ERROR_UNKNOWN_COMPONENT; 01037 } 01038 01039 /* check simple case, only one product */ 01040 rc = RegEnumValueW(compkey, 1, squished_prod, &sz, NULL, NULL, NULL, NULL); 01041 if (rc == ERROR_NO_MORE_ITEMS) 01042 { 01043 rc = ERROR_SUCCESS; 01044 goto done; 01045 } 01046 01047 index = 0; 01048 while ((rc = RegEnumValueW(compkey, index, squished_prod, &sz, 01049 NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS) 01050 { 01051 index++; 01052 sz = GUID_SIZE; 01053 unsquash_guid(squished_prod, szBuffer); 01054 01055 if (MSIREG_OpenProductKey(szBuffer, NULL, 01056 MSIINSTALLCONTEXT_USERMANAGED, 01057 &prodkey, FALSE) == ERROR_SUCCESS || 01058 MSIREG_OpenProductKey(szBuffer, NULL, 01059 MSIINSTALLCONTEXT_USERUNMANAGED, 01060 &prodkey, FALSE) == ERROR_SUCCESS || 01061 MSIREG_OpenProductKey(szBuffer, NULL, 01062 MSIINSTALLCONTEXT_MACHINE, 01063 &prodkey, FALSE) == ERROR_SUCCESS) 01064 { 01065 RegCloseKey(prodkey); 01066 rc = ERROR_SUCCESS; 01067 goto done; 01068 } 01069 } 01070 01071 rc = ERROR_INSTALL_FAILURE; 01072 01073 done: 01074 RegCloseKey(compkey); 01075 unsquash_guid(squished_prod, szBuffer); 01076 return rc; 01077 } 01078 01079 static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type) 01080 { 01081 DWORD dval; 01082 LONG res; 01083 WCHAR temp[20]; 01084 01085 static const WCHAR format[] = {'%','d',0}; 01086 01087 res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL); 01088 if (res != ERROR_SUCCESS) 01089 return NULL; 01090 01091 if (*type == REG_SZ) 01092 return msi_reg_get_val_str(hkey, name); 01093 01094 if (!msi_reg_get_val_dword(hkey, name, &dval)) 01095 return NULL; 01096 01097 sprintfW(temp, format, dval); 01098 return strdupW(temp); 01099 } 01100 01101 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, 01102 awstring *szValue, LPDWORD pcchValueBuf) 01103 { 01104 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED; 01105 UINT r = ERROR_UNKNOWN_PROPERTY; 01106 HKEY prodkey, userdata, source; 01107 LPWSTR val = NULL; 01108 WCHAR squished_pc[GUID_SIZE]; 01109 WCHAR packagecode[GUID_SIZE]; 01110 BOOL badconfig = FALSE; 01111 LONG res; 01112 DWORD type = REG_NONE; 01113 01114 static WCHAR empty[] = {0}; 01115 static const WCHAR sourcelist[] = { 01116 'S','o','u','r','c','e','L','i','s','t',0}; 01117 static const WCHAR display_name[] = { 01118 'D','i','s','p','l','a','y','N','a','m','e',0}; 01119 static const WCHAR display_version[] = { 01120 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0}; 01121 static const WCHAR assignment[] = { 01122 'A','s','s','i','g','n','m','e','n','t',0}; 01123 01124 TRACE("%s %s %p %p\n", debugstr_w(szProduct), 01125 debugstr_w(szAttribute), szValue, pcchValueBuf); 01126 01127 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute) 01128 return ERROR_INVALID_PARAMETER; 01129 01130 if (!squash_guid(szProduct, squished_pc)) 01131 return ERROR_INVALID_PARAMETER; 01132 01133 if ((r = MSIREG_OpenProductKey(szProduct, NULL, 01134 MSIINSTALLCONTEXT_USERMANAGED, 01135 &prodkey, FALSE)) != ERROR_SUCCESS && 01136 (r = MSIREG_OpenProductKey(szProduct, NULL, 01137 MSIINSTALLCONTEXT_USERUNMANAGED, 01138 &prodkey, FALSE)) != ERROR_SUCCESS && 01139 (r = MSIREG_OpenProductKey(szProduct, NULL, 01140 MSIINSTALLCONTEXT_MACHINE, 01141 &prodkey, FALSE)) == ERROR_SUCCESS) 01142 { 01143 context = MSIINSTALLCONTEXT_MACHINE; 01144 } 01145 01146 MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE); 01147 01148 if (!strcmpW( szAttribute, INSTALLPROPERTY_HELPLINKW ) || 01149 !strcmpW( szAttribute, INSTALLPROPERTY_HELPTELEPHONEW ) || 01150 !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLDATEW ) || 01151 !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) || 01152 !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW ) || 01153 !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLSOURCEW ) || 01154 !strcmpW( szAttribute, INSTALLPROPERTY_LOCALPACKAGEW ) || 01155 !strcmpW( szAttribute, INSTALLPROPERTY_PUBLISHERW ) || 01156 !strcmpW( szAttribute, INSTALLPROPERTY_URLINFOABOUTW ) || 01157 !strcmpW( szAttribute, INSTALLPROPERTY_URLUPDATEINFOW ) || 01158 !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMINORW ) || 01159 !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMAJORW ) || 01160 !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ) || 01161 !strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTIDW ) || 01162 !strcmpW( szAttribute, INSTALLPROPERTY_REGCOMPANYW ) || 01163 !strcmpW( szAttribute, INSTALLPROPERTY_REGOWNERW )) 01164 { 01165 if (!prodkey) 01166 { 01167 r = ERROR_UNKNOWN_PRODUCT; 01168 goto done; 01169 } 01170 01171 if (!userdata) 01172 return ERROR_UNKNOWN_PROPERTY; 01173 01174 if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW )) 01175 szAttribute = display_name; 01176 else if (!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW )) 01177 szAttribute = display_version; 01178 01179 val = msi_reg_get_value(userdata, szAttribute, &type); 01180 if (!val) 01181 val = empty; 01182 } 01183 else if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTANCETYPEW ) || 01184 !strcmpW( szAttribute, INSTALLPROPERTY_TRANSFORMSW ) || 01185 !strcmpW( szAttribute, INSTALLPROPERTY_LANGUAGEW ) || 01186 !strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTNAMEW ) || 01187 !strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ) || 01188 !strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW ) || 01189 !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONW ) || 01190 !strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTICONW ) || 01191 !strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ) || 01192 !strcmpW( szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW )) 01193 { 01194 if (!prodkey) 01195 { 01196 r = ERROR_UNKNOWN_PRODUCT; 01197 goto done; 01198 } 01199 01200 if (!strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW )) 01201 szAttribute = assignment; 01202 01203 if (!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW )) 01204 { 01205 res = RegOpenKeyW(prodkey, sourcelist, &source); 01206 if (res != ERROR_SUCCESS) 01207 { 01208 r = ERROR_UNKNOWN_PRODUCT; 01209 goto done; 01210 } 01211 01212 val = msi_reg_get_value(source, szAttribute, &type); 01213 if (!val) 01214 val = empty; 01215 01216 RegCloseKey(source); 01217 } 01218 else 01219 { 01220 val = msi_reg_get_value(prodkey, szAttribute, &type); 01221 if (!val) 01222 val = empty; 01223 } 01224 01225 if (val != empty && type != REG_DWORD && 01226 !strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW )) 01227 { 01228 if (lstrlenW(val) != SQUISH_GUID_SIZE - 1) 01229 badconfig = TRUE; 01230 else 01231 { 01232 unsquash_guid(val, packagecode); 01233 msi_free(val); 01234 val = strdupW(packagecode); 01235 } 01236 } 01237 } 01238 01239 if (!val) 01240 { 01241 r = ERROR_UNKNOWN_PROPERTY; 01242 goto done; 01243 } 01244 01245 if (pcchValueBuf) 01246 { 01247 /* If szBuffer (szValue->str) is NULL, there's no need to copy the value 01248 * out. Also, *pcchValueBuf may be uninitialized in this case, so we 01249 * can't rely on its value. 01250 */ 01251 if (szValue->str.a || szValue->str.w) 01252 { 01253 DWORD size = *pcchValueBuf; 01254 if (strlenW(val) < size) 01255 r = msi_strcpy_to_awstring(val, szValue, &size); 01256 else 01257 { 01258 r = ERROR_MORE_DATA; 01259 } 01260 } 01261 01262 if (!badconfig) 01263 *pcchValueBuf = lstrlenW(val); 01264 } 01265 01266 if (badconfig) 01267 r = ERROR_BAD_CONFIGURATION; 01268 01269 if (val != empty) 01270 msi_free(val); 01271 01272 done: 01273 RegCloseKey(prodkey); 01274 RegCloseKey(userdata); 01275 return r; 01276 } 01277 01278 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, 01279 LPSTR szBuffer, LPDWORD pcchValueBuf) 01280 { 01281 LPWSTR szwProduct, szwAttribute = NULL; 01282 UINT r = ERROR_OUTOFMEMORY; 01283 awstring buffer; 01284 01285 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute), 01286 szBuffer, pcchValueBuf); 01287 01288 szwProduct = strdupAtoW( szProduct ); 01289 if( szProduct && !szwProduct ) 01290 goto end; 01291 01292 szwAttribute = strdupAtoW( szAttribute ); 01293 if( szAttribute && !szwAttribute ) 01294 goto end; 01295 01296 buffer.unicode = FALSE; 01297 buffer.str.a = szBuffer; 01298 01299 r = MSI_GetProductInfo( szwProduct, szwAttribute, 01300 &buffer, pcchValueBuf ); 01301 01302 end: 01303 msi_free( szwProduct ); 01304 msi_free( szwAttribute ); 01305 01306 return r; 01307 } 01308 01309 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute, 01310 LPWSTR szBuffer, LPDWORD pcchValueBuf) 01311 { 01312 awstring buffer; 01313 01314 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute), 01315 szBuffer, pcchValueBuf); 01316 01317 buffer.unicode = TRUE; 01318 buffer.str.w = szBuffer; 01319 01320 return MSI_GetProductInfo( szProduct, szAttribute, 01321 &buffer, pcchValueBuf ); 01322 } 01323 01324 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid, 01325 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty, 01326 LPSTR szValue, LPDWORD pcchValue) 01327 { 01328 LPWSTR product = NULL; 01329 LPWSTR usersid = NULL; 01330 LPWSTR property = NULL; 01331 LPWSTR value = NULL; 01332 DWORD len = 0; 01333 UINT r; 01334 01335 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode), 01336 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty), 01337 szValue, pcchValue); 01338 01339 if (szValue && !pcchValue) 01340 return ERROR_INVALID_PARAMETER; 01341 01342 if (szProductCode) product = strdupAtoW(szProductCode); 01343 if (szUserSid) usersid = strdupAtoW(szUserSid); 01344 if (szProperty) property = strdupAtoW(szProperty); 01345 01346 r = MsiGetProductInfoExW(product, usersid, dwContext, property, 01347 NULL, &len); 01348 if (r != ERROR_SUCCESS) 01349 goto done; 01350 01351 value = msi_alloc(++len * sizeof(WCHAR)); 01352 if (!value) 01353 { 01354 r = ERROR_OUTOFMEMORY; 01355 goto done; 01356 } 01357 01358 r = MsiGetProductInfoExW(product, usersid, dwContext, property, 01359 value, &len); 01360 if (r != ERROR_SUCCESS) 01361 goto done; 01362 01363 if (!pcchValue) 01364 goto done; 01365 01366 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL); 01367 if (*pcchValue >= len) 01368 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL); 01369 else if (szValue) 01370 { 01371 r = ERROR_MORE_DATA; 01372 if (*pcchValue > 0) 01373 *szValue = '\0'; 01374 } 01375 01376 if (*pcchValue <= len || !szValue) 01377 len = len * sizeof(WCHAR) - 1; 01378 01379 *pcchValue = len - 1; 01380 01381 done: 01382 msi_free(product); 01383 msi_free(usersid); 01384 msi_free(property); 01385 msi_free(value); 01386 01387 return r; 01388 } 01389 01390 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size) 01391 { 01392 UINT r = ERROR_SUCCESS; 01393 01394 if (!val) 01395 return ERROR_UNKNOWN_PROPERTY; 01396 01397 if (out) 01398 { 01399 if (strlenW(val) >= *size) 01400 { 01401 r = ERROR_MORE_DATA; 01402 if (*size > 0) 01403 *out = '\0'; 01404 } 01405 else 01406 lstrcpyW(out, val); 01407 } 01408 01409 if (size) 01410 *size = lstrlenW(val); 01411 01412 return r; 01413 } 01414 01415 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid, 01416 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty, 01417 LPWSTR szValue, LPDWORD pcchValue) 01418 { 01419 WCHAR squished_pc[GUID_SIZE]; 01420 LPWSTR val = NULL; 01421 LPCWSTR package = NULL; 01422 HKEY props = NULL, prod; 01423 HKEY classes = NULL, managed; 01424 HKEY hkey = NULL; 01425 DWORD type; 01426 UINT r = ERROR_UNKNOWN_PRODUCT; 01427 01428 static const WCHAR five[] = {'5',0}; 01429 static const WCHAR displayname[] = { 01430 'D','i','s','p','l','a','y','N','a','m','e',0}; 01431 static const WCHAR displayversion[] = { 01432 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0}; 01433 static const WCHAR managed_local_package[] = { 01434 'M','a','n','a','g','e','d','L','o','c','a','l', 01435 'P','a','c','k','a','g','e',0}; 01436 01437 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode), 01438 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty), 01439 szValue, pcchValue); 01440 01441 if (!szProductCode || !squash_guid(szProductCode, squished_pc)) 01442 return ERROR_INVALID_PARAMETER; 01443 01444 if (szValue && !pcchValue) 01445 return ERROR_INVALID_PARAMETER; 01446 01447 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED && 01448 dwContext != MSIINSTALLCONTEXT_USERMANAGED && 01449 dwContext != MSIINSTALLCONTEXT_MACHINE) 01450 return ERROR_INVALID_PARAMETER; 01451 01452 if (!szProperty || !*szProperty) 01453 return ERROR_INVALID_PARAMETER; 01454 01455 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid) 01456 return ERROR_INVALID_PARAMETER; 01457 01458 /* FIXME: dwContext is provided, no need to search for it */ 01459 MSIREG_OpenProductKey(szProductCode, NULL,MSIINSTALLCONTEXT_USERMANAGED, 01460 &managed, FALSE); 01461 MSIREG_OpenProductKey(szProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 01462 &prod, FALSE); 01463 01464 MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE); 01465 01466 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED) 01467 { 01468 package = INSTALLPROPERTY_LOCALPACKAGEW; 01469 01470 if (!props && !prod) 01471 goto done; 01472 } 01473 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED) 01474 { 01475 package = managed_local_package; 01476 01477 if (!props && !managed) 01478 goto done; 01479 } 01480 else if (dwContext == MSIINSTALLCONTEXT_MACHINE) 01481 { 01482 package = INSTALLPROPERTY_LOCALPACKAGEW; 01483 MSIREG_OpenProductKey(szProductCode, NULL, dwContext, &classes, FALSE); 01484 01485 if (!props && !classes) 01486 goto done; 01487 } 01488 01489 if (!strcmpW( szProperty, INSTALLPROPERTY_HELPLINKW ) || 01490 !strcmpW( szProperty, INSTALLPROPERTY_HELPTELEPHONEW ) || 01491 !strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW ) || 01492 !strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) || 01493 !strcmpW( szProperty, INSTALLPROPERTY_INSTALLLOCATIONW ) || 01494 !strcmpW( szProperty, INSTALLPROPERTY_INSTALLSOURCEW ) || 01495 !strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ) || 01496 !strcmpW( szProperty, INSTALLPROPERTY_PUBLISHERW ) || 01497 !strcmpW( szProperty, INSTALLPROPERTY_URLINFOABOUTW ) || 01498 !strcmpW( szProperty, INSTALLPROPERTY_URLUPDATEINFOW ) || 01499 !strcmpW( szProperty, INSTALLPROPERTY_VERSIONMINORW ) || 01500 !strcmpW( szProperty, INSTALLPROPERTY_VERSIONMAJORW ) || 01501 !strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ) || 01502 !strcmpW( szProperty, INSTALLPROPERTY_PRODUCTIDW ) || 01503 !strcmpW( szProperty, INSTALLPROPERTY_REGCOMPANYW ) || 01504 !strcmpW( szProperty, INSTALLPROPERTY_REGOWNERW ) || 01505 !strcmpW( szProperty, INSTALLPROPERTY_INSTANCETYPEW )) 01506 { 01507 val = msi_reg_get_value(props, package, &type); 01508 if (!val) 01509 { 01510 if (prod || classes) 01511 r = ERROR_UNKNOWN_PROPERTY; 01512 01513 goto done; 01514 } 01515 01516 msi_free(val); 01517 01518 if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW )) 01519 szProperty = displayname; 01520 else if (!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW )) 01521 szProperty = displayversion; 01522 01523 val = msi_reg_get_value(props, szProperty, &type); 01524 if (!val) 01525 val = strdupW(szEmpty); 01526 01527 r = msi_copy_outval(val, szValue, pcchValue); 01528 } 01529 else if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW ) || 01530 !strcmpW( szProperty, INSTALLPROPERTY_LANGUAGEW ) || 01531 !strcmpW( szProperty, INSTALLPROPERTY_PRODUCTNAMEW ) || 01532 !strcmpW( szProperty, INSTALLPROPERTY_PACKAGECODEW ) || 01533 !strcmpW( szProperty, INSTALLPROPERTY_VERSIONW ) || 01534 !strcmpW( szProperty, INSTALLPROPERTY_PRODUCTICONW ) || 01535 !strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ) || 01536 !strcmpW( szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW )) 01537 { 01538 if (!prod && !classes) 01539 goto done; 01540 01541 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED) 01542 hkey = prod; 01543 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED) 01544 hkey = managed; 01545 else if (dwContext == MSIINSTALLCONTEXT_MACHINE) 01546 hkey = classes; 01547 01548 val = msi_reg_get_value(hkey, szProperty, &type); 01549 if (!val) 01550 val = strdupW(szEmpty); 01551 01552 r = msi_copy_outval(val, szValue, pcchValue); 01553 } 01554 else if (!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTSTATEW )) 01555 { 01556 if (dwContext == MSIINSTALLCONTEXT_MACHINE) 01557 { 01558 if (props) 01559 { 01560 val = msi_reg_get_value(props, package, &type); 01561 if (!val) 01562 goto done; 01563 01564 msi_free(val); 01565 val = strdupW(five); 01566 } 01567 else 01568 val = strdupW(szOne); 01569 01570 r = msi_copy_outval(val, szValue, pcchValue); 01571 goto done; 01572 } 01573 else if (props && (val = msi_reg_get_value(props, package, &type))) 01574 { 01575 msi_free(val); 01576 val = strdupW(five); 01577 r = msi_copy_outval(val, szValue, pcchValue); 01578 goto done; 01579 } 01580 01581 if (prod || managed) 01582 val = strdupW(szOne); 01583 else 01584 goto done; 01585 01586 r = msi_copy_outval(val, szValue, pcchValue); 01587 } 01588 else if (!strcmpW( szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW )) 01589 { 01590 if (!prod && !classes) 01591 goto done; 01592 01593 /* FIXME */ 01594 val = strdupW(szEmpty); 01595 r = msi_copy_outval(val, szValue, pcchValue); 01596 } 01597 else 01598 r = ERROR_UNKNOWN_PROPERTY; 01599 01600 done: 01601 RegCloseKey(props); 01602 RegCloseKey(prod); 01603 RegCloseKey(managed); 01604 RegCloseKey(classes); 01605 msi_free(val); 01606 01607 return r; 01608 } 01609 01610 UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode, 01611 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, 01612 LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue) 01613 { 01614 LPWSTR patch = NULL, product = NULL, usersid = NULL; 01615 LPWSTR property = NULL, val = NULL; 01616 DWORD len; 01617 UINT r; 01618 01619 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode), 01620 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext, 01621 debugstr_a(szProperty), lpValue, pcchValue); 01622 01623 if (lpValue && !pcchValue) 01624 return ERROR_INVALID_PARAMETER; 01625 01626 if (szPatchCode) patch = strdupAtoW(szPatchCode); 01627 if (szProductCode) product = strdupAtoW(szProductCode); 01628 if (szUserSid) usersid = strdupAtoW(szUserSid); 01629 if (szProperty) property = strdupAtoW(szProperty); 01630 01631 len = 0; 01632 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property, 01633 NULL, &len); 01634 if (r != ERROR_SUCCESS) 01635 goto done; 01636 01637 val = msi_alloc(++len * sizeof(WCHAR)); 01638 if (!val) 01639 { 01640 r = ERROR_OUTOFMEMORY; 01641 goto done; 01642 } 01643 01644 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property, 01645 val, &len); 01646 if (r != ERROR_SUCCESS || !pcchValue) 01647 goto done; 01648 01649 if (lpValue) 01650 WideCharToMultiByte(CP_ACP, 0, val, -1, lpValue, 01651 *pcchValue - 1, NULL, NULL); 01652 01653 len = lstrlenW(val); 01654 if ((*val && *pcchValue < len + 1) || !lpValue) 01655 { 01656 if (lpValue) 01657 { 01658 r = ERROR_MORE_DATA; 01659 lpValue[*pcchValue - 1] = '\0'; 01660 } 01661 01662 *pcchValue = len * sizeof(WCHAR); 01663 } 01664 else 01665 *pcchValue = len; 01666 01667 done: 01668 msi_free(val); 01669 msi_free(patch); 01670 msi_free(product); 01671 msi_free(usersid); 01672 msi_free(property); 01673 01674 return r; 01675 } 01676 01677 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode, 01678 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext, 01679 LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue) 01680 { 01681 WCHAR squished_pc[GUID_SIZE]; 01682 WCHAR squished_patch[GUID_SIZE]; 01683 HKEY udprod = 0, prod = 0, props = 0; 01684 HKEY patch = 0, patches = 0; 01685 HKEY udpatch = 0, datakey = 0; 01686 HKEY prodpatches = 0; 01687 LPWSTR val = NULL; 01688 UINT r = ERROR_UNKNOWN_PRODUCT; 01689 DWORD len; 01690 LONG res; 01691 01692 static const WCHAR szManagedPackage[] = {'M','a','n','a','g','e','d', 01693 'L','o','c','a','l','P','a','c','k','a','g','e',0}; 01694 01695 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode), 01696 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext, 01697 debugstr_w(szProperty), lpValue, pcchValue); 01698 01699 if (!szProductCode || !squash_guid(szProductCode, squished_pc)) 01700 return ERROR_INVALID_PARAMETER; 01701 01702 if (!szPatchCode || !squash_guid(szPatchCode, squished_patch)) 01703 return ERROR_INVALID_PARAMETER; 01704 01705 if (!szProperty) 01706 return ERROR_INVALID_PARAMETER; 01707 01708 if (lpValue && !pcchValue) 01709 return ERROR_INVALID_PARAMETER; 01710 01711 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED && 01712 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED && 01713 dwContext != MSIINSTALLCONTEXT_MACHINE) 01714 return ERROR_INVALID_PARAMETER; 01715 01716 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid) 01717 return ERROR_INVALID_PARAMETER; 01718 01719 if (szUserSid && !strcmpW( szUserSid, szLocalSid )) 01720 return ERROR_INVALID_PARAMETER; 01721 01722 if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL, 01723 &udprod, FALSE) != ERROR_SUCCESS) 01724 goto done; 01725 01726 if (MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, 01727 &props, FALSE) != ERROR_SUCCESS) 01728 goto done; 01729 01730 r = ERROR_UNKNOWN_PATCH; 01731 01732 res = RegOpenKeyExW(udprod, szPatches, 0, KEY_WOW64_64KEY|KEY_READ, &patches); 01733 if (res != ERROR_SUCCESS) 01734 goto done; 01735 01736 res = RegOpenKeyExW(patches, squished_patch, 0, KEY_WOW64_64KEY|KEY_READ, &patch); 01737 if (res != ERROR_SUCCESS) 01738 goto done; 01739 01740 if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW )) 01741 { 01742 if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext, 01743 &prod, FALSE) != ERROR_SUCCESS) 01744 goto done; 01745 01746 res = RegOpenKeyExW(prod, szPatches, 0, KEY_WOW64_64KEY|KEY_ALL_ACCESS, &prodpatches); 01747 if (res != ERROR_SUCCESS) 01748 goto done; 01749 01750 datakey = prodpatches; 01751 szProperty = squished_patch; 01752 } 01753 else 01754 { 01755 if (MSIREG_OpenUserDataPatchKey(szPatchCode, dwContext, 01756 &udpatch, FALSE) != ERROR_SUCCESS) 01757 goto done; 01758 01759 if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW )) 01760 { 01761 if (dwContext == MSIINSTALLCONTEXT_USERMANAGED) 01762 szProperty = szManagedPackage; 01763 datakey = udpatch; 01764 } 01765 else if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW )) 01766 { 01767 datakey = patch; 01768 szProperty = szInstalled; 01769 } 01770 else if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW )) 01771 { 01772 datakey = udpatch; 01773 } 01774 else if (!strcmpW( szProperty, INSTALLPROPERTY_UNINSTALLABLEW ) || 01775 !strcmpW( szProperty, INSTALLPROPERTY_PATCHSTATEW ) || 01776 !strcmpW( szProperty, INSTALLPROPERTY_DISPLAYNAMEW ) || 01777 !strcmpW( szProperty, INSTALLPROPERTY_MOREINFOURLW )) 01778 { 01779 datakey = patch; 01780 } 01781 else 01782 { 01783 r = ERROR_UNKNOWN_PROPERTY; 01784 goto done; 01785 } 01786 } 01787 01788 val = msi_reg_get_val_str(datakey, szProperty); 01789 if (!val) 01790 val = strdupW(szEmpty); 01791 01792 r = ERROR_SUCCESS; 01793 01794 if (!pcchValue) 01795 goto done; 01796 01797 if (lpValue) 01798 lstrcpynW(lpValue, val, *pcchValue); 01799 01800 len = lstrlenW(val); 01801 if ((*val && *pcchValue < len + 1) || !lpValue) 01802 { 01803 if (lpValue) 01804 r = ERROR_MORE_DATA; 01805 01806 *pcchValue = len * sizeof(WCHAR); 01807 } 01808 01809 *pcchValue = len; 01810 01811 done: 01812 msi_free(val); 01813 RegCloseKey(prodpatches); 01814 RegCloseKey(prod); 01815 RegCloseKey(patch); 01816 RegCloseKey(patches); 01817 RegCloseKey(udpatch); 01818 RegCloseKey(props); 01819 RegCloseKey(udprod); 01820 01821 return r; 01822 } 01823 01824 UINT WINAPI MsiGetPatchInfoA( LPCSTR patch, LPCSTR attr, LPSTR buffer, LPDWORD buflen ) 01825 { 01826 UINT r = ERROR_OUTOFMEMORY; 01827 DWORD size; 01828 LPWSTR patchW = NULL, attrW = NULL, bufferW = NULL; 01829 01830 TRACE("%s %s %p %p\n", debugstr_a(patch), debugstr_a(attr), buffer, buflen); 01831 01832 if (!patch || !attr) 01833 return ERROR_INVALID_PARAMETER; 01834 01835 if (!(patchW = strdupAtoW( patch ))) 01836 goto done; 01837 01838 if (!(attrW = strdupAtoW( attr ))) 01839 goto done; 01840 01841 size = 0; 01842 r = MsiGetPatchInfoW( patchW, attrW, NULL, &size ); 01843 if (r != ERROR_SUCCESS) 01844 goto done; 01845 01846 size++; 01847 if (!(bufferW = msi_alloc( size * sizeof(WCHAR) ))) 01848 { 01849 r = ERROR_OUTOFMEMORY; 01850 goto done; 01851 } 01852 01853 r = MsiGetPatchInfoW( patchW, attrW, bufferW, &size ); 01854 if (r == ERROR_SUCCESS) 01855 { 01856 int len = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL ); 01857 if (len > *buflen) 01858 r = ERROR_MORE_DATA; 01859 else if (buffer) 01860 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL ); 01861 01862 *buflen = len - 1; 01863 } 01864 01865 done: 01866 msi_free( patchW ); 01867 msi_free( attrW ); 01868 msi_free( bufferW ); 01869 return r; 01870 } 01871 01872 UINT WINAPI MsiGetPatchInfoW( LPCWSTR patch, LPCWSTR attr, LPWSTR buffer, LPDWORD buflen ) 01873 { 01874 UINT r; 01875 WCHAR product[GUID_SIZE]; 01876 DWORD index; 01877 01878 TRACE("%s %s %p %p\n", debugstr_w(patch), debugstr_w(attr), buffer, buflen); 01879 01880 if (!patch || !attr) 01881 return ERROR_INVALID_PARAMETER; 01882 01883 if (strcmpW( INSTALLPROPERTY_LOCALPACKAGEW, attr )) 01884 return ERROR_UNKNOWN_PROPERTY; 01885 01886 index = 0; 01887 while (1) 01888 { 01889 r = MsiEnumProductsW( index, product ); 01890 if (r != ERROR_SUCCESS) 01891 break; 01892 01893 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERMANAGED, attr, buffer, buflen ); 01894 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA) 01895 return r; 01896 01897 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, attr, buffer, buflen ); 01898 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA) 01899 return r; 01900 01901 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_MACHINE, attr, buffer, buflen ); 01902 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA) 01903 return r; 01904 01905 index++; 01906 } 01907 01908 return ERROR_UNKNOWN_PRODUCT; 01909 } 01910 01911 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes) 01912 { 01913 LPWSTR szwLogFile = NULL; 01914 UINT r; 01915 01916 TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes); 01917 01918 if( szLogFile ) 01919 { 01920 szwLogFile = strdupAtoW( szLogFile ); 01921 if( !szwLogFile ) 01922 return ERROR_OUTOFMEMORY; 01923 } 01924 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes ); 01925 msi_free( szwLogFile ); 01926 return r; 01927 } 01928 01929 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes) 01930 { 01931 TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes); 01932 01933 msi_free(gszLogFile); 01934 gszLogFile = NULL; 01935 if (szLogFile) 01936 { 01937 HANDLE file; 01938 01939 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND)) 01940 DeleteFileW(szLogFile); 01941 file = CreateFileW(szLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 01942 FILE_ATTRIBUTE_NORMAL, NULL); 01943 if (file != INVALID_HANDLE_VALUE) 01944 { 01945 gszLogFile = strdupW(szLogFile); 01946 CloseHandle(file); 01947 } 01948 else 01949 ERR("Unable to enable log %s (%u)\n", debugstr_w(szLogFile), GetLastError()); 01950 } 01951 01952 return ERROR_SUCCESS; 01953 } 01954 01955 UINT WINAPI MsiEnumComponentCostsA( MSIHANDLE handle, LPCSTR component, DWORD index, 01956 INSTALLSTATE state, LPSTR drive, DWORD *buflen, 01957 int *cost, int *temp ) 01958 { 01959 UINT r; 01960 DWORD len; 01961 WCHAR *driveW, *componentW = NULL; 01962 01963 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle, debugstr_a(component), index, 01964 state, drive, buflen, cost, temp); 01965 01966 if (!drive || !buflen) return ERROR_INVALID_PARAMETER; 01967 if (component && !(componentW = strdupAtoW( component ))) return ERROR_OUTOFMEMORY; 01968 01969 len = *buflen; 01970 if (!(driveW = msi_alloc( len * sizeof(WCHAR) ))) 01971 { 01972 msi_free( componentW ); 01973 return ERROR_OUTOFMEMORY; 01974 } 01975 r = MsiEnumComponentCostsW( handle, componentW, index, state, driveW, buflen, cost, temp ); 01976 if (!r) 01977 { 01978 WideCharToMultiByte( CP_ACP, 0, driveW, -1, drive, len, NULL, NULL ); 01979 } 01980 msi_free( componentW ); 01981 msi_free( driveW ); 01982 return r; 01983 } 01984 01985 static UINT set_drive( WCHAR *buffer, WCHAR letter ) 01986 { 01987 buffer[0] = letter; 01988 buffer[1] = ':'; 01989 buffer[2] = 0; 01990 return 2; 01991 } 01992 01993 UINT WINAPI MsiEnumComponentCostsW( MSIHANDLE handle, LPCWSTR component, DWORD index, 01994 INSTALLSTATE state, LPWSTR drive, DWORD *buflen, 01995 int *cost, int *temp ) 01996 { 01997 UINT r = ERROR_NO_MORE_ITEMS; 01998 MSICOMPONENT *comp = NULL; 01999 MSIPACKAGE *package; 02000 MSIFILE *file; 02001 STATSTG stat = {0}; 02002 WCHAR path[MAX_PATH]; 02003 02004 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle, debugstr_w(component), index, 02005 state, drive, buflen, cost, temp); 02006 02007 if (!drive || !buflen || !cost || !temp) return ERROR_INVALID_PARAMETER; 02008 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE ))) 02009 { 02010 HRESULT hr; 02011 IWineMsiRemotePackage *remote_package; 02012 BSTR bname = NULL; 02013 02014 if (!(remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle ))) 02015 return ERROR_INVALID_HANDLE; 02016 02017 if (component && !(bname = SysAllocString( component ))) 02018 { 02019 IWineMsiRemotePackage_Release( remote_package ); 02020 return ERROR_OUTOFMEMORY; 02021 } 02022 hr = IWineMsiRemotePackage_EnumComponentCosts( remote_package, bname, index, state, drive, buflen, cost, temp ); 02023 IWineMsiRemotePackage_Release( remote_package ); 02024 SysFreeString( bname ); 02025 if (FAILED(hr)) 02026 { 02027 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) return HRESULT_CODE(hr); 02028 return ERROR_FUNCTION_FAILED; 02029 } 02030 return ERROR_SUCCESS; 02031 } 02032 02033 if (!msi_get_property_int( package->db, szCostingComplete, 0 )) 02034 { 02035 msiobj_release( &package->hdr ); 02036 return ERROR_FUNCTION_NOT_CALLED; 02037 } 02038 if (component && component[0] && !(comp = msi_get_loaded_component( package, component ))) 02039 { 02040 msiobj_release( &package->hdr ); 02041 return ERROR_UNKNOWN_COMPONENT; 02042 } 02043 if (*buflen < 3) 02044 { 02045 *buflen = 2; 02046 msiobj_release( &package->hdr ); 02047 return ERROR_MORE_DATA; 02048 } 02049 if (index) 02050 { 02051 msiobj_release( &package->hdr ); 02052 return ERROR_NO_MORE_ITEMS; 02053 } 02054 02055 drive[0] = 0; 02056 *cost = *temp = 0; 02057 GetWindowsDirectoryW( path, MAX_PATH ); 02058 if (component && component[0]) 02059 { 02060 if (comp->assembly && !comp->assembly->application) *temp = comp->Cost; 02061 if (!comp->Enabled || !comp->KeyPath) 02062 { 02063 *cost = 0; 02064 *buflen = set_drive( drive, path[0] ); 02065 r = ERROR_SUCCESS; 02066 } 02067 else if ((file = msi_get_loaded_file( package, comp->KeyPath ))) 02068 { 02069 *cost = max( 8, comp->Cost / 512 ); 02070 *buflen = set_drive( drive, file->TargetPath[0] ); 02071 r = ERROR_SUCCESS; 02072 } 02073 } 02074 else if (IStorage_Stat( package->db->storage, &stat, STATFLAG_NONAME ) == S_OK) 02075 { 02076 *temp = max( 8, stat.cbSize.QuadPart / 512 ); 02077 *buflen = set_drive( drive, path[0] ); 02078 r = ERROR_SUCCESS; 02079 } 02080 msiobj_release( &package->hdr ); 02081 return r; 02082 } 02083 02084 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode, 02085 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, 02086 LPCSTR szComponent, INSTALLSTATE *pdwState) 02087 { 02088 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL; 02089 UINT r; 02090 02091 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode), 02092 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState); 02093 02094 if (szProductCode && !(prodcode = strdupAtoW(szProductCode))) 02095 return ERROR_OUTOFMEMORY; 02096 02097 if (szUserSid && !(usersid = strdupAtoW(szUserSid))) 02098 return ERROR_OUTOFMEMORY; 02099 02100 if (szComponent && !(comp = strdupAtoW(szComponent))) 02101 return ERROR_OUTOFMEMORY; 02102 02103 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState); 02104 02105 msi_free(prodcode); 02106 msi_free(usersid); 02107 msi_free(comp); 02108 02109 return r; 02110 } 02111 02112 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context) 02113 { 02114 UINT r; 02115 HKEY hkey = NULL; 02116 02117 r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE); 02118 RegCloseKey(hkey); 02119 return (r == ERROR_SUCCESS); 02120 } 02121 02122 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context) 02123 { 02124 LPCWSTR package; 02125 HKEY hkey; 02126 DWORD sz; 02127 LONG res; 02128 UINT r; 02129 02130 static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0}; 02131 static const WCHAR managed_local_package[] = { 02132 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0 02133 }; 02134 02135 r = MSIREG_OpenInstallProps(prodcode, context, NULL, &hkey, FALSE); 02136 if (r != ERROR_SUCCESS) 02137 return FALSE; 02138 02139 if (context == MSIINSTALLCONTEXT_USERMANAGED) 02140 package = managed_local_package; 02141 else 02142 package = local_package; 02143 02144 sz = 0; 02145 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz); 02146 RegCloseKey(hkey); 02147 02148 return (res == ERROR_SUCCESS); 02149 } 02150 02151 static UINT msi_comp_find_prodcode(LPWSTR squished_pc, 02152 MSIINSTALLCONTEXT context, 02153 LPCWSTR comp, LPWSTR val, DWORD *sz) 02154 { 02155 HKEY hkey; 02156 LONG res; 02157 UINT r; 02158 02159 if (context == MSIINSTALLCONTEXT_MACHINE) 02160 r = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE); 02161 else 02162 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE); 02163 02164 if (r != ERROR_SUCCESS) 02165 return r; 02166 02167 res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz); 02168 if (res != ERROR_SUCCESS) 02169 return res; 02170 02171 RegCloseKey(hkey); 02172 return res; 02173 } 02174 02175 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode, 02176 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext, 02177 LPCWSTR szComponent, INSTALLSTATE *pdwState) 02178 { 02179 WCHAR squished_pc[GUID_SIZE]; 02180 BOOL found; 02181 DWORD sz; 02182 02183 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode), 02184 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState); 02185 02186 if (!pdwState || !szComponent) 02187 return ERROR_INVALID_PARAMETER; 02188 02189 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1) 02190 return ERROR_INVALID_PARAMETER; 02191 02192 if (!squash_guid(szProductCode, squished_pc)) 02193 return ERROR_INVALID_PARAMETER; 02194 02195 found = msi_comp_find_prod_key(szProductCode, dwContext); 02196 02197 if (!msi_comp_find_package(szProductCode, dwContext)) 02198 { 02199 if (found) 02200 { 02201 *pdwState = INSTALLSTATE_UNKNOWN; 02202 return ERROR_UNKNOWN_COMPONENT; 02203 } 02204 02205 return ERROR_UNKNOWN_PRODUCT; 02206 } 02207 02208 *pdwState = INSTALLSTATE_UNKNOWN; 02209 02210 sz = 0; 02211 if (msi_comp_find_prodcode(squished_pc, dwContext, szComponent, NULL, &sz)) 02212 return ERROR_UNKNOWN_COMPONENT; 02213 02214 if (sz == 0) 02215 *pdwState = INSTALLSTATE_NOTUSED; 02216 else 02217 { 02218 WCHAR *val; 02219 UINT r; 02220 02221 if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY; 02222 if ((r = msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))) 02223 return r; 02224 02225 if (lstrlenW(val) > 2 && 02226 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && val[2] != ':') 02227 { 02228 *pdwState = INSTALLSTATE_SOURCE; 02229 } 02230 else 02231 *pdwState = INSTALLSTATE_LOCAL; 02232 msi_free( val ); 02233 } 02234 02235 TRACE("-> %d\n", *pdwState); 02236 return ERROR_SUCCESS; 02237 } 02238 02239 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct) 02240 { 02241 LPWSTR szwProduct = NULL; 02242 INSTALLSTATE r; 02243 02244 if( szProduct ) 02245 { 02246 szwProduct = strdupAtoW( szProduct ); 02247 if( !szwProduct ) 02248 return ERROR_OUTOFMEMORY; 02249 } 02250 r = MsiQueryProductStateW( szwProduct ); 02251 msi_free( szwProduct ); 02252 return r; 02253 } 02254 02255 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct) 02256 { 02257 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED; 02258 INSTALLSTATE state = INSTALLSTATE_ADVERTISED; 02259 HKEY prodkey = 0, userdata = 0; 02260 DWORD val; 02261 UINT r; 02262 02263 TRACE("%s\n", debugstr_w(szProduct)); 02264 02265 if (!szProduct || !*szProduct) 02266 return INSTALLSTATE_INVALIDARG; 02267 02268 if (lstrlenW(szProduct) != GUID_SIZE - 1) 02269 return INSTALLSTATE_INVALIDARG; 02270 02271 if (szProduct[0] != '{' || szProduct[37] != '}') 02272 return INSTALLSTATE_UNKNOWN; 02273 02274 SetLastError( ERROR_SUCCESS ); 02275 02276 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, 02277 &prodkey, FALSE) != ERROR_SUCCESS && 02278 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 02279 &prodkey, FALSE) != ERROR_SUCCESS && 02280 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, 02281 &prodkey, FALSE) == ERROR_SUCCESS) 02282 { 02283 context = MSIINSTALLCONTEXT_MACHINE; 02284 } 02285 02286 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE); 02287 if (r != ERROR_SUCCESS) 02288 goto done; 02289 02290 if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val)) 02291 goto done; 02292 02293 if (val) 02294 state = INSTALLSTATE_DEFAULT; 02295 else 02296 state = INSTALLSTATE_UNKNOWN; 02297 02298 done: 02299 if (!prodkey) 02300 { 02301 state = INSTALLSTATE_UNKNOWN; 02302 02303 if (userdata) 02304 state = INSTALLSTATE_ABSENT; 02305 } 02306 02307 RegCloseKey(prodkey); 02308 RegCloseKey(userdata); 02309 TRACE("-> %d\n", state); 02310 return state; 02311 } 02312 02313 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd) 02314 { 02315 INSTALLUILEVEL old = gUILevel; 02316 HWND oldwnd = gUIhwnd; 02317 02318 TRACE("%08x %p\n", dwUILevel, phWnd); 02319 02320 gUILevel = dwUILevel; 02321 if (phWnd) 02322 { 02323 gUIhwnd = *phWnd; 02324 *phWnd = oldwnd; 02325 } 02326 return old; 02327 } 02328 02329 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler, 02330 DWORD dwMessageFilter, LPVOID pvContext) 02331 { 02332 INSTALLUI_HANDLERA prev = gUIHandlerA; 02333 02334 TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext); 02335 02336 gUIHandlerA = puiHandler; 02337 gUIHandlerW = NULL; 02338 gUIFilter = dwMessageFilter; 02339 gUIContext = pvContext; 02340 02341 return prev; 02342 } 02343 02344 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler, 02345 DWORD dwMessageFilter, LPVOID pvContext) 02346 { 02347 INSTALLUI_HANDLERW prev = gUIHandlerW; 02348 02349 TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext); 02350 02351 gUIHandlerA = NULL; 02352 gUIHandlerW = puiHandler; 02353 gUIFilter = dwMessageFilter; 02354 gUIContext = pvContext; 02355 02356 return prev; 02357 } 02358 02359 /****************************************************************** 02360 * MsiLoadStringW [MSI.@] 02361 * 02362 * Loads a string from MSI's string resources. 02363 * 02364 * PARAMS 02365 * 02366 * handle [I] only -1 is handled currently 02367 * id [I] id of the string to be loaded 02368 * lpBuffer [O] buffer for the string to be written to 02369 * nBufferMax [I] maximum size of the buffer in characters 02370 * lang [I] the preferred language for the string 02371 * 02372 * RETURNS 02373 * 02374 * If successful, this function returns the language id of the string loaded 02375 * If the function fails, the function returns zero. 02376 * 02377 * NOTES 02378 * 02379 * The type of the first parameter is unknown. LoadString's prototype 02380 * suggests that it might be a module handle. I have made it an MSI handle 02381 * for starters, as -1 is an invalid MSI handle, but not an invalid module 02382 * handle. Maybe strings can be stored in an MSI database somehow. 02383 */ 02384 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer, 02385 int nBufferMax, LANGID lang ) 02386 { 02387 HRSRC hres; 02388 HGLOBAL hResData; 02389 LPWSTR p; 02390 DWORD i, len; 02391 02392 TRACE("%d %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang); 02393 02394 if( handle != -1 ) 02395 FIXME("don't know how to deal with handle = %08x\n", handle); 02396 02397 if( !lang ) 02398 lang = GetUserDefaultLangID(); 02399 02400 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING, 02401 (LPWSTR)1, lang ); 02402 if( !hres ) 02403 return 0; 02404 hResData = LoadResource( msi_hInstance, hres ); 02405 if( !hResData ) 02406 return 0; 02407 p = LockResource( hResData ); 02408 if( !p ) 02409 return 0; 02410 02411 for (i = 0; i < (id & 0xf); i++) p += *p + 1; 02412 len = *p; 02413 02414 if( nBufferMax <= len ) 02415 return 0; 02416 02417 memcpy( lpBuffer, p+1, len * sizeof(WCHAR)); 02418 lpBuffer[ len ] = 0; 02419 02420 TRACE("found -> %s\n", debugstr_w(lpBuffer)); 02421 return lang; 02422 } 02423 02424 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer, 02425 int nBufferMax, LANGID lang ) 02426 { 02427 LPWSTR bufW; 02428 LANGID r; 02429 INT len; 02430 02431 bufW = msi_alloc(nBufferMax*sizeof(WCHAR)); 02432 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang); 02433 if( r ) 02434 { 02435 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL ); 02436 if( len <= nBufferMax ) 02437 WideCharToMultiByte( CP_ACP, 0, bufW, -1, 02438 lpBuffer, nBufferMax, NULL, NULL ); 02439 else 02440 r = 0; 02441 } 02442 msi_free(bufW); 02443 return r; 02444 } 02445 02446 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf, 02447 LPDWORD pcchBuf) 02448 { 02449 char szProduct[GUID_SIZE]; 02450 02451 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf); 02452 02453 if (!szComponent || !pcchBuf) 02454 return INSTALLSTATE_INVALIDARG; 02455 02456 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS) 02457 return INSTALLSTATE_UNKNOWN; 02458 02459 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf ); 02460 } 02461 02462 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf, 02463 LPDWORD pcchBuf) 02464 { 02465 WCHAR szProduct[GUID_SIZE]; 02466 02467 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf); 02468 02469 if (!szComponent || !pcchBuf) 02470 return INSTALLSTATE_INVALIDARG; 02471 02472 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS) 02473 return INSTALLSTATE_UNKNOWN; 02474 02475 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf ); 02476 } 02477 02478 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, 02479 WORD wLanguageId, DWORD f) 02480 { 02481 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption), 02482 uType, wLanguageId, f); 02483 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId); 02484 } 02485 02486 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, 02487 WORD wLanguageId, DWORD f) 02488 { 02489 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption), 02490 uType, wLanguageId, f); 02491 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId); 02492 } 02493 02494 UINT WINAPI MsiMessageBoxExA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, 02495 DWORD unknown, WORD wLanguageId, DWORD f) 02496 { 02497 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_a(lpText), 02498 debugstr_a(lpCaption), uType, unknown, wLanguageId, f); 02499 return MessageBoxExA(hWnd, lpText, lpCaption, uType, wLanguageId); 02500 } 02501 02502 UINT WINAPI MsiMessageBoxExW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, 02503 DWORD unknown, WORD wLanguageId, DWORD f) 02504 { 02505 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_w(lpText), 02506 debugstr_w(lpCaption), uType, unknown, wLanguageId, f); 02507 return MessageBoxExW(hWnd, lpText, lpCaption, uType, wLanguageId); 02508 } 02509 02510 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext, 02511 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, 02512 LPDWORD pcchPathBuf ) 02513 { 02514 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName), 02515 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, 02516 pcchPathBuf); 02517 return ERROR_CALL_NOT_IMPLEMENTED; 02518 } 02519 02520 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext, 02521 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf, 02522 LPDWORD pcchPathBuf ) 02523 { 02524 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName), 02525 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf, 02526 pcchPathBuf); 02527 return ERROR_CALL_NOT_IMPLEMENTED; 02528 } 02529 02530 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor, 02531 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs ) 02532 { 02533 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs ); 02534 return ERROR_CALL_NOT_IMPLEMENTED; 02535 } 02536 02537 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor, 02538 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs ) 02539 { 02540 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs ); 02541 return ERROR_CALL_NOT_IMPLEMENTED; 02542 } 02543 02544 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR path, DWORD flags, PCCERT_CONTEXT *cert, 02545 LPBYTE hash, LPDWORD hashlen ) 02546 { 02547 UINT r; 02548 WCHAR *pathW = NULL; 02549 02550 TRACE("%s %08x %p %p %p\n", debugstr_a(path), flags, cert, hash, hashlen); 02551 02552 if (path && !(pathW = strdupAtoW( path ))) return ERROR_OUTOFMEMORY; 02553 r = MsiGetFileSignatureInformationW( pathW, flags, cert, hash, hashlen ); 02554 msi_free( pathW ); 02555 return r; 02556 } 02557 02558 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR path, DWORD flags, PCCERT_CONTEXT *cert, 02559 LPBYTE hash, LPDWORD hashlen ) 02560 { 02561 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2; 02562 HRESULT hr; 02563 WINTRUST_DATA data; 02564 WINTRUST_FILE_INFO info; 02565 CRYPT_PROVIDER_SGNR *signer; 02566 CRYPT_PROVIDER_CERT *provider; 02567 02568 TRACE("%s %08x %p %p %p\n", debugstr_w(path), flags, cert, hash, hashlen); 02569 02570 if (!path || !cert) return E_INVALIDARG; 02571 02572 info.cbStruct = sizeof(info); 02573 info.pcwszFilePath = path; 02574 info.hFile = NULL; 02575 info.pgKnownSubject = NULL; 02576 02577 data.cbStruct = sizeof(data); 02578 data.pPolicyCallbackData = NULL; 02579 data.pSIPClientData = NULL; 02580 data.dwUIChoice = WTD_UI_NONE; 02581 data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN; 02582 data.dwUnionChoice = WTD_CHOICE_FILE; 02583 data.u.pFile = &info; 02584 data.dwStateAction = WTD_STATEACTION_VERIFY; 02585 data.hWVTStateData = NULL; 02586 data.pwszURLReference = NULL; 02587 data.dwProvFlags = 0; 02588 data.dwUIContext = WTD_UICONTEXT_INSTALL; 02589 hr = WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data ); 02590 *cert = NULL; 02591 if (FAILED(hr)) goto done; 02592 02593 if (!(signer = WTHelperGetProvSignerFromChain( data.hWVTStateData, 0, FALSE, 0 ))) 02594 { 02595 hr = TRUST_E_NOSIGNATURE; 02596 goto done; 02597 } 02598 if (hash) 02599 { 02600 DWORD len = signer->psSigner->EncryptedHash.cbData; 02601 if (*hashlen < len) 02602 { 02603 *hashlen = len; 02604 hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA); 02605 goto done; 02606 } 02607 memcpy( hash, signer->psSigner->EncryptedHash.pbData, len ); 02608 *hashlen = len; 02609 } 02610 if (!(provider = WTHelperGetProvCertFromChain( signer, 0 ))) 02611 { 02612 hr = TRUST_E_PROVIDER_UNKNOWN; 02613 goto done; 02614 } 02615 *cert = CertDuplicateCertificateContext( provider->pCert ); 02616 02617 done: 02618 data.dwStateAction = WTD_STATEACTION_CLOSE; 02619 WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data ); 02620 return hr; 02621 } 02622 02623 /****************************************************************** 02624 * MsiGetProductPropertyA [MSI.@] 02625 */ 02626 UINT WINAPI MsiGetProductPropertyA(MSIHANDLE hProduct, LPCSTR szProperty, 02627 LPSTR szValue, LPDWORD pccbValue) 02628 { 02629 LPWSTR prop = NULL, val = NULL; 02630 DWORD len; 02631 UINT r; 02632 02633 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_a(szProperty), 02634 szValue, pccbValue); 02635 02636 if (szValue && !pccbValue) 02637 return ERROR_INVALID_PARAMETER; 02638 02639 if (szProperty) prop = strdupAtoW(szProperty); 02640 02641 len = 0; 02642 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len); 02643 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) 02644 goto done; 02645 02646 if (r == ERROR_SUCCESS) 02647 { 02648 if (szValue) *szValue = '\0'; 02649 if (pccbValue) *pccbValue = 0; 02650 goto done; 02651 } 02652 02653 val = msi_alloc(++len * sizeof(WCHAR)); 02654 if (!val) 02655 { 02656 r = ERROR_OUTOFMEMORY; 02657 goto done; 02658 } 02659 02660 r = MsiGetProductPropertyW(hProduct, prop, val, &len); 02661 if (r != ERROR_SUCCESS) 02662 goto done; 02663 02664 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL); 02665 02666 if (szValue) 02667 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue, 02668 *pccbValue, NULL, NULL); 02669 02670 if (pccbValue) 02671 { 02672 if (len > *pccbValue) 02673 r = ERROR_MORE_DATA; 02674 02675 *pccbValue = len - 1; 02676 } 02677 02678 done: 02679 msi_free(prop); 02680 msi_free(val); 02681 02682 return r; 02683 } 02684 02685 /****************************************************************** 02686 * MsiGetProductPropertyW [MSI.@] 02687 */ 02688 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE hProduct, LPCWSTR szProperty, 02689 LPWSTR szValue, LPDWORD pccbValue) 02690 { 02691 MSIPACKAGE *package; 02692 MSIQUERY *view = NULL; 02693 MSIRECORD *rec = NULL; 02694 LPCWSTR val; 02695 UINT r; 02696 02697 static const WCHAR query[] = { 02698 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 02699 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ', 02700 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0}; 02701 02702 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_w(szProperty), 02703 szValue, pccbValue); 02704 02705 if (!szProperty) 02706 return ERROR_INVALID_PARAMETER; 02707 02708 if (szValue && !pccbValue) 02709 return ERROR_INVALID_PARAMETER; 02710 02711 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE); 02712 if (!package) 02713 return ERROR_INVALID_HANDLE; 02714 02715 r = MSI_OpenQuery(package->db, &view, query, szProperty); 02716 if (r != ERROR_SUCCESS) 02717 goto done; 02718 02719 r = MSI_ViewExecute(view, 0); 02720 if (r != ERROR_SUCCESS) 02721 goto done; 02722 02723 r = MSI_ViewFetch(view, &rec); 02724 if (r != ERROR_SUCCESS) 02725 goto done; 02726 02727 val = MSI_RecordGetString(rec, 2); 02728 if (!val) 02729 goto done; 02730 02731 if (lstrlenW(val) >= *pccbValue) 02732 { 02733 lstrcpynW(szValue, val, *pccbValue); 02734 *pccbValue = lstrlenW(val); 02735 r = ERROR_MORE_DATA; 02736 } 02737 else 02738 { 02739 lstrcpyW(szValue, val); 02740 *pccbValue = lstrlenW(val); 02741 r = ERROR_SUCCESS; 02742 } 02743 02744 done: 02745 if (view) 02746 { 02747 MSI_ViewClose(view); 02748 msiobj_release(&view->hdr); 02749 if (rec) msiobj_release(&rec->hdr); 02750 } 02751 02752 if (!rec) 02753 { 02754 if (szValue) *szValue = '\0'; 02755 if (pccbValue) *pccbValue = 0; 02756 r = ERROR_SUCCESS; 02757 } 02758 02759 msiobj_release(&package->hdr); 02760 return r; 02761 } 02762 02763 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage ) 02764 { 02765 UINT r; 02766 LPWSTR szPack = NULL; 02767 02768 TRACE("%s\n", debugstr_a(szPackage) ); 02769 02770 if( szPackage ) 02771 { 02772 szPack = strdupAtoW( szPackage ); 02773 if( !szPack ) 02774 return ERROR_OUTOFMEMORY; 02775 } 02776 02777 r = MsiVerifyPackageW( szPack ); 02778 02779 msi_free( szPack ); 02780 02781 return r; 02782 } 02783 02784 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage ) 02785 { 02786 MSIHANDLE handle; 02787 UINT r; 02788 02789 TRACE("%s\n", debugstr_w(szPackage) ); 02790 02791 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle ); 02792 MsiCloseHandle( handle ); 02793 02794 return r; 02795 } 02796 02797 static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent, 02798 awstring* lpPathBuf, LPDWORD pcchBuf) 02799 { 02800 static const WCHAR wininstaller[] = 02801 {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0}; 02802 WCHAR squished_pc[GUID_SIZE]; 02803 WCHAR squished_comp[GUID_SIZE]; 02804 HKEY hkey; 02805 LPWSTR path = NULL; 02806 INSTALLSTATE state; 02807 DWORD version; 02808 02809 if (!szProduct || !szComponent) 02810 return INSTALLSTATE_INVALIDARG; 02811 02812 if (lpPathBuf->str.w && !pcchBuf) 02813 return INSTALLSTATE_INVALIDARG; 02814 02815 if (!squash_guid(szProduct, squished_pc) || 02816 !squash_guid(szComponent, squished_comp)) 02817 return INSTALLSTATE_INVALIDARG; 02818 02819 state = INSTALLSTATE_UNKNOWN; 02820 02821 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS || 02822 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS) 02823 { 02824 path = msi_reg_get_val_str(hkey, squished_pc); 02825 RegCloseKey(hkey); 02826 02827 state = INSTALLSTATE_ABSENT; 02828 02829 if ((MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, 02830 &hkey, FALSE) == ERROR_SUCCESS || 02831 MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, 02832 NULL, &hkey, FALSE) == ERROR_SUCCESS) && 02833 msi_reg_get_val_dword(hkey, wininstaller, &version) && 02834 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) 02835 { 02836 RegCloseKey(hkey); 02837 state = INSTALLSTATE_LOCAL; 02838 } 02839 } 02840 02841 if (state != INSTALLSTATE_LOCAL && 02842 (MSIREG_OpenProductKey(szProduct, NULL, 02843 MSIINSTALLCONTEXT_USERUNMANAGED, 02844 &hkey, FALSE) == ERROR_SUCCESS || 02845 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, 02846 &hkey, FALSE) == ERROR_SUCCESS)) 02847 { 02848 RegCloseKey(hkey); 02849 02850 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS || 02851 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS) 02852 { 02853 msi_free(path); 02854 path = msi_reg_get_val_str(hkey, squished_pc); 02855 RegCloseKey(hkey); 02856 02857 state = INSTALLSTATE_ABSENT; 02858 02859 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) 02860 state = INSTALLSTATE_LOCAL; 02861 } 02862 } 02863 02864 if (!path) 02865 return INSTALLSTATE_UNKNOWN; 02866 02867 if (state == INSTALLSTATE_LOCAL && !*path) 02868 state = INSTALLSTATE_NOTUSED; 02869 02870 msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf); 02871 msi_free(path); 02872 return state; 02873 } 02874 02875 /****************************************************************** 02876 * MsiGetComponentPathW [MSI.@] 02877 */ 02878 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent, 02879 LPWSTR lpPathBuf, LPDWORD pcchBuf) 02880 { 02881 awstring path; 02882 02883 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szComponent), lpPathBuf, pcchBuf); 02884 02885 path.unicode = TRUE; 02886 path.str.w = lpPathBuf; 02887 02888 return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf ); 02889 } 02890 02891 /****************************************************************** 02892 * MsiGetComponentPathA [MSI.@] 02893 */ 02894 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent, 02895 LPSTR lpPathBuf, LPDWORD pcchBuf) 02896 { 02897 LPWSTR szwProduct, szwComponent = NULL; 02898 INSTALLSTATE r = INSTALLSTATE_UNKNOWN; 02899 awstring path; 02900 02901 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szComponent), lpPathBuf, pcchBuf); 02902 02903 szwProduct = strdupAtoW( szProduct ); 02904 if( szProduct && !szwProduct) 02905 goto end; 02906 02907 szwComponent = strdupAtoW( szComponent ); 02908 if( szComponent && !szwComponent ) 02909 goto end; 02910 02911 path.unicode = FALSE; 02912 path.str.a = lpPathBuf; 02913 02914 r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf ); 02915 02916 end: 02917 msi_free( szwProduct ); 02918 msi_free( szwComponent ); 02919 02920 return r; 02921 } 02922 02923 /****************************************************************** 02924 * MsiQueryFeatureStateA [MSI.@] 02925 */ 02926 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature) 02927 { 02928 LPWSTR szwProduct = NULL, szwFeature= NULL; 02929 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN; 02930 02931 szwProduct = strdupAtoW( szProduct ); 02932 if ( szProduct && !szwProduct ) 02933 goto end; 02934 02935 szwFeature = strdupAtoW( szFeature ); 02936 if ( szFeature && !szwFeature ) 02937 goto end; 02938 02939 rc = MsiQueryFeatureStateW(szwProduct, szwFeature); 02940 02941 end: 02942 msi_free( szwProduct); 02943 msi_free( szwFeature); 02944 02945 return rc; 02946 } 02947 02948 /****************************************************************** 02949 * MsiQueryFeatureStateW [MSI.@] 02950 * 02951 * Checks the state of a feature 02952 * 02953 * PARAMS 02954 * szProduct [I] Product's GUID string 02955 * szFeature [I] Feature's GUID string 02956 * 02957 * RETURNS 02958 * INSTALLSTATE_LOCAL Feature is installed and usable 02959 * INSTALLSTATE_ABSENT Feature is absent 02960 * INSTALLSTATE_ADVERTISED Feature should be installed on demand 02961 * INSTALLSTATE_UNKNOWN An error occurred 02962 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid 02963 * 02964 */ 02965 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) 02966 { 02967 WCHAR squishProduct[33], comp[GUID_SIZE]; 02968 GUID guid; 02969 LPWSTR components, p, parent_feature, path; 02970 UINT rc; 02971 HKEY hkey; 02972 INSTALLSTATE r; 02973 BOOL missing = FALSE; 02974 BOOL machine = FALSE; 02975 BOOL source = FALSE; 02976 02977 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); 02978 02979 if (!szProduct || !szFeature) 02980 return INSTALLSTATE_INVALIDARG; 02981 02982 if (!squash_guid( szProduct, squishProduct )) 02983 return INSTALLSTATE_INVALIDARG; 02984 02985 SetLastError( ERROR_SUCCESS ); 02986 02987 if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED, 02988 &hkey, FALSE) != ERROR_SUCCESS && 02989 MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, 02990 &hkey, FALSE) != ERROR_SUCCESS) 02991 { 02992 rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE, 02993 &hkey, FALSE); 02994 if (rc != ERROR_SUCCESS) 02995 return INSTALLSTATE_UNKNOWN; 02996 02997 machine = TRUE; 02998 } 02999 03000 parent_feature = msi_reg_get_val_str( hkey, szFeature ); 03001 RegCloseKey(hkey); 03002 03003 if (!parent_feature) 03004 return INSTALLSTATE_UNKNOWN; 03005 03006 r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL; 03007 msi_free(parent_feature); 03008 if (r == INSTALLSTATE_ABSENT) 03009 return r; 03010 03011 if (machine) 03012 rc = MSIREG_OpenUserDataFeaturesKey(szProduct, 03013 MSIINSTALLCONTEXT_MACHINE, 03014 &hkey, FALSE); 03015 else 03016 rc = MSIREG_OpenUserDataFeaturesKey(szProduct, 03017 MSIINSTALLCONTEXT_USERUNMANAGED, 03018 &hkey, FALSE); 03019 03020 if (rc != ERROR_SUCCESS) 03021 return INSTALLSTATE_ADVERTISED; 03022 03023 components = msi_reg_get_val_str( hkey, szFeature ); 03024 RegCloseKey(hkey); 03025 03026 TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components)); 03027 03028 if (!components) 03029 return INSTALLSTATE_ADVERTISED; 03030 03031 for( p = components; *p && *p != 2 ; p += 20) 03032 { 03033 if (!decode_base85_guid( p, &guid )) 03034 { 03035 if (p != components) 03036 break; 03037 03038 msi_free(components); 03039 return INSTALLSTATE_BADCONFIG; 03040 } 03041 03042 StringFromGUID2(&guid, comp, GUID_SIZE); 03043 03044 if (machine) 03045 rc = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE); 03046 else 03047 rc = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE); 03048 03049 if (rc != ERROR_SUCCESS) 03050 { 03051 msi_free(components); 03052 return INSTALLSTATE_ADVERTISED; 03053 } 03054 03055 path = msi_reg_get_val_str(hkey, squishProduct); 03056 if (!path) 03057 missing = TRUE; 03058 else if (lstrlenW(path) > 2 && 03059 path[0] >= '0' && path[0] <= '9' && 03060 path[1] >= '0' && path[1] <= '9') 03061 { 03062 source = TRUE; 03063 } 03064 03065 msi_free(path); 03066 } 03067 msi_free(components); 03068 03069 if (missing) 03070 r = INSTALLSTATE_ADVERTISED; 03071 else if (source) 03072 r = INSTALLSTATE_SOURCE; 03073 else 03074 r = INSTALLSTATE_LOCAL; 03075 03076 TRACE("-> %d\n", r); 03077 return r; 03078 } 03079 03080 /****************************************************************** 03081 * MsiGetFileVersionA [MSI.@] 03082 */ 03083 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, 03084 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf) 03085 { 03086 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL; 03087 UINT ret = ERROR_OUTOFMEMORY; 03088 03089 if ((lpVersionBuf && !pcchVersionBuf) || 03090 (lpLangBuf && !pcchLangBuf)) 03091 return ERROR_INVALID_PARAMETER; 03092 03093 if( szFilePath ) 03094 { 03095 szwFilePath = strdupAtoW( szFilePath ); 03096 if( !szwFilePath ) 03097 goto end; 03098 } 03099 03100 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf ) 03101 { 03102 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR)); 03103 if( !lpwVersionBuff ) 03104 goto end; 03105 } 03106 03107 if( lpLangBuf && pcchLangBuf && *pcchLangBuf ) 03108 { 03109 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR)); 03110 if( !lpwLangBuff ) 03111 goto end; 03112 } 03113 03114 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf, 03115 lpwLangBuff, pcchLangBuf); 03116 03117 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff ) 03118 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1, 03119 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL); 03120 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff ) 03121 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1, 03122 lpLangBuf, *pcchLangBuf + 1, NULL, NULL); 03123 03124 end: 03125 msi_free(szwFilePath); 03126 msi_free(lpwVersionBuff); 03127 msi_free(lpwLangBuff); 03128 03129 return ret; 03130 } 03131 03132 static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen, 03133 WCHAR *langbuf, DWORD *langlen ) 03134 { 03135 static const WCHAR szVersionResource[] = {'\\',0}; 03136 static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0}; 03137 static const WCHAR szLangFormat[] = {'%','d',0}; 03138 UINT ret = ERROR_SUCCESS; 03139 DWORD len, error; 03140 LPVOID version; 03141 VS_FIXEDFILEINFO *ffi; 03142 USHORT *lang; 03143 WCHAR tmp[32]; 03144 03145 if (!(len = GetFileVersionInfoSizeW( path, NULL ))) 03146 { 03147 error = GetLastError(); 03148 if (error == ERROR_BAD_PATHNAME) return ERROR_FILE_NOT_FOUND; 03149 return error; 03150 } 03151 if (!(version = msi_alloc( len ))) return ERROR_OUTOFMEMORY; 03152 if (!GetFileVersionInfoW( path, 0, len, version )) 03153 { 03154 msi_free( version ); 03155 return GetLastError(); 03156 } 03157 if (verlen) 03158 { 03159 if (VerQueryValueW( version, szVersionResource, (LPVOID *)&ffi, &len ) && len > 0) 03160 { 03161 sprintfW( tmp, szVersionFormat, 03162 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), 03163 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS) ); 03164 if (verbuf) lstrcpynW( verbuf, tmp, *verlen ); 03165 len = strlenW( tmp ); 03166 if (len >= *verlen) ret = ERROR_MORE_DATA; 03167 *verlen = len; 03168 } 03169 else 03170 { 03171 if (verbuf) *verbuf = 0; 03172 *verlen = 0; 03173 } 03174 } 03175 if (langlen) 03176 { 03177 if (VerQueryValueW( version, szLangResource, (LPVOID *)&lang, &len ) && len > 0) 03178 { 03179 sprintfW( tmp, szLangFormat, *lang ); 03180 if (langbuf) lstrcpynW( langbuf, tmp, *langlen ); 03181 len = strlenW( tmp ); 03182 if (len >= *langlen) ret = ERROR_MORE_DATA; 03183 *langlen = len; 03184 } 03185 else 03186 { 03187 if (langbuf) *langbuf = 0; 03188 *langlen = 0; 03189 } 03190 } 03191 msi_free( version ); 03192 return ret; 03193 } 03194 03195 03196 /****************************************************************** 03197 * MsiGetFileVersionW [MSI.@] 03198 */ 03199 UINT WINAPI MsiGetFileVersionW( LPCWSTR path, LPWSTR verbuf, LPDWORD verlen, 03200 LPWSTR langbuf, LPDWORD langlen ) 03201 { 03202 UINT ret; 03203 03204 TRACE("%s %p %u %p %u\n", debugstr_w(path), verbuf, verlen ? *verlen : 0, 03205 langbuf, langlen ? *langlen : 0); 03206 03207 if ((verbuf && !verlen) || (langbuf && !langlen)) 03208 return ERROR_INVALID_PARAMETER; 03209 03210 ret = get_file_version( path, verbuf, verlen, langbuf, langlen ); 03211 if (ret == ERROR_RESOURCE_DATA_NOT_FOUND && verlen) 03212 { 03213 int len; 03214 WCHAR *version = msi_font_version_from_file( path ); 03215 if (!version) return ERROR_FILE_INVALID; 03216 len = strlenW( version ); 03217 if (len >= *verlen) ret = ERROR_MORE_DATA; 03218 else if (verbuf) 03219 { 03220 strcpyW( verbuf, version ); 03221 ret = ERROR_SUCCESS; 03222 } 03223 *verlen = len; 03224 msi_free( version ); 03225 } 03226 return ret; 03227 } 03228 03229 /*********************************************************************** 03230 * MsiGetFeatureUsageW [MSI.@] 03231 */ 03232 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature, 03233 LPDWORD pdwUseCount, LPWORD pwDateUsed ) 03234 { 03235 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature), 03236 pdwUseCount, pwDateUsed); 03237 return ERROR_CALL_NOT_IMPLEMENTED; 03238 } 03239 03240 /*********************************************************************** 03241 * MsiGetFeatureUsageA [MSI.@] 03242 */ 03243 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature, 03244 LPDWORD pdwUseCount, LPWORD pwDateUsed ) 03245 { 03246 LPWSTR prod = NULL, feat = NULL; 03247 UINT ret = ERROR_OUTOFMEMORY; 03248 03249 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature), 03250 pdwUseCount, pwDateUsed); 03251 03252 prod = strdupAtoW( szProduct ); 03253 if (szProduct && !prod) 03254 goto end; 03255 03256 feat = strdupAtoW( szFeature ); 03257 if (szFeature && !feat) 03258 goto end; 03259 03260 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed ); 03261 03262 end: 03263 msi_free( prod ); 03264 msi_free( feat ); 03265 03266 return ret; 03267 } 03268 03269 /*********************************************************************** 03270 * MsiUseFeatureExW [MSI.@] 03271 */ 03272 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature, 03273 DWORD dwInstallMode, DWORD dwReserved ) 03274 { 03275 INSTALLSTATE state; 03276 03277 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature), 03278 dwInstallMode, dwReserved); 03279 03280 state = MsiQueryFeatureStateW( szProduct, szFeature ); 03281 03282 if (dwReserved) 03283 return INSTALLSTATE_INVALIDARG; 03284 03285 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION) 03286 { 03287 FIXME("mark product %s feature %s as used\n", 03288 debugstr_w(szProduct), debugstr_w(szFeature) ); 03289 } 03290 03291 return state; 03292 } 03293 03294 /*********************************************************************** 03295 * MsiUseFeatureExA [MSI.@] 03296 */ 03297 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature, 03298 DWORD dwInstallMode, DWORD dwReserved ) 03299 { 03300 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN; 03301 LPWSTR prod = NULL, feat = NULL; 03302 03303 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature), 03304 dwInstallMode, dwReserved); 03305 03306 prod = strdupAtoW( szProduct ); 03307 if (szProduct && !prod) 03308 goto end; 03309 03310 feat = strdupAtoW( szFeature ); 03311 if (szFeature && !feat) 03312 goto end; 03313 03314 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved ); 03315 03316 end: 03317 msi_free( prod ); 03318 msi_free( feat ); 03319 03320 return ret; 03321 } 03322 03323 /*********************************************************************** 03324 * MsiUseFeatureW [MSI.@] 03325 */ 03326 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature ) 03327 { 03328 return MsiUseFeatureExW(szProduct, szFeature, 0, 0); 03329 } 03330 03331 /*********************************************************************** 03332 * MsiUseFeatureA [MSI.@] 03333 */ 03334 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature ) 03335 { 03336 return MsiUseFeatureExA(szProduct, szFeature, 0, 0); 03337 } 03338 03339 /*********************************************************************** 03340 * MSI_ProvideQualifiedComponentEx [internal] 03341 */ 03342 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent, 03343 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct, 03344 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf, 03345 LPDWORD pcchPathBuf) 03346 { 03347 WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1], 03348 feature[MAX_FEATURE_CHARS+1]; 03349 LPWSTR info; 03350 HKEY hkey; 03351 DWORD sz; 03352 UINT rc; 03353 03354 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE); 03355 if (rc != ERROR_SUCCESS) 03356 return ERROR_INDEX_ABSENT; 03357 03358 info = msi_reg_get_val_str( hkey, szQualifier ); 03359 RegCloseKey(hkey); 03360 03361 if (!info) 03362 return ERROR_INDEX_ABSENT; 03363 03364 MsiDecomposeDescriptorW(info, product, feature, component, &sz); 03365 03366 if (!szProduct) 03367 rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf); 03368 else 03369 rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf); 03370 03371 msi_free( info ); 03372 03373 if (rc != INSTALLSTATE_LOCAL) 03374 return ERROR_FILE_NOT_FOUND; 03375 03376 return ERROR_SUCCESS; 03377 } 03378 03379 /*********************************************************************** 03380 * MsiProvideQualifiedComponentExW [MSI.@] 03381 */ 03382 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent, 03383 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct, 03384 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf, 03385 LPDWORD pcchPathBuf) 03386 { 03387 awstring path; 03388 03389 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_w(szComponent), 03390 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct), 03391 Unused1, Unused2, lpPathBuf, pcchPathBuf); 03392 03393 path.unicode = TRUE; 03394 path.str.w = lpPathBuf; 03395 03396 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier, 03397 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf); 03398 } 03399 03400 /*********************************************************************** 03401 * MsiProvideQualifiedComponentExA [MSI.@] 03402 */ 03403 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent, 03404 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct, 03405 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf, 03406 LPDWORD pcchPathBuf) 03407 { 03408 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL; 03409 UINT r = ERROR_OUTOFMEMORY; 03410 awstring path; 03411 03412 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent), 03413 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct), 03414 Unused1, Unused2, lpPathBuf, pcchPathBuf); 03415 03416 szwComponent = strdupAtoW( szComponent ); 03417 if (szComponent && !szwComponent) 03418 goto end; 03419 03420 szwQualifier = strdupAtoW( szQualifier ); 03421 if (szQualifier && !szwQualifier) 03422 goto end; 03423 03424 szwProduct = strdupAtoW( szProduct ); 03425 if (szProduct && !szwProduct) 03426 goto end; 03427 03428 path.unicode = FALSE; 03429 path.str.a = lpPathBuf; 03430 03431 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier, 03432 dwInstallMode, szwProduct, Unused1, 03433 Unused2, &path, pcchPathBuf); 03434 end: 03435 msi_free(szwProduct); 03436 msi_free(szwComponent); 03437 msi_free(szwQualifier); 03438 03439 return r; 03440 } 03441 03442 /*********************************************************************** 03443 * MsiProvideQualifiedComponentW [MSI.@] 03444 */ 03445 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent, 03446 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf, 03447 LPDWORD pcchPathBuf) 03448 { 03449 return MsiProvideQualifiedComponentExW(szComponent, szQualifier, 03450 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf); 03451 } 03452 03453 /*********************************************************************** 03454 * MsiProvideQualifiedComponentA [MSI.@] 03455 */ 03456 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent, 03457 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf, 03458 LPDWORD pcchPathBuf) 03459 { 03460 return MsiProvideQualifiedComponentExA(szComponent, szQualifier, 03461 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf); 03462 } 03463 03464 /*********************************************************************** 03465 * MSI_GetUserInfo [internal] 03466 */ 03467 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct, 03468 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf, 03469 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf, 03470 awstring *lpSerialBuf, LPDWORD pcchSerialBuf) 03471 { 03472 WCHAR squished_pc[SQUISH_GUID_SIZE]; 03473 LPWSTR user, org, serial; 03474 USERINFOSTATE state; 03475 HKEY hkey, props; 03476 LPCWSTR orgptr; 03477 UINT r; 03478 03479 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf, 03480 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf, 03481 pcchSerialBuf); 03482 03483 if (!szProduct || !squash_guid(szProduct, squished_pc)) 03484 return USERINFOSTATE_INVALIDARG; 03485 03486 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED, 03487 &hkey, FALSE) != ERROR_SUCCESS && 03488 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 03489 &hkey, FALSE) != ERROR_SUCCESS && 03490 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, 03491 &hkey, FALSE) != ERROR_SUCCESS) 03492 { 03493 return USERINFOSTATE_UNKNOWN; 03494 } 03495 03496 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, 03497 NULL, &props, FALSE) != ERROR_SUCCESS && 03498 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, 03499 NULL, &props, FALSE) != ERROR_SUCCESS) 03500 { 03501 RegCloseKey(hkey); 03502 return USERINFOSTATE_ABSENT; 03503 } 03504 03505 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW); 03506 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW); 03507 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW); 03508 state = USERINFOSTATE_ABSENT; 03509 03510 RegCloseKey(hkey); 03511 RegCloseKey(props); 03512 03513 if (user && serial) 03514 state = USERINFOSTATE_PRESENT; 03515 03516 if (pcchUserNameBuf) 03517 { 03518 if (lpUserNameBuf && !user) 03519 { 03520 (*pcchUserNameBuf)--; 03521 goto done; 03522 } 03523 03524 r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf); 03525 if (r == ERROR_MORE_DATA) 03526 { 03527 state = USERINFOSTATE_MOREDATA; 03528 goto done; 03529 } 03530 } 03531 03532 if (pcchOrgNameBuf) 03533 { 03534 orgptr = org; 03535 if (!orgptr) orgptr = szEmpty; 03536 03537 r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf); 03538 if (r == ERROR_MORE_DATA) 03539 { 03540 state = USERINFOSTATE_MOREDATA; 03541 goto done; 03542 } 03543 } 03544 03545 if (pcchSerialBuf) 03546 { 03547 if (!serial) 03548 { 03549 (*pcchSerialBuf)--; 03550 goto done; 03551 } 03552 03553 r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf); 03554 if (r == ERROR_MORE_DATA) 03555 state = USERINFOSTATE_MOREDATA; 03556 } 03557 03558 done: 03559 msi_free(user); 03560 msi_free(org); 03561 msi_free(serial); 03562 03563 return state; 03564 } 03565 03566 /*********************************************************************** 03567 * MsiGetUserInfoW [MSI.@] 03568 */ 03569 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, 03570 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf, 03571 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf, 03572 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf) 03573 { 03574 awstring user, org, serial; 03575 03576 if ((lpUserNameBuf && !pcchUserNameBuf) || 03577 (lpOrgNameBuf && !pcchOrgNameBuf) || 03578 (lpSerialBuf && !pcchSerialBuf)) 03579 return USERINFOSTATE_INVALIDARG; 03580 03581 user.unicode = TRUE; 03582 user.str.w = lpUserNameBuf; 03583 org.unicode = TRUE; 03584 org.str.w = lpOrgNameBuf; 03585 serial.unicode = TRUE; 03586 serial.str.w = lpSerialBuf; 03587 03588 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf, 03589 &org, pcchOrgNameBuf, 03590 &serial, pcchSerialBuf ); 03591 } 03592 03593 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, 03594 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf, 03595 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf, 03596 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf) 03597 { 03598 awstring user, org, serial; 03599 LPWSTR prod; 03600 UINT r; 03601 03602 if ((lpUserNameBuf && !pcchUserNameBuf) || 03603 (lpOrgNameBuf && !pcchOrgNameBuf) || 03604 (lpSerialBuf && !pcchSerialBuf)) 03605 return USERINFOSTATE_INVALIDARG; 03606 03607 prod = strdupAtoW( szProduct ); 03608 if (szProduct && !prod) 03609 return ERROR_OUTOFMEMORY; 03610 03611 user.unicode = FALSE; 03612 user.str.a = lpUserNameBuf; 03613 org.unicode = FALSE; 03614 org.str.a = lpOrgNameBuf; 03615 serial.unicode = FALSE; 03616 serial.str.a = lpSerialBuf; 03617 03618 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf, 03619 &org, pcchOrgNameBuf, 03620 &serial, pcchSerialBuf ); 03621 03622 msi_free( prod ); 03623 03624 return r; 03625 } 03626 03627 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct) 03628 { 03629 MSIHANDLE handle; 03630 UINT rc; 03631 MSIPACKAGE *package; 03632 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0}; 03633 03634 TRACE("(%s)\n",debugstr_w(szProduct)); 03635 03636 rc = MsiOpenProductW(szProduct,&handle); 03637 if (rc != ERROR_SUCCESS) 03638 return ERROR_INVALID_PARAMETER; 03639 03640 /* MsiCollectUserInfo cannot be called from a custom action. */ 03641 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE); 03642 if (!package) 03643 return ERROR_CALL_NOT_IMPLEMENTED; 03644 03645 rc = ACTION_PerformUIAction(package, szFirstRun, SCRIPT_NONE); 03646 msiobj_release( &package->hdr ); 03647 03648 MsiCloseHandle(handle); 03649 03650 return rc; 03651 } 03652 03653 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct) 03654 { 03655 MSIHANDLE handle; 03656 UINT rc; 03657 MSIPACKAGE *package; 03658 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0}; 03659 03660 TRACE("(%s)\n",debugstr_a(szProduct)); 03661 03662 rc = MsiOpenProductA(szProduct,&handle); 03663 if (rc != ERROR_SUCCESS) 03664 return ERROR_INVALID_PARAMETER; 03665 03666 /* MsiCollectUserInfo cannot be called from a custom action. */ 03667 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE); 03668 if (!package) 03669 return ERROR_CALL_NOT_IMPLEMENTED; 03670 03671 rc = ACTION_PerformUIAction(package, szFirstRun, SCRIPT_NONE); 03672 msiobj_release( &package->hdr ); 03673 03674 MsiCloseHandle(handle); 03675 03676 return rc; 03677 } 03678 03679 /*********************************************************************** 03680 * MsiConfigureFeatureA [MSI.@] 03681 */ 03682 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState) 03683 { 03684 LPWSTR prod, feat = NULL; 03685 UINT r = ERROR_OUTOFMEMORY; 03686 03687 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState); 03688 03689 prod = strdupAtoW( szProduct ); 03690 if (szProduct && !prod) 03691 goto end; 03692 03693 feat = strdupAtoW( szFeature ); 03694 if (szFeature && !feat) 03695 goto end; 03696 03697 r = MsiConfigureFeatureW(prod, feat, eInstallState); 03698 03699 end: 03700 msi_free(feat); 03701 msi_free(prod); 03702 03703 return r; 03704 } 03705 03706 /*********************************************************************** 03707 * MsiConfigureFeatureW [MSI.@] 03708 */ 03709 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState) 03710 { 03711 MSIPACKAGE *package = NULL; 03712 UINT r; 03713 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH]; 03714 DWORD sz; 03715 03716 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState); 03717 03718 if (!szProduct || !szFeature) 03719 return ERROR_INVALID_PARAMETER; 03720 03721 switch (eInstallState) 03722 { 03723 case INSTALLSTATE_DEFAULT: 03724 /* FIXME: how do we figure out the default location? */ 03725 eInstallState = INSTALLSTATE_LOCAL; 03726 break; 03727 case INSTALLSTATE_LOCAL: 03728 case INSTALLSTATE_SOURCE: 03729 case INSTALLSTATE_ABSENT: 03730 case INSTALLSTATE_ADVERTISED: 03731 break; 03732 default: 03733 return ERROR_INVALID_PARAMETER; 03734 } 03735 03736 r = MSI_OpenProductW( szProduct, &package ); 03737 if (r != ERROR_SUCCESS) 03738 return r; 03739 03740 sz = sizeof(sourcepath); 03741 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 03742 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); 03743 03744 sz = sizeof(filename); 03745 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, 03746 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); 03747 03748 lstrcatW( sourcepath, filename ); 03749 03750 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL ); 03751 03752 r = ACTION_PerformUIAction( package, szCostInitialize, SCRIPT_NONE ); 03753 if (r != ERROR_SUCCESS) 03754 goto end; 03755 03756 r = MSI_SetFeatureStateW( package, szFeature, eInstallState); 03757 if (r != ERROR_SUCCESS) 03758 goto end; 03759 03760 r = MSI_InstallPackage( package, sourcepath, NULL ); 03761 03762 end: 03763 msiobj_release( &package->hdr ); 03764 03765 return r; 03766 } 03767 03768 /*********************************************************************** 03769 * MsiCreateAndVerifyInstallerDirectory [MSI.@] 03770 * 03771 * Notes: undocumented 03772 */ 03773 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved) 03774 { 03775 WCHAR path[MAX_PATH]; 03776 03777 TRACE("%d\n", dwReserved); 03778 03779 if (dwReserved) 03780 { 03781 FIXME("dwReserved=%d\n", dwReserved); 03782 return ERROR_INVALID_PARAMETER; 03783 } 03784 03785 if (!GetWindowsDirectoryW(path, MAX_PATH)) 03786 return ERROR_FUNCTION_FAILED; 03787 03788 lstrcatW(path, installerW); 03789 03790 if (!CreateDirectoryW(path, NULL)) 03791 return ERROR_FUNCTION_FAILED; 03792 03793 return ERROR_SUCCESS; 03794 } 03795 03796 /*********************************************************************** 03797 * MsiGetShortcutTargetA [MSI.@] 03798 */ 03799 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget, 03800 LPSTR szProductCode, LPSTR szFeatureId, 03801 LPSTR szComponentCode ) 03802 { 03803 LPWSTR target; 03804 const int len = MAX_FEATURE_CHARS+1; 03805 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1]; 03806 UINT r; 03807 03808 target = strdupAtoW( szShortcutTarget ); 03809 if (szShortcutTarget && !target ) 03810 return ERROR_OUTOFMEMORY; 03811 product[0] = 0; 03812 feature[0] = 0; 03813 component[0] = 0; 03814 r = MsiGetShortcutTargetW( target, product, feature, component ); 03815 msi_free( target ); 03816 if (r == ERROR_SUCCESS) 03817 { 03818 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL ); 03819 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL ); 03820 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL ); 03821 } 03822 return r; 03823 } 03824 03825 /*********************************************************************** 03826 * MsiGetShortcutTargetW [MSI.@] 03827 */ 03828 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget, 03829 LPWSTR szProductCode, LPWSTR szFeatureId, 03830 LPWSTR szComponentCode ) 03831 { 03832 IShellLinkDataList *dl = NULL; 03833 IPersistFile *pf = NULL; 03834 LPEXP_DARWIN_LINK darwin = NULL; 03835 HRESULT r, init; 03836 03837 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget), 03838 szProductCode, szFeatureId, szComponentCode ); 03839 03840 init = CoInitialize(NULL); 03841 03842 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 03843 &IID_IPersistFile, (LPVOID*) &pf ); 03844 if( SUCCEEDED( r ) ) 03845 { 03846 r = IPersistFile_Load( pf, szShortcutTarget, 03847 STGM_READ | STGM_SHARE_DENY_WRITE ); 03848 if( SUCCEEDED( r ) ) 03849 { 03850 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList, 03851 (LPVOID*) &dl ); 03852 if( SUCCEEDED( r ) ) 03853 { 03854 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG, 03855 (LPVOID) &darwin ); 03856 IShellLinkDataList_Release( dl ); 03857 } 03858 } 03859 IPersistFile_Release( pf ); 03860 } 03861 03862 if (SUCCEEDED(init)) 03863 CoUninitialize(); 03864 03865 TRACE("darwin = %p\n", darwin); 03866 03867 if (darwin) 03868 { 03869 DWORD sz; 03870 UINT ret; 03871 03872 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID, 03873 szProductCode, szFeatureId, szComponentCode, &sz ); 03874 LocalFree( darwin ); 03875 return ret; 03876 } 03877 03878 return ERROR_FUNCTION_FAILED; 03879 } 03880 03881 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature, DWORD dwReinstallMode ) 03882 { 03883 static const WCHAR fmtW[] = {'%','s','=','%','s',' ','%','s','=','%','s',0}; 03884 MSIPACKAGE *package; 03885 MSIINSTALLCONTEXT context; 03886 UINT r; 03887 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH], reinstallmode[11]; 03888 WCHAR *ptr, *cmdline; 03889 DWORD sz; 03890 03891 TRACE("%s, %s, 0x%08x\n", debugstr_w(szProduct), debugstr_w(szFeature), dwReinstallMode); 03892 03893 r = msi_locate_product( szProduct, &context ); 03894 if (r != ERROR_SUCCESS) 03895 return r; 03896 03897 ptr = reinstallmode; 03898 03899 if (dwReinstallMode & REINSTALLMODE_FILEMISSING) 03900 *ptr++ = 'p'; 03901 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION) 03902 *ptr++ = 'o'; 03903 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION) 03904 *ptr++ = 'w'; 03905 if (dwReinstallMode & REINSTALLMODE_FILEEXACT) 03906 *ptr++ = 'd'; 03907 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY) 03908 *ptr++ = 'c'; 03909 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE) 03910 *ptr++ = 'a'; 03911 if (dwReinstallMode & REINSTALLMODE_USERDATA) 03912 *ptr++ = 'u'; 03913 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA) 03914 *ptr++ = 'm'; 03915 if (dwReinstallMode & REINSTALLMODE_SHORTCUT) 03916 *ptr++ = 's'; 03917 if (dwReinstallMode & REINSTALLMODE_PACKAGE) 03918 *ptr++ = 'v'; 03919 *ptr = 0; 03920 03921 sz = sizeof(sourcepath); 03922 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT, 03923 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz ); 03924 sz = sizeof(filename); 03925 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT, 03926 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz ); 03927 strcatW( sourcepath, filename ); 03928 03929 if (dwReinstallMode & REINSTALLMODE_PACKAGE) 03930 r = MSI_OpenPackageW( sourcepath, &package ); 03931 else 03932 r = MSI_OpenProductW( szProduct, &package ); 03933 03934 if (r != ERROR_SUCCESS) 03935 return r; 03936 03937 sz = (strlenW( fmtW ) + strlenW( szReinstallMode ) + strlenW( reinstallmode )) * sizeof(WCHAR); 03938 sz += (strlenW( szReinstall ) + strlenW( szFeature )) * sizeof(WCHAR); 03939 if (!(cmdline = msi_alloc( sz ))) 03940 { 03941 msiobj_release( &package->hdr ); 03942 return ERROR_OUTOFMEMORY; 03943 } 03944 sprintfW( cmdline, fmtW, szReinstallMode, reinstallmode, szReinstall, szFeature ); 03945 03946 r = MSI_InstallPackage( package, sourcepath, cmdline ); 03947 msiobj_release( &package->hdr ); 03948 msi_free( cmdline ); 03949 03950 return r; 03951 } 03952 03953 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature, 03954 DWORD dwReinstallMode ) 03955 { 03956 LPWSTR wszProduct; 03957 LPWSTR wszFeature; 03958 UINT rc; 03959 03960 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), 03961 dwReinstallMode); 03962 03963 wszProduct = strdupAtoW(szProduct); 03964 wszFeature = strdupAtoW(szFeature); 03965 03966 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode); 03967 03968 msi_free(wszProduct); 03969 msi_free(wszFeature); 03970 return rc; 03971 } 03972 03973 typedef struct 03974 { 03975 unsigned int i[2]; 03976 unsigned int buf[4]; 03977 unsigned char in[64]; 03978 unsigned char digest[16]; 03979 } MD5_CTX; 03980 03981 extern VOID WINAPI MD5Init( MD5_CTX *); 03982 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int ); 03983 extern VOID WINAPI MD5Final( MD5_CTX *); 03984 03985 /*********************************************************************** 03986 * MsiGetFileHashW [MSI.@] 03987 */ 03988 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions, 03989 PMSIFILEHASHINFO pHash ) 03990 { 03991 HANDLE handle, mapping; 03992 void *p; 03993 DWORD length; 03994 UINT r = ERROR_FUNCTION_FAILED; 03995 03996 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash ); 03997 03998 if (!szFilePath) 03999 return ERROR_INVALID_PARAMETER; 04000 04001 if (!*szFilePath) 04002 return ERROR_PATH_NOT_FOUND; 04003 04004 if (dwOptions) 04005 return ERROR_INVALID_PARAMETER; 04006 if (!pHash) 04007 return ERROR_INVALID_PARAMETER; 04008 if (pHash->dwFileHashInfoSize < sizeof *pHash) 04009 return ERROR_INVALID_PARAMETER; 04010 04011 handle = CreateFileW( szFilePath, GENERIC_READ, 04012 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL ); 04013 if (handle == INVALID_HANDLE_VALUE) 04014 { 04015 WARN("can't open file %u\n", GetLastError()); 04016 return ERROR_FILE_NOT_FOUND; 04017 } 04018 length = GetFileSize( handle, NULL ); 04019 04020 if (length) 04021 { 04022 mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL ); 04023 if (mapping) 04024 { 04025 p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length ); 04026 if (p) 04027 { 04028 MD5_CTX ctx; 04029 04030 MD5Init( &ctx ); 04031 MD5Update( &ctx, p, length ); 04032 MD5Final( &ctx ); 04033 UnmapViewOfFile( p ); 04034 04035 memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData ); 04036 r = ERROR_SUCCESS; 04037 } 04038 CloseHandle( mapping ); 04039 } 04040 } 04041 else 04042 { 04043 /* Empty file -> set hash to 0 */ 04044 memset( pHash->dwData, 0, sizeof pHash->dwData ); 04045 r = ERROR_SUCCESS; 04046 } 04047 04048 CloseHandle( handle ); 04049 04050 return r; 04051 } 04052 04053 /*********************************************************************** 04054 * MsiGetFileHashA [MSI.@] 04055 */ 04056 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions, 04057 PMSIFILEHASHINFO pHash ) 04058 { 04059 LPWSTR file; 04060 UINT r; 04061 04062 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash ); 04063 04064 file = strdupAtoW( szFilePath ); 04065 if (szFilePath && !file) 04066 return ERROR_OUTOFMEMORY; 04067 04068 r = MsiGetFileHashW( file, dwOptions, pHash ); 04069 msi_free( file ); 04070 return r; 04071 } 04072 04073 /*********************************************************************** 04074 * MsiAdvertiseScriptW [MSI.@] 04075 */ 04076 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags, 04077 PHKEY phRegData, BOOL fRemoveItems ) 04078 { 04079 FIXME("%s %08x %p %d\n", 04080 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems ); 04081 return ERROR_CALL_NOT_IMPLEMENTED; 04082 } 04083 04084 /*********************************************************************** 04085 * MsiAdvertiseScriptA [MSI.@] 04086 */ 04087 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags, 04088 PHKEY phRegData, BOOL fRemoveItems ) 04089 { 04090 FIXME("%s %08x %p %d\n", 04091 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems ); 04092 return ERROR_CALL_NOT_IMPLEMENTED; 04093 } 04094 04095 /*********************************************************************** 04096 * MsiIsProductElevatedW [MSI.@] 04097 */ 04098 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated ) 04099 { 04100 FIXME("%s %p - stub\n", 04101 debugstr_w( szProduct ), pfElevated ); 04102 *pfElevated = TRUE; 04103 return ERROR_SUCCESS; 04104 } 04105 04106 /*********************************************************************** 04107 * MsiIsProductElevatedA [MSI.@] 04108 */ 04109 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated ) 04110 { 04111 FIXME("%s %p - stub\n", 04112 debugstr_a( szProduct ), pfElevated ); 04113 *pfElevated = TRUE; 04114 return ERROR_SUCCESS; 04115 } 04116 04117 /*********************************************************************** 04118 * MsiSetExternalUIRecord [MSI.@] 04119 */ 04120 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler, 04121 DWORD filter, LPVOID context, 04122 PINSTALLUI_HANDLER_RECORD prev ) 04123 { 04124 TRACE("%p %08x %p %p\n", handler, filter, context, prev); 04125 04126 if (prev) 04127 *prev = gUIHandlerRecord; 04128 04129 gUIHandlerRecord = handler; 04130 gUIFilter = filter; 04131 gUIContext = context; 04132 04133 return ERROR_SUCCESS; 04134 } 04135 04136 /*********************************************************************** 04137 * MsiInstallMissingComponentA [MSI.@] 04138 */ 04139 UINT WINAPI MsiInstallMissingComponentA( LPCSTR product, LPCSTR component, INSTALLSTATE state ) 04140 { 04141 UINT r; 04142 WCHAR *productW = NULL, *componentW = NULL; 04143 04144 TRACE("%s, %s, %d\n", debugstr_a(product), debugstr_a(component), state); 04145 04146 if (product && !(productW = strdupAtoW( product ))) 04147 return ERROR_OUTOFMEMORY; 04148 04149 if (component && !(componentW = strdupAtoW( component ))) 04150 { 04151 msi_free( productW ); 04152 return ERROR_OUTOFMEMORY; 04153 } 04154 04155 r = MsiInstallMissingComponentW( productW, componentW, state ); 04156 msi_free( productW ); 04157 msi_free( componentW ); 04158 return r; 04159 } 04160 04161 /*********************************************************************** 04162 * MsiInstallMissingComponentW [MSI.@] 04163 */ 04164 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState) 04165 { 04166 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState); 04167 return ERROR_SUCCESS; 04168 } 04169 04170 /*********************************************************************** 04171 * MsiBeginTransactionA [MSI.@] 04172 */ 04173 UINT WINAPI MsiBeginTransactionA( LPCSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event ) 04174 { 04175 WCHAR *nameW; 04176 UINT r; 04177 04178 FIXME("%s %u %p %p\n", debugstr_a(name), attrs, id, event); 04179 04180 nameW = strdupAtoW( name ); 04181 if (name && !nameW) 04182 return ERROR_OUTOFMEMORY; 04183 04184 r = MsiBeginTransactionW( nameW, attrs, id, event ); 04185 msi_free( nameW ); 04186 return r; 04187 } 04188 04189 /*********************************************************************** 04190 * MsiBeginTransactionW [MSI.@] 04191 */ 04192 UINT WINAPI MsiBeginTransactionW( LPCWSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event ) 04193 { 04194 FIXME("%s %u %p %p\n", debugstr_w(name), attrs, id, event); 04195 04196 *id = (MSIHANDLE)0xdeadbeef; 04197 *event = (HANDLE)0xdeadbeef; 04198 04199 return ERROR_SUCCESS; 04200 } 04201 04202 /*********************************************************************** 04203 * MsiEndTransaction [MSI.@] 04204 */ 04205 UINT WINAPI MsiEndTransaction( DWORD state ) 04206 { 04207 FIXME("%u\n", state); 04208 return ERROR_SUCCESS; 04209 } Generated on Thu May 24 2012 04:22:57 for ReactOS by
1.7.6.1
|