d2d1: Implement D2D1MakeSkewMatrix().
[wine.git] / dlls / msi / msi.c
blob39b9354552a083b6a5d365a20db66aaed2853fe9
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"
51 #include "wine/unicode.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(msi);
55 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
57 UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context)
59 HKEY hkey = NULL;
61 *context = MSIINSTALLCONTEXT_NONE;
62 if (!szProduct) return ERROR_UNKNOWN_PRODUCT;
64 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
65 &hkey, FALSE) == ERROR_SUCCESS)
66 *context = MSIINSTALLCONTEXT_USERMANAGED;
67 else if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
68 &hkey, FALSE) == ERROR_SUCCESS)
69 *context = MSIINSTALLCONTEXT_MACHINE;
70 else if (MSIREG_OpenProductKey(szProduct, NULL,
71 MSIINSTALLCONTEXT_USERUNMANAGED,
72 &hkey, FALSE) == ERROR_SUCCESS)
73 *context = MSIINSTALLCONTEXT_USERUNMANAGED;
75 RegCloseKey(hkey);
77 if (*context == MSIINSTALLCONTEXT_NONE)
78 return ERROR_UNKNOWN_PRODUCT;
80 return ERROR_SUCCESS;
83 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
85 UINT r;
86 LPWSTR szwProd = NULL;
88 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
90 if( szProduct )
92 szwProd = strdupAtoW( szProduct );
93 if( !szwProd )
94 return ERROR_OUTOFMEMORY;
97 r = MsiOpenProductW( szwProd, phProduct );
99 msi_free( szwProd );
101 return r;
104 static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package)
106 UINT r;
107 HKEY props;
108 LPWSTR path;
109 MSIINSTALLCONTEXT context;
111 static const WCHAR managed[] = {
112 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
113 static const WCHAR local[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
115 TRACE("%s %p\n", debugstr_w(szProduct), package);
117 r = msi_locate_product(szProduct, &context);
118 if (r != ERROR_SUCCESS)
119 return r;
121 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &props, FALSE);
122 if (r != ERROR_SUCCESS)
123 return ERROR_UNKNOWN_PRODUCT;
125 if (context == MSIINSTALLCONTEXT_USERMANAGED)
126 path = msi_reg_get_val_str(props, managed);
127 else
128 path = msi_reg_get_val_str(props, local);
130 r = ERROR_UNKNOWN_PRODUCT;
132 if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
133 goto done;
135 if (PathIsRelativeW(path))
137 r = ERROR_INSTALL_PACKAGE_OPEN_FAILED;
138 goto done;
141 r = MSI_OpenPackageW(path, 0, package);
143 done:
144 RegCloseKey(props);
145 msi_free(path);
146 return r;
149 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
151 MSIPACKAGE *package = NULL;
152 WCHAR squashed_pc[SQUASHED_GUID_SIZE];
153 UINT r;
155 if (!szProduct || !squash_guid( szProduct, squashed_pc ))
156 return ERROR_INVALID_PARAMETER;
158 if (!phProduct)
159 return ERROR_INVALID_PARAMETER;
161 r = MSI_OpenProductW(szProduct, &package);
162 if (r != ERROR_SUCCESS)
163 return r;
165 *phProduct = alloc_msihandle(&package->hdr);
166 if (!*phProduct)
167 r = ERROR_NOT_ENOUGH_MEMORY;
169 msiobj_release(&package->hdr);
170 return r;
173 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
174 LPCSTR szTransforms, LANGID lgidLanguage)
176 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
177 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
178 return ERROR_CALL_NOT_IMPLEMENTED;
181 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
182 LPCWSTR szTransforms, LANGID lgidLanguage)
184 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
185 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
186 return ERROR_CALL_NOT_IMPLEMENTED;
189 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
190 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
192 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath),
193 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
194 lgidLanguage, dwPlatform, dwOptions);
195 return ERROR_CALL_NOT_IMPLEMENTED;
198 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
199 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
201 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath),
202 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
203 lgidLanguage, dwPlatform, dwOptions);
204 return ERROR_CALL_NOT_IMPLEMENTED;
207 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
209 LPWSTR szwPath = NULL, szwCommand = NULL;
210 UINT r = ERROR_OUTOFMEMORY;
212 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
214 if( szPackagePath )
216 szwPath = strdupAtoW( szPackagePath );
217 if( !szwPath )
218 goto end;
221 if( szCommandLine )
223 szwCommand = strdupAtoW( szCommandLine );
224 if( !szwCommand )
225 goto end;
228 r = MsiInstallProductW( szwPath, szwCommand );
230 end:
231 msi_free( szwPath );
232 msi_free( szwCommand );
234 return r;
237 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
239 MSIPACKAGE *package = NULL;
240 const WCHAR *reinstallmode;
241 DWORD options = 0;
242 UINT r, len;
244 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
246 if (!szPackagePath)
247 return ERROR_INVALID_PARAMETER;
249 if (!*szPackagePath)
250 return ERROR_PATH_NOT_FOUND;
252 reinstallmode = msi_get_command_line_option(szCommandLine, szReinstallMode, &len);
253 if (reinstallmode)
255 while (len > 0)
257 if (reinstallmode[--len] == 'v' || reinstallmode[len] == 'V')
259 options |= WINE_OPENPACKAGEFLAGS_RECACHE;
260 break;
265 r = MSI_OpenPackageW( szPackagePath, options, &package );
266 if (r == ERROR_SUCCESS)
268 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
269 msiobj_release( &package->hdr );
272 return r;
275 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
277 LPWSTR wszProduct;
278 UINT rc;
280 TRACE("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
282 wszProduct = strdupAtoW(szProduct);
284 rc = MsiReinstallProductW(wszProduct, dwReinstallMode);
286 msi_free(wszProduct);
287 return rc;
290 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
292 TRACE("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
294 return MsiReinstallFeatureW(szProduct, szAll, dwReinstallMode);
297 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
298 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
300 LPWSTR patch_package = NULL;
301 LPWSTR install_package = NULL;
302 LPWSTR command_line = NULL;
303 UINT r = ERROR_OUTOFMEMORY;
305 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
306 eInstallType, debugstr_a(szCommandLine));
308 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage)))
309 goto done;
311 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage)))
312 goto done;
314 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine)))
315 goto done;
317 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line);
319 done:
320 msi_free(patch_package);
321 msi_free(install_package);
322 msi_free(command_line);
324 return r;
327 static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes )
329 MSIHANDLE patch, info = 0;
330 UINT r, type;
331 DWORD size;
332 static WCHAR empty[] = {0};
333 WCHAR *codes = NULL;
335 r = MsiOpenDatabaseW( szPatchPackage, MSIDBOPEN_READONLY, &patch );
336 if (r != ERROR_SUCCESS)
337 return r;
339 r = MsiGetSummaryInformationW( patch, NULL, 0, &info );
340 if (r != ERROR_SUCCESS)
341 goto done;
343 size = 0;
344 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, empty, &size );
345 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
347 ERR("Failed to read product codes from patch\n");
348 r = ERROR_FUNCTION_FAILED;
349 goto done;
352 codes = msi_alloc( ++size * sizeof(WCHAR) );
353 if (!codes)
355 r = ERROR_OUTOFMEMORY;
356 goto done;
359 r = MsiSummaryInfoGetPropertyW( info, PID_TEMPLATE, &type, NULL, NULL, codes, &size );
360 if (r == ERROR_SUCCESS)
361 *product_codes = msi_split_string( codes, ';' );
363 done:
364 MsiCloseHandle( info );
365 MsiCloseHandle( patch );
366 msi_free( codes );
367 return r;
370 static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
372 UINT i, r = ERROR_FUNCTION_FAILED;
373 DWORD size;
374 LPCWSTR cmd_ptr = szCommandLine;
375 LPWSTR cmd, *codes = NULL;
376 BOOL succeeded = FALSE;
378 static const WCHAR fmt[] = {'%','s',' ','P','A','T','C','H','=','"','%','s','"',0};
379 static const WCHAR empty[] = {0};
381 if (!szPatchPackage || !szPatchPackage[0])
382 return ERROR_INVALID_PARAMETER;
384 if (!szProductCode && (r = get_patch_product_codes( szPatchPackage, &codes )))
385 return r;
387 if (!szCommandLine)
388 cmd_ptr = empty;
390 size = strlenW(cmd_ptr) + strlenW(fmt) + strlenW(szPatchPackage) + 1;
391 cmd = msi_alloc(size * sizeof(WCHAR));
392 if (!cmd)
394 msi_free(codes);
395 return ERROR_OUTOFMEMORY;
397 sprintfW(cmd, fmt, cmd_ptr, szPatchPackage);
399 if (szProductCode)
400 r = MsiConfigureProductExW(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
401 else
403 for (i = 0; codes[i]; i++)
405 r = MsiConfigureProductExW(codes[i], INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
406 if (r == ERROR_SUCCESS)
408 TRACE("patch applied\n");
409 succeeded = TRUE;
413 if (succeeded)
414 r = ERROR_SUCCESS;
417 msi_free(cmd);
418 msi_free(codes);
419 return r;
422 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
423 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
425 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
426 eInstallType, debugstr_w(szCommandLine));
428 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
429 eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
431 FIXME("Only reading target products from patch\n");
432 return ERROR_CALL_NOT_IMPLEMENTED;
435 return MSI_ApplyPatchW(szPatchPackage, NULL, szCommandLine);
438 UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR szPatchPackages,
439 LPCSTR szProductCode, LPCSTR szPropertiesList)
441 LPWSTR patch_packages = NULL;
442 LPWSTR product_code = NULL;
443 LPWSTR properties_list = NULL;
444 UINT r = ERROR_OUTOFMEMORY;
446 TRACE("%s %s %s\n", debugstr_a(szPatchPackages), debugstr_a(szProductCode),
447 debugstr_a(szPropertiesList));
449 if (!szPatchPackages || !szPatchPackages[0])
450 return ERROR_INVALID_PARAMETER;
452 if (!(patch_packages = strdupAtoW(szPatchPackages)))
453 return ERROR_OUTOFMEMORY;
455 if (szProductCode && !(product_code = strdupAtoW(szProductCode)))
456 goto done;
458 if (szPropertiesList && !(properties_list = strdupAtoW(szPropertiesList)))
459 goto done;
461 r = MsiApplyMultiplePatchesW(patch_packages, product_code, properties_list);
463 done:
464 msi_free(patch_packages);
465 msi_free(product_code);
466 msi_free(properties_list);
468 return r;
471 UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages,
472 LPCWSTR szProductCode, LPCWSTR szPropertiesList)
474 UINT r = ERROR_SUCCESS;
475 LPCWSTR beg, end;
477 TRACE("%s %s %s\n", debugstr_w(szPatchPackages), debugstr_w(szProductCode),
478 debugstr_w(szPropertiesList));
480 if (!szPatchPackages || !szPatchPackages[0])
481 return ERROR_INVALID_PARAMETER;
483 beg = end = szPatchPackages;
484 while (*beg)
486 DWORD len;
487 LPWSTR patch;
489 while (*beg == ' ') beg++;
490 while (*end && *end != ';') end++;
492 len = end - beg;
493 while (len && beg[len - 1] == ' ') len--;
495 if (!len) return ERROR_INVALID_NAME;
497 patch = msi_alloc((len + 1) * sizeof(WCHAR));
498 if (!patch)
499 return ERROR_OUTOFMEMORY;
501 memcpy(patch, beg, len * sizeof(WCHAR));
502 patch[len] = '\0';
504 r = MSI_ApplyPatchW(patch, szProductCode, szPropertiesList);
505 msi_free(patch);
507 if (r != ERROR_SUCCESS || !*end)
508 break;
510 beg = ++end;
512 return r;
515 static void free_patchinfo( DWORD count, MSIPATCHSEQUENCEINFOW *info )
517 DWORD i;
518 for (i = 0; i < count; i++) msi_free( (WCHAR *)info[i].szPatchData );
519 msi_free( info );
522 static MSIPATCHSEQUENCEINFOW *patchinfoAtoW( DWORD count, const MSIPATCHSEQUENCEINFOA *info )
524 DWORD i;
525 MSIPATCHSEQUENCEINFOW *ret;
527 if (!(ret = msi_alloc( count * sizeof(MSIPATCHSEQUENCEINFOW) ))) return NULL;
528 for (i = 0; i < count; i++)
530 if (info[i].szPatchData && !(ret[i].szPatchData = strdupAtoW( info[i].szPatchData )))
532 free_patchinfo( i, ret );
533 return NULL;
535 ret[i].ePatchDataType = info[i].ePatchDataType;
536 ret[i].dwOrder = info[i].dwOrder;
537 ret[i].uStatus = info[i].uStatus;
539 return ret;
542 UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
543 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
545 UINT i, r;
546 WCHAR *package_path = NULL;
547 MSIPATCHSEQUENCEINFOW *psi;
549 TRACE("%s, %u, %p\n", debugstr_a(szProductPackagePath), cPatchInfo, pPatchInfo);
551 if (szProductPackagePath && !(package_path = strdupAtoW( szProductPackagePath )))
552 return ERROR_OUTOFMEMORY;
554 if (!(psi = patchinfoAtoW( cPatchInfo, pPatchInfo )))
556 msi_free( package_path );
557 return ERROR_OUTOFMEMORY;
559 r = MsiDetermineApplicablePatchesW( package_path, cPatchInfo, psi );
560 if (r == ERROR_SUCCESS)
562 for (i = 0; i < cPatchInfo; i++)
564 pPatchInfo[i].dwOrder = psi[i].dwOrder;
565 pPatchInfo[i].uStatus = psi[i].uStatus;
568 msi_free( package_path );
569 free_patchinfo( cPatchInfo, psi );
570 return r;
573 static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
575 MSISUMMARYINFO *si;
576 MSIDATABASE *patch_db;
577 UINT r;
579 r = MSI_OpenDatabaseW( patch, MSIDBOPEN_READONLY, &patch_db );
580 if (r != ERROR_SUCCESS)
582 WARN("failed to open patch file %s\n", debugstr_w(patch));
583 return r;
586 r = msi_get_suminfo( patch_db->storage, 0, &si );
587 if (r != ERROR_SUCCESS)
589 msiobj_release( &patch_db->hdr );
590 return ERROR_FUNCTION_FAILED;
593 r = msi_check_patch_applicable( package, si );
594 if (r != ERROR_SUCCESS)
595 TRACE("patch not applicable\n");
597 msiobj_release( &patch_db->hdr );
598 msiobj_release( &si->hdr );
599 return r;
602 /* IXMLDOMDocument should be set to XPath mode already */
603 static UINT MSI_ApplicablePatchXML( MSIPACKAGE *package, IXMLDOMDocument *desc )
605 static const WCHAR queryW[] = {'M','s','i','P','a','t','c','h','/',
606 'T','a','r','g','e','t','P','r','o','d','u','c','t','/',
607 'T','a','r','g','e','t','P','r','o','d','u','c','t','C','o','d','e',0};
608 UINT r = ERROR_FUNCTION_FAILED;
609 IXMLDOMNodeList *list;
610 LPWSTR product_code;
611 IXMLDOMNode *node;
612 HRESULT hr;
613 BSTR s;
615 product_code = msi_dup_property( package->db, szProductCode );
616 if (!product_code)
618 /* FIXME: the property ProductCode should be written into the DB somewhere */
619 ERR("no product code to check\n");
620 return ERROR_SUCCESS;
623 s = SysAllocString(queryW);
624 hr = IXMLDOMDocument_selectNodes( desc, s, &list );
625 SysFreeString(s);
626 if (hr != S_OK)
627 return ERROR_INVALID_PATCH_XML;
629 while (IXMLDOMNodeList_nextNode( list, &node ) == S_OK && r != ERROR_SUCCESS)
631 hr = IXMLDOMNode_get_text( node, &s );
632 IXMLDOMNode_Release( node );
633 if (hr == S_OK)
635 if (!strcmpW( s, product_code )) r = ERROR_SUCCESS;
636 SysFreeString( s );
639 IXMLDOMNodeList_Release( list );
641 if (r != ERROR_SUCCESS)
642 TRACE("patch not applicable\n");
644 msi_free( product_code );
645 return r;
648 static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCHSEQUENCEINFOW *info )
650 IXMLDOMDocument *desc = NULL;
651 DWORD i;
653 if (count > 1)
654 FIXME("patch ordering not supported\n");
656 for (i = 0; i < count; i++)
658 switch (info[i].ePatchDataType)
660 case MSIPATCH_DATATYPE_PATCHFILE:
662 if (MSI_ApplicablePatchW( package, info[i].szPatchData ) != ERROR_SUCCESS)
664 info[i].dwOrder = ~0u;
665 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
667 else
669 info[i].dwOrder = i;
670 info[i].uStatus = ERROR_SUCCESS;
672 break;
674 case MSIPATCH_DATATYPE_XMLPATH:
675 case MSIPATCH_DATATYPE_XMLBLOB:
677 VARIANT_BOOL b;
678 HRESULT hr;
679 BSTR s;
681 if (!desc)
683 hr = CoCreateInstance( &CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER,
684 &IID_IXMLDOMDocument, (void**)&desc );
685 if (hr != S_OK)
687 ERR("failed to create DOMDocument30 instance, 0x%08x\n", hr);
688 return ERROR_FUNCTION_FAILED;
692 s = SysAllocString( info[i].szPatchData );
693 if (info[i].ePatchDataType == MSIPATCH_DATATYPE_XMLPATH)
695 VARIANT src;
697 V_VT(&src) = VT_BSTR;
698 V_BSTR(&src) = s;
699 hr = IXMLDOMDocument_load( desc, src, &b );
701 else
702 hr = IXMLDOMDocument_loadXML( desc, s, &b );
703 SysFreeString( s );
704 if ( hr != S_OK )
706 ERR("failed to parse patch description\n");
707 IXMLDOMDocument_Release( desc );
708 break;
711 if (MSI_ApplicablePatchXML( package, desc ) != ERROR_SUCCESS)
713 info[i].dwOrder = ~0u;
714 info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
716 else
718 info[i].dwOrder = i;
719 info[i].uStatus = ERROR_SUCCESS;
721 break;
723 default:
725 FIXME("unknown patch data type %u\n", info[i].ePatchDataType);
726 info[i].dwOrder = i;
727 info[i].uStatus = ERROR_SUCCESS;
728 break;
732 TRACE("szPatchData: %s\n", debugstr_w(info[i].szPatchData));
733 TRACE("ePatchDataType: %u\n", info[i].ePatchDataType);
734 TRACE("dwOrder: %u\n", info[i].dwOrder);
735 TRACE("uStatus: %u\n", info[i].uStatus);
738 if (desc) IXMLDOMDocument_Release( desc );
740 return ERROR_SUCCESS;
743 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath,
744 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
746 UINT r;
747 MSIPACKAGE *package;
749 TRACE("%s, %u, %p\n", debugstr_w(szProductPackagePath), cPatchInfo, pPatchInfo);
751 r = MSI_OpenPackageW( szProductPackagePath, 0, &package );
752 if (r != ERROR_SUCCESS)
754 ERR("failed to open package %u\n", r);
755 return r;
757 r = determine_patch_sequence( package, cPatchInfo, pPatchInfo );
758 msiobj_release( &package->hdr );
759 return r;
762 UINT WINAPI MsiDeterminePatchSequenceA( LPCSTR product, LPCSTR usersid,
763 MSIINSTALLCONTEXT context, DWORD count, PMSIPATCHSEQUENCEINFOA patchinfo )
765 UINT i, r;
766 WCHAR *productW, *usersidW = NULL;
767 MSIPATCHSEQUENCEINFOW *patchinfoW;
769 TRACE("%s, %s, %d, %d, %p\n", debugstr_a(product), debugstr_a(usersid),
770 context, count, patchinfo);
772 if (!product) return ERROR_INVALID_PARAMETER;
773 if (!(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
774 if (usersid && !(usersidW = strdupAtoW( usersid )))
776 msi_free( productW );
777 return ERROR_OUTOFMEMORY;
779 if (!(patchinfoW = patchinfoAtoW( count, patchinfo )))
781 msi_free( productW );
782 msi_free( usersidW );
783 return ERROR_OUTOFMEMORY;
785 r = MsiDeterminePatchSequenceW( productW, usersidW, context, count, patchinfoW );
786 if (r == ERROR_SUCCESS)
788 for (i = 0; i < count; i++)
790 patchinfo[i].dwOrder = patchinfoW[i].dwOrder;
791 patchinfo[i].uStatus = patchinfoW[i].uStatus;
794 msi_free( productW );
795 msi_free( usersidW );
796 free_patchinfo( count, patchinfoW );
797 return r;
800 static UINT open_package( const WCHAR *product, const WCHAR *usersid,
801 MSIINSTALLCONTEXT context, MSIPACKAGE **package )
803 UINT r;
804 HKEY props;
805 WCHAR *localpath, sourcepath[MAX_PATH], filename[MAX_PATH];
807 r = MSIREG_OpenInstallProps( product, context, usersid, &props, FALSE );
808 if (r != ERROR_SUCCESS) return ERROR_BAD_CONFIGURATION;
810 if ((localpath = msi_reg_get_val_str( props, szLocalPackage )))
812 strcpyW( sourcepath, localpath );
813 msi_free( localpath );
815 RegCloseKey( props );
816 if (!localpath || GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES)
818 DWORD sz = sizeof(sourcepath);
819 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT,
820 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz );
821 sz = sizeof(filename);
822 MsiSourceListGetInfoW( product, usersid, context, MSICODE_PRODUCT,
823 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz );
824 strcatW( sourcepath, filename );
826 if (GetFileAttributesW( sourcepath ) == INVALID_FILE_ATTRIBUTES)
827 return ERROR_INSTALL_SOURCE_ABSENT;
829 return MSI_OpenPackageW( sourcepath, 0, package );
832 UINT WINAPI MsiDeterminePatchSequenceW( LPCWSTR product, LPCWSTR usersid,
833 MSIINSTALLCONTEXT context, DWORD count, PMSIPATCHSEQUENCEINFOW patchinfo )
835 UINT r;
836 MSIPACKAGE *package;
838 TRACE("%s, %s, %d, %d, %p\n", debugstr_w(product), debugstr_w(usersid),
839 context, count, patchinfo);
841 if (!product) return ERROR_INVALID_PARAMETER;
842 r = open_package( product, usersid, context, &package );
843 if (r != ERROR_SUCCESS) return r;
845 r = determine_patch_sequence( package, count, patchinfo );
846 msiobj_release( &package->hdr );
847 return r;
850 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
851 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
853 MSIPACKAGE* package = NULL;
854 MSIINSTALLCONTEXT context;
855 UINT r;
856 DWORD sz;
857 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
858 LPWSTR commandline;
860 static const WCHAR szInstalled[] = {
861 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
862 static const WCHAR szMaxInstallLevel[] = {
863 ' ','I','N','S','T','A','L','L','L','E','V','E','L','=','3','2','7','6','7',0};
864 static const WCHAR szRemoveAll[] = {
865 ' ','R','E','M','O','V','E','=','A','L','L',0};
866 static const WCHAR szMachine[] = {
867 ' ','A','L','L','U','S','E','R','S','=','1',0};
869 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
870 debugstr_w(szCommandLine));
872 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1)
873 return ERROR_INVALID_PARAMETER;
875 if (eInstallState == INSTALLSTATE_ADVERTISED ||
876 eInstallState == INSTALLSTATE_SOURCE)
878 FIXME("State %d not implemented\n", eInstallState);
879 return ERROR_CALL_NOT_IMPLEMENTED;
882 r = msi_locate_product(szProduct, &context);
883 if (r != ERROR_SUCCESS)
884 return r;
886 r = open_package(szProduct, NULL, context, &package);
887 if (r != ERROR_SUCCESS)
888 return r;
890 sz = lstrlenW(szInstalled) + 1;
892 if (szCommandLine)
893 sz += lstrlenW(szCommandLine);
895 if (eInstallState != INSTALLSTATE_DEFAULT)
896 sz += lstrlenW(szMaxInstallLevel);
898 if (eInstallState == INSTALLSTATE_ABSENT)
899 sz += lstrlenW(szRemoveAll);
901 if (context == MSIINSTALLCONTEXT_MACHINE)
902 sz += lstrlenW(szMachine);
904 commandline = msi_alloc(sz * sizeof(WCHAR));
905 if (!commandline)
907 r = ERROR_OUTOFMEMORY;
908 goto end;
911 commandline[0] = 0;
912 if (szCommandLine)
913 lstrcpyW(commandline,szCommandLine);
915 if (eInstallState != INSTALLSTATE_DEFAULT)
916 lstrcatW(commandline, szMaxInstallLevel);
918 if (eInstallState == INSTALLSTATE_ABSENT)
919 lstrcatW(commandline, szRemoveAll);
921 if (context == MSIINSTALLCONTEXT_MACHINE)
922 lstrcatW(commandline, szMachine);
924 sz = sizeof(sourcepath);
925 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
926 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
928 sz = sizeof(filename);
929 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
930 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
932 strcatW(sourcepath, filename);
934 r = MSI_InstallPackage( package, sourcepath, commandline );
936 msi_free(commandline);
938 end:
939 msiobj_release( &package->hdr );
941 return r;
944 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
945 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
947 LPWSTR szwProduct = NULL;
948 LPWSTR szwCommandLine = NULL;
949 UINT r = ERROR_OUTOFMEMORY;
951 if( szProduct )
953 szwProduct = strdupAtoW( szProduct );
954 if( !szwProduct )
955 goto end;
958 if( szCommandLine)
960 szwCommandLine = strdupAtoW( szCommandLine );
961 if( !szwCommandLine)
962 goto end;
965 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
966 szwCommandLine );
967 end:
968 msi_free( szwProduct );
969 msi_free( szwCommandLine);
971 return r;
974 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
975 INSTALLSTATE eInstallState)
977 LPWSTR szwProduct = NULL;
978 UINT r;
980 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
982 if( szProduct )
984 szwProduct = strdupAtoW( szProduct );
985 if( !szwProduct )
986 return ERROR_OUTOFMEMORY;
989 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
990 msi_free( szwProduct );
992 return r;
995 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
996 INSTALLSTATE eInstallState)
998 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
1001 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
1003 LPWSTR szwComponent = NULL;
1004 UINT r;
1005 WCHAR szwBuffer[GUID_SIZE];
1007 TRACE("%s %p\n", debugstr_a(szComponent), szBuffer);
1009 if( szComponent )
1011 szwComponent = strdupAtoW( szComponent );
1012 if( !szwComponent )
1013 return ERROR_OUTOFMEMORY;
1016 *szwBuffer = '\0';
1017 r = MsiGetProductCodeW( szwComponent, szwBuffer );
1019 if(*szwBuffer)
1020 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
1022 msi_free( szwComponent );
1024 return r;
1027 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
1029 UINT rc, index;
1030 HKEY compkey, prodkey;
1031 WCHAR squashed_comp[SQUASHED_GUID_SIZE], squashed_prod[SQUASHED_GUID_SIZE];
1032 DWORD sz = ARRAY_SIZE(squashed_prod);
1034 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer);
1036 if (!szComponent || !*szComponent)
1037 return ERROR_INVALID_PARAMETER;
1039 if (!squash_guid( szComponent, squashed_comp ))
1040 return ERROR_INVALID_PARAMETER;
1042 if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &compkey, FALSE) != ERROR_SUCCESS &&
1043 MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &compkey, FALSE) != ERROR_SUCCESS)
1045 return ERROR_UNKNOWN_COMPONENT;
1048 rc = RegEnumValueW( compkey, 0, squashed_prod, &sz, NULL, NULL, NULL, NULL );
1049 if (rc != ERROR_SUCCESS)
1051 RegCloseKey(compkey);
1052 return ERROR_UNKNOWN_COMPONENT;
1055 /* check simple case, only one product */
1056 rc = RegEnumValueW( compkey, 1, squashed_prod, &sz, NULL, NULL, NULL, NULL );
1057 if (rc == ERROR_NO_MORE_ITEMS)
1059 rc = ERROR_SUCCESS;
1060 goto done;
1063 index = 0;
1064 while ((rc = RegEnumValueW( compkey, index, squashed_prod, &sz, NULL, NULL, NULL, NULL )) !=
1065 ERROR_NO_MORE_ITEMS)
1067 index++;
1068 sz = GUID_SIZE;
1069 unsquash_guid( squashed_prod, szBuffer );
1071 if (MSIREG_OpenProductKey(szBuffer, NULL,
1072 MSIINSTALLCONTEXT_USERMANAGED,
1073 &prodkey, FALSE) == ERROR_SUCCESS ||
1074 MSIREG_OpenProductKey(szBuffer, NULL,
1075 MSIINSTALLCONTEXT_USERUNMANAGED,
1076 &prodkey, FALSE) == ERROR_SUCCESS ||
1077 MSIREG_OpenProductKey(szBuffer, NULL,
1078 MSIINSTALLCONTEXT_MACHINE,
1079 &prodkey, FALSE) == ERROR_SUCCESS)
1081 RegCloseKey(prodkey);
1082 rc = ERROR_SUCCESS;
1083 goto done;
1087 rc = ERROR_INSTALL_FAILURE;
1089 done:
1090 RegCloseKey(compkey);
1091 unsquash_guid( squashed_prod, szBuffer );
1092 return rc;
1095 static WCHAR *reg_get_value( HKEY hkey, const WCHAR *name, DWORD *type )
1097 LONG res;
1099 if ((res = RegQueryValueExW( hkey, name, NULL, type, NULL, NULL )) != ERROR_SUCCESS) return NULL;
1101 if (*type == REG_SZ) return msi_reg_get_val_str( hkey, name );
1102 if (*type == REG_DWORD)
1104 static const WCHAR fmt[] = {'%','u',0};
1105 WCHAR temp[11];
1106 DWORD val;
1108 if (!msi_reg_get_val_dword( hkey, name, &val )) return NULL;
1109 sprintfW( temp, fmt, val );
1110 return strdupW( temp );
1113 ERR( "unhandled value type %u\n", *type );
1114 return NULL;
1117 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
1118 awstring *szValue, LPDWORD pcchValueBuf)
1120 static WCHAR empty[] = {0};
1121 static const WCHAR sourcelist[] = {'S','o','u','r','c','e','L','i','s','t',0};
1122 static const WCHAR display_name[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
1123 static const WCHAR display_version[] = {'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1124 static const WCHAR assignment[] = {'A','s','s','i','g','n','m','e','n','t',0};
1125 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
1126 UINT r = ERROR_UNKNOWN_PROPERTY;
1127 HKEY prodkey, userdata, source;
1128 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE], packagecode[GUID_SIZE];
1129 BOOL badconfig = FALSE;
1130 LONG res;
1131 DWORD type = REG_NONE;
1133 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1134 debugstr_w(szAttribute), szValue, pcchValueBuf);
1136 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
1137 return ERROR_INVALID_PARAMETER;
1139 if (!squash_guid( szProduct, squashed_pc ))
1140 return ERROR_INVALID_PARAMETER;
1142 if ((r = MSIREG_OpenProductKey(szProduct, NULL,
1143 MSIINSTALLCONTEXT_USERMANAGED,
1144 &prodkey, FALSE)) != ERROR_SUCCESS &&
1145 (r = MSIREG_OpenProductKey(szProduct, NULL,
1146 MSIINSTALLCONTEXT_USERUNMANAGED,
1147 &prodkey, FALSE)) != ERROR_SUCCESS &&
1148 (r = MSIREG_OpenProductKey(szProduct, NULL,
1149 MSIINSTALLCONTEXT_MACHINE,
1150 &prodkey, FALSE)) == ERROR_SUCCESS)
1152 context = MSIINSTALLCONTEXT_MACHINE;
1155 if (!strcmpW( szAttribute, INSTALLPROPERTY_HELPLINKW ) ||
1156 !strcmpW( szAttribute, INSTALLPROPERTY_HELPTELEPHONEW ) ||
1157 !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLDATEW ) ||
1158 !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
1159 !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
1160 !strcmpW( szAttribute, INSTALLPROPERTY_INSTALLSOURCEW ) ||
1161 !strcmpW( szAttribute, INSTALLPROPERTY_LOCALPACKAGEW ) ||
1162 !strcmpW( szAttribute, INSTALLPROPERTY_PUBLISHERW ) ||
1163 !strcmpW( szAttribute, INSTALLPROPERTY_URLINFOABOUTW ) ||
1164 !strcmpW( szAttribute, INSTALLPROPERTY_URLUPDATEINFOW ) ||
1165 !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMINORW ) ||
1166 !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONMAJORW ) ||
1167 !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ) ||
1168 !strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTIDW ) ||
1169 !strcmpW( szAttribute, INSTALLPROPERTY_REGCOMPANYW ) ||
1170 !strcmpW( szAttribute, INSTALLPROPERTY_REGOWNERW ))
1172 if (!prodkey)
1174 r = ERROR_UNKNOWN_PRODUCT;
1175 goto done;
1177 if (MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE))
1179 r = ERROR_UNKNOWN_PROPERTY;
1180 goto done;
1183 if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
1184 szAttribute = display_name;
1185 else if (!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
1186 szAttribute = display_version;
1188 val = reg_get_value(userdata, szAttribute, &type);
1189 if (!val)
1190 val = empty;
1191 RegCloseKey(userdata);
1193 else if (!strcmpW( szAttribute, INSTALLPROPERTY_INSTANCETYPEW ) ||
1194 !strcmpW( szAttribute, INSTALLPROPERTY_TRANSFORMSW ) ||
1195 !strcmpW( szAttribute, INSTALLPROPERTY_LANGUAGEW ) ||
1196 !strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTNAMEW ) ||
1197 !strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ) ||
1198 !strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW ) ||
1199 !strcmpW( szAttribute, INSTALLPROPERTY_VERSIONW ) ||
1200 !strcmpW( szAttribute, INSTALLPROPERTY_PRODUCTICONW ) ||
1201 !strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ) ||
1202 !strcmpW( szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
1204 if (!prodkey)
1206 r = ERROR_UNKNOWN_PRODUCT;
1207 goto done;
1210 if (!strcmpW( szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
1211 szAttribute = assignment;
1213 if (!strcmpW( szAttribute, INSTALLPROPERTY_PACKAGENAMEW ))
1215 res = RegOpenKeyW(prodkey, sourcelist, &source);
1216 if (res != ERROR_SUCCESS)
1218 r = ERROR_UNKNOWN_PRODUCT;
1219 goto done;
1222 val = reg_get_value(source, szAttribute, &type);
1223 if (!val)
1224 val = empty;
1226 RegCloseKey(source);
1228 else
1230 val = reg_get_value(prodkey, szAttribute, &type);
1231 if (!val)
1232 val = empty;
1235 if (val != empty && type != REG_DWORD &&
1236 !strcmpW( szAttribute, INSTALLPROPERTY_PACKAGECODEW ))
1238 if (lstrlenW( val ) != SQUASHED_GUID_SIZE - 1)
1239 badconfig = TRUE;
1240 else
1242 unsquash_guid(val, packagecode);
1243 msi_free(val);
1244 val = strdupW(packagecode);
1249 if (!val)
1251 r = ERROR_UNKNOWN_PROPERTY;
1252 goto done;
1255 if (pcchValueBuf)
1257 int len = strlenW( val );
1259 /* If szBuffer (szValue->str) is NULL, there's no need to copy the value
1260 * out. Also, *pcchValueBuf may be uninitialized in this case, so we
1261 * can't rely on its value.
1263 if (szValue->str.a || szValue->str.w)
1265 DWORD size = *pcchValueBuf;
1266 if (len < size)
1267 r = msi_strcpy_to_awstring( val, len, szValue, &size );
1268 else
1269 r = ERROR_MORE_DATA;
1272 if (!badconfig)
1273 *pcchValueBuf = len;
1276 if (badconfig)
1277 r = ERROR_BAD_CONFIGURATION;
1279 if (val != empty)
1280 msi_free(val);
1282 done:
1283 RegCloseKey(prodkey);
1284 return r;
1287 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
1288 LPSTR szBuffer, LPDWORD pcchValueBuf)
1290 LPWSTR szwProduct, szwAttribute = NULL;
1291 UINT r = ERROR_OUTOFMEMORY;
1292 awstring buffer;
1294 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
1295 szBuffer, pcchValueBuf);
1297 szwProduct = strdupAtoW( szProduct );
1298 if( szProduct && !szwProduct )
1299 goto end;
1301 szwAttribute = strdupAtoW( szAttribute );
1302 if( szAttribute && !szwAttribute )
1303 goto end;
1305 buffer.unicode = FALSE;
1306 buffer.str.a = szBuffer;
1308 r = MSI_GetProductInfo( szwProduct, szwAttribute,
1309 &buffer, pcchValueBuf );
1311 end:
1312 msi_free( szwProduct );
1313 msi_free( szwAttribute );
1315 return r;
1318 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
1319 LPWSTR szBuffer, LPDWORD pcchValueBuf)
1321 awstring buffer;
1323 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
1324 szBuffer, pcchValueBuf);
1326 buffer.unicode = TRUE;
1327 buffer.str.w = szBuffer;
1329 return MSI_GetProductInfo( szProduct, szAttribute,
1330 &buffer, pcchValueBuf );
1333 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
1334 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
1335 LPSTR szValue, LPDWORD pcchValue)
1337 LPWSTR product = NULL;
1338 LPWSTR usersid = NULL;
1339 LPWSTR property = NULL;
1340 LPWSTR value = NULL;
1341 DWORD len = 0;
1342 UINT r;
1344 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
1345 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
1346 szValue, pcchValue);
1348 if (szValue && !pcchValue)
1349 return ERROR_INVALID_PARAMETER;
1351 if (szProductCode) product = strdupAtoW(szProductCode);
1352 if (szUserSid) usersid = strdupAtoW(szUserSid);
1353 if (szProperty) property = strdupAtoW(szProperty);
1355 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1356 NULL, &len);
1357 if (r != ERROR_SUCCESS)
1358 goto done;
1360 value = msi_alloc(++len * sizeof(WCHAR));
1361 if (!value)
1363 r = ERROR_OUTOFMEMORY;
1364 goto done;
1367 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1368 value, &len);
1369 if (r != ERROR_SUCCESS)
1370 goto done;
1372 if (!pcchValue)
1373 goto done;
1375 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
1376 if (*pcchValue >= len)
1377 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
1378 else if (szValue)
1380 r = ERROR_MORE_DATA;
1381 if (*pcchValue > 0)
1382 *szValue = '\0';
1385 if (*pcchValue <= len || !szValue)
1386 len = len * sizeof(WCHAR) - 1;
1388 *pcchValue = len - 1;
1390 done:
1391 msi_free(product);
1392 msi_free(usersid);
1393 msi_free(property);
1394 msi_free(value);
1396 return r;
1399 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
1401 UINT r = ERROR_SUCCESS;
1403 if (!val)
1404 return ERROR_UNKNOWN_PROPERTY;
1406 if (out)
1408 if (strlenW(val) >= *size)
1410 r = ERROR_MORE_DATA;
1411 if (*size > 0)
1412 *out = '\0';
1414 else
1415 lstrcpyW(out, val);
1418 if (size)
1419 *size = lstrlenW(val);
1421 return r;
1424 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
1425 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
1426 LPWSTR szValue, LPDWORD pcchValue)
1428 static const WCHAR five[] = {'5',0};
1429 static const WCHAR displayname[] = {
1430 'D','i','s','p','l','a','y','N','a','m','e',0};
1431 static const WCHAR displayversion[] = {
1432 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1433 static const WCHAR managed_local_package[] = {
1434 'M','a','n','a','g','e','d','L','o','c','a','l',
1435 'P','a','c','k','a','g','e',0};
1436 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE];
1437 LPCWSTR package = NULL;
1438 HKEY props = NULL, prod, classes = NULL, managed, hkey = NULL;
1439 DWORD type;
1440 UINT r = ERROR_UNKNOWN_PRODUCT;
1442 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
1443 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
1444 szValue, pcchValue);
1446 if (!szProductCode || !squash_guid( szProductCode, squashed_pc ))
1447 return ERROR_INVALID_PARAMETER;
1449 if (szValue && !pcchValue)
1450 return ERROR_INVALID_PARAMETER;
1452 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1453 dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1454 dwContext != MSIINSTALLCONTEXT_MACHINE)
1455 return ERROR_INVALID_PARAMETER;
1457 if (!szProperty || !*szProperty)
1458 return ERROR_INVALID_PARAMETER;
1460 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1461 return ERROR_INVALID_PARAMETER;
1463 /* FIXME: dwContext is provided, no need to search for it */
1464 MSIREG_OpenProductKey(szProductCode, NULL,MSIINSTALLCONTEXT_USERMANAGED,
1465 &managed, FALSE);
1466 MSIREG_OpenProductKey(szProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1467 &prod, FALSE);
1469 MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE);
1471 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1473 package = INSTALLPROPERTY_LOCALPACKAGEW;
1475 if (!props && !prod)
1476 goto done;
1478 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1480 package = managed_local_package;
1482 if (!props && !managed)
1483 goto done;
1485 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1487 package = INSTALLPROPERTY_LOCALPACKAGEW;
1488 MSIREG_OpenProductKey(szProductCode, NULL, dwContext, &classes, FALSE);
1490 if (!props && !classes)
1491 goto done;
1494 if (!strcmpW( szProperty, INSTALLPROPERTY_HELPLINKW ) ||
1495 !strcmpW( szProperty, INSTALLPROPERTY_HELPTELEPHONEW ) ||
1496 !strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW ) ||
1497 !strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ) ||
1498 !strcmpW( szProperty, INSTALLPROPERTY_INSTALLLOCATIONW ) ||
1499 !strcmpW( szProperty, INSTALLPROPERTY_INSTALLSOURCEW ) ||
1500 !strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ) ||
1501 !strcmpW( szProperty, INSTALLPROPERTY_PUBLISHERW ) ||
1502 !strcmpW( szProperty, INSTALLPROPERTY_URLINFOABOUTW ) ||
1503 !strcmpW( szProperty, INSTALLPROPERTY_URLUPDATEINFOW ) ||
1504 !strcmpW( szProperty, INSTALLPROPERTY_VERSIONMINORW ) ||
1505 !strcmpW( szProperty, INSTALLPROPERTY_VERSIONMAJORW ) ||
1506 !strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ) ||
1507 !strcmpW( szProperty, INSTALLPROPERTY_PRODUCTIDW ) ||
1508 !strcmpW( szProperty, INSTALLPROPERTY_REGCOMPANYW ) ||
1509 !strcmpW( szProperty, INSTALLPROPERTY_REGOWNERW ) ||
1510 !strcmpW( szProperty, INSTALLPROPERTY_INSTANCETYPEW ))
1512 val = reg_get_value(props, package, &type);
1513 if (!val)
1515 if (prod || classes)
1516 r = ERROR_UNKNOWN_PROPERTY;
1518 goto done;
1521 msi_free(val);
1523 if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW ))
1524 szProperty = displayname;
1525 else if (!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ))
1526 szProperty = displayversion;
1528 val = reg_get_value(props, szProperty, &type);
1529 if (!val)
1530 val = strdupW(szEmpty);
1532 r = msi_copy_outval(val, szValue, pcchValue);
1534 else if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW ) ||
1535 !strcmpW( szProperty, INSTALLPROPERTY_LANGUAGEW ) ||
1536 !strcmpW( szProperty, INSTALLPROPERTY_PRODUCTNAMEW ) ||
1537 !strcmpW( szProperty, INSTALLPROPERTY_PACKAGECODEW ) ||
1538 !strcmpW( szProperty, INSTALLPROPERTY_VERSIONW ) ||
1539 !strcmpW( szProperty, INSTALLPROPERTY_PRODUCTICONW ) ||
1540 !strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ) ||
1541 !strcmpW( szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW ))
1543 if (!prod && !classes)
1544 goto done;
1546 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1547 hkey = prod;
1548 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1549 hkey = managed;
1550 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1551 hkey = classes;
1553 val = reg_get_value(hkey, szProperty, &type);
1554 if (!val)
1555 val = strdupW(szEmpty);
1557 r = msi_copy_outval(val, szValue, pcchValue);
1559 else if (!strcmpW( szProperty, INSTALLPROPERTY_PRODUCTSTATEW ))
1561 if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1563 if (props)
1565 val = reg_get_value(props, package, &type);
1566 if (!val)
1567 goto done;
1569 msi_free(val);
1570 val = strdupW(five);
1572 else
1573 val = strdupW(szOne);
1575 r = msi_copy_outval(val, szValue, pcchValue);
1576 goto done;
1578 else if (props && (val = reg_get_value(props, package, &type)))
1580 msi_free(val);
1581 val = strdupW(five);
1582 r = msi_copy_outval(val, szValue, pcchValue);
1583 goto done;
1586 if (prod || managed)
1587 val = strdupW(szOne);
1588 else
1589 goto done;
1591 r = msi_copy_outval(val, szValue, pcchValue);
1593 else if (!strcmpW( szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW ))
1595 if (!prod && !classes)
1596 goto done;
1598 /* FIXME */
1599 val = strdupW(szEmpty);
1600 r = msi_copy_outval(val, szValue, pcchValue);
1602 else
1603 r = ERROR_UNKNOWN_PROPERTY;
1605 done:
1606 RegCloseKey(props);
1607 RegCloseKey(prod);
1608 RegCloseKey(managed);
1609 RegCloseKey(classes);
1610 msi_free(val);
1612 return r;
1615 UINT WINAPI MsiGetPatchFileListA(LPCSTR szProductCode, LPCSTR szPatchList,
1616 LPDWORD pcFiles, MSIHANDLE **pphFileRecords)
1618 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_a(szProductCode),
1619 debugstr_a(szPatchList), pcFiles, pphFileRecords);
1620 return ERROR_FUNCTION_FAILED;
1623 UINT WINAPI MsiGetPatchFileListW(LPCWSTR szProductCode, LPCWSTR szPatchList,
1624 LPDWORD pcFiles, MSIHANDLE **pphFileRecords)
1626 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_w(szProductCode),
1627 debugstr_w(szPatchList), pcFiles, pphFileRecords);
1628 return ERROR_FUNCTION_FAILED;
1631 UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode,
1632 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1633 LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
1635 LPWSTR patch = NULL, product = NULL, usersid = NULL;
1636 LPWSTR property = NULL, val = NULL;
1637 DWORD len;
1638 UINT r;
1640 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode),
1641 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext,
1642 debugstr_a(szProperty), lpValue, pcchValue);
1644 if (lpValue && !pcchValue)
1645 return ERROR_INVALID_PARAMETER;
1647 if (szPatchCode) patch = strdupAtoW(szPatchCode);
1648 if (szProductCode) product = strdupAtoW(szProductCode);
1649 if (szUserSid) usersid = strdupAtoW(szUserSid);
1650 if (szProperty) property = strdupAtoW(szProperty);
1652 len = 0;
1653 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1654 NULL, &len);
1655 if (r != ERROR_SUCCESS)
1656 goto done;
1658 val = msi_alloc(++len * sizeof(WCHAR));
1659 if (!val)
1661 r = ERROR_OUTOFMEMORY;
1662 goto done;
1665 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1666 val, &len);
1667 if (r != ERROR_SUCCESS || !pcchValue)
1668 goto done;
1670 if (lpValue)
1671 WideCharToMultiByte(CP_ACP, 0, val, -1, lpValue,
1672 *pcchValue - 1, NULL, NULL);
1674 len = lstrlenW(val);
1675 if ((*val && *pcchValue < len + 1) || !lpValue)
1677 if (lpValue)
1679 r = ERROR_MORE_DATA;
1680 lpValue[*pcchValue - 1] = '\0';
1683 *pcchValue = len * sizeof(WCHAR);
1685 else
1686 *pcchValue = len;
1688 done:
1689 msi_free(val);
1690 msi_free(patch);
1691 msi_free(product);
1692 msi_free(usersid);
1693 msi_free(property);
1695 return r;
1698 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
1699 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1700 LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue)
1702 static const WCHAR szManagedPackage[] =
1703 {'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
1704 WCHAR *val = NULL, squashed_pc[SQUASHED_GUID_SIZE], squashed_patch[SQUASHED_GUID_SIZE];
1705 HKEY udprod = 0, prod = 0, props = 0;
1706 HKEY patch = 0, patches = 0;
1707 HKEY udpatch = 0, datakey = 0;
1708 HKEY prodpatches = 0;
1709 UINT r = ERROR_UNKNOWN_PRODUCT;
1710 DWORD len, type;
1711 LONG res;
1713 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode),
1714 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext,
1715 debugstr_w(szProperty), lpValue, pcchValue);
1717 if (!szProductCode || !squash_guid( szProductCode, squashed_pc ))
1718 return ERROR_INVALID_PARAMETER;
1720 if (!szPatchCode || !squash_guid( szPatchCode, squashed_patch ))
1721 return ERROR_INVALID_PARAMETER;
1723 if (!szProperty)
1724 return ERROR_INVALID_PARAMETER;
1726 if (lpValue && !pcchValue)
1727 return ERROR_INVALID_PARAMETER;
1729 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1730 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1731 dwContext != MSIINSTALLCONTEXT_MACHINE)
1732 return ERROR_INVALID_PARAMETER;
1734 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1735 return ERROR_INVALID_PARAMETER;
1737 if (szUserSid && !strcmpW( szUserSid, szLocalSid ))
1738 return ERROR_INVALID_PARAMETER;
1740 if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
1741 &udprod, FALSE) != ERROR_SUCCESS)
1742 goto done;
1744 if (MSIREG_OpenInstallProps(szProductCode, dwContext, NULL,
1745 &props, FALSE) != ERROR_SUCCESS)
1746 goto done;
1748 r = ERROR_UNKNOWN_PATCH;
1750 res = RegOpenKeyExW(udprod, szPatches, 0, KEY_WOW64_64KEY|KEY_READ, &patches);
1751 if (res != ERROR_SUCCESS)
1752 goto done;
1754 res = RegOpenKeyExW( patches, squashed_patch, 0, KEY_WOW64_64KEY|KEY_READ, &patch );
1755 if (res != ERROR_SUCCESS)
1756 goto done;
1758 if (!strcmpW( szProperty, INSTALLPROPERTY_TRANSFORMSW ))
1760 if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
1761 &prod, FALSE) != ERROR_SUCCESS)
1762 goto done;
1764 res = RegOpenKeyExW(prod, szPatches, 0, KEY_WOW64_64KEY|KEY_ALL_ACCESS, &prodpatches);
1765 if (res != ERROR_SUCCESS)
1766 goto done;
1768 datakey = prodpatches;
1769 szProperty = squashed_patch;
1771 else
1773 if (MSIREG_OpenUserDataPatchKey(szPatchCode, dwContext,
1774 &udpatch, FALSE) != ERROR_SUCCESS)
1775 goto done;
1777 if (!strcmpW( szProperty, INSTALLPROPERTY_LOCALPACKAGEW ))
1779 if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1780 szProperty = szManagedPackage;
1781 datakey = udpatch;
1783 else if (!strcmpW( szProperty, INSTALLPROPERTY_INSTALLDATEW ))
1785 datakey = patch;
1786 szProperty = szInstalled;
1788 else if (!strcmpW( szProperty, INSTALLPROPERTY_UNINSTALLABLEW ) ||
1789 !strcmpW( szProperty, INSTALLPROPERTY_PATCHSTATEW ) ||
1790 !strcmpW( szProperty, INSTALLPROPERTY_DISPLAYNAMEW ) ||
1791 !strcmpW( szProperty, INSTALLPROPERTY_MOREINFOURLW ))
1793 datakey = patch;
1795 else
1797 r = ERROR_UNKNOWN_PROPERTY;
1798 goto done;
1802 val = reg_get_value(datakey, szProperty, &type);
1803 if (!val)
1804 val = strdupW(szEmpty);
1806 r = ERROR_SUCCESS;
1808 if (!pcchValue)
1809 goto done;
1811 if (lpValue)
1812 lstrcpynW(lpValue, val, *pcchValue);
1814 len = lstrlenW(val);
1815 if ((*val && *pcchValue < len + 1) || !lpValue)
1817 if (lpValue)
1818 r = ERROR_MORE_DATA;
1820 *pcchValue = len * sizeof(WCHAR);
1823 *pcchValue = len;
1825 done:
1826 msi_free(val);
1827 RegCloseKey(prodpatches);
1828 RegCloseKey(prod);
1829 RegCloseKey(patch);
1830 RegCloseKey(patches);
1831 RegCloseKey(udpatch);
1832 RegCloseKey(props);
1833 RegCloseKey(udprod);
1835 return r;
1838 UINT WINAPI MsiGetPatchInfoA( LPCSTR patch, LPCSTR attr, LPSTR buffer, LPDWORD buflen )
1840 UINT r = ERROR_OUTOFMEMORY;
1841 DWORD size;
1842 LPWSTR patchW = NULL, attrW = NULL, bufferW = NULL;
1844 TRACE("%s %s %p %p\n", debugstr_a(patch), debugstr_a(attr), buffer, buflen);
1846 if (!patch || !attr)
1847 return ERROR_INVALID_PARAMETER;
1849 if (!(patchW = strdupAtoW( patch )))
1850 goto done;
1852 if (!(attrW = strdupAtoW( attr )))
1853 goto done;
1855 size = 0;
1856 r = MsiGetPatchInfoW( patchW, attrW, NULL, &size );
1857 if (r != ERROR_SUCCESS)
1858 goto done;
1860 size++;
1861 if (!(bufferW = msi_alloc( size * sizeof(WCHAR) )))
1863 r = ERROR_OUTOFMEMORY;
1864 goto done;
1867 r = MsiGetPatchInfoW( patchW, attrW, bufferW, &size );
1868 if (r == ERROR_SUCCESS)
1870 int len = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
1871 if (len > *buflen)
1872 r = ERROR_MORE_DATA;
1873 else if (buffer)
1874 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL );
1876 *buflen = len - 1;
1879 done:
1880 msi_free( patchW );
1881 msi_free( attrW );
1882 msi_free( bufferW );
1883 return r;
1886 UINT WINAPI MsiGetPatchInfoW( LPCWSTR patch, LPCWSTR attr, LPWSTR buffer, LPDWORD buflen )
1888 UINT r;
1889 WCHAR product[GUID_SIZE];
1890 DWORD index;
1892 TRACE("%s %s %p %p\n", debugstr_w(patch), debugstr_w(attr), buffer, buflen);
1894 if (!patch || !attr)
1895 return ERROR_INVALID_PARAMETER;
1897 if (strcmpW( INSTALLPROPERTY_LOCALPACKAGEW, attr ))
1898 return ERROR_UNKNOWN_PROPERTY;
1900 index = 0;
1901 while (1)
1903 r = MsiEnumProductsW( index, product );
1904 if (r != ERROR_SUCCESS)
1905 break;
1907 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERMANAGED, attr, buffer, buflen );
1908 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
1909 return r;
1911 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, attr, buffer, buflen );
1912 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
1913 return r;
1915 r = MsiGetPatchInfoExW( patch, product, NULL, MSIINSTALLCONTEXT_MACHINE, attr, buffer, buflen );
1916 if (r == ERROR_SUCCESS || r == ERROR_MORE_DATA)
1917 return r;
1919 index++;
1922 return ERROR_UNKNOWN_PRODUCT;
1925 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
1927 LPWSTR szwLogFile = NULL;
1928 UINT r;
1930 TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
1932 if( szLogFile )
1934 szwLogFile = strdupAtoW( szLogFile );
1935 if( !szwLogFile )
1936 return ERROR_OUTOFMEMORY;
1938 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
1939 msi_free( szwLogFile );
1940 return r;
1943 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
1945 TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
1947 msi_free(gszLogFile);
1948 gszLogFile = NULL;
1949 if (szLogFile)
1951 HANDLE file;
1953 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
1954 DeleteFileW(szLogFile);
1955 file = CreateFileW(szLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
1956 FILE_ATTRIBUTE_NORMAL, NULL);
1957 if (file != INVALID_HANDLE_VALUE)
1959 gszLogFile = strdupW(szLogFile);
1960 CloseHandle(file);
1962 else
1963 ERR("Unable to enable log %s (%u)\n", debugstr_w(szLogFile), GetLastError());
1966 return ERROR_SUCCESS;
1969 UINT WINAPI MsiEnumComponentCostsA( MSIHANDLE handle, LPCSTR component, DWORD index,
1970 INSTALLSTATE state, LPSTR drive, DWORD *buflen,
1971 int *cost, int *temp )
1973 UINT r;
1974 DWORD len;
1975 WCHAR *driveW, *componentW = NULL;
1977 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle, debugstr_a(component), index,
1978 state, drive, buflen, cost, temp);
1980 if (!drive || !buflen) return ERROR_INVALID_PARAMETER;
1981 if (component && !(componentW = strdupAtoW( component ))) return ERROR_OUTOFMEMORY;
1983 len = *buflen;
1984 if (!(driveW = msi_alloc( len * sizeof(WCHAR) )))
1986 msi_free( componentW );
1987 return ERROR_OUTOFMEMORY;
1989 r = MsiEnumComponentCostsW( handle, componentW, index, state, driveW, buflen, cost, temp );
1990 if (!r)
1992 WideCharToMultiByte( CP_ACP, 0, driveW, -1, drive, len, NULL, NULL );
1994 msi_free( componentW );
1995 msi_free( driveW );
1996 return r;
1999 static UINT set_drive( WCHAR *buffer, WCHAR letter )
2001 buffer[0] = letter;
2002 buffer[1] = ':';
2003 buffer[2] = 0;
2004 return 2;
2007 UINT WINAPI MsiEnumComponentCostsW( MSIHANDLE handle, LPCWSTR component, DWORD index,
2008 INSTALLSTATE state, LPWSTR drive, DWORD *buflen,
2009 int *cost, int *temp )
2011 UINT r = ERROR_NO_MORE_ITEMS;
2012 MSICOMPONENT *comp = NULL;
2013 MSIPACKAGE *package;
2014 MSIFILE *file;
2015 STATSTG stat = {0};
2016 WCHAR path[MAX_PATH];
2018 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle, debugstr_w(component), index,
2019 state, drive, buflen, cost, temp);
2021 if (!drive || !buflen || !cost || !temp) return ERROR_INVALID_PARAMETER;
2022 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
2024 WCHAR buffer[3];
2025 MSIHANDLE remote;
2027 if (!(remote = msi_get_remote(handle)))
2028 return ERROR_INVALID_HANDLE;
2030 __TRY
2032 r = remote_EnumComponentCosts(remote, component, index, state, buffer, cost, temp);
2034 __EXCEPT(rpc_filter)
2036 r = GetExceptionCode();
2038 __ENDTRY
2040 if (r == ERROR_SUCCESS)
2042 lstrcpynW(drive, buffer, *buflen);
2043 if (*buflen < 3)
2044 r = ERROR_MORE_DATA;
2045 *buflen = 2;
2047 return r;
2050 if (!msi_get_property_int( package->db, szCostingComplete, 0 ))
2052 msiobj_release( &package->hdr );
2053 return ERROR_FUNCTION_NOT_CALLED;
2055 if (component && component[0] && !(comp = msi_get_loaded_component( package, component )))
2057 msiobj_release( &package->hdr );
2058 return ERROR_UNKNOWN_COMPONENT;
2060 if (*buflen < 3)
2062 *buflen = 2;
2063 msiobj_release( &package->hdr );
2064 return ERROR_MORE_DATA;
2066 if (index)
2068 msiobj_release( &package->hdr );
2069 return ERROR_NO_MORE_ITEMS;
2072 drive[0] = 0;
2073 *cost = *temp = 0;
2074 GetWindowsDirectoryW( path, MAX_PATH );
2075 if (component && component[0])
2077 if (msi_is_global_assembly( comp )) *temp = comp->Cost;
2078 if (!comp->Enabled || !comp->KeyPath)
2080 *cost = 0;
2081 *buflen = set_drive( drive, path[0] );
2082 r = ERROR_SUCCESS;
2084 else if ((file = msi_get_loaded_file( package, comp->KeyPath )))
2086 *cost = max( 8, comp->Cost / 512 );
2087 *buflen = set_drive( drive, file->TargetPath[0] );
2088 r = ERROR_SUCCESS;
2091 else if (IStorage_Stat( package->db->storage, &stat, STATFLAG_NONAME ) == S_OK)
2093 *temp = max( 8, stat.cbSize.QuadPart / 512 );
2094 *buflen = set_drive( drive, path[0] );
2095 r = ERROR_SUCCESS;
2097 msiobj_release( &package->hdr );
2098 return r;
2101 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
2102 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
2103 LPCSTR szComponent, INSTALLSTATE *pdwState)
2105 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL;
2106 UINT r;
2108 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode),
2109 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
2111 if (szProductCode && !(prodcode = strdupAtoW(szProductCode)))
2112 return ERROR_OUTOFMEMORY;
2114 if (szUserSid && !(usersid = strdupAtoW(szUserSid)))
2115 return ERROR_OUTOFMEMORY;
2117 if (szComponent && !(comp = strdupAtoW(szComponent)))
2118 return ERROR_OUTOFMEMORY;
2120 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState);
2122 msi_free(prodcode);
2123 msi_free(usersid);
2124 msi_free(comp);
2126 return r;
2129 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
2131 UINT r;
2132 HKEY hkey = NULL;
2134 r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE);
2135 RegCloseKey(hkey);
2136 return (r == ERROR_SUCCESS);
2139 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
2141 LPCWSTR package;
2142 HKEY hkey;
2143 DWORD sz;
2144 LONG res;
2145 UINT r;
2147 static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
2148 static const WCHAR managed_local_package[] = {
2149 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
2152 r = MSIREG_OpenInstallProps(prodcode, context, NULL, &hkey, FALSE);
2153 if (r != ERROR_SUCCESS)
2154 return FALSE;
2156 if (context == MSIINSTALLCONTEXT_USERMANAGED)
2157 package = managed_local_package;
2158 else
2159 package = local_package;
2161 sz = 0;
2162 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
2163 RegCloseKey(hkey);
2165 return (res == ERROR_SUCCESS);
2168 static UINT msi_comp_find_prodcode(WCHAR *squashed_pc,
2169 MSIINSTALLCONTEXT context,
2170 LPCWSTR comp, LPWSTR val, DWORD *sz)
2172 HKEY hkey;
2173 LONG res;
2174 UINT r;
2176 if (context == MSIINSTALLCONTEXT_MACHINE)
2177 r = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
2178 else
2179 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
2181 if (r != ERROR_SUCCESS)
2182 return r;
2184 res = RegQueryValueExW( hkey, squashed_pc, NULL, NULL, (BYTE *)val, sz );
2185 if (res != ERROR_SUCCESS)
2186 return res;
2188 RegCloseKey(hkey);
2189 return res;
2192 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
2193 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
2194 LPCWSTR szComponent, INSTALLSTATE *pdwState)
2196 WCHAR squashed_pc[SQUASHED_GUID_SIZE];
2197 BOOL found;
2198 DWORD sz;
2200 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
2201 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
2203 if (!pdwState || !szComponent)
2204 return ERROR_INVALID_PARAMETER;
2206 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1)
2207 return ERROR_INVALID_PARAMETER;
2209 if (!squash_guid( szProductCode, squashed_pc ))
2210 return ERROR_INVALID_PARAMETER;
2212 found = msi_comp_find_prod_key(szProductCode, dwContext);
2214 if (!msi_comp_find_package(szProductCode, dwContext))
2216 if (found)
2218 *pdwState = INSTALLSTATE_UNKNOWN;
2219 return ERROR_UNKNOWN_COMPONENT;
2222 return ERROR_UNKNOWN_PRODUCT;
2225 *pdwState = INSTALLSTATE_UNKNOWN;
2227 sz = 0;
2228 if (msi_comp_find_prodcode( squashed_pc, dwContext, szComponent, NULL, &sz ))
2229 return ERROR_UNKNOWN_COMPONENT;
2231 if (sz == 0)
2232 *pdwState = INSTALLSTATE_NOTUSED;
2233 else
2235 WCHAR *val;
2236 UINT r;
2238 if (!(val = msi_alloc( sz ))) return ERROR_OUTOFMEMORY;
2239 if ((r = msi_comp_find_prodcode( squashed_pc, dwContext, szComponent, val, &sz )))
2241 msi_free(val);
2242 return r;
2245 if (lstrlenW(val) > 2 &&
2246 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9' && val[2] != ':')
2248 *pdwState = INSTALLSTATE_SOURCE;
2250 else
2251 *pdwState = INSTALLSTATE_LOCAL;
2252 msi_free( val );
2255 TRACE("-> %d\n", *pdwState);
2256 return ERROR_SUCCESS;
2259 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
2261 LPWSTR szwProduct = NULL;
2262 INSTALLSTATE r;
2264 if( szProduct )
2266 szwProduct = strdupAtoW( szProduct );
2267 if( !szwProduct )
2268 return ERROR_OUTOFMEMORY;
2270 r = MsiQueryProductStateW( szwProduct );
2271 msi_free( szwProduct );
2272 return r;
2275 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
2277 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
2278 INSTALLSTATE state = INSTALLSTATE_ADVERTISED;
2279 HKEY prodkey = 0, userdata = 0;
2280 DWORD val;
2281 UINT r;
2283 TRACE("%s\n", debugstr_w(szProduct));
2285 if (!szProduct || !*szProduct)
2286 return INSTALLSTATE_INVALIDARG;
2288 if (lstrlenW(szProduct) != GUID_SIZE - 1)
2289 return INSTALLSTATE_INVALIDARG;
2291 if (szProduct[0] != '{' || szProduct[37] != '}')
2292 return INSTALLSTATE_UNKNOWN;
2294 SetLastError( ERROR_SUCCESS );
2296 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
2297 &prodkey, FALSE) != ERROR_SUCCESS &&
2298 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2299 &prodkey, FALSE) != ERROR_SUCCESS &&
2300 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2301 &prodkey, FALSE) == ERROR_SUCCESS)
2303 context = MSIINSTALLCONTEXT_MACHINE;
2306 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
2307 if (r != ERROR_SUCCESS)
2308 goto done;
2310 if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val))
2311 goto done;
2313 if (val)
2314 state = INSTALLSTATE_DEFAULT;
2315 else
2316 state = INSTALLSTATE_UNKNOWN;
2318 done:
2319 if (!prodkey)
2321 state = INSTALLSTATE_UNKNOWN;
2323 if (userdata)
2324 state = INSTALLSTATE_ABSENT;
2327 RegCloseKey(prodkey);
2328 RegCloseKey(userdata);
2329 TRACE("-> %d\n", state);
2330 return state;
2333 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
2335 INSTALLUILEVEL old = gUILevel;
2336 HWND oldwnd = gUIhwnd;
2338 TRACE("%08x %p\n", dwUILevel, phWnd);
2340 if (dwUILevel & ~(INSTALLUILEVEL_MASK|INSTALLUILEVEL_HIDECANCEL|INSTALLUILEVEL_PROGRESSONLY|
2341 INSTALLUILEVEL_ENDDIALOG|INSTALLUILEVEL_SOURCERESONLY))
2343 FIXME("Unrecognized flags %08x\n", dwUILevel);
2344 return INSTALLUILEVEL_NOCHANGE;
2347 if (dwUILevel != INSTALLUILEVEL_NOCHANGE)
2348 gUILevel = dwUILevel;
2350 if (phWnd)
2352 gUIhwnd = *phWnd;
2353 *phWnd = oldwnd;
2355 return old;
2358 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
2359 DWORD dwMessageFilter, LPVOID pvContext)
2361 INSTALLUI_HANDLERA prev = gUIHandlerA;
2363 TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext);
2365 gUIHandlerA = puiHandler;
2366 gUIHandlerW = NULL;
2367 gUIFilter = dwMessageFilter;
2368 gUIContext = pvContext;
2370 return prev;
2373 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
2374 DWORD dwMessageFilter, LPVOID pvContext)
2376 INSTALLUI_HANDLERW prev = gUIHandlerW;
2378 TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext);
2380 gUIHandlerA = NULL;
2381 gUIHandlerW = puiHandler;
2382 gUIFilter = dwMessageFilter;
2383 gUIContext = pvContext;
2385 return prev;
2388 /******************************************************************
2389 * MsiLoadStringW [MSI.@]
2391 * Loads a string from MSI's string resources.
2393 * PARAMS
2395 * handle [I] only -1 is handled currently
2396 * id [I] id of the string to be loaded
2397 * lpBuffer [O] buffer for the string to be written to
2398 * nBufferMax [I] maximum size of the buffer in characters
2399 * lang [I] the preferred language for the string
2401 * RETURNS
2403 * If successful, this function returns the language id of the string loaded
2404 * If the function fails, the function returns zero.
2406 * NOTES
2408 * The type of the first parameter is unknown. LoadString's prototype
2409 * suggests that it might be a module handle. I have made it an MSI handle
2410 * for starters, as -1 is an invalid MSI handle, but not an invalid module
2411 * handle. Maybe strings can be stored in an MSI database somehow.
2413 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
2414 int nBufferMax, LANGID lang )
2416 HRSRC hres;
2417 HGLOBAL hResData;
2418 LPWSTR p;
2419 DWORD i, len;
2421 TRACE("%d %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
2423 if( handle != -1 )
2424 FIXME("don't know how to deal with handle = %08x\n", handle);
2426 if( !lang )
2427 lang = GetUserDefaultLangID();
2429 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
2430 (LPWSTR)1, lang );
2431 if( !hres )
2432 return 0;
2433 hResData = LoadResource( msi_hInstance, hres );
2434 if( !hResData )
2435 return 0;
2436 p = LockResource( hResData );
2437 if( !p )
2438 return 0;
2440 for (i = 0; i < (id & 0xf); i++) p += *p + 1;
2441 len = *p;
2443 if( nBufferMax <= len )
2444 return 0;
2446 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
2447 lpBuffer[ len ] = 0;
2449 TRACE("found -> %s\n", debugstr_w(lpBuffer));
2450 return lang;
2453 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
2454 int nBufferMax, LANGID lang )
2456 LPWSTR bufW;
2457 LANGID r;
2458 INT len;
2460 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
2461 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
2462 if( r )
2464 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
2465 if( len <= nBufferMax )
2466 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
2467 lpBuffer, nBufferMax, NULL, NULL );
2468 else
2469 r = 0;
2471 msi_free(bufW);
2472 return r;
2475 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
2476 LPDWORD pcchBuf)
2478 char szProduct[GUID_SIZE];
2480 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
2482 if (!szComponent || !pcchBuf)
2483 return INSTALLSTATE_INVALIDARG;
2485 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
2486 return INSTALLSTATE_UNKNOWN;
2488 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
2491 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
2492 LPDWORD pcchBuf)
2494 WCHAR szProduct[GUID_SIZE];
2496 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
2498 if (!szComponent || !pcchBuf)
2499 return INSTALLSTATE_INVALIDARG;
2501 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
2502 return INSTALLSTATE_UNKNOWN;
2504 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
2507 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
2508 WORD wLanguageId, DWORD f)
2510 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
2511 uType, wLanguageId, f);
2512 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
2515 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
2516 WORD wLanguageId, DWORD f)
2518 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
2519 uType, wLanguageId, f);
2520 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
2523 UINT WINAPI MsiMessageBoxExA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
2524 DWORD unknown, WORD wLanguageId, DWORD f)
2526 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_a(lpText),
2527 debugstr_a(lpCaption), uType, unknown, wLanguageId, f);
2528 return MessageBoxExA(hWnd, lpText, lpCaption, uType, wLanguageId);
2531 UINT WINAPI MsiMessageBoxExW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
2532 DWORD unknown, WORD wLanguageId, DWORD f)
2534 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_w(lpText),
2535 debugstr_w(lpCaption), uType, unknown, wLanguageId, f);
2536 return MessageBoxExW(hWnd, lpText, lpCaption, uType, wLanguageId);
2539 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
2540 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
2541 LPDWORD pcchPathBuf )
2543 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
2544 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2545 pcchPathBuf);
2546 return ERROR_CALL_NOT_IMPLEMENTED;
2549 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
2550 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
2551 LPDWORD pcchPathBuf )
2553 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
2554 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2555 pcchPathBuf);
2556 return ERROR_CALL_NOT_IMPLEMENTED;
2559 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
2560 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2562 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
2563 return ERROR_CALL_NOT_IMPLEMENTED;
2566 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
2567 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2569 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
2570 return ERROR_CALL_NOT_IMPLEMENTED;
2573 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR path, DWORD flags, PCCERT_CONTEXT *cert,
2574 LPBYTE hash, LPDWORD hashlen )
2576 UINT r;
2577 WCHAR *pathW = NULL;
2579 TRACE("%s %08x %p %p %p\n", debugstr_a(path), flags, cert, hash, hashlen);
2581 if (path && !(pathW = strdupAtoW( path ))) return E_OUTOFMEMORY;
2582 r = MsiGetFileSignatureInformationW( pathW, flags, cert, hash, hashlen );
2583 msi_free( pathW );
2584 return r;
2587 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR path, DWORD flags, PCCERT_CONTEXT *cert,
2588 LPBYTE hash, LPDWORD hashlen )
2590 static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
2591 HRESULT hr;
2592 WINTRUST_DATA data;
2593 WINTRUST_FILE_INFO info;
2594 CRYPT_PROVIDER_SGNR *signer;
2595 CRYPT_PROVIDER_CERT *provider;
2597 TRACE("%s %08x %p %p %p\n", debugstr_w(path), flags, cert, hash, hashlen);
2599 if (!path || !cert) return E_INVALIDARG;
2601 info.cbStruct = sizeof(info);
2602 info.pcwszFilePath = path;
2603 info.hFile = NULL;
2604 info.pgKnownSubject = NULL;
2606 data.cbStruct = sizeof(data);
2607 data.pPolicyCallbackData = NULL;
2608 data.pSIPClientData = NULL;
2609 data.dwUIChoice = WTD_UI_NONE;
2610 data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
2611 data.dwUnionChoice = WTD_CHOICE_FILE;
2612 data.u.pFile = &info;
2613 data.dwStateAction = WTD_STATEACTION_VERIFY;
2614 data.hWVTStateData = NULL;
2615 data.pwszURLReference = NULL;
2616 data.dwProvFlags = 0;
2617 data.dwUIContext = WTD_UICONTEXT_INSTALL;
2618 hr = WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data );
2619 *cert = NULL;
2620 if (FAILED(hr)) goto done;
2622 if (!(signer = WTHelperGetProvSignerFromChain( data.hWVTStateData, 0, FALSE, 0 )))
2624 hr = TRUST_E_NOSIGNATURE;
2625 goto done;
2627 if (hash)
2629 DWORD len = signer->psSigner->EncryptedHash.cbData;
2630 if (*hashlen < len)
2632 *hashlen = len;
2633 hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
2634 goto done;
2636 memcpy( hash, signer->psSigner->EncryptedHash.pbData, len );
2637 *hashlen = len;
2639 if (!(provider = WTHelperGetProvCertFromChain( signer, 0 )))
2641 hr = TRUST_E_PROVIDER_UNKNOWN;
2642 goto done;
2644 *cert = CertDuplicateCertificateContext( provider->pCert );
2646 done:
2647 data.dwStateAction = WTD_STATEACTION_CLOSE;
2648 WinVerifyTrustEx( INVALID_HANDLE_VALUE, &generic_verify_v2, &data );
2649 return hr;
2652 /******************************************************************
2653 * MsiGetProductPropertyA [MSI.@]
2655 UINT WINAPI MsiGetProductPropertyA(MSIHANDLE hProduct, LPCSTR szProperty,
2656 LPSTR szValue, LPDWORD pccbValue)
2658 LPWSTR prop = NULL, val = NULL;
2659 DWORD len;
2660 UINT r;
2662 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_a(szProperty),
2663 szValue, pccbValue);
2665 if (szValue && !pccbValue)
2666 return ERROR_INVALID_PARAMETER;
2668 if (szProperty) prop = strdupAtoW(szProperty);
2670 len = 0;
2671 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len);
2672 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2673 goto done;
2675 if (r == ERROR_SUCCESS)
2677 if (szValue) *szValue = '\0';
2678 if (pccbValue) *pccbValue = 0;
2679 goto done;
2682 val = msi_alloc(++len * sizeof(WCHAR));
2683 if (!val)
2685 r = ERROR_OUTOFMEMORY;
2686 goto done;
2689 r = MsiGetProductPropertyW(hProduct, prop, val, &len);
2690 if (r != ERROR_SUCCESS)
2691 goto done;
2693 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL);
2695 if (szValue)
2696 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue,
2697 *pccbValue, NULL, NULL);
2699 if (pccbValue)
2701 if (len > *pccbValue)
2702 r = ERROR_MORE_DATA;
2704 *pccbValue = len - 1;
2707 done:
2708 msi_free(prop);
2709 msi_free(val);
2711 return r;
2714 /******************************************************************
2715 * MsiGetProductPropertyW [MSI.@]
2717 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE hProduct, LPCWSTR szProperty,
2718 LPWSTR szValue, LPDWORD pccbValue)
2720 MSIPACKAGE *package;
2721 MSIQUERY *view = NULL;
2722 MSIRECORD *rec = NULL;
2723 LPCWSTR val;
2724 UINT r;
2726 static const WCHAR query[] = {
2727 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
2728 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
2729 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
2731 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_w(szProperty),
2732 szValue, pccbValue);
2734 if (!szProperty)
2735 return ERROR_INVALID_PARAMETER;
2737 if (szValue && !pccbValue)
2738 return ERROR_INVALID_PARAMETER;
2740 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE);
2741 if (!package)
2742 return ERROR_INVALID_HANDLE;
2744 r = MSI_OpenQuery(package->db, &view, query, szProperty);
2745 if (r != ERROR_SUCCESS)
2746 goto done;
2748 r = MSI_ViewExecute(view, 0);
2749 if (r != ERROR_SUCCESS)
2750 goto done;
2752 r = MSI_ViewFetch(view, &rec);
2753 if (r != ERROR_SUCCESS)
2754 goto done;
2756 val = MSI_RecordGetString(rec, 2);
2757 if (!val)
2758 goto done;
2760 if (lstrlenW(val) >= *pccbValue)
2762 if (szValue) lstrcpynW(szValue, val, *pccbValue);
2763 r = ERROR_MORE_DATA;
2765 else
2767 if (szValue) lstrcpyW(szValue, val);
2768 r = ERROR_SUCCESS;
2771 *pccbValue = lstrlenW(val);
2773 done:
2774 if (view)
2776 MSI_ViewClose(view);
2777 msiobj_release(&view->hdr);
2778 if (rec) msiobj_release(&rec->hdr);
2781 if (!rec)
2783 if (szValue) *szValue = '\0';
2784 if (pccbValue) *pccbValue = 0;
2785 r = ERROR_SUCCESS;
2788 msiobj_release(&package->hdr);
2789 return r;
2792 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
2794 UINT r;
2795 LPWSTR szPack = NULL;
2797 TRACE("%s\n", debugstr_a(szPackage) );
2799 if( szPackage )
2801 szPack = strdupAtoW( szPackage );
2802 if( !szPack )
2803 return ERROR_OUTOFMEMORY;
2806 r = MsiVerifyPackageW( szPack );
2808 msi_free( szPack );
2810 return r;
2813 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
2815 MSIHANDLE handle;
2816 UINT r;
2818 TRACE("%s\n", debugstr_w(szPackage) );
2820 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
2821 MsiCloseHandle( handle );
2823 return r;
2826 static BOOL open_userdata_comp_key( const WCHAR *comp, const WCHAR *usersid, MSIINSTALLCONTEXT ctx,
2827 HKEY *hkey )
2829 if (ctx & MSIINSTALLCONTEXT_MACHINE)
2831 if (!MSIREG_OpenUserDataComponentKey( comp, szLocalSid, hkey, FALSE )) return TRUE;
2833 if (ctx & (MSIINSTALLCONTEXT_USERMANAGED|MSIINSTALLCONTEXT_USERUNMANAGED))
2835 if (usersid && !strcmpiW( usersid, szAllSid ))
2837 FIXME( "only looking at the current user\n" );
2838 usersid = NULL;
2840 if (!MSIREG_OpenUserDataComponentKey( comp, usersid, hkey, FALSE )) return TRUE;
2842 return FALSE;
2845 static INSTALLSTATE MSI_GetComponentPath( const WCHAR *szProduct, const WCHAR *szComponent,
2846 const WCHAR *szUserSid, MSIINSTALLCONTEXT ctx,
2847 awstring *lpPathBuf, DWORD *pcchBuf )
2849 static const WCHAR wininstaller[] =
2850 {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
2851 WCHAR *path = NULL, squashed_pc[SQUASHED_GUID_SIZE], squashed_comp[SQUASHED_GUID_SIZE];
2852 HKEY hkey;
2853 INSTALLSTATE state;
2854 DWORD version;
2856 if (!szProduct || !szComponent)
2857 return INSTALLSTATE_INVALIDARG;
2859 if (lpPathBuf->str.w && !pcchBuf)
2860 return INSTALLSTATE_INVALIDARG;
2862 if (!squash_guid( szProduct, squashed_pc ) || !squash_guid( szComponent, squashed_comp ))
2863 return INSTALLSTATE_INVALIDARG;
2865 if (szUserSid && ctx == MSIINSTALLCONTEXT_MACHINE)
2866 return INSTALLSTATE_INVALIDARG;
2868 state = INSTALLSTATE_UNKNOWN;
2870 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
2872 path = msi_reg_get_val_str( hkey, squashed_pc );
2873 RegCloseKey(hkey);
2875 state = INSTALLSTATE_ABSENT;
2877 if ((!MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, &hkey, FALSE) ||
2878 !MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, NULL, &hkey, FALSE)) &&
2879 msi_reg_get_val_dword(hkey, wininstaller, &version) &&
2880 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2882 RegCloseKey(hkey);
2883 state = INSTALLSTATE_LOCAL;
2887 if (state != INSTALLSTATE_LOCAL &&
2888 (!MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, &hkey, FALSE) ||
2889 !MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, &hkey, FALSE)))
2891 RegCloseKey(hkey);
2893 if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
2895 msi_free(path);
2896 path = msi_reg_get_val_str( hkey, squashed_pc );
2897 RegCloseKey(hkey);
2899 state = INSTALLSTATE_ABSENT;
2901 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2902 state = INSTALLSTATE_LOCAL;
2906 if (!path)
2907 return INSTALLSTATE_UNKNOWN;
2909 if (state == INSTALLSTATE_LOCAL && !*path)
2910 state = INSTALLSTATE_NOTUSED;
2912 if (msi_strcpy_to_awstring(path, -1, lpPathBuf, pcchBuf) == ERROR_MORE_DATA)
2913 state = INSTALLSTATE_MOREDATA;
2915 msi_free(path);
2916 return state;
2919 /******************************************************************
2920 * MsiGetComponentPathExW [MSI.@]
2922 INSTALLSTATE WINAPI MsiGetComponentPathExW( LPCWSTR product, LPCWSTR comp, LPCWSTR usersid,
2923 MSIINSTALLCONTEXT ctx, LPWSTR buf, LPDWORD buflen )
2925 awstring path;
2927 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_w(product), debugstr_w(comp), debugstr_w(usersid),
2928 ctx, buf, buflen );
2930 path.unicode = TRUE;
2931 path.str.w = buf;
2933 return MSI_GetComponentPath( product, comp, usersid, ctx, &path, buflen );
2936 INSTALLSTATE WINAPI MsiGetComponentPathExA( LPCSTR product, LPCSTR comp, LPCSTR usersid,
2937 MSIINSTALLCONTEXT ctx, LPSTR buf, LPDWORD buflen )
2939 WCHAR *productW = NULL, *compW = NULL, *usersidW = NULL;
2940 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
2941 awstring path;
2943 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_a(product), debugstr_a(comp), debugstr_a(usersid),
2944 ctx, buf, buflen );
2946 if (product && !(productW = strdupAtoW( product ))) return INSTALLSTATE_UNKNOWN;
2947 if (comp && !(compW = strdupAtoW( comp ))) goto end;
2948 if (usersid && !(usersidW = strdupAtoW( usersid ))) goto end;
2950 path.unicode = FALSE;
2951 path.str.a = buf;
2953 r = MSI_GetComponentPath( productW, compW, usersidW, ctx, &path, buflen );
2955 end:
2956 msi_free( productW );
2957 msi_free( compW );
2958 msi_free( usersidW );
2960 return r;
2963 /******************************************************************
2964 * MsiGetComponentPathW [MSI.@]
2966 INSTALLSTATE WINAPI MsiGetComponentPathW( LPCWSTR product, LPCWSTR comp, LPWSTR buf, LPDWORD buflen )
2968 return MsiGetComponentPathExW( product, comp, szAllSid, MSIINSTALLCONTEXT_ALL, buf, buflen );
2971 /******************************************************************
2972 * MsiGetComponentPathA [MSI.@]
2974 INSTALLSTATE WINAPI MsiGetComponentPathA( LPCSTR product, LPCSTR comp, LPSTR buf, LPDWORD buflen )
2976 return MsiGetComponentPathExA( product, comp, "s-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen );
2979 static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid,
2980 MSIINSTALLCONTEXT ctx, const WCHAR *feature, INSTALLSTATE *state )
2982 UINT r;
2983 HKEY hkey;
2984 WCHAR *parent, *components, *path;
2985 const WCHAR *p;
2986 BOOL missing = FALSE, source = FALSE;
2987 WCHAR comp[GUID_SIZE];
2988 GUID guid;
2990 if (ctx != MSIINSTALLCONTEXT_MACHINE) SetLastError( ERROR_SUCCESS );
2992 if (MSIREG_OpenFeaturesKey( product, usersid, ctx, &hkey, FALSE )) return ERROR_UNKNOWN_PRODUCT;
2994 parent = msi_reg_get_val_str( hkey, feature );
2995 RegCloseKey( hkey );
2996 if (!parent) return ERROR_UNKNOWN_FEATURE;
2998 *state = (parent[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
2999 msi_free( parent );
3000 if (*state == INSTALLSTATE_ABSENT)
3001 return ERROR_SUCCESS;
3003 r = MSIREG_OpenUserDataFeaturesKey( product, usersid, ctx, &hkey, FALSE );
3004 if (r != ERROR_SUCCESS)
3006 *state = INSTALLSTATE_ADVERTISED;
3007 return ERROR_SUCCESS;
3009 components = msi_reg_get_val_str( hkey, feature );
3010 RegCloseKey( hkey );
3012 TRACE("buffer = %s\n", debugstr_w(components));
3014 if (!components)
3016 *state = INSTALLSTATE_ADVERTISED;
3017 return ERROR_SUCCESS;
3019 for (p = components; *p && *p != 2 ; p += 20)
3021 if (!decode_base85_guid( p, &guid ))
3023 if (p != components) break;
3024 msi_free( components );
3025 *state = INSTALLSTATE_BADCONFIG;
3026 return ERROR_BAD_CONFIGURATION;
3028 StringFromGUID2( &guid, comp, GUID_SIZE );
3029 if (ctx == MSIINSTALLCONTEXT_MACHINE)
3030 r = MSIREG_OpenUserDataComponentKey( comp, szLocalSid, &hkey, FALSE );
3031 else
3032 r = MSIREG_OpenUserDataComponentKey( comp, usersid, &hkey, FALSE );
3034 if (r != ERROR_SUCCESS)
3036 msi_free( components );
3037 *state = INSTALLSTATE_ADVERTISED;
3038 return ERROR_SUCCESS;
3040 path = msi_reg_get_val_str( hkey, squashed );
3041 if (!path) missing = TRUE;
3042 else if (strlenW( path ) > 2 &&
3043 path[0] >= '0' && path[0] <= '9' &&
3044 path[1] >= '0' && path[1] <= '9')
3046 source = TRUE;
3048 msi_free( path );
3050 msi_free( components );
3052 if (missing)
3053 *state = INSTALLSTATE_ADVERTISED;
3054 else if (source)
3055 *state = INSTALLSTATE_SOURCE;
3056 else
3057 *state = INSTALLSTATE_LOCAL;
3059 TRACE("returning state %d\n", *state);
3060 return ERROR_SUCCESS;
3063 UINT WINAPI MsiQueryFeatureStateExA( LPCSTR product, LPCSTR usersid, MSIINSTALLCONTEXT ctx,
3064 LPCSTR feature, INSTALLSTATE *state )
3066 UINT r;
3067 WCHAR *productW = NULL, *usersidW = NULL, *featureW = NULL;
3069 if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
3070 if (usersid && !(usersidW = strdupAtoW( usersid )))
3072 msi_free( productW );
3073 return ERROR_OUTOFMEMORY;
3075 if (feature && !(featureW = strdupAtoW( feature )))
3077 msi_free( productW );
3078 msi_free( usersidW );
3079 return ERROR_OUTOFMEMORY;
3081 r = MsiQueryFeatureStateExW( productW, usersidW, ctx, featureW, state );
3082 msi_free( productW );
3083 msi_free( usersidW );
3084 msi_free( featureW );
3085 return r;
3088 UINT WINAPI MsiQueryFeatureStateExW( LPCWSTR product, LPCWSTR usersid, MSIINSTALLCONTEXT ctx,
3089 LPCWSTR feature, INSTALLSTATE *state )
3091 WCHAR squashed[33];
3092 if (!squash_guid( product, squashed )) return ERROR_INVALID_PARAMETER;
3093 return query_feature_state( product, squashed, usersid, ctx, feature, state );
3096 /******************************************************************
3097 * MsiQueryFeatureStateA [MSI.@]
3099 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
3101 LPWSTR szwProduct = NULL, szwFeature= NULL;
3102 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
3104 szwProduct = strdupAtoW( szProduct );
3105 if ( szProduct && !szwProduct )
3106 goto end;
3108 szwFeature = strdupAtoW( szFeature );
3109 if ( szFeature && !szwFeature )
3110 goto end;
3112 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
3114 end:
3115 msi_free( szwProduct);
3116 msi_free( szwFeature);
3118 return rc;
3121 /******************************************************************
3122 * MsiQueryFeatureStateW [MSI.@]
3124 * Checks the state of a feature
3126 * PARAMS
3127 * szProduct [I] Product's GUID string
3128 * szFeature [I] Feature's GUID string
3130 * RETURNS
3131 * INSTALLSTATE_LOCAL Feature is installed and usable
3132 * INSTALLSTATE_ABSENT Feature is absent
3133 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
3134 * INSTALLSTATE_UNKNOWN An error occurred
3135 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
3138 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
3140 UINT r;
3141 INSTALLSTATE state;
3142 WCHAR squashed[33];
3144 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
3146 if (!szProduct || !szFeature || !squash_guid( szProduct, squashed ))
3147 return INSTALLSTATE_INVALIDARG;
3149 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERMANAGED, szFeature, &state );
3150 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state;
3152 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, szFeature, &state );
3153 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state;
3155 r = query_feature_state( szProduct, squashed, NULL, MSIINSTALLCONTEXT_MACHINE, szFeature, &state );
3156 if (r == ERROR_SUCCESS || r == ERROR_BAD_CONFIGURATION) return state;
3158 return INSTALLSTATE_UNKNOWN;
3161 /******************************************************************
3162 * MsiGetFileVersionA [MSI.@]
3164 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
3165 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
3167 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
3168 UINT ret = ERROR_OUTOFMEMORY;
3170 if ((lpVersionBuf && !pcchVersionBuf) ||
3171 (lpLangBuf && !pcchLangBuf))
3172 return ERROR_INVALID_PARAMETER;
3174 if( szFilePath )
3176 szwFilePath = strdupAtoW( szFilePath );
3177 if( !szwFilePath )
3178 goto end;
3181 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
3183 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
3184 if( !lpwVersionBuff )
3185 goto end;
3188 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
3190 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
3191 if( !lpwLangBuff )
3192 goto end;
3195 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
3196 lpwLangBuff, pcchLangBuf);
3198 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
3199 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
3200 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
3201 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
3202 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
3203 lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
3205 end:
3206 msi_free(szwFilePath);
3207 msi_free(lpwVersionBuff);
3208 msi_free(lpwLangBuff);
3210 return ret;
3213 static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen,
3214 WCHAR *langbuf, DWORD *langlen )
3216 static const WCHAR szVersionResource[] = {'\\',0};
3217 static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3218 static const WCHAR szLangFormat[] = {'%','d',0};
3219 UINT ret = ERROR_MORE_DATA;
3220 DWORD len, error;
3221 LPVOID version;
3222 VS_FIXEDFILEINFO *ffi;
3223 USHORT *lang;
3224 WCHAR tmp[32];
3226 if (!(len = GetFileVersionInfoSizeW( path, NULL )))
3228 error = GetLastError();
3229 if (error == ERROR_BAD_PATHNAME) return ERROR_FILE_NOT_FOUND;
3230 if (error == ERROR_RESOURCE_DATA_NOT_FOUND) return ERROR_FILE_INVALID;
3231 return error;
3233 if (!(version = msi_alloc( len ))) return ERROR_OUTOFMEMORY;
3234 if (!GetFileVersionInfoW( path, 0, len, version ))
3236 msi_free( version );
3237 return GetLastError();
3239 if (!verbuf && !verlen && !langbuf && !langlen)
3241 msi_free( version );
3242 return ERROR_SUCCESS;
3244 if (verlen)
3246 if (VerQueryValueW( version, szVersionResource, (LPVOID *)&ffi, &len ) && len > 0)
3248 sprintfW( tmp, szVersionFormat,
3249 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
3250 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS) );
3251 if (verbuf) lstrcpynW( verbuf, tmp, *verlen );
3252 len = strlenW( tmp );
3253 if (*verlen > len) ret = ERROR_SUCCESS;
3254 *verlen = len;
3256 else
3258 if (verbuf) *verbuf = 0;
3259 *verlen = 0;
3262 if (langlen)
3264 if (VerQueryValueW( version, szLangResource, (LPVOID *)&lang, &len ) && len > 0)
3266 sprintfW( tmp, szLangFormat, *lang );
3267 if (langbuf) lstrcpynW( langbuf, tmp, *langlen );
3268 len = strlenW( tmp );
3269 if (*langlen > len) ret = ERROR_SUCCESS;
3270 *langlen = len;
3272 else
3274 if (langbuf) *langbuf = 0;
3275 *langlen = 0;
3278 msi_free( version );
3279 return ret;
3283 /******************************************************************
3284 * MsiGetFileVersionW [MSI.@]
3286 UINT WINAPI MsiGetFileVersionW( LPCWSTR path, LPWSTR verbuf, LPDWORD verlen,
3287 LPWSTR langbuf, LPDWORD langlen )
3289 UINT ret;
3291 TRACE("%s %p %u %p %u\n", debugstr_w(path), verbuf, verlen ? *verlen : 0,
3292 langbuf, langlen ? *langlen : 0);
3294 if ((verbuf && !verlen) || (langbuf && !langlen))
3295 return ERROR_INVALID_PARAMETER;
3297 ret = get_file_version( path, verbuf, verlen, langbuf, langlen );
3298 if (ret == ERROR_RESOURCE_DATA_NOT_FOUND && verlen)
3300 int len;
3301 WCHAR *version = msi_font_version_from_file( path );
3302 if (!version) return ERROR_FILE_INVALID;
3303 len = strlenW( version );
3304 if (len >= *verlen) ret = ERROR_MORE_DATA;
3305 else if (verbuf)
3307 strcpyW( verbuf, version );
3308 ret = ERROR_SUCCESS;
3310 *verlen = len;
3311 msi_free( version );
3313 return ret;
3316 /***********************************************************************
3317 * MsiGetFeatureUsageW [MSI.@]
3319 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
3320 LPDWORD pdwUseCount, LPWORD pwDateUsed )
3322 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
3323 pdwUseCount, pwDateUsed);
3324 return ERROR_CALL_NOT_IMPLEMENTED;
3327 /***********************************************************************
3328 * MsiGetFeatureUsageA [MSI.@]
3330 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
3331 LPDWORD pdwUseCount, LPWORD pwDateUsed )
3333 LPWSTR prod = NULL, feat = NULL;
3334 UINT ret = ERROR_OUTOFMEMORY;
3336 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
3337 pdwUseCount, pwDateUsed);
3339 prod = strdupAtoW( szProduct );
3340 if (szProduct && !prod)
3341 goto end;
3343 feat = strdupAtoW( szFeature );
3344 if (szFeature && !feat)
3345 goto end;
3347 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
3349 end:
3350 msi_free( prod );
3351 msi_free( feat );
3353 return ret;
3356 /***********************************************************************
3357 * MsiUseFeatureExW [MSI.@]
3359 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
3360 DWORD dwInstallMode, DWORD dwReserved )
3362 INSTALLSTATE state;
3364 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
3365 dwInstallMode, dwReserved);
3367 state = MsiQueryFeatureStateW( szProduct, szFeature );
3369 if (dwReserved)
3370 return INSTALLSTATE_INVALIDARG;
3372 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
3374 FIXME("mark product %s feature %s as used\n",
3375 debugstr_w(szProduct), debugstr_w(szFeature) );
3378 return state;
3381 /***********************************************************************
3382 * MsiUseFeatureExA [MSI.@]
3384 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
3385 DWORD dwInstallMode, DWORD dwReserved )
3387 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
3388 LPWSTR prod = NULL, feat = NULL;
3390 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
3391 dwInstallMode, dwReserved);
3393 prod = strdupAtoW( szProduct );
3394 if (szProduct && !prod)
3395 goto end;
3397 feat = strdupAtoW( szFeature );
3398 if (szFeature && !feat)
3399 goto end;
3401 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
3403 end:
3404 msi_free( prod );
3405 msi_free( feat );
3407 return ret;
3410 /***********************************************************************
3411 * MsiUseFeatureW [MSI.@]
3413 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
3415 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
3418 /***********************************************************************
3419 * MsiUseFeatureA [MSI.@]
3421 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
3423 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
3426 static WCHAR *reg_get_multisz( HKEY hkey, const WCHAR *name )
3428 WCHAR *ret;
3429 DWORD len, type;
3430 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_MULTI_SZ) return NULL;
3431 if ((ret = msi_alloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len );
3432 return ret;
3435 static WCHAR *reg_get_sz( HKEY hkey, const WCHAR *name )
3437 WCHAR *ret;
3438 DWORD len, type;
3439 if (RegQueryValueExW( hkey, name, NULL, &type, NULL, &len ) || type != REG_SZ) return NULL;
3440 if ((ret = msi_alloc( len ))) RegQueryValueExW( hkey, name, NULL, NULL, (BYTE *)ret, &len );
3441 return ret;
3444 #define BASE85_SIZE 20
3446 /***********************************************************************
3447 * MSI_ProvideQualifiedComponentEx [internal]
3449 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
3450 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
3451 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
3452 LPDWORD pcchPathBuf)
3454 WCHAR product[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
3455 WCHAR *desc;
3456 HKEY hkey;
3457 DWORD size;
3458 UINT ret;
3459 INSTALLSTATE state;
3461 if (MSIREG_OpenUserComponentsKey( szComponent, &hkey, FALSE )) return ERROR_UNKNOWN_COMPONENT;
3463 desc = reg_get_multisz( hkey, szQualifier );
3464 RegCloseKey(hkey);
3465 if (!desc) return ERROR_INDEX_ABSENT;
3467 /* FIXME: handle multiple descriptors */
3468 ret = MsiDecomposeDescriptorW( desc, product, feature, comp, &size );
3469 msi_free( desc );
3470 if (ret != ERROR_SUCCESS) return ret;
3472 if (!szProduct) szProduct = product;
3473 if (!comp[0])
3475 MSIINSTALLCONTEXT ctx;
3476 WCHAR *components;
3477 GUID guid;
3479 /* use the first component of the feature if the descriptor component is empty */
3480 if ((ret = msi_locate_product( szProduct, &ctx ))) return ret;
3481 if ((ret = MSIREG_OpenUserDataFeaturesKey( szProduct, NULL, ctx, &hkey, FALSE )))
3483 return ERROR_FILE_NOT_FOUND;
3485 components = reg_get_sz( hkey, feature );
3486 RegCloseKey( hkey );
3487 if (!components) return ERROR_FILE_NOT_FOUND;
3489 if (strlenW( components ) < BASE85_SIZE || !decode_base85_guid( components, &guid ))
3491 msi_free( components );
3492 return ERROR_FILE_NOT_FOUND;
3494 msi_free( components );
3495 StringFromGUID2( &guid, comp, ARRAY_SIZE( comp ));
3498 state = MSI_GetComponentPath( szProduct, comp, szAllSid, MSIINSTALLCONTEXT_ALL, lpPathBuf, pcchPathBuf );
3500 if (state == INSTALLSTATE_MOREDATA) return ERROR_MORE_DATA;
3501 if (state != INSTALLSTATE_LOCAL) return ERROR_FILE_NOT_FOUND;
3502 return ERROR_SUCCESS;
3505 /***********************************************************************
3506 * MsiProvideQualifiedComponentExW [MSI.@]
3508 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
3509 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
3510 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
3511 LPDWORD pcchPathBuf)
3513 awstring path;
3515 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_w(szComponent),
3516 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
3517 Unused1, Unused2, lpPathBuf, pcchPathBuf);
3519 path.unicode = TRUE;
3520 path.str.w = lpPathBuf;
3522 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
3523 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
3526 /***********************************************************************
3527 * MsiProvideQualifiedComponentExA [MSI.@]
3529 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
3530 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct,
3531 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
3532 LPDWORD pcchPathBuf)
3534 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
3535 UINT r = ERROR_OUTOFMEMORY;
3536 awstring path;
3538 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
3539 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
3540 Unused1, Unused2, lpPathBuf, pcchPathBuf);
3542 szwComponent = strdupAtoW( szComponent );
3543 if (szComponent && !szwComponent)
3544 goto end;
3546 szwQualifier = strdupAtoW( szQualifier );
3547 if (szQualifier && !szwQualifier)
3548 goto end;
3550 szwProduct = strdupAtoW( szProduct );
3551 if (szProduct && !szwProduct)
3552 goto end;
3554 path.unicode = FALSE;
3555 path.str.a = lpPathBuf;
3557 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
3558 dwInstallMode, szwProduct, Unused1,
3559 Unused2, &path, pcchPathBuf);
3560 end:
3561 msi_free(szwProduct);
3562 msi_free(szwComponent);
3563 msi_free(szwQualifier);
3565 return r;
3568 /***********************************************************************
3569 * MsiProvideQualifiedComponentW [MSI.@]
3571 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
3572 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
3573 LPDWORD pcchPathBuf)
3575 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
3576 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
3579 /***********************************************************************
3580 * MsiProvideQualifiedComponentA [MSI.@]
3582 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
3583 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
3584 LPDWORD pcchPathBuf)
3586 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
3587 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
3590 /***********************************************************************
3591 * MSI_GetUserInfo [internal]
3593 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
3594 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
3595 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3596 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
3598 WCHAR *user, *org, *serial, squashed_pc[SQUASHED_GUID_SIZE];
3599 USERINFOSTATE state;
3600 HKEY hkey, props;
3601 LPCWSTR orgptr;
3602 UINT r;
3604 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
3605 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
3606 pcchSerialBuf);
3608 if (!szProduct || !squash_guid( szProduct, squashed_pc ))
3609 return USERINFOSTATE_INVALIDARG;
3611 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
3612 &hkey, FALSE) != ERROR_SUCCESS &&
3613 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3614 &hkey, FALSE) != ERROR_SUCCESS &&
3615 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
3616 &hkey, FALSE) != ERROR_SUCCESS)
3618 return USERINFOSTATE_UNKNOWN;
3621 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
3622 NULL, &props, FALSE) != ERROR_SUCCESS &&
3623 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE,
3624 NULL, &props, FALSE) != ERROR_SUCCESS)
3626 RegCloseKey(hkey);
3627 return USERINFOSTATE_ABSENT;
3630 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
3631 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
3632 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
3633 state = USERINFOSTATE_ABSENT;
3635 RegCloseKey(hkey);
3636 RegCloseKey(props);
3638 if (user && serial)
3639 state = USERINFOSTATE_PRESENT;
3641 if (pcchUserNameBuf)
3643 if (lpUserNameBuf && !user)
3645 (*pcchUserNameBuf)--;
3646 goto done;
3649 r = msi_strcpy_to_awstring(user, -1, lpUserNameBuf, pcchUserNameBuf);
3650 if (r == ERROR_MORE_DATA)
3652 state = USERINFOSTATE_MOREDATA;
3653 goto done;
3657 if (pcchOrgNameBuf)
3659 orgptr = org;
3660 if (!orgptr) orgptr = szEmpty;
3662 r = msi_strcpy_to_awstring(orgptr, -1, lpOrgNameBuf, pcchOrgNameBuf);
3663 if (r == ERROR_MORE_DATA)
3665 state = USERINFOSTATE_MOREDATA;
3666 goto done;
3670 if (pcchSerialBuf)
3672 if (!serial)
3674 (*pcchSerialBuf)--;
3675 goto done;
3678 r = msi_strcpy_to_awstring(serial, -1, lpSerialBuf, pcchSerialBuf);
3679 if (r == ERROR_MORE_DATA)
3680 state = USERINFOSTATE_MOREDATA;
3683 done:
3684 msi_free(user);
3685 msi_free(org);
3686 msi_free(serial);
3688 return state;
3691 /***********************************************************************
3692 * MsiGetUserInfoW [MSI.@]
3694 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
3695 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3696 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3697 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3699 awstring user, org, serial;
3701 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3702 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3703 (lpSerialBuf && !pcchSerialBuf))
3704 return USERINFOSTATE_INVALIDARG;
3706 user.unicode = TRUE;
3707 user.str.w = lpUserNameBuf;
3708 org.unicode = TRUE;
3709 org.str.w = lpOrgNameBuf;
3710 serial.unicode = TRUE;
3711 serial.str.w = lpSerialBuf;
3713 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
3714 &org, pcchOrgNameBuf,
3715 &serial, pcchSerialBuf );
3718 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
3719 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3720 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3721 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3723 awstring user, org, serial;
3724 LPWSTR prod;
3725 UINT r;
3727 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3728 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3729 (lpSerialBuf && !pcchSerialBuf))
3730 return USERINFOSTATE_INVALIDARG;
3732 prod = strdupAtoW( szProduct );
3733 if (szProduct && !prod)
3734 return ERROR_OUTOFMEMORY;
3736 user.unicode = FALSE;
3737 user.str.a = lpUserNameBuf;
3738 org.unicode = FALSE;
3739 org.str.a = lpOrgNameBuf;
3740 serial.unicode = FALSE;
3741 serial.str.a = lpSerialBuf;
3743 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
3744 &org, pcchOrgNameBuf,
3745 &serial, pcchSerialBuf );
3747 msi_free( prod );
3749 return r;
3752 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
3754 MSIHANDLE handle;
3755 UINT rc;
3756 MSIPACKAGE *package;
3757 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3759 TRACE("(%s)\n",debugstr_w(szProduct));
3761 rc = MsiOpenProductW(szProduct,&handle);
3762 if (rc != ERROR_SUCCESS)
3763 return ERROR_INVALID_PARAMETER;
3765 /* MsiCollectUserInfo cannot be called from a custom action. */
3766 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3767 if (!package)
3768 return ERROR_CALL_NOT_IMPLEMENTED;
3770 rc = ACTION_PerformAction(package, szFirstRun);
3771 msiobj_release( &package->hdr );
3773 MsiCloseHandle(handle);
3775 return rc;
3778 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
3780 MSIHANDLE handle;
3781 UINT rc;
3782 MSIPACKAGE *package;
3783 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3785 TRACE("(%s)\n",debugstr_a(szProduct));
3787 rc = MsiOpenProductA(szProduct,&handle);
3788 if (rc != ERROR_SUCCESS)
3789 return ERROR_INVALID_PARAMETER;
3791 /* MsiCollectUserInfo cannot be called from a custom action. */
3792 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3793 if (!package)
3794 return ERROR_CALL_NOT_IMPLEMENTED;
3796 rc = ACTION_PerformAction(package, szFirstRun);
3797 msiobj_release( &package->hdr );
3799 MsiCloseHandle(handle);
3801 return rc;
3804 /***********************************************************************
3805 * MsiConfigureFeatureA [MSI.@]
3807 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
3809 LPWSTR prod, feat = NULL;
3810 UINT r = ERROR_OUTOFMEMORY;
3812 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
3814 prod = strdupAtoW( szProduct );
3815 if (szProduct && !prod)
3816 goto end;
3818 feat = strdupAtoW( szFeature );
3819 if (szFeature && !feat)
3820 goto end;
3822 r = MsiConfigureFeatureW(prod, feat, eInstallState);
3824 end:
3825 msi_free(feat);
3826 msi_free(prod);
3828 return r;
3831 /***********************************************************************
3832 * MsiConfigureFeatureW [MSI.@]
3834 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
3836 MSIPACKAGE *package = NULL;
3837 UINT r;
3838 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
3839 DWORD sz;
3841 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
3843 if (!szProduct || !szFeature)
3844 return ERROR_INVALID_PARAMETER;
3846 switch (eInstallState)
3848 case INSTALLSTATE_DEFAULT:
3849 /* FIXME: how do we figure out the default location? */
3850 eInstallState = INSTALLSTATE_LOCAL;
3851 break;
3852 case INSTALLSTATE_LOCAL:
3853 case INSTALLSTATE_SOURCE:
3854 case INSTALLSTATE_ABSENT:
3855 case INSTALLSTATE_ADVERTISED:
3856 break;
3857 default:
3858 return ERROR_INVALID_PARAMETER;
3861 r = MSI_OpenProductW( szProduct, &package );
3862 if (r != ERROR_SUCCESS)
3863 return r;
3865 sz = sizeof(sourcepath);
3866 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3867 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3869 sz = sizeof(filename);
3870 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3871 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3873 lstrcatW( sourcepath, filename );
3875 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
3877 r = ACTION_PerformAction(package, szCostInitialize);
3878 if (r != ERROR_SUCCESS)
3879 goto end;
3881 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
3882 if (r != ERROR_SUCCESS)
3883 goto end;
3885 r = MSI_InstallPackage( package, sourcepath, NULL );
3887 end:
3888 msiobj_release( &package->hdr );
3890 return r;
3893 /***********************************************************************
3894 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3896 * Notes: undocumented
3898 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
3900 WCHAR path[MAX_PATH];
3902 TRACE("%d\n", dwReserved);
3904 if (dwReserved)
3906 FIXME("dwReserved=%d\n", dwReserved);
3907 return ERROR_INVALID_PARAMETER;
3910 if (!GetWindowsDirectoryW(path, MAX_PATH))
3911 return ERROR_FUNCTION_FAILED;
3913 lstrcatW(path, installerW);
3915 if (!CreateDirectoryW(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
3916 return ERROR_FUNCTION_FAILED;
3918 return ERROR_SUCCESS;
3921 /***********************************************************************
3922 * MsiGetShortcutTargetA [MSI.@]
3924 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
3925 LPSTR szProductCode, LPSTR szFeatureId,
3926 LPSTR szComponentCode )
3928 LPWSTR target;
3929 const int len = MAX_FEATURE_CHARS+1;
3930 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
3931 UINT r;
3933 target = strdupAtoW( szShortcutTarget );
3934 if (szShortcutTarget && !target )
3935 return ERROR_OUTOFMEMORY;
3936 product[0] = 0;
3937 feature[0] = 0;
3938 component[0] = 0;
3939 r = MsiGetShortcutTargetW( target, product, feature, component );
3940 msi_free( target );
3941 if (r == ERROR_SUCCESS)
3943 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
3944 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
3945 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
3947 return r;
3950 /***********************************************************************
3951 * MsiGetShortcutTargetW [MSI.@]
3953 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
3954 LPWSTR szProductCode, LPWSTR szFeatureId,
3955 LPWSTR szComponentCode )
3957 IShellLinkDataList *dl = NULL;
3958 IPersistFile *pf = NULL;
3959 LPEXP_DARWIN_LINK darwin = NULL;
3960 HRESULT r, init;
3962 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
3963 szProductCode, szFeatureId, szComponentCode );
3965 init = CoInitialize(NULL);
3967 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
3968 &IID_IPersistFile, (LPVOID*) &pf );
3969 if( SUCCEEDED( r ) )
3971 r = IPersistFile_Load( pf, szShortcutTarget,
3972 STGM_READ | STGM_SHARE_DENY_WRITE );
3973 if( SUCCEEDED( r ) )
3975 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
3976 (LPVOID*) &dl );
3977 if( SUCCEEDED( r ) )
3979 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
3980 (LPVOID) &darwin );
3981 IShellLinkDataList_Release( dl );
3984 IPersistFile_Release( pf );
3987 if (SUCCEEDED(init))
3988 CoUninitialize();
3990 TRACE("darwin = %p\n", darwin);
3992 if (darwin)
3994 DWORD sz;
3995 UINT ret;
3997 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
3998 szProductCode, szFeatureId, szComponentCode, &sz );
3999 LocalFree( darwin );
4000 return ret;
4003 return ERROR_FUNCTION_FAILED;
4006 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature, DWORD dwReinstallMode )
4008 static const WCHAR fmtW[] = {'%','s','=','%','s',' ','%','s','=','%','s',0};
4009 MSIPACKAGE *package;
4010 MSIINSTALLCONTEXT context;
4011 UINT r;
4012 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH], reinstallmode[11];
4013 WCHAR *ptr, *cmdline;
4014 DWORD sz;
4016 TRACE("%s, %s, 0x%08x\n", debugstr_w(szProduct), debugstr_w(szFeature), dwReinstallMode);
4018 r = msi_locate_product( szProduct, &context );
4019 if (r != ERROR_SUCCESS)
4020 return r;
4022 ptr = reinstallmode;
4024 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
4025 *ptr++ = 'p';
4026 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
4027 *ptr++ = 'o';
4028 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
4029 *ptr++ = 'w';
4030 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
4031 *ptr++ = 'd';
4032 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
4033 *ptr++ = 'c';
4034 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
4035 *ptr++ = 'a';
4036 if (dwReinstallMode & REINSTALLMODE_USERDATA)
4037 *ptr++ = 'u';
4038 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
4039 *ptr++ = 'm';
4040 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
4041 *ptr++ = 's';
4042 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
4043 *ptr++ = 'v';
4044 *ptr = 0;
4046 sz = sizeof(sourcepath);
4047 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT,
4048 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz );
4049 sz = sizeof(filename);
4050 MsiSourceListGetInfoW( szProduct, NULL, context, MSICODE_PRODUCT,
4051 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz );
4052 strcatW( sourcepath, filename );
4054 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
4055 r = MSI_OpenPackageW( sourcepath, 0, &package );
4056 else
4057 r = MSI_OpenProductW( szProduct, &package );
4059 if (r != ERROR_SUCCESS)
4060 return r;
4062 sz = (strlenW( fmtW ) + strlenW( szReinstallMode ) + strlenW( reinstallmode )) * sizeof(WCHAR);
4063 sz += (strlenW( szReinstall ) + strlenW( szFeature )) * sizeof(WCHAR);
4064 if (!(cmdline = msi_alloc( sz )))
4066 msiobj_release( &package->hdr );
4067 return ERROR_OUTOFMEMORY;
4069 sprintfW( cmdline, fmtW, szReinstallMode, reinstallmode, szReinstall, szFeature );
4071 r = MSI_InstallPackage( package, sourcepath, cmdline );
4072 msiobj_release( &package->hdr );
4073 msi_free( cmdline );
4075 return r;
4078 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
4079 DWORD dwReinstallMode )
4081 LPWSTR wszProduct;
4082 LPWSTR wszFeature;
4083 UINT rc;
4085 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
4086 dwReinstallMode);
4088 wszProduct = strdupAtoW(szProduct);
4089 wszFeature = strdupAtoW(szFeature);
4091 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
4093 msi_free(wszProduct);
4094 msi_free(wszFeature);
4095 return rc;
4098 typedef struct
4100 unsigned int i[2];
4101 unsigned int buf[4];
4102 unsigned char in[64];
4103 unsigned char digest[16];
4104 } MD5_CTX;
4106 extern VOID WINAPI MD5Init( MD5_CTX *);
4107 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
4108 extern VOID WINAPI MD5Final( MD5_CTX *);
4110 UINT msi_get_filehash( const WCHAR *path, MSIFILEHASHINFO *hash )
4112 HANDLE handle, mapping;
4113 void *p;
4114 DWORD length;
4115 UINT r = ERROR_FUNCTION_FAILED;
4117 handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
4118 if (handle == INVALID_HANDLE_VALUE)
4120 WARN("can't open file %u\n", GetLastError());
4121 return ERROR_FILE_NOT_FOUND;
4123 if ((length = GetFileSize( handle, NULL )))
4125 if ((mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL )))
4127 if ((p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length )))
4129 MD5_CTX ctx;
4131 MD5Init( &ctx );
4132 MD5Update( &ctx, p, length );
4133 MD5Final( &ctx );
4134 UnmapViewOfFile( p );
4136 memcpy( hash->dwData, ctx.digest, sizeof(hash->dwData) );
4137 r = ERROR_SUCCESS;
4139 CloseHandle( mapping );
4142 else
4144 /* Empty file -> set hash to 0 */
4145 memset( hash->dwData, 0, sizeof(hash->dwData) );
4146 r = ERROR_SUCCESS;
4149 CloseHandle( handle );
4150 return r;
4153 /***********************************************************************
4154 * MsiGetFileHashW [MSI.@]
4156 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
4157 PMSIFILEHASHINFO pHash )
4159 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
4161 if (!szFilePath)
4162 return ERROR_INVALID_PARAMETER;
4164 if (!*szFilePath)
4165 return ERROR_PATH_NOT_FOUND;
4167 if (dwOptions)
4168 return ERROR_INVALID_PARAMETER;
4169 if (!pHash)
4170 return ERROR_INVALID_PARAMETER;
4171 if (pHash->dwFileHashInfoSize < sizeof *pHash)
4172 return ERROR_INVALID_PARAMETER;
4174 return msi_get_filehash( szFilePath, pHash );
4177 /***********************************************************************
4178 * MsiGetFileHashA [MSI.@]
4180 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
4181 PMSIFILEHASHINFO pHash )
4183 LPWSTR file;
4184 UINT r;
4186 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
4188 file = strdupAtoW( szFilePath );
4189 if (szFilePath && !file)
4190 return ERROR_OUTOFMEMORY;
4192 r = MsiGetFileHashW( file, dwOptions, pHash );
4193 msi_free( file );
4194 return r;
4197 /***********************************************************************
4198 * MsiAdvertiseScriptW [MSI.@]
4200 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
4201 PHKEY phRegData, BOOL fRemoveItems )
4203 FIXME("%s %08x %p %d\n",
4204 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
4205 return ERROR_CALL_NOT_IMPLEMENTED;
4208 /***********************************************************************
4209 * MsiAdvertiseScriptA [MSI.@]
4211 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
4212 PHKEY phRegData, BOOL fRemoveItems )
4214 FIXME("%s %08x %p %d\n",
4215 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
4216 return ERROR_CALL_NOT_IMPLEMENTED;
4219 /***********************************************************************
4220 * MsiIsProductElevatedW [MSI.@]
4222 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
4224 FIXME("%s %p - stub\n",
4225 debugstr_w( szProduct ), pfElevated );
4226 *pfElevated = TRUE;
4227 return ERROR_SUCCESS;
4230 /***********************************************************************
4231 * MsiIsProductElevatedA [MSI.@]
4233 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
4235 FIXME("%s %p - stub\n",
4236 debugstr_a( szProduct ), pfElevated );
4237 *pfElevated = TRUE;
4238 return ERROR_SUCCESS;
4241 /***********************************************************************
4242 * MsiSetExternalUIRecord [MSI.@]
4244 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler,
4245 DWORD filter, LPVOID context,
4246 PINSTALLUI_HANDLER_RECORD prev )
4248 TRACE("%p %08x %p %p\n", handler, filter, context, prev);
4250 if (prev)
4251 *prev = gUIHandlerRecord;
4253 gUIHandlerRecord = handler;
4254 gUIFilterRecord = filter;
4255 gUIContextRecord = context;
4257 return ERROR_SUCCESS;
4260 /***********************************************************************
4261 * MsiInstallMissingComponentA [MSI.@]
4263 UINT WINAPI MsiInstallMissingComponentA( LPCSTR product, LPCSTR component, INSTALLSTATE state )
4265 UINT r;
4266 WCHAR *productW = NULL, *componentW = NULL;
4268 TRACE("%s, %s, %d\n", debugstr_a(product), debugstr_a(component), state);
4270 if (product && !(productW = strdupAtoW( product )))
4271 return ERROR_OUTOFMEMORY;
4273 if (component && !(componentW = strdupAtoW( component )))
4275 msi_free( productW );
4276 return ERROR_OUTOFMEMORY;
4279 r = MsiInstallMissingComponentW( productW, componentW, state );
4280 msi_free( productW );
4281 msi_free( componentW );
4282 return r;
4285 /***********************************************************************
4286 * MsiInstallMissingComponentW [MSI.@]
4288 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState)
4290 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
4291 return ERROR_SUCCESS;
4294 UINT WINAPI MsiProvideComponentA( LPCSTR product, LPCSTR feature, LPCSTR component, DWORD mode, LPSTR buf, LPDWORD buflen )
4296 WCHAR *productW = NULL, *componentW = NULL, *featureW = NULL, *bufW = NULL;
4297 UINT r = ERROR_OUTOFMEMORY;
4298 DWORD lenW = 0;
4299 int len;
4301 TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_a(product), debugstr_a(component), debugstr_a(feature), mode, buf, buflen);
4303 if (product && !(productW = strdupAtoW( product ))) goto done;
4304 if (feature && !(featureW = strdupAtoW( feature ))) goto done;
4305 if (component && !(componentW = strdupAtoW( component ))) goto done;
4307 r = MsiProvideComponentW( productW, featureW, componentW, mode, NULL, &lenW );
4308 if (r != ERROR_SUCCESS)
4309 goto done;
4311 if (!(bufW = msi_alloc( ++lenW * sizeof(WCHAR) )))
4313 r = ERROR_OUTOFMEMORY;
4314 goto done;
4317 r = MsiProvideComponentW( productW, featureW, componentW, mode, bufW, &lenW );
4318 if (r != ERROR_SUCCESS)
4319 goto done;
4321 len = WideCharToMultiByte( CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
4322 if (buf)
4324 if (len > *buflen)
4325 r = ERROR_MORE_DATA;
4326 else
4327 WideCharToMultiByte( CP_ACP, 0, bufW, -1, buf, *buflen, NULL, NULL );
4330 *buflen = len - 1;
4332 done:
4333 msi_free( productW );
4334 msi_free( featureW );
4335 msi_free( componentW );
4336 msi_free( bufW );
4337 return r;
4340 UINT WINAPI MsiProvideComponentW( LPCWSTR product, LPCWSTR feature, LPCWSTR component, DWORD mode, LPWSTR buf, LPDWORD buflen )
4342 INSTALLSTATE state;
4344 TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_w(product), debugstr_w(component), debugstr_w(feature), mode, buf, buflen);
4346 state = MsiQueryFeatureStateW( product, feature );
4347 TRACE("feature state: %d\n", state);
4348 switch (mode)
4350 case INSTALLMODE_NODETECTION:
4351 break;
4353 default:
4354 FIXME("mode %x not implemented\n", mode);
4355 return ERROR_INSTALL_FAILURE;
4358 state = MsiGetComponentPathW( product, component, buf, buflen );
4359 TRACE("component state: %d\n", state);
4360 switch (state)
4362 case INSTALLSTATE_INVALIDARG:
4363 return ERROR_INVALID_PARAMETER;
4365 case INSTALLSTATE_MOREDATA:
4366 return ERROR_MORE_DATA;
4368 case INSTALLSTATE_ADVERTISED:
4369 case INSTALLSTATE_LOCAL:
4370 case INSTALLSTATE_SOURCE:
4371 MsiUseFeatureW( product, feature );
4372 return ERROR_SUCCESS;
4374 default:
4375 TRACE("MsiGetComponentPathW returned %d\n", state);
4376 return ERROR_INSTALL_FAILURE;
4380 /***********************************************************************
4381 * MsiBeginTransactionA [MSI.@]
4383 UINT WINAPI MsiBeginTransactionA( LPCSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event )
4385 WCHAR *nameW;
4386 UINT r;
4388 FIXME("%s %u %p %p\n", debugstr_a(name), attrs, id, event);
4390 nameW = strdupAtoW( name );
4391 if (name && !nameW)
4392 return ERROR_OUTOFMEMORY;
4394 r = MsiBeginTransactionW( nameW, attrs, id, event );
4395 msi_free( nameW );
4396 return r;
4399 /***********************************************************************
4400 * MsiBeginTransactionW [MSI.@]
4402 UINT WINAPI MsiBeginTransactionW( LPCWSTR name, DWORD attrs, MSIHANDLE *id, HANDLE *event )
4404 FIXME("%s %u %p %p\n", debugstr_w(name), attrs, id, event);
4406 *id = (MSIHANDLE)0xdeadbeef;
4407 *event = (HANDLE)0xdeadbeef;
4409 return ERROR_SUCCESS;
4412 /***********************************************************************
4413 * MsiJoinTransaction [MSI.@]
4415 UINT WINAPI MsiJoinTransaction( MSIHANDLE handle, DWORD attrs, HANDLE *event )
4417 FIXME("%u %08x %p\n", handle, attrs, event);
4419 *event = (HANDLE)0xdeadbeef;
4420 return ERROR_SUCCESS;
4423 /***********************************************************************
4424 * MsiEndTransaction [MSI.@]
4426 UINT WINAPI MsiEndTransaction( DWORD state )
4428 FIXME("%u\n", state);
4429 return ERROR_SUCCESS;
4432 UINT WINAPI Migrate10CachedPackagesW(void* a, void* b, void* c, DWORD d)
4434 FIXME("%p,%p,%p,%08x\n", a, b, c, d);
4435 return ERROR_SUCCESS;
4438 /***********************************************************************
4439 * MsiRemovePatchesA [MSI.@]
4441 UINT WINAPI MsiRemovePatchesA(LPCSTR patchlist, LPCSTR product, INSTALLTYPE type, LPCSTR propertylist)
4443 FIXME("(%s %s %d %s\n", debugstr_a(patchlist), debugstr_a(product), type, debugstr_a(propertylist));
4444 return ERROR_SUCCESS;
4447 /***********************************************************************
4448 * MsiRemovePatchesW [MSI.@]
4450 UINT WINAPI MsiRemovePatchesW(LPCWSTR patchlist, LPCWSTR product, INSTALLTYPE type, LPCWSTR propertylist)
4452 FIXME("(%s %s %d %s\n", debugstr_w(patchlist), debugstr_w(product), type, debugstr_w(propertylist));
4453 return ERROR_SUCCESS;