push c22b4aa826b27f0c6bc5101b378e6e68716a85d9
[wine/hacks.git] / dlls / msi / msi.c
blob86713fdfabdde53929efc407d0d1e47cf8100b4f
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 "wine/debug.h"
32 #include "msi.h"
33 #include "msidefs.h"
34 #include "msiquery.h"
35 #include "msipriv.h"
36 #include "wincrypt.h"
37 #include "winver.h"
38 #include "winuser.h"
39 #include "shlobj.h"
40 #include "shobjidl.h"
41 #include "objidl.h"
42 #include "wine/unicode.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(msi);
46 static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0};
48 static UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context)
50 HKEY hkey = NULL;
52 *context = MSIINSTALLCONTEXT_NONE;
54 if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
55 &hkey, FALSE) == ERROR_SUCCESS)
56 *context = MSIINSTALLCONTEXT_USERMANAGED;
57 else if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
58 &hkey, FALSE) == ERROR_SUCCESS)
59 *context = MSIINSTALLCONTEXT_MACHINE;
60 else if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
61 &hkey, FALSE) == ERROR_SUCCESS)
62 *context = MSIINSTALLCONTEXT_USERUNMANAGED;
64 RegCloseKey(hkey);
66 if (*context == MSIINSTALLCONTEXT_NONE)
67 return ERROR_UNKNOWN_PRODUCT;
69 return ERROR_SUCCESS;
72 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
74 UINT r;
75 LPWSTR szwProd = NULL;
77 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
79 if( szProduct )
81 szwProd = strdupAtoW( szProduct );
82 if( !szwProd )
83 return ERROR_OUTOFMEMORY;
86 r = MsiOpenProductW( szwProd, phProduct );
88 msi_free( szwProd );
90 return r;
93 static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package)
95 UINT r;
96 HKEY props;
97 LPWSTR path;
98 MSIINSTALLCONTEXT context;
100 static const WCHAR managed[] = {
101 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
102 static const WCHAR local[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
104 TRACE("%s %p\n", debugstr_w(szProduct), package);
106 r = msi_locate_product(szProduct, &context);
107 if (r != ERROR_SUCCESS)
108 return r;
110 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &props, FALSE);
111 if (r != ERROR_SUCCESS)
112 return ERROR_UNKNOWN_PRODUCT;
114 if (context == MSIINSTALLCONTEXT_USERMANAGED)
115 path = msi_reg_get_val_str(props, managed);
116 else
117 path = msi_reg_get_val_str(props, local);
119 r = ERROR_UNKNOWN_PRODUCT;
121 if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
122 goto done;
124 if (PathIsRelativeW(path))
126 r = ERROR_INSTALL_PACKAGE_OPEN_FAILED;
127 goto done;
130 r = MSI_OpenPackageW(path, package);
132 done:
133 RegCloseKey(props);
134 msi_free(path);
135 return r;
138 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
140 MSIPACKAGE *package = NULL;
141 WCHAR squished_pc[GUID_SIZE];
142 UINT r;
144 if (!szProduct || !squash_guid(szProduct, squished_pc))
145 return ERROR_INVALID_PARAMETER;
147 if (!phProduct)
148 return ERROR_INVALID_PARAMETER;
150 r = MSI_OpenProductW(szProduct, &package);
151 if (r != ERROR_SUCCESS)
152 return r;
154 *phProduct = alloc_msihandle(&package->hdr);
155 if (!*phProduct)
156 r = ERROR_NOT_ENOUGH_MEMORY;
158 msiobj_release(&package->hdr);
159 return r;
162 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
163 LPCSTR szTransforms, LANGID lgidLanguage)
165 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
166 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
167 return ERROR_CALL_NOT_IMPLEMENTED;
170 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
171 LPCWSTR szTransforms, LANGID lgidLanguage)
173 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
174 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
175 return ERROR_CALL_NOT_IMPLEMENTED;
178 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
179 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
181 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath),
182 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
183 lgidLanguage, dwPlatform, dwOptions);
184 return ERROR_CALL_NOT_IMPLEMENTED;
187 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
188 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
190 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath),
191 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
192 lgidLanguage, dwPlatform, dwOptions);
193 return ERROR_CALL_NOT_IMPLEMENTED;
196 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
198 LPWSTR szwPath = NULL, szwCommand = NULL;
199 UINT r = ERROR_OUTOFMEMORY;
201 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
203 if( szPackagePath )
205 szwPath = strdupAtoW( szPackagePath );
206 if( !szwPath )
207 goto end;
210 if( szCommandLine )
212 szwCommand = strdupAtoW( szCommandLine );
213 if( !szwCommand )
214 goto end;
217 r = MsiInstallProductW( szwPath, szwCommand );
219 end:
220 msi_free( szwPath );
221 msi_free( szwCommand );
223 return r;
226 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
228 MSIPACKAGE *package = NULL;
229 UINT r;
231 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
233 r = MSI_OpenPackageW( szPackagePath, &package );
234 if (r == ERROR_SUCCESS)
236 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
237 msiobj_release( &package->hdr );
240 return r;
243 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
245 FIXME("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
246 return ERROR_CALL_NOT_IMPLEMENTED;
249 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
251 FIXME("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
252 return ERROR_CALL_NOT_IMPLEMENTED;
255 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
256 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
258 LPWSTR patch_package = NULL;
259 LPWSTR install_package = NULL;
260 LPWSTR command_line = NULL;
261 UINT r = ERROR_OUTOFMEMORY;
263 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
264 eInstallType, debugstr_a(szCommandLine));
266 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage)))
267 goto done;
269 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage)))
270 goto done;
272 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine)))
273 goto done;
275 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line);
277 done:
278 msi_free(patch_package);
279 msi_free(install_package);
280 msi_free(command_line);
282 return r;
285 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
286 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
288 MSIHANDLE patch, info;
289 UINT r, type;
290 DWORD size = 0;
291 LPCWSTR cmd_ptr = szCommandLine;
292 LPWSTR beg, end;
293 LPWSTR cmd = NULL, codes = NULL;
295 static const WCHAR space[] = {' ',0};
296 static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
297 static WCHAR empty[] = {0};
299 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
300 eInstallType, debugstr_w(szCommandLine));
302 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
303 eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
305 FIXME("Only reading target products from patch\n");
306 return ERROR_CALL_NOT_IMPLEMENTED;
309 r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
310 if (r != ERROR_SUCCESS)
311 return r;
313 r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
314 if (r != ERROR_SUCCESS)
315 goto done;
317 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
318 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
320 ERR("Failed to read product codes from patch\n");
321 goto done;
324 codes = msi_alloc(++size * sizeof(WCHAR));
325 if (!codes)
327 r = ERROR_OUTOFMEMORY;
328 goto done;
331 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
332 if (r != ERROR_SUCCESS)
333 goto done;
335 if (!szCommandLine)
336 cmd_ptr = empty;
338 size = lstrlenW(cmd_ptr) + lstrlenW(patcheq) + lstrlenW(szPatchPackage) + 1;
339 cmd = msi_alloc(size * sizeof(WCHAR));
340 if (!cmd)
342 r = ERROR_OUTOFMEMORY;
343 goto done;
346 lstrcpyW(cmd, cmd_ptr);
347 if (szCommandLine) lstrcatW(cmd, space);
348 lstrcatW(cmd, patcheq);
349 lstrcatW(cmd, szPatchPackage);
351 beg = codes;
352 while ((end = strchrW(beg, '}')))
354 *(end + 1) = '\0';
356 r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
357 if (r != ERROR_SUCCESS)
358 goto done;
360 beg = end + 2;
363 done:
364 msi_free(cmd);
365 msi_free(codes);
367 MsiCloseHandle(info);
368 MsiCloseHandle(patch);
370 return r;
373 UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
374 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
376 FIXME("(%s, %d, %p): stub!\n", debugstr_a(szProductPackagePath),
377 cPatchInfo, pPatchInfo);
379 return ERROR_CALL_NOT_IMPLEMENTED;
382 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath,
383 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
385 FIXME("(%s, %d, %p): stub!\n", debugstr_w(szProductPackagePath),
386 cPatchInfo, pPatchInfo);
388 return ERROR_CALL_NOT_IMPLEMENTED;
391 static UINT msi_open_package(LPCWSTR product, MSIINSTALLCONTEXT context,
392 MSIPACKAGE **package)
394 UINT r;
395 DWORD sz;
396 HKEY props;
397 LPWSTR localpack;
398 WCHAR sourcepath[MAX_PATH];
399 WCHAR filename[MAX_PATH];
401 static const WCHAR szLocalPackage[] = {
402 'L','o','c','a','l','P','a','c','k','a','g','e',0};
405 r = MSIREG_OpenInstallProps(product, context, NULL, &props, FALSE);
406 if (r != ERROR_SUCCESS)
407 return ERROR_BAD_CONFIGURATION;
409 localpack = msi_reg_get_val_str(props, szLocalPackage);
410 if (localpack)
412 lstrcpyW(sourcepath, localpack);
413 msi_free(localpack);
416 if (!localpack || GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
418 sz = sizeof(sourcepath);
419 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
420 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
422 sz = sizeof(filename);
423 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
424 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
426 lstrcatW(sourcepath, filename);
429 if (GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
430 return ERROR_INSTALL_SOURCE_ABSENT;
432 return MSI_OpenPackageW(sourcepath, package);
435 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
436 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
438 MSIPACKAGE* package = NULL;
439 MSIINSTALLCONTEXT context;
440 UINT r;
441 DWORD sz;
442 WCHAR sourcepath[MAX_PATH];
443 LPWSTR commandline;
445 static const WCHAR szInstalled[] = {
446 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
447 static const WCHAR szRemoveAll[] = {
448 ' ','R','E','M','O','V','E','=','A','L','L',0};
449 static const WCHAR szMachine[] = {
450 ' ','A','L','L','U','S','E','R','S','=','1',0};
452 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
453 debugstr_w(szCommandLine));
455 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1)
456 return ERROR_INVALID_PARAMETER;
458 if (eInstallState == INSTALLSTATE_ADVERTISED ||
459 eInstallState == INSTALLSTATE_SOURCE)
461 FIXME("State %d not implemented\n", eInstallState);
462 return ERROR_CALL_NOT_IMPLEMENTED;
465 r = msi_locate_product(szProduct, &context);
466 if (r != ERROR_SUCCESS)
467 return r;
469 r = msi_open_package(szProduct, context, &package);
470 if (r != ERROR_SUCCESS)
471 return r;
473 sz = lstrlenW(szInstalled) + 1;
475 if (szCommandLine)
476 sz += lstrlenW(szCommandLine);
478 if (eInstallState == INSTALLSTATE_ABSENT)
479 sz += lstrlenW(szRemoveAll);
481 if (context == MSIINSTALLCONTEXT_MACHINE)
482 sz += lstrlenW(szMachine);
484 commandline = msi_alloc(sz * sizeof(WCHAR));
485 if (!commandline)
487 r = ERROR_OUTOFMEMORY;
488 goto end;
491 commandline[0] = 0;
492 if (szCommandLine)
493 lstrcpyW(commandline,szCommandLine);
495 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
496 lstrcatW(commandline,szInstalled);
498 if (eInstallState == INSTALLSTATE_ABSENT)
499 lstrcatW(commandline, szRemoveAll);
501 if (context == MSIINSTALLCONTEXT_MACHINE)
502 lstrcatW(commandline, szMachine);
504 r = MSI_InstallPackage( package, sourcepath, commandline );
506 msi_free(commandline);
508 end:
509 msiobj_release( &package->hdr );
511 return r;
514 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
515 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
517 LPWSTR szwProduct = NULL;
518 LPWSTR szwCommandLine = NULL;
519 UINT r = ERROR_OUTOFMEMORY;
521 if( szProduct )
523 szwProduct = strdupAtoW( szProduct );
524 if( !szwProduct )
525 goto end;
528 if( szCommandLine)
530 szwCommandLine = strdupAtoW( szCommandLine );
531 if( !szwCommandLine)
532 goto end;
535 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
536 szwCommandLine );
537 end:
538 msi_free( szwProduct );
539 msi_free( szwCommandLine);
541 return r;
544 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
545 INSTALLSTATE eInstallState)
547 LPWSTR szwProduct = NULL;
548 UINT r;
550 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
552 if( szProduct )
554 szwProduct = strdupAtoW( szProduct );
555 if( !szwProduct )
556 return ERROR_OUTOFMEMORY;
559 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
560 msi_free( szwProduct );
562 return r;
565 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
566 INSTALLSTATE eInstallState)
568 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
571 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
573 LPWSTR szwComponent = NULL;
574 UINT r;
575 WCHAR szwBuffer[GUID_SIZE];
577 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
579 if( szComponent )
581 szwComponent = strdupAtoW( szComponent );
582 if( !szwComponent )
583 return ERROR_OUTOFMEMORY;
586 *szwBuffer = '\0';
587 r = MsiGetProductCodeW( szwComponent, szwBuffer );
589 if(*szwBuffer)
590 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
592 msi_free( szwComponent );
594 return r;
597 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
599 UINT rc, index;
600 HKEY compkey, prodkey;
601 WCHAR squished_comp[GUID_SIZE];
602 WCHAR squished_prod[GUID_SIZE];
603 DWORD sz = GUID_SIZE;
605 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer);
607 if (!szComponent || !*szComponent)
608 return ERROR_INVALID_PARAMETER;
610 if (!squash_guid(szComponent, squished_comp))
611 return ERROR_INVALID_PARAMETER;
613 if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &compkey, FALSE) != ERROR_SUCCESS &&
614 MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &compkey, FALSE) != ERROR_SUCCESS)
616 return ERROR_UNKNOWN_COMPONENT;
619 rc = RegEnumValueW(compkey, 0, squished_prod, &sz, NULL, NULL, NULL, NULL);
620 if (rc != ERROR_SUCCESS)
622 RegCloseKey(compkey);
623 return ERROR_UNKNOWN_COMPONENT;
626 /* check simple case, only one product */
627 rc = RegEnumValueW(compkey, 1, squished_prod, &sz, NULL, NULL, NULL, NULL);
628 if (rc == ERROR_NO_MORE_ITEMS)
630 rc = ERROR_SUCCESS;
631 goto done;
634 index = 0;
635 while ((rc = RegEnumValueW(compkey, index, squished_prod, &sz,
636 NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS)
638 index++;
639 sz = GUID_SIZE;
640 unsquash_guid(squished_prod, szBuffer);
642 if (MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_USERMANAGED,
643 &prodkey, FALSE) == ERROR_SUCCESS ||
644 MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_USERUNMANAGED,
645 &prodkey, FALSE) == ERROR_SUCCESS ||
646 MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_MACHINE,
647 &prodkey, FALSE) == ERROR_SUCCESS)
649 RegCloseKey(prodkey);
650 rc = ERROR_SUCCESS;
651 goto done;
655 rc = ERROR_INSTALL_FAILURE;
657 done:
658 RegCloseKey(compkey);
659 unsquash_guid(squished_prod, szBuffer);
660 return rc;
663 static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
665 DWORD dval;
666 LONG res;
667 WCHAR temp[20];
669 static const WCHAR format[] = {'%','d',0};
671 res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL);
672 if (res != ERROR_SUCCESS)
673 return NULL;
675 if (*type == REG_SZ)
676 return msi_reg_get_val_str(hkey, name);
678 if (!msi_reg_get_val_dword(hkey, name, &dval))
679 return NULL;
681 sprintfW(temp, format, dval);
682 return strdupW(temp);
685 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
686 awstring *szValue, LPDWORD pcchValueBuf)
688 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
689 UINT r = ERROR_UNKNOWN_PROPERTY;
690 HKEY prodkey, userdata, source;
691 LPWSTR val = NULL;
692 WCHAR squished_pc[GUID_SIZE];
693 WCHAR packagecode[GUID_SIZE];
694 BOOL badconfig = FALSE;
695 LONG res;
696 DWORD save, type = REG_NONE;
698 static WCHAR empty[] = {0};
699 static const WCHAR sourcelist[] = {
700 'S','o','u','r','c','e','L','i','s','t',0};
701 static const WCHAR display_name[] = {
702 'D','i','s','p','l','a','y','N','a','m','e',0};
703 static const WCHAR display_version[] = {
704 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
705 static const WCHAR assignment[] = {
706 'A','s','s','i','g','n','m','e','n','t',0};
708 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
709 debugstr_w(szAttribute), szValue, pcchValueBuf);
711 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
712 return ERROR_INVALID_PARAMETER;
714 if (!squash_guid(szProduct, squished_pc))
715 return ERROR_INVALID_PARAMETER;
717 if ((r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
718 &prodkey, FALSE)) != ERROR_SUCCESS &&
719 (r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
720 &prodkey, FALSE)) != ERROR_SUCCESS &&
721 (r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
722 &prodkey, FALSE)) == ERROR_SUCCESS)
724 context = MSIINSTALLCONTEXT_MACHINE;
727 MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
729 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
730 !lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
731 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
732 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
733 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
734 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
735 !lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
736 !lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
737 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
738 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
739 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
740 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
741 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
742 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
743 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
744 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
746 if (!prodkey)
748 r = ERROR_UNKNOWN_PRODUCT;
749 goto done;
752 if (!userdata)
753 return ERROR_UNKNOWN_PROPERTY;
755 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
756 szAttribute = display_name;
757 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
758 szAttribute = display_version;
760 val = msi_reg_get_value(userdata, szAttribute, &type);
761 if (!val)
762 val = empty;
764 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
765 !lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
766 !lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
767 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
768 !lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
769 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
770 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
771 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
772 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
773 !lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
775 if (!prodkey)
777 r = ERROR_UNKNOWN_PRODUCT;
778 goto done;
781 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
782 szAttribute = assignment;
784 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
786 res = RegOpenKeyW(prodkey, sourcelist, &source);
787 if (res == ERROR_SUCCESS)
788 val = msi_reg_get_value(source, szAttribute, &type);
790 RegCloseKey(source);
792 else
794 val = msi_reg_get_value(prodkey, szAttribute, &type);
795 if (!val)
796 val = empty;
799 if (val != empty && type != REG_DWORD &&
800 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
802 if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
803 badconfig = TRUE;
804 else
806 unsquash_guid(val, packagecode);
807 msi_free(val);
808 val = strdupW(packagecode);
813 if (!val)
815 r = ERROR_UNKNOWN_PROPERTY;
816 goto done;
819 if (pcchValueBuf)
821 save = *pcchValueBuf;
823 if (strlenW(val) < *pcchValueBuf)
824 r = msi_strcpy_to_awstring(val, szValue, pcchValueBuf);
825 else if (szValue->str.a || szValue->str.w)
826 r = ERROR_MORE_DATA;
828 if (!badconfig)
829 *pcchValueBuf = lstrlenW(val);
830 else if (r == ERROR_SUCCESS)
832 *pcchValueBuf = save;
833 r = ERROR_BAD_CONFIGURATION;
836 else if (badconfig)
837 r = ERROR_BAD_CONFIGURATION;
839 if (val != empty)
840 msi_free(val);
842 done:
843 RegCloseKey(prodkey);
844 RegCloseKey(userdata);
845 return r;
848 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
849 LPSTR szBuffer, LPDWORD pcchValueBuf)
851 LPWSTR szwProduct, szwAttribute = NULL;
852 UINT r = ERROR_OUTOFMEMORY;
853 awstring buffer;
855 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
856 szBuffer, pcchValueBuf);
858 szwProduct = strdupAtoW( szProduct );
859 if( szProduct && !szwProduct )
860 goto end;
862 szwAttribute = strdupAtoW( szAttribute );
863 if( szAttribute && !szwAttribute )
864 goto end;
866 buffer.unicode = FALSE;
867 buffer.str.a = szBuffer;
869 r = MSI_GetProductInfo( szwProduct, szwAttribute,
870 &buffer, pcchValueBuf );
872 end:
873 msi_free( szwProduct );
874 msi_free( szwAttribute );
876 return r;
879 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
880 LPWSTR szBuffer, LPDWORD pcchValueBuf)
882 awstring buffer;
884 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
885 szBuffer, pcchValueBuf);
887 buffer.unicode = TRUE;
888 buffer.str.w = szBuffer;
890 return MSI_GetProductInfo( szProduct, szAttribute,
891 &buffer, pcchValueBuf );
894 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
895 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
896 LPSTR szValue, LPDWORD pcchValue)
898 LPWSTR product = NULL;
899 LPWSTR usersid = NULL;
900 LPWSTR property = NULL;
901 LPWSTR value = NULL;
902 DWORD len = 0;
903 UINT r;
905 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
906 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
907 szValue, pcchValue);
909 if (szValue && !pcchValue)
910 return ERROR_INVALID_PARAMETER;
912 if (szProductCode) product = strdupAtoW(szProductCode);
913 if (szUserSid) usersid = strdupAtoW(szUserSid);
914 if (szProperty) property = strdupAtoW(szProperty);
916 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
917 NULL, &len);
918 if (r != ERROR_SUCCESS)
919 goto done;
921 value = msi_alloc(++len * sizeof(WCHAR));
922 if (!value)
924 r = ERROR_OUTOFMEMORY;
925 goto done;
928 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
929 value, &len);
930 if (r != ERROR_SUCCESS)
931 goto done;
933 if (!pcchValue)
934 goto done;
936 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
937 if (*pcchValue >= len)
938 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
939 else if (szValue)
941 r = ERROR_MORE_DATA;
942 if (*pcchValue > 0)
943 *szValue = '\0';
946 if (*pcchValue <= len || !szValue)
947 len = len * sizeof(WCHAR) - 1;
949 *pcchValue = len - 1;
951 done:
952 msi_free(product);
953 msi_free(usersid);
954 msi_free(property);
955 msi_free(value);
957 return r;
960 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
962 UINT r;
964 if (!val)
965 return ERROR_UNKNOWN_PROPERTY;
967 if (out)
969 if (strlenW(val) >= *size)
971 r = ERROR_MORE_DATA;
972 if (*size > 0)
973 *out = '\0';
975 else
976 lstrcpyW(out, val);
979 if (size)
980 *size = lstrlenW(val);
982 return ERROR_SUCCESS;
985 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
986 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
987 LPWSTR szValue, LPDWORD pcchValue)
989 WCHAR squished_pc[GUID_SIZE];
990 LPWSTR val = NULL;
991 LPCWSTR package = NULL;
992 HKEY props = NULL, prod;
993 HKEY classes = NULL, managed;
994 HKEY hkey = NULL;
995 DWORD type;
996 UINT r = ERROR_UNKNOWN_PRODUCT;
998 static const WCHAR one[] = {'1',0};
999 static const WCHAR five[] = {'5',0};
1000 static const WCHAR empty[] = {0};
1001 static const WCHAR displayname[] = {
1002 'D','i','s','p','l','a','y','N','a','m','e',0};
1003 static const WCHAR displayversion[] = {
1004 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1005 static const WCHAR managed_local_package[] = {
1006 'M','a','n','a','g','e','d','L','o','c','a','l',
1007 'P','a','c','k','a','g','e',0};
1009 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
1010 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
1011 szValue, pcchValue);
1013 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1014 return ERROR_INVALID_PARAMETER;
1016 if (szValue && !pcchValue)
1017 return ERROR_INVALID_PARAMETER;
1019 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1020 dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1021 dwContext != MSIINSTALLCONTEXT_MACHINE)
1022 return ERROR_INVALID_PARAMETER;
1024 if (!szProperty || !*szProperty)
1025 return ERROR_INVALID_PARAMETER;
1027 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1028 return ERROR_INVALID_PARAMETER;
1030 /* FIXME: dwContext is provided, no need to search for it */
1031 MSIREG_OpenProductKey(szProductCode, MSIINSTALLCONTEXT_USERMANAGED,
1032 &managed, FALSE);
1033 MSIREG_OpenProductKey(szProductCode, MSIINSTALLCONTEXT_USERUNMANAGED,
1034 &prod, FALSE);
1036 MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE);
1038 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1040 package = INSTALLPROPERTY_LOCALPACKAGEW;
1042 if (!props && !prod)
1043 goto done;
1045 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1047 package = managed_local_package;
1049 if (!props && !managed)
1050 goto done;
1052 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1054 package = INSTALLPROPERTY_LOCALPACKAGEW;
1055 MSIREG_OpenProductKey(szProductCode, dwContext, &classes, FALSE);
1057 if (!props && !classes)
1058 goto done;
1061 if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
1062 !lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
1063 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
1064 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
1065 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
1066 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
1067 !lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
1068 !lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
1069 !lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
1070 !lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
1071 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
1072 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
1073 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
1074 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
1075 !lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
1076 !lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
1077 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
1079 val = msi_reg_get_value(props, package, &type);
1080 if (!val)
1082 if (prod || classes)
1083 r = ERROR_UNKNOWN_PROPERTY;
1085 goto done;
1088 msi_free(val);
1090 if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
1091 szProperty = displayname;
1092 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
1093 szProperty = displayversion;
1095 val = msi_reg_get_value(props, szProperty, &type);
1096 if (!val)
1097 val = strdupW(empty);
1099 r = msi_copy_outval(val, szValue, pcchValue);
1101 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
1102 !lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
1103 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
1104 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
1105 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
1106 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
1107 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
1108 !lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
1110 if (!prod && !classes)
1111 goto done;
1113 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1114 hkey = prod;
1115 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1116 hkey = managed;
1117 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1118 hkey = classes;
1120 val = msi_reg_get_value(hkey, szProperty, &type);
1121 if (!val)
1122 val = strdupW(empty);
1124 r = msi_copy_outval(val, szValue, pcchValue);
1126 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
1128 if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1130 if (props)
1132 val = msi_reg_get_value(props, package, &type);
1133 if (!val)
1134 goto done;
1136 msi_free(val);
1137 val = strdupW(five);
1139 else
1140 val = strdupW(one);
1142 r = msi_copy_outval(val, szValue, pcchValue);
1143 goto done;
1145 else if (props && (val = msi_reg_get_value(props, package, &type)))
1147 msi_free(val);
1148 val = strdupW(five);
1149 r = msi_copy_outval(val, szValue, pcchValue);
1150 goto done;
1153 if (prod || managed)
1154 val = strdupW(one);
1155 else
1156 goto done;
1158 r = msi_copy_outval(val, szValue, pcchValue);
1160 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
1162 if (!prod && !classes)
1163 goto done;
1165 /* FIXME */
1166 val = strdupW(empty);
1167 r = msi_copy_outval(val, szValue, pcchValue);
1169 else
1170 r = ERROR_UNKNOWN_PROPERTY;
1172 done:
1173 RegCloseKey(props);
1174 RegCloseKey(prod);
1175 RegCloseKey(managed);
1176 RegCloseKey(classes);
1177 msi_free(val);
1179 return r;
1182 UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode,
1183 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1184 LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
1186 LPWSTR patch = NULL, product = NULL, usersid = NULL;
1187 LPWSTR property = NULL, val = NULL;
1188 DWORD len;
1189 UINT r;
1191 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode),
1192 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext,
1193 debugstr_a(szProperty), lpValue, pcchValue);
1195 if (lpValue && !pcchValue)
1196 return ERROR_INVALID_PARAMETER;
1198 if (szPatchCode) patch = strdupAtoW(szPatchCode);
1199 if (szProductCode) product = strdupAtoW(szProductCode);
1200 if (szUserSid) usersid = strdupAtoW(szUserSid);
1201 if (szProperty) property = strdupAtoW(szProperty);
1203 len = 0;
1204 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1205 NULL, &len);
1206 if (r != ERROR_SUCCESS)
1207 goto done;
1209 val = msi_alloc(++len * sizeof(WCHAR));
1210 if (!val)
1212 r = ERROR_OUTOFMEMORY;
1213 goto done;
1216 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1217 val, &len);
1218 if (r != ERROR_SUCCESS || !pcchValue)
1219 goto done;
1221 if (lpValue)
1222 WideCharToMultiByte(CP_ACP, 0, val, -1, lpValue,
1223 *pcchValue - 1, NULL, NULL);
1225 len = lstrlenW(val);
1226 if ((*val && *pcchValue < len + 1) || !lpValue)
1228 if (lpValue)
1230 r = ERROR_MORE_DATA;
1231 lpValue[*pcchValue - 1] = '\0';
1234 *pcchValue = len * sizeof(WCHAR);
1236 else
1237 *pcchValue = len;
1239 done:
1240 msi_free(val);
1241 msi_free(patch);
1242 msi_free(product);
1243 msi_free(usersid);
1244 msi_free(property);
1246 return r;
1249 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
1250 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1251 LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue)
1253 WCHAR squished_pc[GUID_SIZE];
1254 WCHAR squished_patch[GUID_SIZE];
1255 HKEY udprod = 0, prod = 0, props = 0;
1256 HKEY patch = 0, patches = 0;
1257 HKEY udpatch = 0, datakey = 0;
1258 HKEY prodpatches = 0;
1259 LPWSTR val = NULL;
1260 UINT r = ERROR_UNKNOWN_PRODUCT;
1261 DWORD len;
1262 LONG res;
1264 static const WCHAR szEmpty[] = {0};
1265 static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
1266 static const WCHAR szInstalled[] = {'I','n','s','t','a','l','l','e','d',0};
1267 static const WCHAR szManagedPackage[] = {'M','a','n','a','g','e','d',
1268 'L','o','c','a','l','P','a','c','k','a','g','e',0};
1270 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode),
1271 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext,
1272 debugstr_w(szProperty), lpValue, pcchValue);
1274 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1275 return ERROR_INVALID_PARAMETER;
1277 if (!szPatchCode || !squash_guid(szPatchCode, squished_patch))
1278 return ERROR_INVALID_PARAMETER;
1280 if (!szProperty)
1281 return ERROR_INVALID_PARAMETER;
1283 if (lpValue && !pcchValue)
1284 return ERROR_INVALID_PARAMETER;
1286 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1287 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1288 dwContext != MSIINSTALLCONTEXT_MACHINE)
1289 return ERROR_INVALID_PARAMETER;
1291 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1292 return ERROR_INVALID_PARAMETER;
1294 if (!lstrcmpW(szUserSid, szLocalSid))
1295 return ERROR_INVALID_PARAMETER;
1297 if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
1298 &udprod, FALSE) != ERROR_SUCCESS)
1299 goto done;
1301 if (MSIREG_OpenInstallProps(szProductCode, dwContext, NULL,
1302 &props, FALSE) != ERROR_SUCCESS)
1303 goto done;
1305 r = ERROR_UNKNOWN_PATCH;
1307 res = RegOpenKeyExW(udprod, szPatches, 0, KEY_READ, &patches);
1308 if (res != ERROR_SUCCESS)
1309 goto done;
1311 res = RegOpenKeyExW(patches, squished_patch, 0, KEY_READ, &patch);
1312 if (res != ERROR_SUCCESS)
1313 goto done;
1315 if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW))
1317 if (MSIREG_OpenProductKey(szProductCode, dwContext,
1318 &prod, FALSE) != ERROR_SUCCESS)
1319 goto done;
1321 res = RegOpenKeyExW(prod, szPatches, 0, KEY_ALL_ACCESS, &prodpatches);
1322 if (res != ERROR_SUCCESS)
1323 goto done;
1325 datakey = prodpatches;
1326 szProperty = squished_patch;
1328 else
1330 if (MSIREG_OpenUserDataPatchKey(szPatchCode, dwContext,
1331 &udpatch, FALSE) != ERROR_SUCCESS)
1332 goto done;
1334 if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
1336 if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1337 szProperty = szManagedPackage;
1338 datakey = udpatch;
1340 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW))
1342 datakey = patch;
1343 szProperty = szInstalled;
1345 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
1347 datakey = udpatch;
1349 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_UNINSTALLABLEW) ||
1350 !lstrcmpW(szProperty, INSTALLPROPERTY_PATCHSTATEW) ||
1351 !lstrcmpW(szProperty, INSTALLPROPERTY_DISPLAYNAMEW) ||
1352 !lstrcmpW(szProperty, INSTALLPROPERTY_MOREINFOURLW))
1354 datakey = patch;
1356 else
1358 r = ERROR_UNKNOWN_PROPERTY;
1359 goto done;
1363 val = msi_reg_get_val_str(datakey, szProperty);
1364 if (!val)
1365 val = strdupW(szEmpty);
1367 r = ERROR_SUCCESS;
1369 if (!pcchValue)
1370 goto done;
1372 if (lpValue)
1373 lstrcpynW(lpValue, val, *pcchValue);
1375 len = lstrlenW(val);
1376 if ((*val && *pcchValue < len + 1) || !lpValue)
1378 if (lpValue)
1379 r = ERROR_MORE_DATA;
1381 *pcchValue = len * sizeof(WCHAR);
1384 *pcchValue = len;
1386 done:
1387 msi_free(val);
1388 RegCloseKey(prodpatches);
1389 RegCloseKey(prod);
1390 RegCloseKey(patch);
1391 RegCloseKey(patches);
1392 RegCloseKey(udpatch);
1393 RegCloseKey(props);
1394 RegCloseKey(udprod);
1396 return r;
1399 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
1401 LPWSTR szwLogFile = NULL;
1402 UINT r;
1404 TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
1406 if( szLogFile )
1408 szwLogFile = strdupAtoW( szLogFile );
1409 if( !szwLogFile )
1410 return ERROR_OUTOFMEMORY;
1412 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
1413 msi_free( szwLogFile );
1414 return r;
1417 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
1419 HANDLE file = INVALID_HANDLE_VALUE;
1421 TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
1423 if (szLogFile)
1425 lstrcpyW(gszLogFile,szLogFile);
1426 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
1427 DeleteFileW(szLogFile);
1428 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
1429 FILE_ATTRIBUTE_NORMAL, NULL);
1430 if (file != INVALID_HANDLE_VALUE)
1431 CloseHandle(file);
1432 else
1433 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
1435 else
1436 gszLogFile[0] = '\0';
1438 return ERROR_SUCCESS;
1441 UINT WINAPI MsiEnumComponentCostsW(MSIHANDLE hInstall, LPCWSTR szComponent,
1442 DWORD dwIndex, INSTALLSTATE iState,
1443 LPWSTR lpDriveBuf, DWORD *pcchDriveBuf,
1444 int *piCost, int *pTempCost)
1446 FIXME("(%d, %s, %d, %d, %p, %p, %p %p): stub!\n", hInstall,
1447 debugstr_w(szComponent), dwIndex, iState, lpDriveBuf,
1448 pcchDriveBuf, piCost, pTempCost);
1450 return ERROR_NO_MORE_ITEMS;
1453 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
1454 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1455 LPCSTR szComponent, INSTALLSTATE *pdwState)
1457 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL;
1458 UINT r;
1460 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode),
1461 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
1463 if (szProductCode && !(prodcode = strdupAtoW(szProductCode)))
1464 return ERROR_OUTOFMEMORY;
1466 if (szUserSid && !(usersid = strdupAtoW(szUserSid)))
1467 return ERROR_OUTOFMEMORY;
1469 if (szComponent && !(comp = strdupAtoW(szComponent)))
1470 return ERROR_OUTOFMEMORY;
1472 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState);
1474 msi_free(prodcode);
1475 msi_free(usersid);
1476 msi_free(comp);
1478 return r;
1481 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1483 UINT r;
1484 HKEY hkey;
1486 r = MSIREG_OpenProductKey(prodcode, context, &hkey, FALSE);
1487 RegCloseKey(hkey);
1488 return (r == ERROR_SUCCESS);
1491 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1493 LPCWSTR package;
1494 HKEY hkey;
1495 DWORD sz;
1496 LONG res;
1497 UINT r;
1499 static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
1500 static const WCHAR managed_local_package[] = {
1501 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
1504 r = MSIREG_OpenInstallProps(prodcode, context, NULL, &hkey, FALSE);
1505 if (r != ERROR_SUCCESS)
1506 return FALSE;
1508 if (context == MSIINSTALLCONTEXT_USERMANAGED)
1509 package = managed_local_package;
1510 else
1511 package = local_package;
1513 sz = 0;
1514 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
1515 RegCloseKey(hkey);
1517 return (res == ERROR_SUCCESS);
1520 static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
1521 MSIINSTALLCONTEXT context,
1522 LPCWSTR comp, LPWSTR val, DWORD *sz)
1524 HKEY hkey;
1525 LONG res;
1526 UINT r;
1528 if (context == MSIINSTALLCONTEXT_MACHINE)
1529 r = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
1530 else
1531 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
1533 if (r != ERROR_SUCCESS)
1534 return FALSE;
1536 res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz);
1537 if (res != ERROR_SUCCESS)
1538 return FALSE;
1540 RegCloseKey(hkey);
1541 return TRUE;
1544 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
1545 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1546 LPCWSTR szComponent, INSTALLSTATE *pdwState)
1548 WCHAR squished_pc[GUID_SIZE];
1549 WCHAR val[MAX_PATH];
1550 BOOL found;
1551 DWORD sz;
1553 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
1554 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
1556 if (!pdwState)
1557 return ERROR_INVALID_PARAMETER;
1559 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1)
1560 return ERROR_INVALID_PARAMETER;
1562 if (!squash_guid(szProductCode, squished_pc))
1563 return ERROR_INVALID_PARAMETER;
1565 found = msi_comp_find_prod_key(szProductCode, dwContext);
1567 if (!msi_comp_find_package(szProductCode, dwContext))
1569 if (found)
1571 *pdwState = INSTALLSTATE_UNKNOWN;
1572 return ERROR_UNKNOWN_COMPONENT;
1575 return ERROR_UNKNOWN_PRODUCT;
1578 *pdwState = INSTALLSTATE_UNKNOWN;
1580 sz = MAX_PATH;
1581 if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))
1582 return ERROR_UNKNOWN_COMPONENT;
1584 if (sz == 0)
1585 *pdwState = INSTALLSTATE_NOTUSED;
1586 else
1588 if (lstrlenW(val) > 2 &&
1589 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9')
1591 *pdwState = INSTALLSTATE_SOURCE;
1593 else
1594 *pdwState = INSTALLSTATE_LOCAL;
1597 return ERROR_SUCCESS;
1600 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
1602 LPWSTR szwProduct = NULL;
1603 INSTALLSTATE r;
1605 if( szProduct )
1607 szwProduct = strdupAtoW( szProduct );
1608 if( !szwProduct )
1609 return ERROR_OUTOFMEMORY;
1611 r = MsiQueryProductStateW( szwProduct );
1612 msi_free( szwProduct );
1613 return r;
1616 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
1618 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
1619 INSTALLSTATE state = INSTALLSTATE_ADVERTISED;
1620 HKEY prodkey = 0, userdata = 0;
1621 DWORD val;
1622 UINT r;
1624 static const WCHAR szWindowsInstaller[] = {
1625 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1627 TRACE("%s\n", debugstr_w(szProduct));
1629 if (!szProduct || !*szProduct)
1630 return INSTALLSTATE_INVALIDARG;
1632 if (lstrlenW(szProduct) != GUID_SIZE - 1)
1633 return INSTALLSTATE_INVALIDARG;
1635 if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
1636 &prodkey, FALSE) != ERROR_SUCCESS &&
1637 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
1638 &prodkey, FALSE) != ERROR_SUCCESS &&
1639 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
1640 &prodkey, FALSE) == ERROR_SUCCESS)
1642 context = MSIINSTALLCONTEXT_MACHINE;
1645 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
1646 if (r != ERROR_SUCCESS)
1647 goto done;
1649 if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val))
1650 goto done;
1652 if (val)
1653 state = INSTALLSTATE_DEFAULT;
1654 else
1655 state = INSTALLSTATE_UNKNOWN;
1657 done:
1658 if (!prodkey)
1660 state = INSTALLSTATE_UNKNOWN;
1662 if (userdata)
1663 state = INSTALLSTATE_ABSENT;
1666 RegCloseKey(prodkey);
1667 RegCloseKey(userdata);
1668 return state;
1671 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
1673 INSTALLUILEVEL old = gUILevel;
1674 HWND oldwnd = gUIhwnd;
1676 TRACE("%08x %p\n", dwUILevel, phWnd);
1678 gUILevel = dwUILevel;
1679 if (phWnd)
1681 gUIhwnd = *phWnd;
1682 *phWnd = oldwnd;
1684 return old;
1687 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
1688 DWORD dwMessageFilter, LPVOID pvContext)
1690 INSTALLUI_HANDLERA prev = gUIHandlerA;
1692 TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
1693 gUIHandlerA = puiHandler;
1694 gUIFilter = dwMessageFilter;
1695 gUIContext = pvContext;
1697 return prev;
1700 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
1701 DWORD dwMessageFilter, LPVOID pvContext)
1703 INSTALLUI_HANDLERW prev = gUIHandlerW;
1705 TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
1706 gUIHandlerW = puiHandler;
1707 gUIFilter = dwMessageFilter;
1708 gUIContext = pvContext;
1710 return prev;
1713 /******************************************************************
1714 * MsiLoadStringW [MSI.@]
1716 * Loads a string from MSI's string resources.
1718 * PARAMS
1720 * handle [I] only -1 is handled currently
1721 * id [I] id of the string to be loaded
1722 * lpBuffer [O] buffer for the string to be written to
1723 * nBufferMax [I] maximum size of the buffer in characters
1724 * lang [I] the preferred language for the string
1726 * RETURNS
1728 * If successful, this function returns the language id of the string loaded
1729 * If the function fails, the function returns zero.
1731 * NOTES
1733 * The type of the first parameter is unknown. LoadString's prototype
1734 * suggests that it might be a module handle. I have made it an MSI handle
1735 * for starters, as -1 is an invalid MSI handle, but not an invalid module
1736 * handle. Maybe strings can be stored in an MSI database somehow.
1738 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
1739 int nBufferMax, LANGID lang )
1741 HRSRC hres;
1742 HGLOBAL hResData;
1743 LPWSTR p;
1744 DWORD i, len;
1746 TRACE("%d %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
1748 if( handle != -1 )
1749 FIXME("don't know how to deal with handle = %08x\n", handle);
1751 if( !lang )
1752 lang = GetUserDefaultLangID();
1754 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
1755 (LPWSTR)1, lang );
1756 if( !hres )
1757 return 0;
1758 hResData = LoadResource( msi_hInstance, hres );
1759 if( !hResData )
1760 return 0;
1761 p = LockResource( hResData );
1762 if( !p )
1763 return 0;
1765 for (i = 0; i < (id&0xf); i++)
1766 p += *p + 1;
1767 len = *p;
1769 if( nBufferMax <= len )
1770 return 0;
1772 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
1773 lpBuffer[ len ] = 0;
1775 TRACE("found -> %s\n", debugstr_w(lpBuffer));
1777 return lang;
1780 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
1781 int nBufferMax, LANGID lang )
1783 LPWSTR bufW;
1784 LANGID r;
1785 INT len;
1787 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
1788 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
1789 if( r )
1791 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
1792 if( len <= nBufferMax )
1793 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
1794 lpBuffer, nBufferMax, NULL, NULL );
1795 else
1796 r = 0;
1798 msi_free(bufW);
1799 return r;
1802 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
1803 LPDWORD pcchBuf)
1805 char szProduct[GUID_SIZE];
1807 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
1809 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
1810 return INSTALLSTATE_UNKNOWN;
1812 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
1815 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
1816 LPDWORD pcchBuf)
1818 WCHAR szProduct[GUID_SIZE];
1820 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
1822 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
1823 return INSTALLSTATE_UNKNOWN;
1825 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
1828 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
1829 WORD wLanguageId, DWORD f)
1831 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
1832 uType, wLanguageId, f);
1833 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
1836 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
1837 WORD wLanguageId, DWORD f)
1839 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
1840 uType, wLanguageId, f);
1841 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
1844 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
1845 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
1846 LPDWORD pcchPathBuf )
1848 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
1849 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
1850 pcchPathBuf);
1851 return ERROR_CALL_NOT_IMPLEMENTED;
1854 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
1855 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
1856 LPDWORD pcchPathBuf )
1858 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
1859 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
1860 pcchPathBuf);
1861 return ERROR_CALL_NOT_IMPLEMENTED;
1864 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
1865 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
1867 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
1868 return ERROR_CALL_NOT_IMPLEMENTED;
1871 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
1872 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
1874 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
1875 return ERROR_CALL_NOT_IMPLEMENTED;
1878 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
1879 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
1880 LPDWORD pcbHashData)
1882 FIXME("%s %08x %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
1883 ppcCertContext, pbHashData, pcbHashData);
1884 return ERROR_CALL_NOT_IMPLEMENTED;
1887 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
1888 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
1889 LPDWORD pcbHashData)
1891 FIXME("%s %08x %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
1892 ppcCertContext, pbHashData, pcbHashData);
1893 return ERROR_CALL_NOT_IMPLEMENTED;
1896 /******************************************************************
1897 * MsiGetProductPropertyA [MSI.@]
1899 UINT WINAPI MsiGetProductPropertyA(MSIHANDLE hProduct, LPCSTR szProperty,
1900 LPSTR szValue, LPDWORD pccbValue)
1902 LPWSTR prop = NULL, val = NULL;
1903 DWORD len;
1904 UINT r;
1906 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_a(szProperty),
1907 szValue, pccbValue);
1909 if (szValue && !pccbValue)
1910 return ERROR_INVALID_PARAMETER;
1912 if (szProperty) prop = strdupAtoW(szProperty);
1914 len = 0;
1915 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len);
1916 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
1917 goto done;
1919 if (r == ERROR_SUCCESS)
1921 if (szValue) *szValue = '\0';
1922 if (pccbValue) *pccbValue = 0;
1923 goto done;
1926 val = msi_alloc(++len * sizeof(WCHAR));
1927 if (!val)
1929 r = ERROR_OUTOFMEMORY;
1930 goto done;
1933 r = MsiGetProductPropertyW(hProduct, prop, val, &len);
1934 if (r != ERROR_SUCCESS)
1935 goto done;
1937 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL);
1939 if (szValue)
1940 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue,
1941 *pccbValue, NULL, NULL);
1943 if (pccbValue)
1945 if (len > *pccbValue)
1946 r = ERROR_MORE_DATA;
1948 *pccbValue = len - 1;
1951 done:
1952 msi_free(prop);
1953 msi_free(val);
1955 return r;
1958 /******************************************************************
1959 * MsiGetProductPropertyW [MSI.@]
1961 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE hProduct, LPCWSTR szProperty,
1962 LPWSTR szValue, LPDWORD pccbValue)
1964 MSIPACKAGE *package;
1965 MSIQUERY *view = NULL;
1966 MSIRECORD *rec = NULL;
1967 LPCWSTR val;
1968 UINT r;
1970 static const WCHAR query[] = {
1971 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1972 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
1973 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
1975 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_w(szProperty),
1976 szValue, pccbValue);
1978 if (!szProperty)
1979 return ERROR_INVALID_PARAMETER;
1981 if (szValue && !pccbValue)
1982 return ERROR_INVALID_PARAMETER;
1984 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE);
1985 if (!package)
1986 return ERROR_INVALID_HANDLE;
1988 r = MSI_OpenQuery(package->db, &view, query, szProperty);
1989 if (r != ERROR_SUCCESS)
1990 goto done;
1992 r = MSI_ViewExecute(view, 0);
1993 if (r != ERROR_SUCCESS)
1994 goto done;
1996 r = MSI_ViewFetch(view, &rec);
1997 if (r != ERROR_SUCCESS)
1998 goto done;
2000 val = MSI_RecordGetString(rec, 2);
2001 if (!val)
2002 goto done;
2004 if (lstrlenW(val) >= *pccbValue)
2006 lstrcpynW(szValue, val, *pccbValue);
2007 *pccbValue = lstrlenW(val);
2008 r = ERROR_MORE_DATA;
2010 else
2012 lstrcpyW(szValue, val);
2013 *pccbValue = lstrlenW(val);
2014 r = ERROR_SUCCESS;
2017 done:
2018 if (view)
2020 MSI_ViewClose(view);
2021 msiobj_release(&view->hdr);
2022 if (rec) msiobj_release(&rec->hdr);
2025 if (!rec)
2027 if (szValue) *szValue = '\0';
2028 if (pccbValue) *pccbValue = 0;
2029 r = ERROR_SUCCESS;
2032 return r;
2035 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
2037 UINT r;
2038 LPWSTR szPack = NULL;
2040 TRACE("%s\n", debugstr_a(szPackage) );
2042 if( szPackage )
2044 szPack = strdupAtoW( szPackage );
2045 if( !szPack )
2046 return ERROR_OUTOFMEMORY;
2049 r = MsiVerifyPackageW( szPack );
2051 msi_free( szPack );
2053 return r;
2056 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
2058 MSIHANDLE handle;
2059 UINT r;
2061 TRACE("%s\n", debugstr_w(szPackage) );
2063 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
2064 MsiCloseHandle( handle );
2066 return r;
2069 static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
2070 awstring* lpPathBuf, LPDWORD pcchBuf)
2072 WCHAR squished_pc[GUID_SIZE];
2073 WCHAR squished_comp[GUID_SIZE];
2074 HKEY hkey;
2075 LPWSTR path = NULL;
2076 INSTALLSTATE state;
2077 DWORD version;
2079 static const WCHAR wininstaller[] = {
2080 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
2082 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
2083 debugstr_w(szComponent), lpPathBuf->str.w, pcchBuf);
2085 if (!szProduct || !szComponent)
2086 return INSTALLSTATE_INVALIDARG;
2088 if (lpPathBuf->str.w && !pcchBuf)
2089 return INSTALLSTATE_INVALIDARG;
2091 if (!squash_guid(szProduct, squished_pc) ||
2092 !squash_guid(szComponent, squished_comp))
2093 return INSTALLSTATE_INVALIDARG;
2095 state = INSTALLSTATE_UNKNOWN;
2097 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
2098 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
2100 path = msi_reg_get_val_str(hkey, squished_pc);
2101 RegCloseKey(hkey);
2103 state = INSTALLSTATE_ABSENT;
2105 if ((MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL,
2106 &hkey, FALSE) == ERROR_SUCCESS ||
2107 MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2108 NULL, &hkey, FALSE) == ERROR_SUCCESS) &&
2109 msi_reg_get_val_dword(hkey, wininstaller, &version) &&
2110 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2112 RegCloseKey(hkey);
2113 state = INSTALLSTATE_LOCAL;
2117 if (state != INSTALLSTATE_LOCAL &&
2118 (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2119 &hkey, FALSE) == ERROR_SUCCESS ||
2120 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2121 &hkey, FALSE) == ERROR_SUCCESS))
2123 RegCloseKey(hkey);
2125 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
2126 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
2128 msi_free(path);
2129 path = msi_reg_get_val_str(hkey, squished_pc);
2130 RegCloseKey(hkey);
2132 state = INSTALLSTATE_ABSENT;
2134 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2135 state = INSTALLSTATE_LOCAL;
2139 if (!path)
2140 return INSTALLSTATE_UNKNOWN;
2142 if (state == INSTALLSTATE_LOCAL && !*path)
2143 state = INSTALLSTATE_NOTUSED;
2145 msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf);
2146 msi_free(path);
2147 return state;
2150 /******************************************************************
2151 * MsiGetComponentPathW [MSI.@]
2153 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
2154 LPWSTR lpPathBuf, LPDWORD pcchBuf)
2156 awstring path;
2158 path.unicode = TRUE;
2159 path.str.w = lpPathBuf;
2161 return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
2164 /******************************************************************
2165 * MsiGetComponentPathA [MSI.@]
2167 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
2168 LPSTR lpPathBuf, LPDWORD pcchBuf)
2170 LPWSTR szwProduct, szwComponent = NULL;
2171 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
2172 awstring path;
2174 szwProduct = strdupAtoW( szProduct );
2175 if( szProduct && !szwProduct)
2176 goto end;
2178 szwComponent = strdupAtoW( szComponent );
2179 if( szComponent && !szwComponent )
2180 goto end;
2182 path.unicode = FALSE;
2183 path.str.a = lpPathBuf;
2185 r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
2187 end:
2188 msi_free( szwProduct );
2189 msi_free( szwComponent );
2191 return r;
2194 /******************************************************************
2195 * MsiQueryFeatureStateA [MSI.@]
2197 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
2199 LPWSTR szwProduct = NULL, szwFeature= NULL;
2200 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
2202 szwProduct = strdupAtoW( szProduct );
2203 if ( szProduct && !szwProduct )
2204 goto end;
2206 szwFeature = strdupAtoW( szFeature );
2207 if ( szFeature && !szwFeature )
2208 goto end;
2210 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
2212 end:
2213 msi_free( szwProduct);
2214 msi_free( szwFeature);
2216 return rc;
2219 /******************************************************************
2220 * MsiQueryFeatureStateW [MSI.@]
2222 * Checks the state of a feature
2224 * PARAMS
2225 * szProduct [I] Product's GUID string
2226 * szFeature [I] Feature's GUID string
2228 * RETURNS
2229 * INSTALLSTATE_LOCAL Feature is installed and usable
2230 * INSTALLSTATE_ABSENT Feature is absent
2231 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
2232 * INSTALLSTATE_UNKNOWN An error occurred
2233 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
2236 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
2238 WCHAR squishProduct[33], comp[GUID_SIZE];
2239 GUID guid;
2240 LPWSTR components, p, parent_feature, path;
2241 UINT rc;
2242 HKEY hkey;
2243 INSTALLSTATE r;
2244 BOOL missing = FALSE;
2245 BOOL machine = FALSE;
2246 BOOL source = FALSE;
2248 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
2250 if (!szProduct || !szFeature)
2251 return INSTALLSTATE_INVALIDARG;
2253 if (!squash_guid( szProduct, squishProduct ))
2254 return INSTALLSTATE_INVALIDARG;
2256 if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2257 &hkey, FALSE) != ERROR_SUCCESS &&
2258 MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2259 &hkey, FALSE) != ERROR_SUCCESS)
2261 rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2262 &hkey, FALSE);
2263 if (rc != ERROR_SUCCESS)
2264 return INSTALLSTATE_UNKNOWN;
2266 machine = TRUE;
2269 parent_feature = msi_reg_get_val_str( hkey, szFeature );
2270 RegCloseKey(hkey);
2272 if (!parent_feature)
2273 return INSTALLSTATE_UNKNOWN;
2275 r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
2276 msi_free(parent_feature);
2277 if (r == INSTALLSTATE_ABSENT)
2278 return r;
2280 if (machine)
2281 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2282 MSIINSTALLCONTEXT_MACHINE,
2283 &hkey, FALSE);
2284 else
2285 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2286 MSIINSTALLCONTEXT_USERUNMANAGED,
2287 &hkey, FALSE);
2289 if (rc != ERROR_SUCCESS)
2290 return INSTALLSTATE_ADVERTISED;
2292 components = msi_reg_get_val_str( hkey, szFeature );
2293 RegCloseKey(hkey);
2295 TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components));
2297 if (!components)
2298 return INSTALLSTATE_ADVERTISED;
2300 for( p = components; *p && *p != 2 ; p += 20)
2302 if (!decode_base85_guid( p, &guid ))
2304 if (p != components)
2305 break;
2307 msi_free(components);
2308 return INSTALLSTATE_BADCONFIG;
2311 StringFromGUID2(&guid, comp, GUID_SIZE);
2313 if (machine)
2314 rc = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
2315 else
2316 rc = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
2318 if (rc != ERROR_SUCCESS)
2320 msi_free(components);
2321 return INSTALLSTATE_ADVERTISED;
2324 path = msi_reg_get_val_str(hkey, squishProduct);
2325 if (!path)
2326 missing = TRUE;
2327 else if (lstrlenW(path) > 2 &&
2328 path[0] >= '0' && path[0] <= '9' &&
2329 path[1] >= '0' && path[1] <= '9')
2331 source = TRUE;
2334 msi_free(path);
2337 TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
2338 msi_free(components);
2340 if (missing)
2341 return INSTALLSTATE_ADVERTISED;
2343 if (source)
2344 return INSTALLSTATE_SOURCE;
2346 return INSTALLSTATE_LOCAL;
2349 /******************************************************************
2350 * MsiGetFileVersionA [MSI.@]
2352 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
2353 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
2355 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
2356 UINT ret = ERROR_OUTOFMEMORY;
2358 if ((lpVersionBuf && !pcchVersionBuf) ||
2359 (lpLangBuf && !pcchLangBuf))
2360 return ERROR_INVALID_PARAMETER;
2362 if( szFilePath )
2364 szwFilePath = strdupAtoW( szFilePath );
2365 if( !szwFilePath )
2366 goto end;
2369 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
2371 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
2372 if( !lpwVersionBuff )
2373 goto end;
2376 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
2378 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
2379 if( !lpwLangBuff )
2380 goto end;
2383 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
2384 lpwLangBuff, pcchLangBuf);
2386 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
2387 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
2388 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
2389 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
2390 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
2391 lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
2393 end:
2394 msi_free(szwFilePath);
2395 msi_free(lpwVersionBuff);
2396 msi_free(lpwLangBuff);
2398 return ret;
2401 /******************************************************************
2402 * MsiGetFileVersionW [MSI.@]
2404 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
2405 LPDWORD pcchVersionBuf, LPWSTR lpLangBuf, LPDWORD pcchLangBuf)
2407 static const WCHAR szVersionResource[] = {'\\',0};
2408 static const WCHAR szVersionFormat[] = {
2409 '%','d','.','%','d','.','%','d','.','%','d',0};
2410 static const WCHAR szLangResource[] = {
2411 '\\','V','a','r','F','i','l','e','I','n','f','o','\\',
2412 'T','r','a','n','s','l','a','t','i','o','n',0};
2413 static const WCHAR szLangFormat[] = {'%','d',0};
2414 UINT ret = 0;
2415 DWORD dwVerLen, gle;
2416 LPVOID lpVer = NULL;
2417 VS_FIXEDFILEINFO *ffi;
2418 USHORT *lang;
2419 UINT puLen;
2420 WCHAR tmp[32];
2422 TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath),
2423 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
2424 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
2426 if ((lpVersionBuf && !pcchVersionBuf) ||
2427 (lpLangBuf && !pcchLangBuf))
2428 return ERROR_INVALID_PARAMETER;
2430 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
2431 if( !dwVerLen )
2433 gle = GetLastError();
2434 if (gle == ERROR_BAD_PATHNAME)
2435 return ERROR_FILE_NOT_FOUND;
2436 else if (gle == ERROR_RESOURCE_DATA_NOT_FOUND)
2437 return ERROR_FILE_INVALID;
2439 return gle;
2442 lpVer = msi_alloc(dwVerLen);
2443 if( !lpVer )
2445 ret = ERROR_OUTOFMEMORY;
2446 goto end;
2449 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
2451 ret = GetLastError();
2452 goto end;
2455 if (pcchVersionBuf)
2457 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
2458 (puLen > 0) )
2460 wsprintfW(tmp, szVersionFormat,
2461 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
2462 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
2463 if (lpVersionBuf) lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
2465 if (strlenW(tmp) >= *pcchVersionBuf)
2466 ret = ERROR_MORE_DATA;
2468 *pcchVersionBuf = lstrlenW(tmp);
2470 else
2472 if (lpVersionBuf) *lpVersionBuf = 0;
2473 *pcchVersionBuf = 0;
2477 if (pcchLangBuf)
2479 if (VerQueryValueW(lpVer, szLangResource, (LPVOID*)&lang, &puLen) &&
2480 (puLen > 0))
2482 wsprintfW(tmp, szLangFormat, *lang);
2483 if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
2485 if (strlenW(tmp) >= *pcchLangBuf)
2486 ret = ERROR_MORE_DATA;
2488 *pcchLangBuf = lstrlenW(tmp);
2490 else
2492 if (lpLangBuf) *lpLangBuf = 0;
2493 *pcchLangBuf = 0;
2497 end:
2498 msi_free(lpVer);
2499 return ret;
2502 /***********************************************************************
2503 * MsiGetFeatureUsageW [MSI.@]
2505 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
2506 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2508 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
2509 pdwUseCount, pwDateUsed);
2510 return ERROR_CALL_NOT_IMPLEMENTED;
2513 /***********************************************************************
2514 * MsiGetFeatureUsageA [MSI.@]
2516 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
2517 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2519 LPWSTR prod = NULL, feat = NULL;
2520 UINT ret = ERROR_OUTOFMEMORY;
2522 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
2523 pdwUseCount, pwDateUsed);
2525 prod = strdupAtoW( szProduct );
2526 if (szProduct && !prod)
2527 goto end;
2529 feat = strdupAtoW( szFeature );
2530 if (szFeature && !feat)
2531 goto end;
2533 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
2535 end:
2536 msi_free( prod );
2537 msi_free( feat );
2539 return ret;
2542 /***********************************************************************
2543 * MsiUseFeatureExW [MSI.@]
2545 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
2546 DWORD dwInstallMode, DWORD dwReserved )
2548 INSTALLSTATE state;
2550 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2551 dwInstallMode, dwReserved);
2553 state = MsiQueryFeatureStateW( szProduct, szFeature );
2555 if (dwReserved)
2556 return INSTALLSTATE_INVALIDARG;
2558 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
2560 FIXME("mark product %s feature %s as used\n",
2561 debugstr_w(szProduct), debugstr_w(szFeature) );
2564 return state;
2567 /***********************************************************************
2568 * MsiUseFeatureExA [MSI.@]
2570 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
2571 DWORD dwInstallMode, DWORD dwReserved )
2573 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
2574 LPWSTR prod = NULL, feat = NULL;
2576 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2577 dwInstallMode, dwReserved);
2579 prod = strdupAtoW( szProduct );
2580 if (szProduct && !prod)
2581 goto end;
2583 feat = strdupAtoW( szFeature );
2584 if (szFeature && !feat)
2585 goto end;
2587 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
2589 end:
2590 msi_free( prod );
2591 msi_free( feat );
2593 return ret;
2596 /***********************************************************************
2597 * MsiUseFeatureW [MSI.@]
2599 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
2601 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
2604 /***********************************************************************
2605 * MsiUseFeatureA [MSI.@]
2607 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
2609 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
2612 /***********************************************************************
2613 * MSI_ProvideQualifiedComponentEx [internal]
2615 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
2616 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2617 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
2618 LPDWORD pcchPathBuf)
2620 WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1],
2621 feature[MAX_FEATURE_CHARS+1];
2622 LPWSTR info;
2623 HKEY hkey;
2624 DWORD sz;
2625 UINT rc;
2627 TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent),
2628 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
2629 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2631 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
2632 if (rc != ERROR_SUCCESS)
2633 return ERROR_INDEX_ABSENT;
2635 info = msi_reg_get_val_str( hkey, szQualifier );
2636 RegCloseKey(hkey);
2638 if (!info)
2639 return ERROR_INDEX_ABSENT;
2641 MsiDecomposeDescriptorW(info, product, feature, component, &sz);
2643 if (!szProduct)
2644 rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf);
2645 else
2646 rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
2648 msi_free( info );
2650 if (rc != INSTALLSTATE_LOCAL)
2651 return ERROR_FILE_NOT_FOUND;
2653 return ERROR_SUCCESS;
2656 /***********************************************************************
2657 * MsiProvideQualifiedComponentExW [MSI.@]
2659 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
2660 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2661 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
2662 LPDWORD pcchPathBuf)
2664 awstring path;
2666 path.unicode = TRUE;
2667 path.str.w = lpPathBuf;
2669 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
2670 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
2673 /***********************************************************************
2674 * MsiProvideQualifiedComponentExA [MSI.@]
2676 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
2677 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct,
2678 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
2679 LPDWORD pcchPathBuf)
2681 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
2682 UINT r = ERROR_OUTOFMEMORY;
2683 awstring path;
2685 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
2686 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
2687 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2689 szwComponent = strdupAtoW( szComponent );
2690 if (szComponent && !szwComponent)
2691 goto end;
2693 szwQualifier = strdupAtoW( szQualifier );
2694 if (szQualifier && !szwQualifier)
2695 goto end;
2697 szwProduct = strdupAtoW( szProduct );
2698 if (szProduct && !szwProduct)
2699 goto end;
2701 path.unicode = FALSE;
2702 path.str.a = lpPathBuf;
2704 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
2705 dwInstallMode, szwProduct, Unused1,
2706 Unused2, &path, pcchPathBuf);
2707 end:
2708 msi_free(szwProduct);
2709 msi_free(szwComponent);
2710 msi_free(szwQualifier);
2712 return r;
2715 /***********************************************************************
2716 * MsiProvideQualifiedComponentW [MSI.@]
2718 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
2719 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
2720 LPDWORD pcchPathBuf)
2722 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
2723 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2726 /***********************************************************************
2727 * MsiProvideQualifiedComponentA [MSI.@]
2729 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
2730 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
2731 LPDWORD pcchPathBuf)
2733 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
2734 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2737 /***********************************************************************
2738 * MSI_GetUserInfo [internal]
2740 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
2741 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
2742 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2743 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
2745 WCHAR squished_pc[SQUISH_GUID_SIZE];
2746 LPWSTR user, org, serial;
2747 USERINFOSTATE state;
2748 HKEY hkey, props;
2749 LPCWSTR orgptr;
2750 UINT r;
2752 static const WCHAR szEmpty[] = {0};
2754 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
2755 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
2756 pcchSerialBuf);
2758 if (!szProduct || !squash_guid(szProduct, squished_pc))
2759 return USERINFOSTATE_INVALIDARG;
2761 if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2762 &hkey, FALSE) != ERROR_SUCCESS &&
2763 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2764 &hkey, FALSE) != ERROR_SUCCESS &&
2765 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2766 &hkey, FALSE) != ERROR_SUCCESS)
2768 return USERINFOSTATE_UNKNOWN;
2771 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2772 NULL, &props, FALSE) != ERROR_SUCCESS &&
2773 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE,
2774 NULL, &props, FALSE) != ERROR_SUCCESS)
2776 RegCloseKey(hkey);
2777 return USERINFOSTATE_ABSENT;
2780 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
2781 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
2782 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
2783 state = USERINFOSTATE_ABSENT;
2785 RegCloseKey(hkey);
2786 RegCloseKey(props);
2788 if (user && serial)
2789 state = USERINFOSTATE_PRESENT;
2791 if (pcchUserNameBuf)
2793 if (lpUserNameBuf && !user)
2795 (*pcchUserNameBuf)--;
2796 goto done;
2799 r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf);
2800 if (r == ERROR_MORE_DATA)
2802 state = USERINFOSTATE_MOREDATA;
2803 goto done;
2807 if (pcchOrgNameBuf)
2809 orgptr = org;
2810 if (!orgptr) orgptr = szEmpty;
2812 r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf);
2813 if (r == ERROR_MORE_DATA)
2815 state = USERINFOSTATE_MOREDATA;
2816 goto done;
2820 if (pcchSerialBuf)
2822 if (!serial)
2824 (*pcchSerialBuf)--;
2825 goto done;
2828 r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf);
2829 if (r == ERROR_MORE_DATA)
2830 state = USERINFOSTATE_MOREDATA;
2833 done:
2834 msi_free(user);
2835 msi_free(org);
2836 msi_free(serial);
2838 return state;
2841 /***********************************************************************
2842 * MsiGetUserInfoW [MSI.@]
2844 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
2845 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2846 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2847 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
2849 awstring user, org, serial;
2851 if ((lpUserNameBuf && !pcchUserNameBuf) ||
2852 (lpOrgNameBuf && !pcchOrgNameBuf) ||
2853 (lpSerialBuf && !pcchSerialBuf))
2854 return USERINFOSTATE_INVALIDARG;
2856 user.unicode = TRUE;
2857 user.str.w = lpUserNameBuf;
2858 org.unicode = TRUE;
2859 org.str.w = lpOrgNameBuf;
2860 serial.unicode = TRUE;
2861 serial.str.w = lpSerialBuf;
2863 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
2864 &org, pcchOrgNameBuf,
2865 &serial, pcchSerialBuf );
2868 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
2869 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2870 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2871 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
2873 awstring user, org, serial;
2874 LPWSTR prod;
2875 UINT r;
2877 if ((lpUserNameBuf && !pcchUserNameBuf) ||
2878 (lpOrgNameBuf && !pcchOrgNameBuf) ||
2879 (lpSerialBuf && !pcchSerialBuf))
2880 return USERINFOSTATE_INVALIDARG;
2882 prod = strdupAtoW( szProduct );
2883 if (szProduct && !prod)
2884 return ERROR_OUTOFMEMORY;
2886 user.unicode = FALSE;
2887 user.str.a = lpUserNameBuf;
2888 org.unicode = FALSE;
2889 org.str.a = lpOrgNameBuf;
2890 serial.unicode = FALSE;
2891 serial.str.a = lpSerialBuf;
2893 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
2894 &org, pcchOrgNameBuf,
2895 &serial, pcchSerialBuf );
2897 msi_free( prod );
2899 return r;
2902 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
2904 MSIHANDLE handle;
2905 UINT rc;
2906 MSIPACKAGE *package;
2907 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
2909 TRACE("(%s)\n",debugstr_w(szProduct));
2911 rc = MsiOpenProductW(szProduct,&handle);
2912 if (rc != ERROR_SUCCESS)
2913 return ERROR_INVALID_PARAMETER;
2915 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
2916 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
2917 msiobj_release( &package->hdr );
2919 MsiCloseHandle(handle);
2921 return rc;
2924 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
2926 MSIHANDLE handle;
2927 UINT rc;
2928 MSIPACKAGE *package;
2929 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
2931 TRACE("(%s)\n",debugstr_a(szProduct));
2933 rc = MsiOpenProductA(szProduct,&handle);
2934 if (rc != ERROR_SUCCESS)
2935 return ERROR_INVALID_PARAMETER;
2937 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
2938 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
2939 msiobj_release( &package->hdr );
2941 MsiCloseHandle(handle);
2943 return rc;
2946 /***********************************************************************
2947 * MsiConfigureFeatureA [MSI.@]
2949 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
2951 LPWSTR prod, feat = NULL;
2952 UINT r = ERROR_OUTOFMEMORY;
2954 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
2956 prod = strdupAtoW( szProduct );
2957 if (szProduct && !prod)
2958 goto end;
2960 feat = strdupAtoW( szFeature );
2961 if (szFeature && !feat)
2962 goto end;
2964 r = MsiConfigureFeatureW(prod, feat, eInstallState);
2966 end:
2967 msi_free(feat);
2968 msi_free(prod);
2970 return r;
2973 /***********************************************************************
2974 * MsiConfigureFeatureW [MSI.@]
2976 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
2978 static const WCHAR szCostInit[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
2979 MSIPACKAGE *package = NULL;
2980 UINT r;
2981 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
2982 DWORD sz;
2984 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
2986 if (!szProduct || !szFeature)
2987 return ERROR_INVALID_PARAMETER;
2989 switch (eInstallState)
2991 case INSTALLSTATE_DEFAULT:
2992 /* FIXME: how do we figure out the default location? */
2993 eInstallState = INSTALLSTATE_LOCAL;
2994 break;
2995 case INSTALLSTATE_LOCAL:
2996 case INSTALLSTATE_SOURCE:
2997 case INSTALLSTATE_ABSENT:
2998 case INSTALLSTATE_ADVERTISED:
2999 break;
3000 default:
3001 return ERROR_INVALID_PARAMETER;
3004 r = MSI_OpenProductW( szProduct, &package );
3005 if (r != ERROR_SUCCESS)
3006 return r;
3008 sz = sizeof(sourcepath);
3009 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3010 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3012 sz = sizeof(filename);
3013 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3014 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3016 lstrcatW( sourcepath, filename );
3018 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
3020 r = ACTION_PerformUIAction( package, szCostInit, -1 );
3021 if (r != ERROR_SUCCESS)
3022 goto end;
3024 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
3025 if (r != ERROR_SUCCESS)
3026 goto end;
3028 r = MSI_InstallPackage( package, sourcepath, NULL );
3030 end:
3031 msiobj_release( &package->hdr );
3033 return r;
3036 /***********************************************************************
3037 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3039 * Notes: undocumented
3041 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
3043 WCHAR path[MAX_PATH];
3045 TRACE("%d\n", dwReserved);
3047 if (dwReserved)
3049 FIXME("dwReserved=%d\n", dwReserved);
3050 return ERROR_INVALID_PARAMETER;
3053 if (!GetWindowsDirectoryW(path, MAX_PATH))
3054 return ERROR_FUNCTION_FAILED;
3056 lstrcatW(path, installerW);
3058 if (!CreateDirectoryW(path, NULL))
3059 return ERROR_FUNCTION_FAILED;
3061 return ERROR_SUCCESS;
3064 /***********************************************************************
3065 * MsiGetShortcutTargetA [MSI.@]
3067 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
3068 LPSTR szProductCode, LPSTR szFeatureId,
3069 LPSTR szComponentCode )
3071 LPWSTR target;
3072 const int len = MAX_FEATURE_CHARS+1;
3073 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
3074 UINT r;
3076 target = strdupAtoW( szShortcutTarget );
3077 if (szShortcutTarget && !target )
3078 return ERROR_OUTOFMEMORY;
3079 product[0] = 0;
3080 feature[0] = 0;
3081 component[0] = 0;
3082 r = MsiGetShortcutTargetW( target, product, feature, component );
3083 msi_free( target );
3084 if (r == ERROR_SUCCESS)
3086 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
3087 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
3088 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
3090 return r;
3093 /***********************************************************************
3094 * MsiGetShortcutTargetW [MSI.@]
3096 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
3097 LPWSTR szProductCode, LPWSTR szFeatureId,
3098 LPWSTR szComponentCode )
3100 IShellLinkDataList *dl = NULL;
3101 IPersistFile *pf = NULL;
3102 LPEXP_DARWIN_LINK darwin = NULL;
3103 HRESULT r, init;
3105 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
3106 szProductCode, szFeatureId, szComponentCode );
3108 init = CoInitialize(NULL);
3110 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
3111 &IID_IPersistFile, (LPVOID*) &pf );
3112 if( SUCCEEDED( r ) )
3114 r = IPersistFile_Load( pf, szShortcutTarget,
3115 STGM_READ | STGM_SHARE_DENY_WRITE );
3116 if( SUCCEEDED( r ) )
3118 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
3119 (LPVOID*) &dl );
3120 if( SUCCEEDED( r ) )
3122 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
3123 (LPVOID) &darwin );
3124 IShellLinkDataList_Release( dl );
3127 IPersistFile_Release( pf );
3130 if (SUCCEEDED(init))
3131 CoUninitialize();
3133 TRACE("darwin = %p\n", darwin);
3135 if (darwin)
3137 DWORD sz;
3138 UINT ret;
3140 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
3141 szProductCode, szFeatureId, szComponentCode, &sz );
3142 LocalFree( darwin );
3143 return ret;
3146 return ERROR_FUNCTION_FAILED;
3149 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
3150 DWORD dwReinstallMode )
3152 MSIPACKAGE* package = NULL;
3153 UINT r;
3154 WCHAR sourcepath[MAX_PATH];
3155 WCHAR filename[MAX_PATH];
3156 static const WCHAR szLogVerbose[] = {
3157 ' ','L','O','G','V','E','R','B','O','S','E',0 };
3158 static const WCHAR szInstalled[] = { 'I','n','s','t','a','l','l','e','d',0};
3159 static const WCHAR szReinstall[] = {'R','E','I','N','S','T','A','L','L',0};
3160 static const WCHAR szReinstallMode[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
3161 static const WCHAR szOne[] = {'1',0};
3162 WCHAR reinstallmode[11];
3163 LPWSTR ptr;
3164 DWORD sz;
3166 FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
3167 dwReinstallMode);
3169 ptr = reinstallmode;
3171 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
3172 *ptr++ = 'p';
3173 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
3174 *ptr++ = 'o';
3175 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
3176 *ptr++ = 'w';
3177 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
3178 *ptr++ = 'd';
3179 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
3180 *ptr++ = 'c';
3181 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
3182 *ptr++ = 'a';
3183 if (dwReinstallMode & REINSTALLMODE_USERDATA)
3184 *ptr++ = 'u';
3185 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
3186 *ptr++ = 'm';
3187 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
3188 *ptr++ = 's';
3189 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
3190 *ptr++ = 'v';
3191 *ptr = 0;
3193 sz = sizeof(sourcepath);
3194 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3195 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3197 sz = sizeof(filename);
3198 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3199 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3201 lstrcatW( sourcepath, filename );
3203 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
3204 r = MSI_OpenPackageW( sourcepath, &package );
3205 else
3206 r = MSI_OpenProductW( szProduct, &package );
3208 if (r != ERROR_SUCCESS)
3209 return r;
3211 MSI_SetPropertyW( package, szReinstallMode, reinstallmode );
3212 MSI_SetPropertyW( package, szInstalled, szOne );
3213 MSI_SetPropertyW( package, szLogVerbose, szOne );
3214 MSI_SetPropertyW( package, szReinstall, szFeature );
3216 r = MSI_InstallPackage( package, sourcepath, NULL );
3218 msiobj_release( &package->hdr );
3220 return r;
3223 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
3224 DWORD dwReinstallMode )
3226 LPWSTR wszProduct;
3227 LPWSTR wszFeature;
3228 UINT rc;
3230 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
3231 dwReinstallMode);
3233 wszProduct = strdupAtoW(szProduct);
3234 wszFeature = strdupAtoW(szFeature);
3236 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
3238 msi_free(wszProduct);
3239 msi_free(wszFeature);
3240 return rc;
3243 typedef struct
3245 unsigned int i[2];
3246 unsigned int buf[4];
3247 unsigned char in[64];
3248 unsigned char digest[16];
3249 } MD5_CTX;
3251 extern VOID WINAPI MD5Init( MD5_CTX *);
3252 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
3253 extern VOID WINAPI MD5Final( MD5_CTX *);
3255 /***********************************************************************
3256 * MsiGetFileHashW [MSI.@]
3258 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
3259 PMSIFILEHASHINFO pHash )
3261 HANDLE handle, mapping;
3262 void *p;
3263 DWORD length;
3264 UINT r = ERROR_FUNCTION_FAILED;
3266 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
3268 if (!szFilePath)
3269 return ERROR_INVALID_PARAMETER;
3271 if (!*szFilePath)
3272 return ERROR_PATH_NOT_FOUND;
3274 if (dwOptions)
3275 return ERROR_INVALID_PARAMETER;
3276 if (!pHash)
3277 return ERROR_INVALID_PARAMETER;
3278 if (pHash->dwFileHashInfoSize < sizeof *pHash)
3279 return ERROR_INVALID_PARAMETER;
3281 handle = CreateFileW( szFilePath, GENERIC_READ,
3282 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
3283 if (handle == INVALID_HANDLE_VALUE)
3284 return ERROR_FILE_NOT_FOUND;
3286 length = GetFileSize( handle, NULL );
3288 mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
3289 if (mapping)
3291 p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
3292 if (p)
3294 MD5_CTX ctx;
3296 MD5Init( &ctx );
3297 MD5Update( &ctx, p, length );
3298 MD5Final( &ctx );
3299 UnmapViewOfFile( p );
3301 memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData );
3302 r = ERROR_SUCCESS;
3304 CloseHandle( mapping );
3306 CloseHandle( handle );
3308 return r;
3311 /***********************************************************************
3312 * MsiGetFileHashA [MSI.@]
3314 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
3315 PMSIFILEHASHINFO pHash )
3317 LPWSTR file;
3318 UINT r;
3320 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
3322 file = strdupAtoW( szFilePath );
3323 if (szFilePath && !file)
3324 return ERROR_OUTOFMEMORY;
3326 r = MsiGetFileHashW( file, dwOptions, pHash );
3327 msi_free( file );
3328 return r;
3331 /***********************************************************************
3332 * MsiAdvertiseScriptW [MSI.@]
3334 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
3335 PHKEY phRegData, BOOL fRemoveItems )
3337 FIXME("%s %08x %p %d\n",
3338 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3339 return ERROR_CALL_NOT_IMPLEMENTED;
3342 /***********************************************************************
3343 * MsiAdvertiseScriptA [MSI.@]
3345 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
3346 PHKEY phRegData, BOOL fRemoveItems )
3348 FIXME("%s %08x %p %d\n",
3349 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3350 return ERROR_CALL_NOT_IMPLEMENTED;
3353 /***********************************************************************
3354 * MsiIsProductElevatedW [MSI.@]
3356 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
3358 FIXME("%s %p - stub\n",
3359 debugstr_w( szProduct ), pfElevated );
3360 *pfElevated = TRUE;
3361 return ERROR_SUCCESS;
3364 /***********************************************************************
3365 * MsiIsProductElevatedA [MSI.@]
3367 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
3369 FIXME("%s %p - stub\n",
3370 debugstr_a( szProduct ), pfElevated );
3371 *pfElevated = TRUE;
3372 return ERROR_SUCCESS;
3375 /***********************************************************************
3376 * MsiSetExternalUIRecord [MSI.@]
3378 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD puiHandler,
3379 DWORD dwMessageFilter, LPVOID pvContext,
3380 PINSTALLUI_HANDLER_RECORD ppuiPrevHandler)
3382 FIXME("%p %08x %p %p\n", puiHandler, dwMessageFilter ,pvContext,
3383 ppuiPrevHandler);
3384 return ERROR_CALL_NOT_IMPLEMENTED;
3387 /***********************************************************************
3388 * MsiInstallMissingComponentW [MSI.@]
3390 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState)
3392 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
3393 return ERROR_SUCCESS;