wined3d: Drop support for WINED3DFMT_D32_UNORM.
[wine.git] / dlls / msi / msi.c
blob7bf5004bed1c0197e94096d9c43f53d656b3fa86
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "shlwapi.h"
31 #include "msi.h"
32 #include "msidefs.h"
33 #include "msiquery.h"
34 #include "wincrypt.h"
35 #include "winver.h"
36 #include "winuser.h"
37 #include "shlobj.h"
38 #include "shobjidl.h"
39 #include "objidl.h"
40 #include "wintrust.h"
41 #include "softpub.h"
43 #include "msipriv.h"
44 #include "winemsi.h"
46 #include "initguid.h"
47 #include "msxml2.h"
49 #include "wine/debug.h"
50 #include "wine/exception.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(msi);
54 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
56 UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context)
58 HKEY hkey = NULL;
60 *context = MSIINSTALLCONTEXT_NONE;
61 if (!szProduct) return ERROR_UNKNOWN_PRODUCT;
63 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
64 &hkey, FALSE) == ERROR_SUCCESS)
65 *context = MSIINSTALLCONTEXT_USERMANAGED;
66 else if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
67 &hkey, FALSE) == ERROR_SUCCESS)
68 *context = MSIINSTALLCONTEXT_MACHINE;
69 else if (MSIREG_OpenProductKey(szProduct, NULL,
70 MSIINSTALLCONTEXT_USERUNMANAGED,
71 &hkey, FALSE) == ERROR_SUCCESS)
72 *context = MSIINSTALLCONTEXT_USERUNMANAGED;
74 RegCloseKey(hkey);
76 if (*context == MSIINSTALLCONTEXT_NONE)
77 return ERROR_UNKNOWN_PRODUCT;
79 return ERROR_SUCCESS;
82 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
84 UINT r;
85 LPWSTR szwProd = NULL;
87 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
89 if( szProduct )
91 szwProd = strdupAtoW( szProduct );
92 if( !szwProd )
93 return ERROR_OUTOFMEMORY;
96 r = MsiOpenProductW( szwProd, phProduct );
98 msi_free( szwProd );
100 return r;
103 static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package)
105 UINT r;
106 HKEY props;
107 LPWSTR path;
108 MSIINSTALLCONTEXT context;
110 static const WCHAR managed[] = {
111 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
112 static const WCHAR local[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
114 TRACE("%s %p\n", debugstr_w(szProduct), package);
116 r = msi_locate_product(szProduct, &context);
117 if (r != ERROR_SUCCESS)
118 return r;
120 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &props, FALSE);
121 if (r != ERROR_SUCCESS)
122 return ERROR_UNKNOWN_PRODUCT;
124 if (context == MSIINSTALLCONTEXT_USERMANAGED)
125 path = msi_reg_get_val_str(props, managed);
126 else
127 path = msi_reg_get_val_str(props, local);
129 r = ERROR_UNKNOWN_PRODUCT;
131 if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
132 goto done;
134 if (PathIsRelativeW(path))
136 r = ERROR_INSTALL_PACKAGE_OPEN_FAILED;
137 goto done;
140 r = MSI_OpenPackageW(path, 0, package);
142 done:
143 RegCloseKey(props);
144 msi_free(path);
145 return r;
148 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
150 MSIPACKAGE *package = NULL;
151 WCHAR squashed_pc[SQUASHED_GUID_SIZE];
152 UINT r;
154 if (!szProduct || !squash_guid( szProduct, squashed_pc ))
155 return ERROR_INVALID_PARAMETER;
157 if (!phProduct)
158 return ERROR_INVALID_PARAMETER;
160 r = MSI_OpenProductW(szProduct, &package);
161 if (r != ERROR_SUCCESS)
162 return r;
164 *phProduct = alloc_msihandle(&package->hdr);
165 if (!*phProduct)
166 r = ERROR_NOT_ENOUGH_MEMORY;
168 msiobj_release(&package->hdr);
169 return r;
172 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
173 LPCSTR szTransforms, LANGID lgidLanguage)
175 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
176 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
177 return ERROR_CALL_NOT_IMPLEMENTED;
180 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
181 LPCWSTR szTransforms, LANGID lgidLanguage)
183 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
184 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
185 return ERROR_CALL_NOT_IMPLEMENTED;
188 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
189 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
191 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath),
192 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
193 lgidLanguage, dwPlatform, dwOptions);
194 return ERROR_CALL_NOT_IMPLEMENTED;
197 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
198 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
200 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath),
201 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
202 lgidLanguage, dwPlatform, dwOptions);
203 return ERROR_CALL_NOT_IMPLEMENTED;
206 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
208 LPWSTR szwPath = NULL, szwCommand = NULL;
209 UINT r = ERROR_OUTOFMEMORY;
211 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
213 if( szPackagePath )
215 szwPath = strdupAtoW( szPackagePath );
216 if( !szwPath )
217 goto end;
220 if( szCommandLine )
222 szwCommand = strdupAtoW( szCommandLine );
223 if( !szwCommand )
224 goto end;
227 r = MsiInstallProductW( szwPath, szwCommand );
229 end:
230 msi_free( szwPath );
231 msi_free( szwCommand );
233 return r;
236 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
238 MSIPACKAGE *package = NULL;
239 const WCHAR *reinstallmode;
240 DWORD options = 0;
241 UINT r, len;
243 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
245 if (!szPackagePath)
246 return ERROR_INVALID_PARAMETER;
248 if (!*szPackagePath)
249 return ERROR_PATH_NOT_FOUND;
251 reinstallmode = msi_get_command_line_option(szCommandLine, szReinstallMode, &len);
252 if (reinstallmode)
254 while (len > 0)
256 if (reinstallmode[--len] == 'v' || reinstallmode[len] == 'V')
258 options |= WINE_OPENPACKAGEFLAGS_RECACHE;
259 break;
264 r = MSI_OpenPackageW( szPackagePath, options, &package );
265 if (r == ERROR_SUCCESS)
267 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
268 msiobj_release( &package->hdr );
271 return r;
274 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
276 LPWSTR wszProduct;
277 UINT rc;
279 TRACE("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
281 wszProduct = strdupAtoW(szProduct);
283 rc = MsiReinstallProductW(wszProduct, dwReinstallMode);
285 msi_free(wszProduct);
286 return rc;
289 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
291 TRACE("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
293 return MsiReinstallFeatureW(szProduct, szAll, dwReinstallMode);
296 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
297 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
299 LPWSTR patch_package = NULL;
300 LPWSTR install_package = NULL;
301 LPWSTR command_line = NULL;
302 UINT r = ERROR_OUTOFMEMORY;
304 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
305 eInstallType, debugstr_a(szCommandLine));
307 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage)))
308 goto done;
310 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage)))
311 goto done;
313 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine)))
314 goto done;
316 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line);
318 done:
319 msi_free(patch_package);
320 msi_free(install_package);
321 msi_free(command_line);
323 return r;
326 static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes )
328 MSIHANDLE patch, info = 0;
329 UINT r, type;
330 DWORD size;
331 static WCHAR empty[] = {0};
332 WCHAR *codes = NULL;
334 r = MsiOpenDatabaseW( szPatchPackage, MSIDBOPEN_READONLY, &patch );
335 if (r != ERROR_SUCCESS)
336 return r;
338 r = MsiGetSummaryInformationW( patch, NULL, 0, &info );
339 if (r != ERROR_SUCCESS)
340 goto done;
342 size = 0;
343 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, empty, &size );
344 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
346 ERR("Failed to read product codes from patch\n");
347 r = ERROR_FUNCTION_FAILED;
348 goto done;
351 codes = msi_alloc( ++size * sizeof(WCHAR) );
352 if (!codes)
354 r = ERROR_OUTOFMEMORY;
355 goto done;
358 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, codes, &size );
359 if (r == ERROR_SUCCESS)
360 *product_codes = msi_split_string( codes, ';' );
362 done:
363 MsiCloseHandle( info );
364 MsiCloseHandle( patch );
365 msi_free( codes );
366 return r;
369 static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
371 UINT i, r = ERROR_FUNCTION_FAILED;
372 DWORD size;
373 LPCWSTR cmd_ptr = szCommandLine;
374 LPWSTR cmd, *codes = NULL;
375 BOOL succeeded = FALSE;
377 static const WCHAR fmt[] = {'%','s',' ','P','A','T','C','H','=','"','%','s','"',0};
378 static const WCHAR empty[] = {0};
380 if (!szPatchPackage || !szPatchPackage[0])
381 return ERROR_INVALID_PARAMETER;
383 if (!szProductCode && (r = get_patch_product_codes( szPatchPackage, &codes )))
384 return r;
386 if (!szCommandLine)
387 cmd_ptr = empty;
389 size = lstrlenW(cmd_ptr) + lstrlenW(fmt) + lstrlenW(szPatchPackage) + 1;
390 cmd = msi_alloc(size * sizeof(WCHAR));
391 if (!cmd)
393 msi_free(codes);
394 return ERROR_OUTOFMEMORY;
396 swprintf(cmd, size, fmt, cmd_ptr, szPatchPackage);
398 if (szProductCode)
399 r = MsiConfigureProductExW(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
400 else
402 for (i = 0; codes[i]; i++)
404 r = MsiConfigureProductExW(codes[i], INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
405 if (r == ERROR_SUCCESS)
407 TRACE("patch applied\n");
408 succeeded = TRUE;
412 if (succeeded)
413 r = ERROR_SUCCESS;
416 msi_free(cmd);
417 msi_free(codes);
418 return r;
421 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
422 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
424 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
425 eInstallType, debugstr_w(szCommandLine));
427 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
428 eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
430 FIXME("Only reading target products from patch\n");
431 return ERROR_CALL_NOT_IMPLEMENTED;
434 return MSI_ApplyPatchW(szPatchPackage, NULL, szCommandLine);
437 UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR szPatchPackages,
438 LPCSTR szProductCode, LPCSTR szPropertiesList)
440 LPWSTR patch_packages = NULL;
441 LPWSTR product_code = NULL;
442 LPWSTR properties_list = NULL;
443 UINT r = ERROR_OUTOFMEMORY;
445 TRACE("%s %s %s\n", debugstr_a(szPatchPackages), debugstr_a(szProductCode),
446 debugstr_a(szPropertiesList));
448 if (!szPatchPackages || !szPatchPackages[0])
449 return ERROR_INVALID_PARAMETER;
451 if (!(patch_packages = strdupAtoW(szPatchPackages)))
452 return ERROR_OUTOFMEMORY;
454 if (szProductCode && !(product_code = strdupAtoW(szProductCode)))
455 goto done;
457 if (szPropertiesList && !(properties_list = strdupAtoW(szPropertiesList)))
458 goto done;
460 r = MsiApplyMultiplePatchesW(patch_packages, product_code, properties_list);
462 done:
463 msi_free(patch_packages);
464 msi_free(product_code);
465 msi_free(properties_list);
467 return r;
470 UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages,
471 LPCWSTR szProductCode, LPCWSTR szPropertiesList)
473 UINT r = ERROR_SUCCESS;
474 LPCWSTR beg, end;
476 TRACE("%s %s %s\n", debugstr_w(szPatchPackages), debugstr_w(szProductCode),
477 debugstr_w(szPropertiesList));
479 if (!szPatchPackages || !szPatchPackages[0])
480 return ERROR_INVALID_PARAMETER;
482 beg = end = szPatchPackages;
483 while (*beg)
485 DWORD len;
486 LPWSTR patch;
488 while (*beg == ' ') beg++;
489 while (*end && *end != ';') end++;
491 len = end - beg;
492 while (len && beg[len - 1] == ' ') len--;
494 if (!len) return ERROR_INVALID_NAME;
496 patch = msi_alloc((len + 1) * sizeof(WCHAR));
497 if (!patch)
498 return ERROR_OUTOFMEMORY;
500 memcpy(patch, beg, len * sizeof(WCHAR));
501 patch[len] = '\0';
503 r = MSI_ApplyPatchW(patch, szProductCode, szPropertiesList);
504 msi_free(patch);
506 if (r != ERROR_SUCCESS || !*end)
507 break;
509 beg = ++end;
511 return r;
514 static void free_patchinfo( DWORD count, MSIPATCHSEQUENCEINFOW *info )
516 DWORD i;
517 for (i = 0; i < count; i++) msi_free( (WCHAR *)info[i].szPatchData );
518 msi_free( info );
521 static MSIPATCHSEQUENCEINFOW *patchinfoAtoW( DWORD count, const MSIPATCHSEQUENCEINFOA *info )
523 DWORD i;
524 MSIPATCHSEQUENCEINFOW *ret;
526 if (!(ret = msi_alloc( count * sizeof(MSIPATCHSEQUENCEINFOW) ))) return NULL;
527 for (i = 0; i < count; i++)
529 if (info[i].szPatchData && !(ret[i].szPatchData = strdupAtoW( info[i].szPatchData )))
531 free_patchinfo( i, ret );
532 return NULL;
534 ret[i].ePatchDataType = info[i].ePatchDataType;
535 ret[i].dwOrder = info[i].dwOrder;
536 ret[i].uStatus = info[i].uStatus;
538 return ret;
541 UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
542 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
544 UINT i, r;
545 WCHAR *package_path = NULL;
546 MSIPATCHSEQUENCEINFOW *psi;
548 TRACE("%s, %u, %p\n", debugstr_a(szProductPackagePath), cPatchInfo, pPatchInfo);
550 if (szProductPackagePath && !(package_path = strdupAtoW( szProductPackagePath )))
551 return ERROR_OUTOFMEMORY;
553 if (!(psi = patchinfoAtoW( cPatchInfo, pPatchInfo )))
555 msi_free( package_path );
556 return ERROR_OUTOFMEMORY;
558 r = MsiDetermineApplicablePatchesW( package_path, cPatchInfo, psi );
559 if (r == ERROR_SUCCESS)
561 for (i = 0; i < cPatchInfo; i++)
563 pPatchInfo[i].dwOrder = psi[i].dwOrder;
564 pPatchInfo[i].uStatus = psi[i].uStatus;
567 msi_free( package_path );
568 free_patchinfo( cPatchInfo, psi );
569 return r;
572 static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
574 MSISUMMARYINFO *si;
575 MSIDATABASE *patch_db;
576 UINT r;
578 r = MSI_OpenDatabaseW( patch, MSIDBOPEN_READONLY, &patch_db );
579 if (r != ERROR_SUCCESS)
581 WARN("failed to open patch file %s\n", debugstr_w(patch));
582 return r;
585 r = msi_get_suminfo( patch_db->storage, 0, &si );
586 if (r != ERROR_SUCCESS)
588 msiobj_release( &patch_db->hdr );
589 return ERROR_FUNCTION_FAILED;
592 r = msi_check_patch_applicable( package, si );
593 if (r != ERROR_SUCCESS)
594 TRACE("patch not applicable\n");
596 msiobj_release( &patch_db->hdr );
597 msiobj_release( &si->hdr );
598 return r;
601 /* IXMLDOMDocument should be set to XPath mode already */
602 static UINT MSI_ApplicablePatchXML( MSIPACKAGE *package, IXMLDOMDocument *desc )
604 static const WCHAR queryW[] = {'M','s','i','P','a','t','c','h','/',
605 'T','a','r','g','e','t','P','r','o','d','u','c','t','/',
606 'T','a','r','g','e','t','P','r','o','d','u','c','t','C','o','d','e',0};
607 UINT r = ERROR_FUNCTION_FAILED;
608 IXMLDOMNodeList *list;
609 LPWSTR product_code;
610 IXMLDOMNode *node;
611 HRESULT hr;
612 BSTR s;
614 product_code = msi_dup_property( package->db, szProductCode );
615 if (!product_code)
617 /* FIXME: the property ProductCode should be written into the DB somewhere */
618 ERR("no product code to check\n");
619 return ERROR_SUCCESS;
622 s = SysAllocString(queryW);
623 hr = IXMLDOMDocument_selectNodes( desc, s, &list );
624 SysFreeString(s);
625 if (hr != S_OK)
626 return ERROR_INVALID_PATCH_XML;
628 while (IXMLDOMNodeList_nextNode( list, &node ) == S_OK && r != ERROR_SUCCESS)
630 hr = IXMLDOMNode_get_text( node, &s );
631 IXMLDOMNode_Release( node );
632 if (hr == S_OK)
634 if (!wcscmp( s, product_code )) r = ERROR_SUCCESS;
635 SysFreeString( s );
638 IXMLDOMNodeList_Release( list );
640 if (r != ERROR_SUCCESS)
641 TRACE("patch not applicable\n");
643 msi_free( product_code );
644 return r;
647 static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCHSEQUENCEINFOW *info )
649 IXMLDOMDocument *desc = NULL;
650 DWORD i;
652 if (count > 1)
653 FIXME("patch ordering not supported\n");
655 for (i = 0; i < count; i++)
657 switch (info[i].ePatchDataType)
659 case MSIPATCH_DATATYPE_PATCHFILE:
661 if (MSI_ApplicablePatchW( package, info[i].szPatchData ) != ERROR_SUCCESS)
663 info[i].dwOrder = ~0u;
664 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
666 else
668 info[i].dwOrder = i;
669 info[i].uStatus = ERROR_SUCCESS;
671 break;
673 case MSIPATCH_DATATYPE_XMLPATH:
674 case MSIPATCH_DATATYPE_XMLBLOB:
676 VARIANT_BOOL b;
677 HRESULT hr;
678 BSTR s;
680 if (!desc)
682 hr = CoCreateInstance( &CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER,
683 &IID_IXMLDOMDocument, (void**)&desc );
684 if (hr != S_OK)
686 ERR("failed to create DOMDocument30 instance, 0x%08x\n", hr);
687 return ERROR_FUNCTION_FAILED;
691 s = SysAllocString( info[i].szPatchData );
692 if (info[i].ePatchDataType == MSIPATCH_DATATYPE_XMLPATH)
694 VARIANT src;
696 V_VT(&src) = VT_BSTR;
697 V_BSTR(&src) = s;
698 hr = IXMLDOMDocument_load( desc, src, &b );
700 else
701 hr = IXMLDOMDocument_loadXML( desc, s, &b );
702 SysFreeString( s );
703 if ( hr != S_OK )
705 ERR("failed to parse patch description\n");
706 IXMLDOMDocument_Release( desc );
707 break;
710 if (MSI_ApplicablePatchXML( package, desc ) != ERROR_SUCCESS)
712 info[i].dwOrder = ~0u;
713 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
715 else
717 info[i].dwOrder = i;
718 info[i].uStatus = ERROR_SUCCESS;
720 break;
722 default:
724 FIXME("unknown patch data type %u\n", info[i].ePatchDataType);
725 info[i].dwOrder = i;
726 info[i].uStatus = ERROR_SUCCESS;
727 break;
731 TRACE("szPatchData: %s\n", debugstr_w(info[i].szPatchData));
732 TRACE("ePatchDataType: %u\n", info[i].ePatchDataType);
733 TRACE("dwOrder: %u\n", info[i].dwOrder);
734 TRACE("uStatus: %u\n", info[i].uStatus);
737 if (desc) IXMLDOMDocument_Release( desc );
739 return ERROR_SUCCESS;
742 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath,
743 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
745 UINT r;
746 MSIPACKAGE *package;
748 TRACE("%s, %u, %p\n", debugstr_w(szProductPackagePath), cPatchInfo, pPatchInfo);
750 r = MSI_OpenPackageW( szProductPackagePath, 0, &package );
751 if (r != ERROR_SUCCESS)
753 ERR("failed to open package %u\n", r);
754 return r;
756 r = determine_patch_sequence( package, cPatchInfo, pPatchInfo );
757 msiobj_release( &package->hdr );
758 return r;
761 UINT WINAPI MsiDeterminePatchSequenceA( LPCSTR product, LPCSTR usersid,
762 MSIINSTALLCONTEXT context, DWORD count, PMSIPATCHSEQUENCEINFOA patchinfo )
764 UINT i, r;
765 WCHAR *productW, *usersidW = NULL;
766 MSIPATCHSEQUENCEINFOW *patchinfoW;
768 TRACE("%s, %s, %d, %d, %p\n", debugstr_a(product), debugstr_a(usersid),
769 context, count, patchinfo);
771 if (!product) return ERROR_INVALID_PARAMETER;
772 if (!(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
773 if (usersid && !(usersidW = strdupAtoW( usersid )))
775 msi_free( productW );
776 return ERROR_OUTOFMEMORY;
778 if (!(patchinfoW = patchinfoAtoW( count, patchinfo )))
780 msi_free( productW );
781 msi_free( usersidW );
782 return ERROR_OUTOFMEMORY;
784 r = MsiDeterminePatchSequenceW( productW, usersidW, context, count, patchinfoW );
785 if (r == ERROR_SUCCESS)
787 for (i = 0; i < count; i++)
789 patchinfo[i].dwOrder = patchinfoW[i].dwOrder;
790 patchinfo[i].uStatus = patchinfoW[i].uStatus;
793 msi_free( productW );
794 msi_free( usersidW );
795 free_patchinfo( count, patchinfoW );
796 return r;
799 static UINT open_package( const WCHAR *product, const WCHAR *usersid,
800 MSIINSTALLCONTEXT context, MSIPACKAGE **package )
802 UINT r;
803 HKEY props;
804 WCHAR *localpath, sourcepath[MAX_PATH], filename[MAX_PATH];
806 r = MSIREG_OpenInstallProps( product, context, usersid, &props, FALSE );
807 if (r != ERROR_SUCCESS) return ERROR_BAD_CONFIGURATION;
809 if ((localpath = msi_reg_get_val_str( props, szLocalPackage )))
811 lstrcpyW( sourcepath, localpath );
812 msi_free( localpath );
814 RegCloseKey( props );
815 if (!localpath || GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES)
817 DWORD sz = sizeof(sourcepath);
818 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT,
819 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz );
820 sz = sizeof(filename);
821 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT,
822 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz );
823 lstrcatW( sourcepath, filename );
825 if (GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES)
826 return ERROR_INSTALL_SOURCE_ABSENT;
828 return MSI_OpenPackageW( sourcepath, 0, package );
831 UINT WINAPI MsiDeterminePatchSequenceW( LPCWSTR product, LPCWSTR usersid,
832 MSIINSTALLCONTEXT context, DWORD count, PMSIPATCHSEQUENCEINFOW patchinfo )
834 UINT r;
835 MSIPACKAGE *package;
837 TRACE("%s, %s, %d, %d, %p\n", debugstr_w(product), debugstr_w(usersid),
838 context, count, patchinfo);
840 if (!product) return ERROR_INVALID_PARAMETER;
841 r = open_package( product, usersid, context, &package );
842 if (r != ERROR_SUCCESS) return r;
844 r = determine_patch_sequence( package, count, patchinfo );
845 msiobj_release( &package->hdr );
846 return r;
849 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
850 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
852 MSIPACKAGE* package = NULL;
853 MSIINSTALLCONTEXT context;
854 UINT r;
855 DWORD sz;
856 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
857 LPWSTR commandline;
859 static const WCHAR szInstalled[] = {
860 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
861 static const WCHAR szMaxInstallLevel[] = {
862 ' ','I','N','S','T','A','L','L','L','E','V','E','L','=','3','2','7','6','7',0};
863 static const WCHAR szRemoveAll[] = {
864 ' ','R','E','M','O','V','E','=','A','L','L',0};
865 static const WCHAR szMachine[] = {
866 ' ','A','L','L','U','S','E','R','S','=','1',0};
868 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
869 debugstr_w(szCommandLine));
871 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1)
872 return ERROR_INVALID_PARAMETER;
874 if (eInstallState == INSTALLSTATE_ADVERTISED ||
875 eInstallState == INSTALLSTATE_SOURCE)
877 FIXME("State %d not implemented\n", eInstallState);
878 return ERROR_CALL_NOT_IMPLEMENTED;
881 r = msi_locate_product(szProduct, &context);
882 if (r != ERROR_SUCCESS)
883 return r;
885 r = open_package(szProduct, NULL, context, &package);
886 if (r != ERROR_SUCCESS)
887 return r;
889 sz = lstrlenW(szInstalled) + 1;
891 if (szCommandLine)
892 sz += lstrlenW(szCommandLine);
894 if (eInstallState != INSTALLSTATE_DEFAULT)
895 sz += lstrlenW(szMaxInstallLevel);
897 if (eInstallState == INSTALLSTATE_ABSENT)
898 sz += lstrlenW(szRemoveAll);
900 if (context == MSIINSTALLCONTEXT_MACHINE)
901 sz += lstrlenW(szMachine);
903 commandline = msi_alloc(sz * sizeof(WCHAR));
904 if (!commandline)
906 r = ERROR_OUTOFMEMORY;
907 goto end;
910 commandline[0] = 0;
911 if (szCommandLine)
912 lstrcpyW(commandline,szCommandLine);
914 if (eInstallState != INSTALLSTATE_DEFAULT)
915 lstrcatW(commandline, szMaxInstallLevel);
917 if (eInstallState == INSTALLSTATE_ABSENT)
918 lstrcatW(commandline, szRemoveAll);
920 if (context == MSIINSTALLCONTEXT_MACHINE)
921 lstrcatW(commandline, szMachine);
923 sz = sizeof(sourcepath);
924 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
925 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
927 sz = sizeof(filename);
928 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
929 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
931 lstrcatW(sourcepath, filename);
933 r = MSI_InstallPackage( package, sourcepath, commandline );
935 msi_free(commandline);
937 end:
938 msiobj_release( &package->hdr );
940 return r;
943 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
944 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
946 LPWSTR szwProduct = NULL;
947 LPWSTR szwCommandLine = NULL;
948 UINT r = ERROR_OUTOFMEMORY;
950 if( szProduct )
952 szwProduct = strdupAtoW( szProduct );
953 if( !szwProduct )
954 goto end;
957 if( szCommandLine)
959 szwCommandLine = strdupAtoW( szCommandLine );
960 if( !szwCommandLine)
961 goto end;
964 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
965 szwCommandLine );
966 end:
967 msi_free( szwProduct );
968 msi_free( szwCommandLine);
970 return r;
973 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
974 INSTALLSTATE eInstallState)
976 LPWSTR szwProduct = NULL;
977 UINT r;
979 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
981 if( szProduct )
983 szwProduct = strdupAtoW( szProduct );
984 if( !szwProduct )
985 return ERROR_OUTOFMEMORY;
988 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
989 msi_free( szwProduct );
991 return r;
994 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
995 INSTALLSTATE eInstallState)
997 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
1000 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
1002 LPWSTR szwComponent = NULL;
1003 UINT r;
1004 WCHAR szwBuffer[GUID_SIZE];
1006 TRACE("%s %p\n", debugstr_a(szComponent), szBuffer);
1008 if( szComponent )
1010 szwComponent = strdupAtoW( szComponent );
1011 if( !szwComponent )
1012 return ERROR_OUTOFMEMORY;
1015 *szwBuffer = '\0';
1016 r = MsiGetProductCodeW( szwComponent, szwBuffer );
1018 if(*szwBuffer)
1019 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
1021 msi_free( szwComponent );
1023 return r;
1026 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
1028 UINT rc, index;
1029 HKEY compkey, prodkey;
1030 WCHAR squashed_comp[SQUASHED_GUID_SIZE], squashed_prod[SQUASHED_GUID_SIZE];
1031 DWORD sz = ARRAY_SIZE(squashed_prod);
1033 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer);
1035 if (!szComponent || !*szComponent)
1036 return ERROR_INVALID_PARAMETER;
1038 if (!squash_guid( szComponent, squashed_comp ))
1039 return ERROR_INVALID_PARAMETER;
1041 if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &compkey, FALSE) != ERROR_SUCCESS &&
1042 MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &compkey, FALSE) != ERROR_SUCCESS)
1044 return ERROR_UNKNOWN_COMPONENT;
1047 rc = RegEnumValueW( compkey, 0, squashed_prod, &sz, NULL, NULL, NULL, NULL );
1048 if (rc != ERROR_SUCCESS)
1050 RegCloseKey(compkey);
1051 return ERROR_UNKNOWN_COMPONENT;
1054 /* check simple case, only one product */
1055 rc = RegEnumValueW( compkey, 1, squashed_prod, &sz, NULL, NULL, NULL, NULL );
1056 if (rc == ERROR_NO_MORE_ITEMS)
1058 rc = ERROR_SUCCESS;
1059 goto done;
1062 index = 0;
1063 while ((rc = RegEnumValueW( compkey, index, squashed_prod, &sz, NULL, NULL, NULL, NULL )) !=
1064 ERROR_NO_MORE_ITEMS)
1066 index++;
1067 sz = GUID_SIZE;
1068 unsquash_guid( squashed_prod, szBuffer );
1070 if (MSIREG_OpenProductKey(szBuffer, NULL,
1071 MSIINSTALLCONTEXT_USERMANAGED,
1072 &prodkey, FALSE) == ERROR_SUCCESS ||
1073 MSIREG_OpenProductKey(szBuffer, NULL,
1074 MSIINSTALLCONTEXT_USERUNMANAGED,
1075 &prodkey, FALSE) == ERROR_SUCCESS ||
1076 MSIREG_OpenProductKey(szBuffer, NULL,
1077 MSIINSTALLCONTEXT_MACHINE,
1078 &prodkey, FALSE) == ERROR_SUCCESS)
1080 RegCloseKey(prodkey);
1081 rc = ERROR_SUCCESS;
1082 goto done;
1086 rc = ERROR_INSTALL_FAILURE;
1088 done:
1089 RegCloseKey(compkey);
1090 unsquash_guid( squashed_prod, szBuffer );
1091 return rc;
1094 static WCHAR *reg_get_value( HKEY hkey, const WCHAR *name, DWORD *type )
1096 LONG res;
1098 if ((res = RegQueryValueExW( hkey, name, NULL, type, NULL, NULL )) != ERROR_SUCCESS) return NULL;
1100 if (*type == REG_SZ) return msi_reg_get_val_str( hkey, name );
1101 if (*type == REG_DWORD)
1103 static const WCHAR fmt[] = {'%','u',0};
1104 WCHAR temp[11];
1105 DWORD val;
1107 if (!msi_reg_get_val_dword( hkey, name, &val )) return NULL;
1108 swprintf( temp, ARRAY_SIZE(temp), fmt, val );
1109 return strdupW( temp );
1112 ERR( "unhandled value type %u\n", *type );
1113 return NULL;
1116 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
1117 awstring *szValue, LPDWORD pcchValueBuf)
1119 static WCHAR empty[] = {0};
1120 static const WCHAR sourcelist[] = {'S','o','u','r','c','e','L','i','s','t',0};
1121 static const WCHAR display_name[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
1122 static const WCHAR display_version[] = {'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1123 static const WCHAR assignment[] = {'A','s','s','i','g','n','m','e','n','t',0};
1124 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
1125 UINT r = ERROR_UNKNOWN_PROPERTY;
1126 HKEY prodkey, userdata, source;
1127 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE], packagecode[GUID_SIZE];
1128 BOOL badconfig = FALSE;
1129 LONG res;
1130 DWORD type = REG_NONE;
1132 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1133 debugstr_w(szAttribute), szValue, pcchValueBuf);
1135 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
1136 return ERROR_INVALID_PARAMETER;
1138 if (!squash_guid( szProduct, squashed_pc ))
1139 return ERROR_INVALID_PARAMETER;
1141 if ((r = MSIREG_OpenProductKey(szProduct, NULL,
1142 MSIINSTALLCONTEXT_USERMANAGED,
1143 &prodkey, FALSE)) != ERROR_SUCCESS &&
1144 (r = MSIREG_OpenProductKey(szProduct, NULL,
1145 MSIINSTALLCONTEXT_USERUNMANAGED,
1146 &prodkey, FALSE)) != ERROR_SUCCESS &&
1147 (r = MSIREG_OpenProductKey(szProduct, NULL,
1148 MSIINSTALLCONTEXT_MACHINE,
1149 &prodkey, FALSE)) == ERROR_SUCCESS)
1151 context = MSIINSTALLCONTEXT_MACHINE;
1154 if (!wcscmp( szAttribute, INSTALLPROPERTY_HELPLINKW ) ||
1155 !wcscmp( szAttribute, INSTALLPROPERTY_HELPTELEPHONEW ) ||
1156 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLDATEW ) ||
1157 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
1158 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
1159 !wcscmp( szAttribute, INSTALLPROPERTY_INSTALLSOURCEW ) ||
1160 !wcscmp( szAttribute, INSTALLPROPERTY_LOCALPACKAGEW ) ||
1161 !wcscmp( szAttribute, INSTALLPROPERTY_PUBLISHERW ) ||
1162 !wcscmp( szAttribute, INSTALLPROPERTY_URLINFOABOUTW ) ||
1163 !wcscmp( szAttribute, INSTALLPROPERTY_URLUPDATEINFOW ) ||
1164 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONMINORW ) ||
1165 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONMAJORW ) ||
1166 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ) ||
1167 !wcscmp( szAttribute, INSTALLPROPERTY_PRODUCTIDW ) ||
1168 !wcscmp( szAttribute, INSTALLPROPERTY_REGCOMPANYW ) ||
1169 !wcscmp( szAttribute, INSTALLPROPERTY_REGOWNERW ))
1171 if (!prodkey)
1173 r = ERROR_UNKNOWN_PRODUCT;
1174 goto done;
1176 if (MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE))
1178 r = ERROR_UNKNOWN_PROPERTY;
1179 goto done;
1182 if (!wcscmp( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
1183 szAttribute = display_name;
1184 else if (!wcscmp( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
1185 szAttribute = display_version;
1187 val = reg_get_value(userdata, szAttribute, &type);
1188 if (!val)
1189 val = empty;
1190 RegCloseKey(userdata);
1192 else if (!wcscmp( szAttribute, INSTALLPROPERTY_INSTANCETYPEW ) ||
1193 !wcscmp( szAttribute, INSTALLPROPERTY_TRANSFORMSW ) ||
1194 !wcscmp( szAttribute, INSTALLPROPERTY_LANGUAGEW ) ||
1195 !wcscmp( szAttribute, INSTALLPROPERTY_PRODUCTNAMEW ) ||
1196 !wcscmp( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ) ||
1197 !wcscmp( szAttribute, INSTALLPROPERTY_PACKAGECODEW ) ||
1198 !wcscmp( szAttribute, INSTALLPROPERTY_VERSIONW ) ||
1199 !wcscmp( szAttribute, INSTALLPROPERTY_PRODUCTICONW ) ||
1200 !wcscmp( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ) ||
1201 !wcscmp( szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
1203 if (!prodkey)
1205 r = ERROR_UNKNOWN_PRODUCT;
1206 goto done;
1209 if (!wcscmp( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
1210 szAttribute = assignment;
1212 if (!wcscmp( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ))
1214 res = RegOpenKeyW(prodkey, sourcelist, &source);
1215 if (res != ERROR_SUCCESS)
1217 r = ERROR_UNKNOWN_PRODUCT;
1218 goto done;
1221 val = reg_get_value(source, szAttribute, &type);
1222 if (!val)
1223 val = empty;
1225 RegCloseKey(source);
1227 else
1229 val = reg_get_value(prodkey, szAttribute, &type);
1230 if (!val)
1231 val = empty;
1234 if (val != empty && type != REG_DWORD &&
1235 !wcscmp( szAttribute, INSTALLPROPERTY_PACKAGECODEW ))
1237 if (lstrlenW( val ) != SQUASHED_GUID_SIZE - 1)
1238 badconfig = TRUE;
1239 else
1241 unsquash_guid(val, packagecode);
1242 msi_free(val);
1243 val = strdupW(packagecode);
1248 if (!val)
1250 r = ERROR_UNKNOWN_PROPERTY;
1251 goto done;
1254 if (pcchValueBuf)
1256 int len = lstrlenW( val );
1258 /* If szBuffer (szValue->str) is NULL, there's no need to copy the value
1259 * out. Also, *pcchValueBuf may be uninitialized in this case, so we
1260 * can't rely on its value.
1262 if (szValue->str.a || szValue->str.w)
1264 DWORD size = *pcchValueBuf;
1265 if (len < size)
1266 r = msi_strcpy_to_awstring( val, len, szValue, &size );
1267 else
1268 r = ERROR_MORE_DATA;
1271 if (!badconfig)
1272 *pcchValueBuf = len;
1275 if (badconfig)
1276 r = ERROR_BAD_CONFIGURATION;
1278 if (val != empty)
1279 msi_free(val);
1281 done:
1282 RegCloseKey(prodkey);
1283 return r;
1286 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
1287 LPSTR szBuffer, LPDWORD pcchValueBuf)
1289 LPWSTR szwProduct, szwAttribute = NULL;
1290 UINT r = ERROR_OUTOFMEMORY;
1291 awstring buffer;
1293 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
1294 szBuffer, pcchValueBuf);
1296 szwProduct = strdupAtoW( szProduct );
1297 if( szProduct && !szwProduct )
1298 goto end;
1300 szwAttribute = strdupAtoW( szAttribute );
1301 if( szAttribute && !szwAttribute )
1302 goto end;
1304 buffer.unicode = FALSE;
1305 buffer.str.a = szBuffer;
1307 r = MSI_GetProductInfo( szwProduct, szwAttribute,
1308 &buffer, pcchValueBuf );
1310 end:
1311 msi_free( szwProduct );
1312 msi_free( szwAttribute );
1314 return r;
1317 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
1318 LPWSTR szBuffer, LPDWORD pcchValueBuf)
1320 awstring buffer;
1322 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
1323 szBuffer, pcchValueBuf);
1325 buffer.unicode = TRUE;
1326 buffer.str.w = szBuffer;
1328 return MSI_GetProductInfo( szProduct, szAttribute,
1329 &buffer, pcchValueBuf );
1332 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
1333 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
1334 LPSTR szValue, LPDWORD pcchValue)
1336 LPWSTR product = NULL;
1337 LPWSTR usersid = NULL;
1338 LPWSTR property = NULL;
1339 LPWSTR value = NULL;
1340 DWORD len = 0;
1341 UINT r;
1343 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
1344 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
1345 szValue, pcchValue);
1347 if (szValue && !pcchValue)
1348 return ERROR_INVALID_PARAMETER;
1350 if (szProductCode) product = strdupAtoW(szProductCode);
1351 if (szUserSid) usersid = strdupAtoW(szUserSid);
1352 if (szProperty) property = strdupAtoW(szProperty);
1354 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1355 NULL, &len);
1356 if (r != ERROR_SUCCESS)
1357 goto done;
1359 value = msi_alloc(++len * sizeof(WCHAR));
1360 if (!value)
1362 r = ERROR_OUTOFMEMORY;
1363 goto done;
1366 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1367 value, &len);
1368 if (r != ERROR_SUCCESS)
1369 goto done;
1371 if (!pcchValue)
1372 goto done;
1374 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
1375 if (*pcchValue >= len)
1376 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
1377 else if (szValue)
1379 r = ERROR_MORE_DATA;
1380 if (*pcchValue > 0)
1381 *szValue = '\0';
1384 if (*pcchValue <= len || !szValue)
1385 len = len * sizeof(WCHAR) - 1;
1387 *pcchValue = len - 1;
1389 done:
1390 msi_free(product);
1391 msi_free(usersid);
1392 msi_free(property);
1393 msi_free(value);
1395 return r;
1398 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
1400 UINT r = ERROR_SUCCESS;
1402 if (!val)
1403 return ERROR_UNKNOWN_PROPERTY;
1405 if (out)
1407 if (lstrlenW(val) >= *size)
1409 r = ERROR_MORE_DATA;
1410 if (*size > 0)
1411 *out = '\0';
1413 else
1414 lstrcpyW(out, val);
1417 if (size)
1418 *size = lstrlenW(val);
1420 return r;
1423 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
1424 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
1425 LPWSTR szValue, LPDWORD pcchValue)
1427 static const WCHAR five[] = {'5',0};
1428 static const WCHAR displayname[] = {
1429 'D','i','s','p','l','a','y','N','a','m','e',0};
1430 static const WCHAR displayversion[] = {
1431 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1432 static const WCHAR managed_local_package[] = {
1433 'M','a','n','a','g','e','d','L','o','c','a','l',
1434 'P','a','c','k','a','g','e',0};
1435 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE];
1436 LPCWSTR package = NULL;
1437 HKEY props = NULL, prod, classes = NULL, managed, hkey = NULL;
1438 DWORD type;
1439 UINT r = ERROR_UNKNOWN_PRODUCT;
1441 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
1442 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
1443 szValue, pcchValue);
1445 if (!szProductCode || !squash_guid( szProductCode, squashed_pc ))
1446 return ERROR_INVALID_PARAMETER;
1448 if (szValue && !pcchValue)
1449 return ERROR_INVALID_PARAMETER;
1451 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1452 dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1453 dwContext != MSIINSTALLCONTEXT_MACHINE)
1454 return ERROR_INVALID_PARAMETER;
1456 if (!szProperty || !*szProperty)
1457 return ERROR_INVALID_PARAMETER;
1459 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1460 return ERROR_INVALID_PARAMETER;
1462 /* FIXME: dwContext is provided, no need to search for it */
1463 MSIREG_OpenProductKey(szProductCode, NULL,MSIINSTALLCONTEXT_USERMANAGED,
1464 &managed, FALSE);
1465 MSIREG_OpenProductKey(szProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1466 &prod, FALSE);
1468 MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE);
1470 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1472 package = INSTALLPROPERTY_LOCALPACKAGEW;
1474 if (!props && !prod)
1475 goto done;
1477 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1479 package = managed_local_package;
1481 if (!props && !managed)
1482 goto done;
1484 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1486 package = INSTALLPROPERTY_LOCALPACKAGEW;
1487 MSIREG_OpenProductKey(szProductCode, NULL, dwContext, &classes, FALSE);
1489 if (!props && !classes)
1490 goto done;
1493 if (!wcscmp( szProperty, INSTALLPROPERTY_HELPLINKW ) ||
1494 !wcscmp( szProperty, INSTALLPROPERTY_HELPTELEPHONEW ) ||
1495 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLDATEW ) ||
1496 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
1497 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
1498 !wcscmp( szProperty, INSTALLPROPERTY_INSTALLSOURCEW ) ||
1499 !wcscmp( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ) ||
1500 !wcscmp( szProperty, INSTALLPROPERTY_PUBLISHERW ) ||
1501 !wcscmp( szProperty, INSTALLPROPERTY_URLINFOABOUTW ) ||
1502 !wcscmp( szProperty, INSTALLPROPERTY_URLUPDATEINFOW ) ||
1503 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONMINORW ) ||
1504 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONMAJORW ) ||
1505 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ) ||
1506 !wcscmp( szProperty, INSTALLPROPERTY_PRODUCTIDW ) ||
1507 !wcscmp( szProperty, INSTALLPROPERTY_REGCOMPANYW ) ||
1508 !wcscmp( szProperty, INSTALLPROPERTY_REGOWNERW ) ||
1509 !wcscmp( szProperty, INSTALLPROPERTY_INSTANCETYPEW ))
1511 val = reg_get_value(props, package, &type);
1512 if (!val)
1514 if (prod || classes)
1515 r = ERROR_UNKNOWN_PROPERTY;
1517 goto done;
1520 msi_free(val);
1522 if (!wcscmp( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
1523 szProperty = displayname;
1524 else if (!wcscmp( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ))
1525 szProperty = displayversion;
1527 val = reg_get_value(props, szProperty, &type);
1528 if (!val)
1529 val = strdupW(szEmpty);
1531 r = msi_copy_outval(val, szValue, pcchValue);
1533 else if (!wcscmp( szProperty, INSTALLPROPERTY_TRANSFORMSW ) ||
1534 !wcscmp( szProperty, INSTALLPROPERTY_LANGUAGEW ) ||
1535 !wcscmp( szProperty, INSTALLPROPERTY_PRODUCTNAMEW ) ||
1536 !wcscmp( szProperty, INSTALLPROPERTY_PACKAGECODEW ) ||
1537 !wcscmp( szProperty, INSTALLPROPERTY_VERSIONW ) ||
1538 !wcscmp( szProperty, INSTALLPROPERTY_PRODUCTICONW ) ||
1539 !wcscmp( szProperty, INSTALLPROPERTY_PACKAGENAMEW ) ||
1540 !wcscmp( szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
1542 if (!prod && !classes)
1543 goto done;
1545 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1546 hkey = prod;
1547 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1548 hkey = managed;
1549 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1550 hkey = classes;
1552 val = reg_get_value(hkey, szProperty, &type);
1553 if (!val)
1554 val = strdupW(szEmpty);
1556 r = msi_copy_outval(val, szValue, pcchValue);
1558 else if (!wcscmp( szProperty, INSTALLPROPERTY_PRODUCTSTATEW ))
1560 if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1562 if (props)
1564 val = reg_get_value(props, package, &type);
1565 if (!val)
1566 goto done;
1568 msi_free(val);
1569 val = strdupW(five);
1571 else
1572 val = strdupW(szOne);
1574 r = msi_copy_outval(val, szValue, pcchValue);
1575 goto done;
1577 else if (props && (val = reg_get_value(props, package, &type)))
1579 msi_free(val);
1580 val = strdupW(five);
1581 r = msi_copy_outval(val, szValue, pcchValue);
1582 goto done;
1585 if (prod || managed)
1586 val = strdupW(szOne);
1587 else
1588 goto done;
1590 r = msi_copy_outval(val, szValue, pcchValue);
1592 else if (!wcscmp( szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
1594 if (!prod && !classes)
1595 goto done;
1597 /* FIXME */
1598 val = strdupW(szEmpty);
1599 r = msi_copy_outval(val, szValue, pcchValue);
1601 else
1602 r = ERROR_UNKNOWN_PROPERTY;
1604 done:
1605 RegCloseKey(props);
1606 RegCloseKey(prod);
1607 RegCloseKey(managed);
1608 RegCloseKey(classes);
1609 msi_free(val);
1611 return r;
1614 UINT WINAPI MsiGetPatchFileListA(LPCSTR szProductCode, LPCSTR szPatchList,
1615 LPDWORD pcFiles, MSIHANDLE **pphFileRecords)
1617 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_a(szProductCode),
1618 debugstr_a(szPatchList), pcFiles, pphFileRecords);
1619 return ERROR_FUNCTION_FAILED;
1622 UINT WINAPI MsiGetPatchFileListW(LPCWSTR szProductCode, LPCWSTR szPatchList,
1623 LPDWORD pcFiles, MSIHANDLE **pphFileRecords)
1625 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_w(szProductCode),
1626 debugstr_w(szPatchList), pcFiles, pphFileRecords);
1627 return ERROR_FUNCTION_FAILED;
1630 UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode,
1631 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1632 LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
1634 LPWSTR patch = NULL, product = NULL, usersid = NULL;
1635 LPWSTR property = NULL, val = NULL;
1636 DWORD len;
1637 UINT r;
1639 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode),
1640 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext,
1641 debugstr_a(szProperty), lpValue, pcchValue);
1643 if (lpValue && !pcchValue)
1644 return ERROR_INVALID_PARAMETER;
1646 if (szPatchCode) patch = strdupAtoW(szPatchCode);
1647 if (szProductCode) product = strdupAtoW(szProductCode);
1648 if (szUserSid) usersid = strdupAtoW(szUserSid);
1649 if (szProperty) property = strdupAtoW(szProperty);
1651 len = 0;
1652 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1653 NULL, &len);
1654 if (r != ERROR_SUCCESS)
1655 goto done;
1657 val = msi_alloc(++len * sizeof(WCHAR));
1658 if (!val)
1660 r = ERROR_OUTOFMEMORY;
1661 goto done;
1664 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1665 val, &len);
1666 if (r != ERROR_SUCCESS || !pcchValue)
1667 goto done;
1669 if (lpValue)
1670 WideCharToMultiByte(CP_ACP, 0, val, -1, lpValue,
1671 *pcchValue - 1, NULL, NULL);
1673 len = lstrlenW(val);
1674 if ((*val && *pcchValue < len + 1) || !lpValue)
1676 if (lpValue)
1678 r = ERROR_MORE_DATA;
1679 lpValue[*pcchValue - 1] = '\0';
1682 *pcchValue = len * sizeof(WCHAR);
1684 else
1685 *pcchValue = len;
1687 done:
1688 msi_free(val);
1689 msi_free(patch);
1690 msi_free(product);
1691 msi_free(usersid);
1692 msi_free(property);
1694 return r;
1697 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
1698 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1699 LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue)
1701 static const WCHAR szManagedPackage[] =
1702 {'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
1703 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE], squashed_patch[SQUASHED_GUID_SIZE];
1704 HKEY udprod = 0, prod = 0, props = 0;
1705 HKEY patch = 0, patches = 0;
1706 HKEY udpatch = 0, datakey = 0;
1707 HKEY prodpatches = 0;
1708 UINT r = ERROR_UNKNOWN_PRODUCT;
1709 DWORD len, type;
1710 LONG res;
1712 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode),
1713 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext,
1714 debugstr_w(szProperty), lpValue, pcchValue);
1716 if (!szProductCode || !squash_guid( szProductCode, squashed_pc ))
1717 return ERROR_INVALID_PARAMETER;
1719 if (!szPatchCode || !squash_guid( szPatchCode, squashed_patch ))
1720 return ERROR_INVALID_PARAMETER;
1722 if (!szProperty)
1723 return ERROR_INVALID_PARAMETER;
1725 if (lpValue && !pcchValue)
1726 return ERROR_INVALID_PARAMETER;
1728 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1729 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1730 dwContext != MSIINSTALLCONTEXT_MACHINE)
1731 return ERROR_INVALID_PARAMETER;
1733 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1734 return ERROR_INVALID_PARAMETER;
1736 if (szUserSid && !wcscmp( szUserSid, szLocalSid ))
1737 return ERROR_INVALID_PARAMETER;
1739 if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
1740 &udprod, FALSE) != ERROR_SUCCESS)
1741 goto done;
1743 if (MSIREG_OpenInstallProps(szProductCode, dwContext, NULL,
1744 &props, FALSE) != ERROR_SUCCESS)
1745 goto done;
1747 r = ERROR_UNKNOWN_PATCH;
1749 res = RegOpenKeyExW(udprod, szPatches, 0, KEY_READ, &patches);
1750 if (res != ERROR_SUCCESS)
1751 goto done;
1753 res = RegOpenKeyExW( patches, squashed_patch, 0, KEY_READ, &patch );
1754 if (res != ERROR_SUCCESS)
1755 goto done;
1757 if (!wcscmp( szProperty, INSTALLPROPERTY_TRANSFORMSW ))
1759 if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
1760 &prod, FALSE) != ERROR_SUCCESS)
1761 goto done;
1763 res = RegOpenKeyExW(prod, szPatches, 0, KEY_ALL_ACCESS, &prodpatches);
1764 if (res != ERROR_SUCCESS)
1765 goto done;
1767 datakey = prodpatches;
1768 szProperty = squashed_patch;
1770 else
1772 if (MSIREG_OpenUserDataPatchKey(szPatchCode, dwContext,
1773 &udpatch, FALSE) != ERROR_SUCCESS)
1774 goto done;
1776 if (!wcscmp( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
1778 if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1779 szProperty = szManagedPackage;
1780 datakey = udpatch;
1782 else if (!wcscmp( szProperty, INSTALLPROPERTY_INSTALLDATEW ))
1784 datakey = patch;
1785 szProperty = szInstalled;
1787 else if (!wcscmp( szProperty, INSTALLPROPERTY_UNINSTALLABLEW ) ||
1788 !wcscmp( szProperty, INSTALLPROPERTY_PATCHSTATEW ) ||
1789 !wcscmp( szProperty, INSTALLPROPERTY_DISPLAYNAMEW ) ||
1790 !wcscmp( szProperty, INSTALLPROPERTY_MOREINFOURLW ))
1792 datakey = patch;
1794 else
1796 r = ERROR_UNKNOWN_PROPERTY;
1797 goto done;
1801 val = reg_get_value(datakey, szProperty, &type);
1802 if (!val)
1803 val = strdupW(szEmpty);
1805 r = ERROR_SUCCESS;
1807 if (!pcchValue)
1808 goto done;
1810 if (lpValue)
1811 lstrcpynW(lpValue, val, *pcchValue);
1813 len = lstrlenW(val);
1814 if ((*val && *pcchValue < len + 1) || !lpValue)
1816 if (lpValue)
1817 r = ERROR_MORE_DATA;
1819 *pcchValue = len * sizeof(WCHAR);
1822 *pcchValue = len;
1824 done:
1825 msi_free(val);
1826 RegCloseKey(prodpatches);
1827 RegCloseKey(prod);
1828 RegCloseKey(patch);
1829 RegCloseKey(patches);
1830 RegCloseKey(udpatch);
1831 RegCloseKey(props);
1832 RegCloseKey(udprod);
1834 return r;
1837 UINT WINAPI MsiGetPatchInfoA( LPCSTR patch, LPCSTR attr, LPSTR buffer, LPDWORD buflen )
1839 UINT r = ERROR_OUTOFMEMORY;
1840 DWORD size;
1841 LPWSTR patchW = NULL, attrW = NULL, bufferW = NULL;
1843 TRACE("%s %s %p %p\n", debugstr_a(patch), debugstr_a(attr), buffer, buflen);
1845 if (!patch || !attr)
1846 return ERROR_INVALID_PARAMETER;
1848 if (!(patchW = strdupAtoW( patch )))
1849 goto done;
1851 if (!(attrW = strdupAtoW( attr )))
1852 goto done;
1854 size = 0;
1855 r = MsiGetPatchInfoW( patchW, attrW, NULL, &size );
1856 if (r != ERROR_SUCCESS)
1857 goto done;
1859 size++;
1860 if (!(bufferW = msi_alloc( size * sizeof(WCHAR) )))
1862 r = ERROR_OUTOFMEMORY;
1863 goto done;
1866 r = MsiGetPatchInfoW( patchW, attrW, bufferW, &size );
1867 if (r == ERROR_SUCCESS)
1869 int len = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
1870 if (len > *buflen)
1871 r = ERROR_MORE_DATA;
1872 else if (buffer)
1873 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL );
1875 *buflen = len - 1;
1878 done:
1879 msi_free( patchW );
1880 msi_free( attrW );
1881 msi_free( bufferW );
1882 return r;
1885 UINT WINAPI MsiGetPatchInfoW( LPCWSTR patch, LPCWSTR attr, LPWSTR buffer, LPDWORD buflen )
1887 UINT r;
1888 WCHAR product[GUID_SIZE];
1889 DWORD index;
1891 TRACE("%s %s %p %p\n", debugstr_w(patch), debugstr_w(attr), buffer, buflen);
1893 if (!patch || !attr)
1894 return ERROR_INVALID_PARAMETER;
1896 if (wcscmp( INSTALLPROPERTY_LOCALPACKAGEW, attr ))
1897 return ERROR_UNKNOWN_PROPERTY;
1899 index = 0;
1900 while (1)
1902 r = MsiEnumProductsW( index, product );
1903 if (r != ERROR_SUCCESS)
1904 break;
1906 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERMANAGED, attr, buffer, buflen );
1907 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
1908 return r;
1910 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, attr, buffer, buflen );
1911 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
1912 return r;
1914 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_MACHINE, attr, buffer, buflen );
1915 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
1916 return r;
1918 index++;
1921 return ERROR_UNKNOWN_PRODUCT;
1924 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
1926 LPWSTR szwLogFile = NULL;
1927 UINT r;
1929 TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
1931 if( szLogFile )
1933 szwLogFile = strdupAtoW( szLogFile );
1934 if( !szwLogFile )
1935 return ERROR_OUTOFMEMORY;
1937 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
1938 msi_free( szwLogFile );
1939 return r;
1942 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
1944 TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
1946 msi_free(gszLogFile);
1947 gszLogFile = NULL;
1948 if (szLogFile)
1950 HANDLE file;
1952 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
1953 DeleteFileW(szLogFile);
1954 file = CreateFileW(szLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
1955 FILE_ATTRIBUTE_NORMAL, NULL);
1956 if (file != INVALID_HANDLE_VALUE)
1958 gszLogFile = strdupW(szLogFile);
1959 CloseHandle(file);
1961 else
1962 ERR("Unable to enable log %s (%u)\n", debugstr_w(szLogFile), GetLastError());
1965 return ERROR_SUCCESS;
1968 UINT WINAPI MsiEnumComponentCostsA( MSIHANDLE handle, LPCSTR component, DWORD index,
1969 INSTALLSTATE state, LPSTR drive, DWORD *buflen,
1970 int *cost, int *temp )
1972 UINT r;
1973 DWORD len;
1974 WCHAR *driveW, *componentW = NULL;
1976 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle, debugstr_a(component), index,
1977 state, drive, buflen, cost, temp);
1979 if (!drive || !buflen) return ERROR_INVALID_PARAMETER;
1980 if (component && !(componentW = strdupAtoW( component ))) return ERROR_OUTOFMEMORY;
1982 len = *buflen;
1983 if (!(driveW = msi_alloc( len * sizeof(WCHAR) )))
1985 msi_free( componentW );
1986 return ERROR_OUTOFMEMORY;
1988 r = MsiEnumComponentCostsW( handle, componentW, index, state, driveW, buflen, cost, temp );
1989 if (!r)
1991 WideCharToMultiByte( CP_ACP, 0, driveW, -1, drive, len, NULL, NULL );
1993 msi_free( componentW );
1994 msi_free( driveW );
1995 return r;
1998 static UINT set_drive( WCHAR *buffer, WCHAR letter )
2000 buffer[0] = letter;
2001 buffer[1] = ':';
2002 buffer[2] = 0;
2003 return 2;
2006 UINT WINAPI MsiEnumComponentCostsW( MSIHANDLE handle, LPCWSTR component, DWORD index,
2007 INSTALLSTATE state, LPWSTR drive, DWORD *buflen,
2008 int *cost, int *temp )
2010 UINT r = ERROR_NO_MORE_ITEMS;
2011 MSICOMPONENT *comp = NULL;
2012 MSIPACKAGE *package;
2013 MSIFILE *file;
2014 STATSTG stat = {0};
2015 WCHAR path[MAX_PATH];
2017 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle, debugstr_w(component), index,
2018 state, drive, buflen, cost, temp);
2020 if (!drive || !buflen || !cost || !temp) return ERROR_INVALID_PARAMETER;
2021 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
2023 WCHAR buffer[3];
2024 MSIHANDLE remote;
2026 if (!(remote = msi_get_remote(handle)))
2027 return ERROR_INVALID_HANDLE;
2029 __TRY
2031 r = remote_EnumComponentCosts(remote, component, index, state, buffer, cost, temp);
2033 __EXCEPT(rpc_filter)
2035 r = GetExceptionCode();
2037 __ENDTRY
2039 if (r == ERROR_SUCCESS)
2041 lstrcpynW(drive, buffer, *buflen);
2042 if (*buflen < 3)
2043 r = ERROR_MORE_DATA;
2044 *buflen = 2;
2046 return r;
2049 if (!msi_get_property_int( package->db, szCostingComplete, 0 ))
2051 msiobj_release( &package->hdr );
2052 return ERROR_FUNCTION_NOT_CALLED;
2054 if (component && component[0] && !(comp = msi_get_loaded_component( package, component )))
2056 msiobj_release( &package->hdr );
2057 return ERROR_UNKNOWN_COMPONENT;
2059 if (*buflen < 3)
2061 *buflen = 2;
2062 msiobj_release( &package->hdr );
2063 return ERROR_MORE_DATA;
2065 if (index)
2067 msiobj_release( &package->hdr );
2068 return ERROR_NO_MORE_ITEMS;
2071 drive[0] = 0;
2072 *cost = *temp = 0;
2073 GetWindowsDirectoryW( path, MAX_PATH );
2074 if (component && component[0])
2076 if (msi_is_global_assembly( comp )) *temp = comp->Cost;
2077 if (!comp->Enabled || !comp->KeyPath)
2079 *cost = 0;
2080 *buflen = set_drive( drive, path[0] );
2081 r = ERROR_SUCCESS;
2083 else if ((file = msi_get_loaded_file( package, comp->KeyPath )))
2085 *cost = max( 8, comp->Cost / 512 );
2086 *buflen = set_drive( drive, file->TargetPath[0] );
2087 r = ERROR_SUCCESS;
2090 else if (IStorage_Stat( package->db->storage, &stat, STATFLAG_NONAME ) == S_OK)
2092 *temp = max( 8, stat.cbSize.QuadPart / 512 );
2093 *buflen = set_drive( drive, path[0] );
2094 r = ERROR_SUCCESS;
2096 msiobj_release( &package->hdr );
2097 return r;
2100 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
2101 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
2102 LPCSTR szComponent, INSTALLSTATE *pdwState)
2104 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL;
2105 UINT r;
2107 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode),
2108 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
2110 if (szProductCode && !(prodcode = strdupAtoW(szProductCode)))
2111 return ERROR_OUTOFMEMORY;
2113 if (szUserSid && !(usersid = strdupAtoW(szUserSid)))
2114 return ERROR_OUTOFMEMORY;
2116 if (szComponent && !(comp = strdupAtoW(szComponent)))
2117 return ERROR_OUTOFMEMORY;
2119 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState);
2121 msi_free(prodcode);
2122 msi_free(usersid);
2123 msi_free(comp);
2125 return r;
2128 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
2130 UINT r;
2131 HKEY hkey = NULL;
2133 r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE);
2134 RegCloseKey(hkey);
2135 return (r == ERROR_SUCCESS);
2138 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
2140 LPCWSTR package;
2141 HKEY hkey;
2142 DWORD sz;
2143 LONG res;
2144 UINT r;
2146 static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
2147 static const WCHAR managed_local_package[] = {
2148 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
2151 r = MSIREG_OpenInstallProps(prodcode, context, NULL, &hkey, FALSE);
2152 if (r != ERROR_SUCCESS)
2153 return FALSE;
2155 if (context == MSIINSTALLCONTEXT_USERMANAGED)
2156 package = managed_local_package;
2157 else
2158 package = local_package;
2160 sz = 0;
2161 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
2162 RegCloseKey(hkey);
2164 return (res == ERROR_SUCCESS);
2167 static UINT msi_comp_find_prodcode(WCHAR *squashed_pc,
2168 MSIINSTALLCONTEXT context,
2169 LPCWSTR comp, LPWSTR val, DWORD *sz)
2171 HKEY hkey;
2172 LONG res;
2173 UINT r;
2175 if (context == MSIINSTALLCONTEXT_MACHINE)
2176 r = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
2177 else
2178 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
2180 if (r != ERROR_SUCCESS)
2181 return r;
2183 res = RegQueryValueExW( hkey, squashed_pc, NULL, NULL, (BYTE *)val, sz );
2184 if (res != ERROR_SUCCESS)
2185 return res;
2187 RegCloseKey(hkey);
2188 return res;
2191 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
2192 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
2193 LPCWSTR szComponent, INSTALLSTATE *pdwState)
2195 WCHAR squashed_pc[SQUASHED_GUID_SIZE];
2196 BOOL found;
2197 DWORD sz;
2199 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
2200 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
2202 if (!pdwState || !szComponent)
2203 return ERROR_INVALID_PARAMETER;
2205 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1)
2206 return ERROR_INVALID_PARAMETER;
2208 if (!squash_guid( szProductCode, squashed_pc ))
2209 return ERROR_INVALID_PARAMETER;
2211 found = msi_comp_find_prod_key(szProductCode, dwContext);
2213 if (!msi_comp_find_package(szProductCode, dwContext))
2215 if (found)
2217 *pdwState = INSTALLSTATE_UNKNOWN;
2218 return ERROR_UNKNOWN_COMPONENT;
2221 return ERROR_UNKNOWN_PRODUCT;
2224 *pdwState = INSTALLSTATE_UNKNOWN;
2226 sz = 0;
2227 if (msi_comp_find_prodcode( squashed_pc, dwContext, szComponent, NULL, &sz ))
2228 return ERROR_UNKNOWN_COMPONENT;
2230 if (sz == 0)
2231 *pdwState = INSTALLSTATE_NOTUSED;
2232 else
2234 WCHAR *val;
2235 UINT r;
2237 if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY;
2238 if ((r = msi_comp_find_prodcode( squashed_pc, dwContext, szComponent, val, &sz )))
2240 msi_free(val);
2241 return r;
2244 if (lstrlenW(val) > 2 &&
2245 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && val[2] != ':')
2247 *pdwState = INSTALLSTATE_SOURCE;
2249 else
2250 *pdwState = INSTALLSTATE_LOCAL;
2251 msi_free( val );
2254 TRACE("-> %d\n", *pdwState);
2255 return ERROR_SUCCESS;
2258 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
2260 LPWSTR szwProduct = NULL;
2261 INSTALLSTATE r;
2263 if( szProduct )
2265 szwProduct = strdupAtoW( szProduct );
2266 if( !szwProduct )
2267 return ERROR_OUTOFMEMORY;
2269 r = MsiQueryProductStateW( szwProduct );
2270 msi_free( szwProduct );
2271 return r;
2274 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
2276 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
2277 INSTALLSTATE state = INSTALLSTATE_ADVERTISED;
2278 HKEY prodkey = 0, userdata = 0;
2279 DWORD val;
2280 UINT r;
2282 TRACE("%s\n", debugstr_w(szProduct));
2284 if (!szProduct || !*szProduct)
2285 return INSTALLSTATE_INVALIDARG;
2287 if (lstrlenW(szProduct) != GUID_SIZE - 1)
2288 return INSTALLSTATE_INVALIDARG;
2290 if (szProduct[0] != '{' || szProduct[37] != '}')
2291 return INSTALLSTATE_UNKNOWN;
2293 SetLastError( ERROR_SUCCESS );
2295 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
2296 &prodkey, FALSE) != ERROR_SUCCESS &&
2297 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2298 &prodkey, FALSE) != ERROR_SUCCESS &&
2299 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2300 &prodkey, FALSE) == ERROR_SUCCESS)
2302 context = MSIINSTALLCONTEXT_MACHINE;
2305 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
2306 if (r != ERROR_SUCCESS)
2307 goto done;
2309 if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val))
2310 goto done;
2312 if (val)
2313 state = INSTALLSTATE_DEFAULT;
2314 else
2315 state = INSTALLSTATE_UNKNOWN;
2317 done:
2318 if (!prodkey)
2320 state = INSTALLSTATE_UNKNOWN;
2322 if (userdata)
2323 state = INSTALLSTATE_ABSENT;
2326 RegCloseKey(prodkey);
2327 RegCloseKey(userdata);
2328 TRACE("-> %d\n", state);
2329 return state;
2332 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
2334 INSTALLUILEVEL old = gUILevel;
2335 HWND oldwnd = gUIhwnd;
2337 TRACE("%08x %p\n", dwUILevel, phWnd);
2339 if (dwUILevel & ~(INSTALLUILEVEL_MASK|INSTALLUILEVEL_HIDECANCEL|INSTALLUILEVEL_PROGRESSONLY|
2340 INSTALLUILEVEL_ENDDIALOG|INSTALLUILEVEL_SOURCERESONLY))
2342 FIXME("Unrecognized flags %08x\n", dwUILevel);
2343 return INSTALLUILEVEL_NOCHANGE;
2346 if (dwUILevel != INSTALLUILEVEL_NOCHANGE)
2347 gUILevel = dwUILevel;
2349 if (phWnd)
2351 gUIhwnd = *phWnd;
2352 *phWnd = oldwnd;
2354 return old;
2357 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
2358 DWORD dwMessageFilter, LPVOID pvContext)
2360 INSTALLUI_HANDLERA prev = gUIHandlerA;
2362 TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext);
2364 gUIHandlerA = puiHandler;
2365 gUIHandlerW = NULL;
2366 gUIFilter = dwMessageFilter;
2367 gUIContext = pvContext;
2369 return prev;
2372 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
2373 DWORD dwMessageFilter, LPVOID pvContext)
2375 INSTALLUI_HANDLERW prev = gUIHandlerW;
2377 TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext);
2379 gUIHandlerA = NULL;
2380 gUIHandlerW = puiHandler;
2381 gUIFilter = dwMessageFilter;
2382 gUIContext = pvContext;
2384 return prev;
2387 /******************************************************************
2388 * MsiLoadStringW [MSI.@]
2390 * Loads a string from MSI's string resources.
2392 * PARAMS
2394 * handle [I] only -1 is handled currently
2395 * id [I] id of the string to be loaded
2396 * lpBuffer [O] buffer for the string to be written to
2397 * nBufferMax [I] maximum size of the buffer in characters
2398 * lang [I] the preferred language for the string
2400 * RETURNS
2402 * If successful, this function returns the language id of the string loaded
2403 * If the function fails, the function returns zero.
2405 * NOTES
2407 * The type of the first parameter is unknown. LoadString's prototype
2408 * suggests that it might be a module handle. I have made it an MSI handle
2409 * for starters, as -1 is an invalid MSI handle, but not an invalid module
2410 * handle. Maybe strings can be stored in an MSI database somehow.
2412 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
2413 int nBufferMax, LANGID lang )
2415 HRSRC hres;
2416 HGLOBAL hResData;
2417 LPWSTR p;
2418 DWORD i, len;
2420 TRACE("%d %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
2422 if( handle != -1 )
2423 FIXME("don't know how to deal with handle = %08x\n", handle);
2425 if( !lang )
2426 lang = GetUserDefaultLangID();
2428 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
2429 (LPWSTR)1, lang );
2430 if( !hres )
2431 return 0;
2432 hResData = LoadResource( msi_hInstance, hres );
2433 if( !hResData )
2434 return 0;
2435 p = LockResource( hResData );
2436 if( !p )
2437 return 0;
2439 for (i = 0; i < (id & 0xf); i++) p += *p + 1;
2440 len = *p;
2442 if( nBufferMax <= len )
2443 return 0;
2445 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
2446 lpBuffer[ len ] = 0;
2448 TRACE("found -> %s\n", debugstr_w(lpBuffer));
2449 return lang;
2452 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
2453 int nBufferMax, LANGID lang )
2455 LPWSTR bufW;
2456 LANGID r;
2457 INT len;
2459 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
2460 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
2461 if( r )
2463 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
2464 if( len <= nBufferMax )
2465 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
2466 lpBuffer, nBufferMax, NULL, NULL );
2467 else
2468 r = 0;
2470 msi_free(bufW);
2471 return r;
2474 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
2475 LPDWORD pcchBuf)
2477 char szProduct[GUID_SIZE];
2479 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
2481 if (!szComponent || !pcchBuf)
2482 return INSTALLSTATE_INVALIDARG;
2484 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
2485 return INSTALLSTATE_UNKNOWN;
2487 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
2490 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
2491 LPDWORD pcchBuf)
2493 WCHAR szProduct[GUID_SIZE];
2495 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
2497 if (!szComponent || !pcchBuf)
2498 return INSTALLSTATE_INVALIDARG;
2500 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
2501 return INSTALLSTATE_UNKNOWN;
2503 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
2506 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
2507 WORD wLanguageId, DWORD f)
2509 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
2510 uType, wLanguageId, f);
2511 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
2514 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
2515 WORD wLanguageId, DWORD f)
2517 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
2518 uType, wLanguageId, f);
2519 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
2522 UINT WINAPI MsiMessageBoxExA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
2523 DWORD unknown, WORD wLanguageId, DWORD f)
2525 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_a(lpText),
2526 debugstr_a(lpCaption), uType, unknown, wLanguageId, f);
2527 return MessageBoxExA(hWnd, lpText, lpCaption, uType, wLanguageId);
2530 UINT WINAPI MsiMessageBoxExW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
2531 DWORD unknown, WORD wLanguageId, DWORD f)
2533 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_w(lpText),
2534 debugstr_w(lpCaption), uType, unknown, wLanguageId, f);
2535 return MessageBoxExW(hWnd, lpText, lpCaption, uType, wLanguageId);
2538 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
2539 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
2540 LPDWORD pcchPathBuf )
2542 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
2543 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2544 pcchPathBuf);
2545 return ERROR_CALL_NOT_IMPLEMENTED;
2548 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
2549 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
2550 LPDWORD pcchPathBuf )
2552 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
2553 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2554 pcchPathBuf);
2555 return ERROR_CALL_NOT_IMPLEMENTED;
2558 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
2559 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2561 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
2562 return ERROR_CALL_NOT_IMPLEMENTED;
2565 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
2566 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2568 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
2569 return ERROR_CALL_NOT_IMPLEMENTED;
2572 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR path, DWORD flags, PCCERT_CONTEXT *cert,
2573 LPBYTE hash, LPDWORD hashlen )
2575 UINT r;
2576 WCHAR *pathW = NULL;
2578 TRACE("%s %08x %p %p %p\n", debugstr_a(path), flags, cert, hash, hashlen);
2580 if (path && !(pathW = strdupAtoW( path ))) return E_OUTOFMEMORY;
2581 r = MsiGetFileSignatureInformationW( pathW, flags, cert, hash, hashlen );
2582 msi_free( pathW );
2583 return r;
2586 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR path, DWORD flags, PCCERT_CONTEXT *cert,
2587 LPBYTE hash, LPDWORD hashlen )
2589 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
2590 HRESULT hr;
2591 WINTRUST_DATA data;
2592 WINTRUST_FILE_INFO info;
2593 CRYPT_PROVIDER_SGNR *signer;
2594 CRYPT_PROVIDER_CERT *provider;
2596 TRACE("%s %08x %p %p %p\n", debugstr_w(path), flags, cert, hash, hashlen);
2598 if (!path || !cert) return E_INVALIDARG;
2600 info.cbStruct = sizeof(info);
2601 info.pcwszFilePath = path;
2602 info.hFile = NULL;
2603 info.pgKnownSubject = NULL;
2605 data.cbStruct = sizeof(data);
2606 data.pPolicyCallbackData = NULL;
2607 data.pSIPClientData = NULL;
2608 data.dwUIChoice = WTD_UI_NONE;
2609 data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
2610 data.dwUnionChoice = WTD_CHOICE_FILE;
2611 data.u.pFile = &info;
2612 data.dwStateAction = WTD_STATEACTION_VERIFY;
2613 data.hWVTStateData = NULL;
2614 data.pwszURLReference = NULL;
2615 data.dwProvFlags = 0;
2616 data.dwUIContext = WTD_UICONTEXT_INSTALL;
2617 hr = WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data );
2618 *cert = NULL;
2619 if (FAILED(hr)) goto done;
2621 if (!(signer = WTHelperGetProvSignerFromChain( data.hWVTStateData, 0, FALSE, 0 )))
2623 hr = TRUST_E_NOSIGNATURE;
2624 goto done;
2626 if (hash)
2628 DWORD len = signer->psSigner->EncryptedHash.cbData;
2629 if (*hashlen < len)
2631 *hashlen = len;
2632 hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
2633 goto done;
2635 memcpy( hash, signer->psSigner->EncryptedHash.pbData, len );
2636 *hashlen = len;
2638 if (!(provider = WTHelperGetProvCertFromChain( signer, 0 )))
2640 hr = TRUST_E_PROVIDER_UNKNOWN;
2641 goto done;
2643 *cert = CertDuplicateCertificateContext( provider->pCert );
2645 done:
2646 data.dwStateAction = WTD_STATEACTION_CLOSE;
2647 WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data );
2648 return hr;
2651 /******************************************************************
2652 * MsiGetProductPropertyA [MSI.@]
2654 UINT WINAPI MsiGetProductPropertyA(MSIHANDLE hProduct, LPCSTR szProperty,
2655 LPSTR szValue, LPDWORD pccbValue)
2657 LPWSTR prop = NULL, val = NULL;
2658 DWORD len;
2659 UINT r;
2661 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_a(szProperty),
2662 szValue, pccbValue);
2664 if (szValue && !pccbValue)
2665 return ERROR_INVALID_PARAMETER;
2667 if (szProperty) prop = strdupAtoW(szProperty);
2669 len = 0;
2670 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len);
2671 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2672 goto done;
2674 if (r == ERROR_SUCCESS)
2676 if (szValue) *szValue = '\0';
2677 if (pccbValue) *pccbValue = 0;
2678 goto done;
2681 val = msi_alloc(++len * sizeof(WCHAR));
2682 if (!val)
2684 r = ERROR_OUTOFMEMORY;
2685 goto done;
2688 r = MsiGetProductPropertyW(hProduct, prop, val, &len);
2689 if (r != ERROR_SUCCESS)
2690 goto done;
2692 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL);
2694 if (szValue)
2695 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue,
2696 *pccbValue, NULL, NULL);
2698 if (pccbValue)
2700 if (len > *pccbValue)
2701 r = ERROR_MORE_DATA;
2703 *pccbValue = len - 1;
2706 done:
2707 msi_free(prop);
2708 msi_free(val);
2710 return r;
2713 /******************************************************************
2714 * MsiGetProductPropertyW [MSI.@]
2716 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE hProduct, LPCWSTR szProperty,
2717 LPWSTR szValue, LPDWORD pccbValue)
2719 MSIPACKAGE *package;
2720 MSIQUERY *view = NULL;
2721 MSIRECORD *rec = NULL;
2722 LPCWSTR val;
2723 UINT r;
2725 static const WCHAR query[] = {
2726 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
2727 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
2728 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
2730 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_w(szProperty),
2731 szValue, pccbValue);
2733 if (!szProperty)
2734 return ERROR_INVALID_PARAMETER;
2736 if (szValue && !pccbValue)
2737 return ERROR_INVALID_PARAMETER;
2739 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE);
2740 if (!package)
2741 return ERROR_INVALID_HANDLE;
2743 r = MSI_OpenQuery(package->db, &view, query, szProperty);
2744 if (r != ERROR_SUCCESS)
2745 goto done;
2747 r = MSI_ViewExecute(view, 0);
2748 if (r != ERROR_SUCCESS)
2749 goto done;
2751 r = MSI_ViewFetch(view, &rec);
2752 if (r != ERROR_SUCCESS)
2753 goto done;
2755 val = MSI_RecordGetString(rec, 2);
2756 if (!val)
2757 goto done;
2759 if (lstrlenW(val) >= *pccbValue)
2761 if (szValue) lstrcpynW(szValue, val, *pccbValue);
2762 r = ERROR_MORE_DATA;
2764 else
2766 if (szValue) lstrcpyW(szValue, val);
2767 r = ERROR_SUCCESS;
2770 *pccbValue = lstrlenW(val);
2772 done:
2773 if (view)
2775 MSI_ViewClose(view);
2776 msiobj_release(&view->hdr);
2777 if (rec) msiobj_release(&rec->hdr);
2780 if (!rec)
2782 if (szValue) *szValue = '\0';
2783 if (pccbValue) *pccbValue = 0;
2784 r = ERROR_SUCCESS;
2787 msiobj_release(&package->hdr);
2788 return r;
2791 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
2793 UINT r;
2794 LPWSTR szPack = NULL;
2796 TRACE("%s\n", debugstr_a(szPackage) );
2798 if( szPackage )
2800 szPack = strdupAtoW( szPackage );
2801 if( !szPack )
2802 return ERROR_OUTOFMEMORY;
2805 r = MsiVerifyPackageW( szPack );
2807 msi_free( szPack );
2809 return r;
2812 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
2814 MSIHANDLE handle;
2815 UINT r;
2817 TRACE("%s\n", debugstr_w(szPackage) );
2819 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
2820 MsiCloseHandle( handle );
2822 return r;
2825 static BOOL open_userdata_comp_key( const WCHAR *comp, const WCHAR *usersid, MSIINSTALLCONTEXT ctx,
2826 HKEY *hkey )
2828 if (ctx & MSIINSTALLCONTEXT_MACHINE)
2830 if (!MSIREG_OpenUserDataComponentKey( comp, szLocalSid, hkey, FALSE )) return TRUE;
2832 if (ctx & (MSIINSTALLCONTEXT_USERMANAGED|MSIINSTALLCONTEXT_USERUNMANAGED))
2834 if (usersid && !wcsicmp( usersid, szAllSid ))
2836 FIXME( "only looking at the current user\n" );
2837 usersid = NULL;
2839 if (!MSIREG_OpenUserDataComponentKey( comp, usersid, hkey, FALSE )) return TRUE;
2841 return FALSE;
2844 static INSTALLSTATE MSI_GetComponentPath( const WCHAR *szProduct, const WCHAR *szComponent,
2845 const WCHAR *szUserSid, MSIINSTALLCONTEXT ctx,
2846 awstring *lpPathBuf, DWORD *pcchBuf )
2848 static const WCHAR wininstaller[] =
2849 {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
2850 WCHAR *path = NULL, squashed_pc[SQUASHED_GUID_SIZE], squashed_comp[SQUASHED_GUID_SIZE];
2851 HKEY hkey;
2852 INSTALLSTATE state;
2853 DWORD version;
2855 if (!szProduct || !szComponent)
2856 return INSTALLSTATE_INVALIDARG;
2858 if (lpPathBuf->str.w && !pcchBuf)
2859 return INSTALLSTATE_INVALIDARG;
2861 if (!squash_guid( szProduct, squashed_pc ) || !squash_guid( szComponent, squashed_comp ))
2862 return INSTALLSTATE_INVALIDARG;
2864 if (szUserSid && ctx == MSIINSTALLCONTEXT_MACHINE)
2865 return INSTALLSTATE_INVALIDARG;
2867 state = INSTALLSTATE_UNKNOWN;
2869 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
2871 path = msi_reg_get_val_str( hkey, squashed_pc );
2872 RegCloseKey(hkey);
2874 state = INSTALLSTATE_ABSENT;
2876 if ((!MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, &hkey, FALSE) ||
2877 !MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, NULL, &hkey, FALSE)) &&
2878 msi_reg_get_val_dword(hkey, wininstaller, &version) &&
2879 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2881 RegCloseKey(hkey);
2882 state = INSTALLSTATE_LOCAL;
2886 if (state != INSTALLSTATE_LOCAL &&
2887 (!MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, &hkey, FALSE) ||
2888 !MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, &hkey, FALSE)))
2890 RegCloseKey(hkey);
2892 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
2894 msi_free(path);
2895 path = msi_reg_get_val_str( hkey, squashed_pc );
2896 RegCloseKey(hkey);
2898 state = INSTALLSTATE_ABSENT;
2900 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2901 state = INSTALLSTATE_LOCAL;
2905 if (!path)
2906 return INSTALLSTATE_UNKNOWN;
2908 if (state == INSTALLSTATE_LOCAL && !*path)
2909 state = INSTALLSTATE_NOTUSED;
2911 if (msi_strcpy_to_awstring(path, -1, lpPathBuf, pcchBuf) == ERROR_MORE_DATA)
2912 state = INSTALLSTATE_MOREDATA;
2914 msi_free(path);
2915 return state;
2918 /******************************************************************
2919 * MsiGetComponentPathExW [MSI.@]
2921 INSTALLSTATE WINAPI MsiGetComponentPathExW( LPCWSTR product, LPCWSTR comp, LPCWSTR usersid,
2922 MSIINSTALLCONTEXT ctx, LPWSTR buf, LPDWORD buflen )
2924 awstring path;
2926 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_w(product), debugstr_w(comp), debugstr_w(usersid),
2927 ctx, buf, buflen );
2929 path.unicode = TRUE;
2930 path.str.w = buf;
2932 return MSI_GetComponentPath( product, comp, usersid, ctx, &path, buflen );
2935 INSTALLSTATE WINAPI MsiGetComponentPathExA( LPCSTR product, LPCSTR comp, LPCSTR usersid,
2936 MSIINSTALLCONTEXT ctx, LPSTR buf, LPDWORD buflen )
2938 WCHAR *productW = NULL, *compW = NULL, *usersidW = NULL;
2939 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
2940 awstring path;
2942 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_a(product), debugstr_a(comp), debugstr_a(usersid),
2943 ctx, buf, buflen );
2945 if (product && !(productW = strdupAtoW( product ))) return INSTALLSTATE_UNKNOWN;
2946 if (comp && !(compW = strdupAtoW( comp ))) goto end;
2947 if (usersid && !(usersidW = strdupAtoW( usersid ))) goto end;
2949 path.unicode = FALSE;
2950 path.str.a = buf;
2952 r = MSI_GetComponentPath( productW, compW, usersidW, ctx, &path, buflen );
2954 end:
2955 msi_free( productW );
2956 msi_free( compW );
2957 msi_free( usersidW );
2959 return r;
2962 /******************************************************************
2963 * MsiGetComponentPathW [MSI.@]
2965 INSTALLSTATE WINAPI MsiGetComponentPathW( LPCWSTR product, LPCWSTR comp, LPWSTR buf, LPDWORD buflen )
2967 return MsiGetComponentPathExW( product, comp, szAllSid, MSIINSTALLCONTEXT_ALL, buf, buflen );
2970 /******************************************************************
2971 * MsiGetComponentPathA [MSI.@]
2973 INSTALLSTATE WINAPI MsiGetComponentPathA( LPCSTR product, LPCSTR comp, LPSTR buf, LPDWORD buflen )
2975 return MsiGetComponentPathExA( product, comp, "s-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen );
2978 static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid,
2979 MSIINSTALLCONTEXT ctx, const WCHAR *feature, INSTALLSTATE *state )
2981 UINT r;
2982 HKEY hkey;
2983 WCHAR *parent, *components, *path;
2984 const WCHAR *p;
2985 BOOL missing = FALSE, source = FALSE;
2986 WCHAR comp[GUID_SIZE];
2987 GUID guid;
2989 if (ctx != MSIINSTALLCONTEXT_MACHINE) SetLastError( ERROR_SUCCESS );
2991 if (MSIREG_OpenFeaturesKey( product, usersid, ctx, &hkey, FALSE )) return ERROR_UNKNOWN_PRODUCT;
2993 parent = msi_reg_get_val_str( hkey, feature );
2994 RegCloseKey( hkey );
2995 if (!parent) return ERROR_UNKNOWN_FEATURE;
2997 *state = (parent[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
2998 msi_free( parent );
2999 if (*state == INSTALLSTATE_ABSENT)
3000 return ERROR_SUCCESS;
3002 r = MSIREG_OpenUserDataFeaturesKey( product, usersid, ctx, &hkey, FALSE );
3003 if (r != ERROR_SUCCESS)
3005 *state = INSTALLSTATE_ADVERTISED;
3006 return ERROR_SUCCESS;
3008 components = msi_reg_get_val_str( hkey, feature );
3009 RegCloseKey( hkey );
3011 TRACE("buffer = %s\n", debugstr_w(components));
3013 if (!components)
3015 *state = INSTALLSTATE_ADVERTISED;
3016 return ERROR_SUCCESS;
3018 for (p = components; *p && *p != 2 ; p += 20)
3020 if (!decode_base85_guid( p, &guid ))
3022 if (p != components) break;
3023 msi_free( components );
3024 *state = INSTALLSTATE_BADCONFIG;
3025 return ERROR_BAD_CONFIGURATION;
3027 StringFromGUID2( &guid, comp, GUID_SIZE );
3028 if (ctx == MSIINSTALLCONTEXT_MACHINE)
3029 r = MSIREG_OpenUserDataComponentKey( comp, szLocalSid, &hkey, FALSE );
3030 else
3031 r = MSIREG_OpenUserDataComponentKey( comp, usersid, &hkey, FALSE );
3033 if (r != ERROR_SUCCESS)
3035 msi_free( components );
3036 *state = INSTALLSTATE_ADVERTISED;
3037 return ERROR_SUCCESS;
3039 path = msi_reg_get_val_str( hkey, squashed );
3040 if (!path) missing = TRUE;
3041 else if (lstrlenW( path ) > 2 &&
3042 path[0] >= '0' && path[0] <= '9' &&
3043 path[1] >= '0' && path[1] <= '9')
3045 source = TRUE;
3047 msi_free( path );
3049 msi_free( components );
3051 if (missing)
3052 *state = INSTALLSTATE_ADVERTISED;
3053 else if (source)
3054 *state = INSTALLSTATE_SOURCE;
3055 else
3056 *state = INSTALLSTATE_LOCAL;
3058 TRACE("returning state %d\n", *state);
3059 return ERROR_SUCCESS;
3062 UINT WINAPI MsiQueryFeatureStateExA( LPCSTR product, LPCSTR usersid, MSIINSTALLCONTEXT ctx,
3063 LPCSTR feature, INSTALLSTATE *state )
3065 UINT r;
3066 WCHAR *productW = NULL, *usersidW = NULL, *featureW = NULL;
3068 if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
3069 if (usersid && !(usersidW = strdupAtoW( usersid )))
3071 msi_free( productW );
3072 return ERROR_OUTOFMEMORY;
3074 if (feature && !(featureW = strdupAtoW( feature )))
3076 msi_free( productW );
3077 msi_free( usersidW );
3078 return ERROR_OUTOFMEMORY;
3080 r = MsiQueryFeatureStateExW( productW, usersidW, ctx, featureW, state );
3081 msi_free( productW );
3082 msi_free( usersidW );
3083 msi_free( featureW );
3084 return r;
3087 UINT WINAPI MsiQueryFeatureStateExW( LPCWSTR product, LPCWSTR usersid, MSIINSTALLCONTEXT ctx,
3088 LPCWSTR feature, INSTALLSTATE *state )
3090 WCHAR squashed[33];
3091 if (!squash_guid( product, squashed )) return ERROR_INVALID_PARAMETER;
3092 return query_feature_state( product, squashed, usersid, ctx, feature, state );
3095 /******************************************************************
3096 * MsiQueryFeatureStateA [MSI.@]
3098 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
3100 LPWSTR szwProduct = NULL, szwFeature= NULL;
3101 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
3103 szwProduct = strdupAtoW( szProduct );
3104 if ( szProduct && !szwProduct )
3105 goto end;
3107 szwFeature = strdupAtoW( szFeature );
3108 if ( szFeature && !szwFeature )
3109 goto end;
3111 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
3113 end:
3114 msi_free( szwProduct);
3115 msi_free( szwFeature);
3117 return rc;
3120 /******************************************************************
3121 * MsiQueryFeatureStateW [MSI.@]
3123 * Checks the state of a feature
3125 * PARAMS
3126 * szProduct [I] Product's GUID string
3127 * szFeature [I] Feature's GUID string
3129 * RETURNS
3130 * INSTALLSTATE_LOCAL Feature is installed and usable
3131 * INSTALLSTATE_ABSENT Feature is absent
3132 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
3133 * INSTALLSTATE_UNKNOWN An error occurred
3134 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
3137 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
3139 UINT r;
3140 INSTALLSTATE state;
3141 WCHAR squashed[33];
3143 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
3145 if (!szProduct || !szFeature || !squash_guid( szProduct, squashed ))
3146 return INSTALLSTATE_INVALIDARG;
3148 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERMANAGED, szFeature, &state );
3149 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state;
3151 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, szFeature, &state );
3152 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state;
3154 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_MACHINE, szFeature, &state );
3155 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state;
3157 return INSTALLSTATE_UNKNOWN;
3160 /******************************************************************
3161 * MsiGetFileVersionA [MSI.@]
3163 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
3164 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
3166 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
3167 UINT ret = ERROR_OUTOFMEMORY;
3169 if ((lpVersionBuf && !pcchVersionBuf) ||
3170 (lpLangBuf && !pcchLangBuf))
3171 return ERROR_INVALID_PARAMETER;
3173 if( szFilePath )
3175 szwFilePath = strdupAtoW( szFilePath );
3176 if( !szwFilePath )
3177 goto end;
3180 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
3182 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
3183 if( !lpwVersionBuff )
3184 goto end;
3187 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
3189 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
3190 if( !lpwLangBuff )
3191 goto end;
3194 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
3195 lpwLangBuff, pcchLangBuf);
3197 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
3198 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
3199 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
3200 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
3201 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
3202 lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
3204 end:
3205 msi_free(szwFilePath);
3206 msi_free(lpwVersionBuff);
3207 msi_free(lpwLangBuff);
3209 return ret;
3212 static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen,
3213 WCHAR *langbuf, DWORD *langlen )
3215 static const WCHAR szVersionResource[] = {'\\',0};
3216 static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3217 static const WCHAR szLangFormat[] = {'%','d',0};
3218 UINT ret = ERROR_MORE_DATA;
3219 DWORD len, error;
3220 LPVOID version;
3221 VS_FIXEDFILEINFO *ffi;
3222 USHORT *lang;
3223 WCHAR tmp[32];
3225 if (!(len = GetFileVersionInfoSizeW( path, NULL )))
3227 error = GetLastError();
3228 if (error == ERROR_BAD_PATHNAME) return ERROR_FILE_NOT_FOUND;
3229 if (error == ERROR_RESOURCE_DATA_NOT_FOUND) return ERROR_FILE_INVALID;
3230 return error;
3232 if (!(version = msi_alloc( len ))) return ERROR_OUTOFMEMORY;
3233 if (!GetFileVersionInfoW( path, 0, len, version ))
3235 msi_free( version );
3236 return GetLastError();
3238 if (!verbuf && !verlen && !langbuf && !langlen)
3240 msi_free( version );
3241 return ERROR_SUCCESS;
3243 if (verlen)
3245 if (VerQueryValueW( version, szVersionResource, (LPVOID *)&ffi, &len ) && len > 0)
3247 swprintf( tmp, ARRAY_SIZE(tmp), szVersionFormat,
3248 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
3249 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS) );
3250 if (verbuf) lstrcpynW( verbuf, tmp, *verlen );
3251 len = lstrlenW( tmp );
3252 if (*verlen > len) ret = ERROR_SUCCESS;
3253 *verlen = len;
3255 else
3257 if (verbuf) *verbuf = 0;
3258 *verlen = 0;
3261 if (langlen)
3263 if (VerQueryValueW( version, szLangResource, (LPVOID *)&lang, &len ) && len > 0)
3265 swprintf( tmp, ARRAY_SIZE(tmp), szLangFormat, *lang );
3266 if (langbuf) lstrcpynW( langbuf, tmp, *langlen );
3267 len = lstrlenW( tmp );
3268 if (*langlen > len) ret = ERROR_SUCCESS;
3269 *langlen = len;
3271 else
3273 if (langbuf) *langbuf = 0;
3274 *langlen = 0;
3277 msi_free( version );
3278 return ret;
3282 /******************************************************************
3283 * MsiGetFileVersionW [MSI.@]
3285 UINT WINAPI MsiGetFileVersionW( LPCWSTR path, LPWSTR verbuf, LPDWORD verlen,
3286 LPWSTR langbuf, LPDWORD langlen )
3288 UINT ret;
3290 TRACE("%s %p %u %p %u\n", debugstr_w(path), verbuf, verlen ? *verlen : 0,
3291 langbuf, langlen ? *langlen : 0);
3293 if ((verbuf && !verlen) || (langbuf && !langlen))
3294 return ERROR_INVALID_PARAMETER;
3296 ret = get_file_version( path, verbuf, verlen, langbuf, langlen );
3297 if (ret == ERROR_RESOURCE_DATA_NOT_FOUND && verlen)
3299 int len;
3300 WCHAR *version = msi_get_font_file_version( NULL, path );
3301 if (!version) return ERROR_FILE_INVALID;
3302 len = lstrlenW( version );
3303 if (len >= *verlen) ret = ERROR_MORE_DATA;
3304 else if (verbuf)
3306 lstrcpyW( verbuf, version );
3307 ret = ERROR_SUCCESS;
3309 *verlen = len;
3310 msi_free( version );
3312 return ret;
3315 /***********************************************************************
3316 * MsiGetFeatureUsageW [MSI.@]
3318 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
3319 LPDWORD pdwUseCount, LPWORD pwDateUsed )
3321 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
3322 pdwUseCount, pwDateUsed);
3323 return ERROR_CALL_NOT_IMPLEMENTED;
3326 /***********************************************************************
3327 * MsiGetFeatureUsageA [MSI.@]
3329 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
3330 LPDWORD pdwUseCount, LPWORD pwDateUsed )
3332 LPWSTR prod = NULL, feat = NULL;
3333 UINT ret = ERROR_OUTOFMEMORY;
3335 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
3336 pdwUseCount, pwDateUsed);
3338 prod = strdupAtoW( szProduct );
3339 if (szProduct && !prod)
3340 goto end;
3342 feat = strdupAtoW( szFeature );
3343 if (szFeature && !feat)
3344 goto end;
3346 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
3348 end:
3349 msi_free( prod );
3350 msi_free( feat );
3352 return ret;
3355 /***********************************************************************
3356 * MsiUseFeatureExW [MSI.@]
3358 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
3359 DWORD dwInstallMode, DWORD dwReserved )
3361 INSTALLSTATE state;
3363 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
3364 dwInstallMode, dwReserved);
3366 state = MsiQueryFeatureStateW( szProduct, szFeature );
3368 if (dwReserved)
3369 return INSTALLSTATE_INVALIDARG;
3371 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
3373 FIXME("mark product %s feature %s as used\n",
3374 debugstr_w(szProduct), debugstr_w(szFeature) );
3377 return state;
3380 /***********************************************************************
3381 * MsiUseFeatureExA [MSI.@]
3383 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
3384 DWORD dwInstallMode, DWORD dwReserved )
3386 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
3387 LPWSTR prod = NULL, feat = NULL;
3389 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
3390 dwInstallMode, dwReserved);
3392 prod = strdupAtoW( szProduct );
3393 if (szProduct && !prod)
3394 goto end;
3396 feat = strdupAtoW( szFeature );
3397 if (szFeature && !feat)
3398 goto end;
3400 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
3402 end:
3403 msi_free( prod );
3404 msi_free( feat );
3406 return ret;
3409 /***********************************************************************
3410 * MsiUseFeatureW [MSI.@]
3412 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
3414 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
3417 /***********************************************************************
3418 * MsiUseFeatureA [MSI.@]
3420 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
3422 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
3425 static WCHAR *reg_get_multisz( HKEY hkey, const WCHAR *name )
3427 WCHAR *ret;
3428 DWORD len, type;
3429 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_MULTI_SZ) return NULL;
3430 if ((ret = msi_alloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len );
3431 return ret;
3434 static WCHAR *reg_get_sz( HKEY hkey, const WCHAR *name )
3436 WCHAR *ret;
3437 DWORD len, type;
3438 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_SZ) return NULL;
3439 if ((ret = msi_alloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len );
3440 return ret;
3443 #define BASE85_SIZE 20
3445 /***********************************************************************
3446 * MSI_ProvideQualifiedComponentEx [internal]
3448 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
3449 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
3450 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
3451 LPDWORD pcchPathBuf)
3453 WCHAR product[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
3454 WCHAR *desc;
3455 HKEY hkey;
3456 DWORD size;
3457 UINT ret;
3458 INSTALLSTATE state;
3460 if (MSIREG_OpenUserComponentsKey( szComponent, &hkey, FALSE )) return ERROR_UNKNOWN_COMPONENT;
3462 desc = reg_get_multisz( hkey, szQualifier );
3463 RegCloseKey(hkey);
3464 if (!desc) return ERROR_INDEX_ABSENT;
3466 /* FIXME: handle multiple descriptors */
3467 ret = MsiDecomposeDescriptorW( desc, product, feature, comp, &size );
3468 msi_free( desc );
3469 if (ret != ERROR_SUCCESS) return ret;
3471 if (!szProduct) szProduct = product;
3472 if (!comp[0])
3474 MSIINSTALLCONTEXT ctx;
3475 WCHAR *components;
3476 GUID guid;
3478 /* use the first component of the feature if the descriptor component is empty */
3479 if ((ret = msi_locate_product( szProduct, &ctx ))) return ret;
3480 if ((ret = MSIREG_OpenUserDataFeaturesKey( szProduct, NULL, ctx, &hkey, FALSE )))
3482 return ERROR_FILE_NOT_FOUND;
3484 components = reg_get_sz( hkey, feature );
3485 RegCloseKey( hkey );
3486 if (!components) return ERROR_FILE_NOT_FOUND;
3488 if (lstrlenW( components ) < BASE85_SIZE || !decode_base85_guid( components, &guid ))
3490 msi_free( components );
3491 return ERROR_FILE_NOT_FOUND;
3493 msi_free( components );
3494 StringFromGUID2( &guid, comp, ARRAY_SIZE( comp ));
3497 state = MSI_GetComponentPath( szProduct, comp, szAllSid, MSIINSTALLCONTEXT_ALL, lpPathBuf, pcchPathBuf );
3499 if (state == INSTALLSTATE_MOREDATA) return ERROR_MORE_DATA;
3500 if (state != INSTALLSTATE_LOCAL) return ERROR_FILE_NOT_FOUND;
3501 return ERROR_SUCCESS;
3504 /***********************************************************************
3505 * MsiProvideQualifiedComponentExW [MSI.@]
3507 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
3508 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
3509 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
3510 LPDWORD pcchPathBuf)
3512 awstring path;
3514 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_w(szComponent),
3515 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
3516 Unused1, Unused2, lpPathBuf, pcchPathBuf);
3518 path.unicode = TRUE;
3519 path.str.w = lpPathBuf;
3521 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
3522 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
3525 /***********************************************************************
3526 * MsiProvideQualifiedComponentExA [MSI.@]
3528 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
3529 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct,
3530 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
3531 LPDWORD pcchPathBuf)
3533 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
3534 UINT r = ERROR_OUTOFMEMORY;
3535 awstring path;
3537 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
3538 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
3539 Unused1, Unused2, lpPathBuf, pcchPathBuf);
3541 szwComponent = strdupAtoW( szComponent );
3542 if (szComponent && !szwComponent)
3543 goto end;
3545 szwQualifier = strdupAtoW( szQualifier );
3546 if (szQualifier && !szwQualifier)
3547 goto end;
3549 szwProduct = strdupAtoW( szProduct );
3550 if (szProduct && !szwProduct)
3551 goto end;
3553 path.unicode = FALSE;
3554 path.str.a = lpPathBuf;
3556 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
3557 dwInstallMode, szwProduct, Unused1,
3558 Unused2, &path, pcchPathBuf);
3559 end:
3560 msi_free(szwProduct);
3561 msi_free(szwComponent);
3562 msi_free(szwQualifier);
3564 return r;
3567 /***********************************************************************
3568 * MsiProvideQualifiedComponentW [MSI.@]
3570 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
3571 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
3572 LPDWORD pcchPathBuf)
3574 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
3575 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
3578 /***********************************************************************
3579 * MsiProvideQualifiedComponentA [MSI.@]
3581 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
3582 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
3583 LPDWORD pcchPathBuf)
3585 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
3586 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
3589 /***********************************************************************
3590 * MSI_GetUserInfo [internal]
3592 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
3593 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
3594 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3595 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
3597 WCHAR *user, *org, *serial, squashed_pc[SQUASHED_GUID_SIZE];
3598 USERINFOSTATE state;
3599 HKEY hkey, props;
3600 LPCWSTR orgptr;
3601 UINT r;
3603 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
3604 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
3605 pcchSerialBuf);
3607 if (!szProduct || !squash_guid( szProduct, squashed_pc ))
3608 return USERINFOSTATE_INVALIDARG;
3610 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
3611 &hkey, FALSE) != ERROR_SUCCESS &&
3612 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3613 &hkey, FALSE) != ERROR_SUCCESS &&
3614 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
3615 &hkey, FALSE) != ERROR_SUCCESS)
3617 return USERINFOSTATE_UNKNOWN;
3620 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
3621 NULL, &props, FALSE) != ERROR_SUCCESS &&
3622 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE,
3623 NULL, &props, FALSE) != ERROR_SUCCESS)
3625 RegCloseKey(hkey);
3626 return USERINFOSTATE_ABSENT;
3629 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
3630 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
3631 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
3632 state = USERINFOSTATE_ABSENT;
3634 RegCloseKey(hkey);
3635 RegCloseKey(props);
3637 if (user && serial)
3638 state = USERINFOSTATE_PRESENT;
3640 if (pcchUserNameBuf)
3642 if (lpUserNameBuf && !user)
3644 (*pcchUserNameBuf)--;
3645 goto done;
3648 r = msi_strcpy_to_awstring(user, -1, lpUserNameBuf, pcchUserNameBuf);
3649 if (r == ERROR_MORE_DATA)
3651 state = USERINFOSTATE_MOREDATA;
3652 goto done;
3656 if (pcchOrgNameBuf)
3658 orgptr = org;
3659 if (!orgptr) orgptr = szEmpty;
3661 r = msi_strcpy_to_awstring(orgptr, -1, lpOrgNameBuf, pcchOrgNameBuf);
3662 if (r == ERROR_MORE_DATA)
3664 state = USERINFOSTATE_MOREDATA;
3665 goto done;
3669 if (pcchSerialBuf)
3671 if (!serial)
3673 (*pcchSerialBuf)--;
3674 goto done;
3677 r = msi_strcpy_to_awstring(serial, -1, lpSerialBuf, pcchSerialBuf);
3678 if (r == ERROR_MORE_DATA)
3679 state = USERINFOSTATE_MOREDATA;
3682 done:
3683 msi_free(user);
3684 msi_free(org);
3685 msi_free(serial);
3687 return state;
3690 /***********************************************************************
3691 * MsiGetUserInfoW [MSI.@]
3693 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
3694 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3695 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3696 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3698 awstring user, org, serial;
3700 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3701 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3702 (lpSerialBuf && !pcchSerialBuf))
3703 return USERINFOSTATE_INVALIDARG;
3705 user.unicode = TRUE;
3706 user.str.w = lpUserNameBuf;
3707 org.unicode = TRUE;
3708 org.str.w = lpOrgNameBuf;
3709 serial.unicode = TRUE;
3710 serial.str.w = lpSerialBuf;
3712 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
3713 &org, pcchOrgNameBuf,
3714 &serial, pcchSerialBuf );
3717 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
3718 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3719 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3720 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3722 awstring user, org, serial;
3723 LPWSTR prod;
3724 UINT r;
3726 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3727 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3728 (lpSerialBuf && !pcchSerialBuf))
3729 return USERINFOSTATE_INVALIDARG;
3731 prod = strdupAtoW( szProduct );
3732 if (szProduct && !prod)
3733 return ERROR_OUTOFMEMORY;
3735 user.unicode = FALSE;
3736 user.str.a = lpUserNameBuf;
3737 org.unicode = FALSE;
3738 org.str.a = lpOrgNameBuf;
3739 serial.unicode = FALSE;
3740 serial.str.a = lpSerialBuf;
3742 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
3743 &org, pcchOrgNameBuf,
3744 &serial, pcchSerialBuf );
3746 msi_free( prod );
3748 return r;
3751 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
3753 MSIHANDLE handle;
3754 UINT rc;
3755 MSIPACKAGE *package;
3756 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3758 TRACE("(%s)\n",debugstr_w(szProduct));
3760 rc = MsiOpenProductW(szProduct,&handle);
3761 if (rc != ERROR_SUCCESS)
3762 return ERROR_INVALID_PARAMETER;
3764 /* MsiCollectUserInfo cannot be called from a custom action. */
3765 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3766 if (!package)
3767 return ERROR_CALL_NOT_IMPLEMENTED;
3769 rc = ACTION_PerformAction(package, szFirstRun);
3770 msiobj_release( &package->hdr );
3772 MsiCloseHandle(handle);
3774 return rc;
3777 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
3779 MSIHANDLE handle;
3780 UINT rc;
3781 MSIPACKAGE *package;
3782 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3784 TRACE("(%s)\n",debugstr_a(szProduct));
3786 rc = MsiOpenProductA(szProduct,&handle);
3787 if (rc != ERROR_SUCCESS)
3788 return ERROR_INVALID_PARAMETER;
3790 /* MsiCollectUserInfo cannot be called from a custom action. */
3791 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3792 if (!package)
3793 return ERROR_CALL_NOT_IMPLEMENTED;
3795 rc = ACTION_PerformAction(package, szFirstRun);
3796 msiobj_release( &package->hdr );
3798 MsiCloseHandle(handle);
3800 return rc;
3803 /***********************************************************************
3804 * MsiConfigureFeatureA [MSI.@]
3806 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
3808 LPWSTR prod, feat = NULL;
3809 UINT r = ERROR_OUTOFMEMORY;
3811 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
3813 prod = strdupAtoW( szProduct );
3814 if (szProduct && !prod)
3815 goto end;
3817 feat = strdupAtoW( szFeature );
3818 if (szFeature && !feat)
3819 goto end;
3821 r = MsiConfigureFeatureW(prod, feat, eInstallState);
3823 end:
3824 msi_free(feat);
3825 msi_free(prod);
3827 return r;
3830 /***********************************************************************
3831 * MsiConfigureFeatureW [MSI.@]
3833 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
3835 MSIPACKAGE *package = NULL;
3836 UINT r;
3837 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
3838 DWORD sz;
3840 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
3842 if (!szProduct || !szFeature)
3843 return ERROR_INVALID_PARAMETER;
3845 switch (eInstallState)
3847 case INSTALLSTATE_DEFAULT:
3848 /* FIXME: how do we figure out the default location? */
3849 eInstallState = INSTALLSTATE_LOCAL;
3850 break;
3851 case INSTALLSTATE_LOCAL:
3852 case INSTALLSTATE_SOURCE:
3853 case INSTALLSTATE_ABSENT:
3854 case INSTALLSTATE_ADVERTISED:
3855 break;
3856 default:
3857 return ERROR_INVALID_PARAMETER;
3860 r = MSI_OpenProductW( szProduct, &package );
3861 if (r != ERROR_SUCCESS)
3862 return r;
3864 sz = sizeof(sourcepath);
3865 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3866 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3868 sz = sizeof(filename);
3869 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3870 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3872 lstrcatW( sourcepath, filename );
3874 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
3876 r = ACTION_PerformAction(package, szCostInitialize);
3877 if (r != ERROR_SUCCESS)
3878 goto end;
3880 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
3881 if (r != ERROR_SUCCESS)
3882 goto end;
3884 r = MSI_InstallPackage( package, sourcepath, NULL );
3886 end:
3887 msiobj_release( &package->hdr );
3889 return r;
3892 /***********************************************************************
3893 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3895 * Notes: undocumented
3897 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
3899 WCHAR path[MAX_PATH];
3901 TRACE("%d\n", dwReserved);
3903 if (dwReserved)
3905 FIXME("dwReserved=%d\n", dwReserved);
3906 return ERROR_INVALID_PARAMETER;
3909 if (!GetWindowsDirectoryW(path, MAX_PATH))
3910 return ERROR_FUNCTION_FAILED;
3912 lstrcatW(path, installerW);
3914 if (!CreateDirectoryW(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
3915 return ERROR_FUNCTION_FAILED;
3917 return ERROR_SUCCESS;
3920 /***********************************************************************
3921 * MsiGetShortcutTargetA [MSI.@]
3923 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
3924 LPSTR szProductCode, LPSTR szFeatureId,
3925 LPSTR szComponentCode )
3927 LPWSTR target;
3928 const int len = MAX_FEATURE_CHARS+1;
3929 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
3930 UINT r;
3932 target = strdupAtoW( szShortcutTarget );
3933 if (szShortcutTarget && !target )
3934 return ERROR_OUTOFMEMORY;
3935 product[0] = 0;
3936 feature[0] = 0;
3937 component[0] = 0;
3938 r = MsiGetShortcutTargetW( target, product, feature, component );
3939 msi_free( target );
3940 if (r == ERROR_SUCCESS)
3942 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
3943 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
3944 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
3946 return r;
3949 /***********************************************************************
3950 * MsiGetShortcutTargetW [MSI.@]
3952 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
3953 LPWSTR szProductCode, LPWSTR szFeatureId,
3954 LPWSTR szComponentCode )
3956 IShellLinkDataList *dl = NULL;
3957 IPersistFile *pf = NULL;
3958 LPEXP_DARWIN_LINK darwin = NULL;
3959 HRESULT r, init;
3961 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
3962 szProductCode, szFeatureId, szComponentCode );
3964 init = CoInitialize(NULL);
3966 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
3967 &IID_IPersistFile, (LPVOID*) &pf );
3968 if( SUCCEEDED( r ) )
3970 r = IPersistFile_Load( pf, szShortcutTarget,
3971 STGM_READ | STGM_SHARE_DENY_WRITE );
3972 if( SUCCEEDED( r ) )
3974 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
3975 (LPVOID*) &dl );
3976 if( SUCCEEDED( r ) )
3978 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
3979 (LPVOID) &darwin );
3980 IShellLinkDataList_Release( dl );
3983 IPersistFile_Release( pf );
3986 if (SUCCEEDED(init))
3987 CoUninitialize();
3989 TRACE("darwin = %p\n", darwin);
3991 if (darwin)
3993 DWORD sz;
3994 UINT ret;
3996 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
3997 szProductCode, szFeatureId, szComponentCode, &sz );
3998 LocalFree( darwin );
3999 return ret;
4002 return ERROR_FUNCTION_FAILED;
4005 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature, DWORD dwReinstallMode )
4007 static const WCHAR fmtW[] = {'%','s','=','%','s',' ','%','s','=','%','s',0};
4008 MSIPACKAGE *package;
4009 MSIINSTALLCONTEXT context;
4010 UINT r;
4011 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH], reinstallmode[11];
4012 WCHAR *ptr, *cmdline;
4013 DWORD sz;
4015 TRACE("%s, %s, 0x%08x\n", debugstr_w(szProduct), debugstr_w(szFeature), dwReinstallMode);
4017 r = msi_locate_product( szProduct, &context );
4018 if (r != ERROR_SUCCESS)
4019 return r;
4021 ptr = reinstallmode;
4023 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
4024 *ptr++ = 'p';
4025 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
4026 *ptr++ = 'o';
4027 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
4028 *ptr++ = 'w';
4029 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
4030 *ptr++ = 'd';
4031 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
4032 *ptr++ = 'c';
4033 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
4034 *ptr++ = 'a';
4035 if (dwReinstallMode & REINSTALLMODE_USERDATA)
4036 *ptr++ = 'u';
4037 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
4038 *ptr++ = 'm';
4039 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
4040 *ptr++ = 's';
4041 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
4042 *ptr++ = 'v';
4043 *ptr = 0;
4045 sz = sizeof(sourcepath);
4046 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT,
4047 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz );
4048 sz = sizeof(filename);
4049 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT,
4050 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz );
4051 lstrcatW( sourcepath, filename );
4053 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
4054 r = MSI_OpenPackageW( sourcepath, 0, &package );
4055 else
4056 r = MSI_OpenProductW( szProduct, &package );
4058 if (r != ERROR_SUCCESS)
4059 return r;
4061 sz = (lstrlenW( fmtW ) + lstrlenW( szReinstallMode ) + lstrlenW( reinstallmode )) * sizeof(WCHAR);
4062 sz += (lstrlenW( szReinstall ) + lstrlenW( szFeature )) * sizeof(WCHAR);
4063 if (!(cmdline = msi_alloc( sz )))
4065 msiobj_release( &package->hdr );
4066 return ERROR_OUTOFMEMORY;
4068 swprintf( cmdline, sz / sizeof(WCHAR), fmtW, szReinstallMode, reinstallmode, szReinstall, szFeature );
4070 r = MSI_InstallPackage( package, sourcepath, cmdline );
4071 msiobj_release( &package->hdr );
4072 msi_free( cmdline );
4074 return r;
4077 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
4078 DWORD dwReinstallMode )
4080 LPWSTR wszProduct;
4081 LPWSTR wszFeature;
4082 UINT rc;
4084 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
4085 dwReinstallMode);
4087 wszProduct = strdupAtoW(szProduct);
4088 wszFeature = strdupAtoW(szFeature);
4090 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
4092 msi_free(wszProduct);
4093 msi_free(wszFeature);
4094 return rc;
4097 typedef struct
4099 unsigned int i[2];
4100 unsigned int buf[4];
4101 unsigned char in[64];
4102 unsigned char digest[16];
4103 } MD5_CTX;
4105 extern VOID WINAPI MD5Init( MD5_CTX *);
4106 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
4107 extern VOID WINAPI MD5Final( MD5_CTX *);
4109 UINT msi_get_filehash( MSIPACKAGE *package, const WCHAR *path, MSIFILEHASHINFO *hash )
4111 HANDLE handle, mapping;
4112 void *p;
4113 DWORD length;
4114 UINT r = ERROR_FUNCTION_FAILED;
4116 if (package)
4117 handle = msi_create_file( package, path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, OPEN_EXISTING, 0 );
4118 else
4119 handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
4120 if (handle == INVALID_HANDLE_VALUE)
4122 WARN("can't open file %u\n", GetLastError());
4123 return ERROR_FILE_NOT_FOUND;
4125 if ((length = GetFileSize( handle, NULL )))
4127 if ((mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL )))
4129 if ((p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length )))
4131 MD5_CTX ctx;
4133 MD5Init( &ctx );
4134 MD5Update( &ctx, p, length );
4135 MD5Final( &ctx );
4136 UnmapViewOfFile( p );
4138 memcpy( hash->dwData, ctx.digest, sizeof(hash->dwData) );
4139 r = ERROR_SUCCESS;
4141 CloseHandle( mapping );
4144 else
4146 /* Empty file -> set hash to 0 */
4147 memset( hash->dwData, 0, sizeof(hash->dwData) );
4148 r = ERROR_SUCCESS;
4151 CloseHandle( handle );
4152 return r;
4155 /***********************************************************************
4156 * MsiGetFileHashW [MSI.@]
4158 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
4159 PMSIFILEHASHINFO pHash )
4161 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
4163 if (!szFilePath)
4164 return ERROR_INVALID_PARAMETER;
4166 if (!*szFilePath)
4167 return ERROR_PATH_NOT_FOUND;
4169 if (dwOptions)
4170 return ERROR_INVALID_PARAMETER;
4171 if (!pHash)
4172 return ERROR_INVALID_PARAMETER;
4173 if (pHash->dwFileHashInfoSize < sizeof *pHash)
4174 return ERROR_INVALID_PARAMETER;
4176 return msi_get_filehash( NULL, szFilePath, pHash );
4179 /***********************************************************************
4180 * MsiGetFileHashA [MSI.@]
4182 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
4183 PMSIFILEHASHINFO pHash )
4185 LPWSTR file;
4186 UINT r;
4188 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
4190 file = strdupAtoW( szFilePath );
4191 if (szFilePath && !file)
4192 return ERROR_OUTOFMEMORY;
4194 r = MsiGetFileHashW( file, dwOptions, pHash );
4195 msi_free( file );
4196 return r;
4199 /***********************************************************************
4200 * MsiAdvertiseScriptW [MSI.@]
4202 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
4203 PHKEY phRegData, BOOL fRemoveItems )
4205 FIXME("%s %08x %p %d\n",
4206 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
4207 return ERROR_CALL_NOT_IMPLEMENTED;
4210 /***********************************************************************
4211 * MsiAdvertiseScriptA [MSI.@]
4213 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
4214 PHKEY phRegData, BOOL fRemoveItems )
4216 FIXME("%s %08x %p %d\n",
4217 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
4218 return ERROR_CALL_NOT_IMPLEMENTED;
4221 /***********************************************************************
4222 * MsiIsProductElevatedW [MSI.@]
4224 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
4226 FIXME("%s %p - stub\n",
4227 debugstr_w( szProduct ), pfElevated );
4228 *pfElevated = TRUE;
4229 return ERROR_SUCCESS;
4232 /***********************************************************************
4233 * MsiIsProductElevatedA [MSI.@]
4235 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
4237 FIXME("%s %p - stub\n",
4238 debugstr_a( szProduct ), pfElevated );
4239 *pfElevated = TRUE;
4240 return ERROR_SUCCESS;
4243 /***********************************************************************
4244 * MsiSetExternalUIRecord [MSI.@]
4246 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler,
4247 DWORD filter, LPVOID context,
4248 PINSTALLUI_HANDLER_RECORD prev )
4250 TRACE("%p %08x %p %p\n", handler, filter, context, prev);
4252 if (prev)
4253 *prev = gUIHandlerRecord;
4255 gUIHandlerRecord = handler;
4256 gUIFilterRecord = filter;
4257 gUIContextRecord = context;
4259 return ERROR_SUCCESS;
4262 /***********************************************************************
4263 * MsiInstallMissingComponentA [MSI.@]
4265 UINT WINAPI MsiInstallMissingComponentA( LPCSTR product, LPCSTR component, INSTALLSTATE state )
4267 UINT r;
4268 WCHAR *productW = NULL, *componentW = NULL;
4270 TRACE("%s, %s, %d\n", debugstr_a(product), debugstr_a(component), state);
4272 if (product && !(productW = strdupAtoW( product )))
4273 return ERROR_OUTOFMEMORY;
4275 if (component && !(componentW = strdupAtoW( component )))
4277 msi_free( productW );
4278 return ERROR_OUTOFMEMORY;
4281 r = MsiInstallMissingComponentW( productW, componentW, state );
4282 msi_free( productW );
4283 msi_free( componentW );
4284 return r;
4287 /***********************************************************************
4288 * MsiInstallMissingComponentW [MSI.@]
4290 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState)
4292 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
4293 return ERROR_SUCCESS;
4296 UINT WINAPI MsiProvideComponentA( LPCSTR product, LPCSTR feature, LPCSTR component, DWORD mode, LPSTR buf, LPDWORD buflen )
4298 WCHAR *productW = NULL, *componentW = NULL, *featureW = NULL, *bufW = NULL;
4299 UINT r = ERROR_OUTOFMEMORY;
4300 DWORD lenW = 0;
4301 int len;
4303 TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_a(product), debugstr_a(component), debugstr_a(feature), mode, buf, buflen);
4305 if (product && !(productW = strdupAtoW( product ))) goto done;
4306 if (feature && !(featureW = strdupAtoW( feature ))) goto done;
4307 if (component && !(componentW = strdupAtoW( component ))) goto done;
4309 r = MsiProvideComponentW( productW, featureW, componentW, mode, NULL, &lenW );
4310 if (r != ERROR_SUCCESS)
4311 goto done;
4313 if (!(bufW = msi_alloc( ++lenW * sizeof(WCHAR) )))
4315 r = ERROR_OUTOFMEMORY;
4316 goto done;
4319 r = MsiProvideComponentW( productW, featureW, componentW, mode, bufW, &lenW );
4320 if (r != ERROR_SUCCESS)
4321 goto done;
4323 len = WideCharToMultiByte( CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
4324 if (buf)
4326 if (len > *buflen)
4327 r = ERROR_MORE_DATA;
4328 else
4329 WideCharToMultiByte( CP_ACP, 0, bufW, -1, buf, *buflen, NULL, NULL );
4332 *buflen = len - 1;
4334 done:
4335 msi_free( productW );
4336 msi_free( featureW );
4337 msi_free( componentW );
4338 msi_free( bufW );
4339 return r;
4342 UINT WINAPI MsiProvideComponentW( LPCWSTR product, LPCWSTR feature, LPCWSTR component, DWORD mode, LPWSTR buf, LPDWORD buflen )
4344 INSTALLSTATE state;
4346 TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_w(product), debugstr_w(component), debugstr_w(feature), mode, buf, buflen);
4348 state = MsiQueryFeatureStateW( product, feature );
4349 TRACE("feature state: %d\n", state);
4350 switch (mode)
4352 case INSTALLMODE_NODETECTION:
4353 break;
4355 default:
4356 FIXME("mode %x not implemented\n", mode);
4357 return ERROR_INSTALL_FAILURE;
4360 state = MsiGetComponentPathW( product, component, buf, buflen );
4361 TRACE("component state: %d\n", state);
4362 switch (state)
4364 case INSTALLSTATE_INVALIDARG:
4365 return ERROR_INVALID_PARAMETER;
4367 case INSTALLSTATE_MOREDATA:
4368 return ERROR_MORE_DATA;
4370 case INSTALLSTATE_ADVERTISED:
4371 case INSTALLSTATE_LOCAL:
4372 case INSTALLSTATE_SOURCE:
4373 MsiUseFeatureW( product, feature );
4374 return ERROR_SUCCESS;
4376 default:
4377 TRACE("MsiGetComponentPathW returned %d\n", state);
4378 return ERROR_INSTALL_FAILURE;
4382 /***********************************************************************
4383 * MsiBeginTransactionA [MSI.@]
4385 UINT WINAPI MsiBeginTransactionA( LPCSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event )
4387 WCHAR *nameW;
4388 UINT r;
4390 FIXME("%s %u %p %p\n", debugstr_a(name), attrs, id, event);
4392 nameW = strdupAtoW( name );
4393 if (name && !nameW)
4394 return ERROR_OUTOFMEMORY;
4396 r = MsiBeginTransactionW( nameW, attrs, id, event );
4397 msi_free( nameW );
4398 return r;
4401 /***********************************************************************
4402 * MsiBeginTransactionW [MSI.@]
4404 UINT WINAPI MsiBeginTransactionW( LPCWSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event )
4406 FIXME("%s %u %p %p\n", debugstr_w(name), attrs, id, event);
4408 *id = (MSIHANDLE)0xdeadbeef;
4409 *event = (HANDLE)0xdeadbeef;
4411 return ERROR_SUCCESS;
4414 /***********************************************************************
4415 * MsiJoinTransaction [MSI.@]
4417 UINT WINAPI MsiJoinTransaction( MSIHANDLE handle, DWORD attrs, HANDLE *event )
4419 FIXME("%u %08x %p\n", handle, attrs, event);
4421 *event = (HANDLE)0xdeadbeef;
4422 return ERROR_SUCCESS;
4425 /***********************************************************************
4426 * MsiEndTransaction [MSI.@]
4428 UINT WINAPI MsiEndTransaction( DWORD state )
4430 FIXME("%u\n", state);
4431 return ERROR_SUCCESS;
4434 UINT WINAPI Migrate10CachedPackagesW(void* a, void* b, void* c, DWORD d)
4436 FIXME("%p,%p,%p,%08x\n", a, b, c, d);
4437 return ERROR_SUCCESS;
4440 /***********************************************************************
4441 * MsiRemovePatchesA [MSI.@]
4443 UINT WINAPI MsiRemovePatchesA(LPCSTR patchlist, LPCSTR product, INSTALLTYPE type, LPCSTR propertylist)
4445 FIXME("(%s %s %d %s\n", debugstr_a(patchlist), debugstr_a(product), type, debugstr_a(propertylist));
4446 return ERROR_SUCCESS;
4449 /***********************************************************************
4450 * MsiRemovePatchesW [MSI.@]
4452 UINT WINAPI MsiRemovePatchesW(LPCWSTR patchlist, LPCWSTR product, INSTALLTYPE type, LPCWSTR propertylist)
4454 FIXME("(%s %s %d %s\n", debugstr_w(patchlist), debugstr_w(product), type, debugstr_w(propertylist));
4455 return ERROR_SUCCESS;