push 9eb9af089d68d39110a91889d3a673043db63c4b
[wine/hacks.git] / dlls / msi / msi.c
blob2b3b635390d43a6fbe1e8f62e99a8963c7215614
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 if (context == MSIINSTALLCONTEXT_MACHINE)
111 r = MSIREG_OpenLocalSystemInstallProps(szProduct, &props, FALSE);
112 else if (context == MSIINSTALLCONTEXT_USERMANAGED ||
113 context == MSIINSTALLCONTEXT_USERUNMANAGED)
114 r = MSIREG_OpenCurrentUserInstallProps(szProduct, &props, FALSE);
116 if (r != ERROR_SUCCESS)
117 return ERROR_UNKNOWN_PRODUCT;
119 if (context == MSIINSTALLCONTEXT_USERMANAGED)
120 path = msi_reg_get_val_str(props, managed);
121 else
122 path = msi_reg_get_val_str(props, local);
124 r = ERROR_UNKNOWN_PRODUCT;
126 if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
127 goto done;
129 if (PathIsRelativeW(path))
131 r = ERROR_INSTALL_PACKAGE_OPEN_FAILED;
132 goto done;
135 r = MSI_OpenPackageW(path, package);
137 done:
138 RegCloseKey(props);
139 msi_free(path);
140 return r;
143 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
145 MSIPACKAGE *package = NULL;
146 WCHAR squished_pc[GUID_SIZE];
147 UINT r;
149 if (!szProduct || !squash_guid(szProduct, squished_pc))
150 return ERROR_INVALID_PARAMETER;
152 if (!phProduct)
153 return ERROR_INVALID_PARAMETER;
155 r = MSI_OpenProductW(szProduct, &package);
156 if (r != ERROR_SUCCESS)
157 return r;
159 *phProduct = alloc_msihandle(&package->hdr);
160 if (!*phProduct)
161 r = ERROR_NOT_ENOUGH_MEMORY;
163 msiobj_release(&package->hdr);
164 return r;
167 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
168 LPCSTR szTransforms, LANGID lgidLanguage)
170 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
171 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
172 return ERROR_CALL_NOT_IMPLEMENTED;
175 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
176 LPCWSTR szTransforms, LANGID lgidLanguage)
178 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
179 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
180 return ERROR_CALL_NOT_IMPLEMENTED;
183 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
184 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
186 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath),
187 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
188 lgidLanguage, dwPlatform, dwOptions);
189 return ERROR_CALL_NOT_IMPLEMENTED;
192 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
193 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
195 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath),
196 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
197 lgidLanguage, dwPlatform, dwOptions);
198 return ERROR_CALL_NOT_IMPLEMENTED;
201 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
203 LPWSTR szwPath = NULL, szwCommand = NULL;
204 UINT r = ERROR_OUTOFMEMORY;
206 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
208 if( szPackagePath )
210 szwPath = strdupAtoW( szPackagePath );
211 if( !szwPath )
212 goto end;
215 if( szCommandLine )
217 szwCommand = strdupAtoW( szCommandLine );
218 if( !szwCommand )
219 goto end;
222 r = MsiInstallProductW( szwPath, szwCommand );
224 end:
225 msi_free( szwPath );
226 msi_free( szwCommand );
228 return r;
231 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
233 MSIPACKAGE *package = NULL;
234 UINT r;
236 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
238 r = MSI_OpenPackageW( szPackagePath, &package );
239 if (r == ERROR_SUCCESS)
241 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
242 msiobj_release( &package->hdr );
245 return r;
248 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
250 FIXME("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
251 return ERROR_CALL_NOT_IMPLEMENTED;
254 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
256 FIXME("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
257 return ERROR_CALL_NOT_IMPLEMENTED;
260 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
261 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
263 LPWSTR patch_package = NULL;
264 LPWSTR install_package = NULL;
265 LPWSTR command_line = NULL;
266 UINT r = ERROR_OUTOFMEMORY;
268 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
269 eInstallType, debugstr_a(szCommandLine));
271 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage)))
272 goto done;
274 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage)))
275 goto done;
277 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine)))
278 goto done;
280 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line);
282 done:
283 msi_free(patch_package);
284 msi_free(install_package);
285 msi_free(command_line);
287 return r;
290 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
291 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
293 MSIHANDLE patch, info;
294 UINT r, type;
295 DWORD size = 0;
296 LPCWSTR cmd_ptr = szCommandLine;
297 LPWSTR beg, end;
298 LPWSTR cmd = NULL, codes = NULL;
300 static const WCHAR space[] = {' ',0};
301 static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
302 static WCHAR empty[] = {0};
304 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
305 eInstallType, debugstr_w(szCommandLine));
307 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
308 eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
310 FIXME("Only reading target products from patch\n");
311 return ERROR_CALL_NOT_IMPLEMENTED;
314 r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
315 if (r != ERROR_SUCCESS)
316 return r;
318 r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
319 if (r != ERROR_SUCCESS)
320 goto done;
322 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
323 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
325 ERR("Failed to read product codes from patch\n");
326 goto done;
329 codes = msi_alloc(++size * sizeof(WCHAR));
330 if (!codes)
332 r = ERROR_OUTOFMEMORY;
333 goto done;
336 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
337 if (r != ERROR_SUCCESS)
338 goto done;
340 if (!szCommandLine)
341 cmd_ptr = empty;
343 size = lstrlenW(cmd_ptr) + lstrlenW(patcheq) + lstrlenW(szPatchPackage) + 1;
344 cmd = msi_alloc(size * sizeof(WCHAR));
345 if (!cmd)
347 r = ERROR_OUTOFMEMORY;
348 goto done;
351 lstrcpyW(cmd, cmd_ptr);
352 if (szCommandLine) lstrcatW(cmd, space);
353 lstrcatW(cmd, patcheq);
354 lstrcatW(cmd, szPatchPackage);
356 beg = codes;
357 while ((end = strchrW(beg, '}')))
359 *(end + 1) = '\0';
361 r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
362 if (r != ERROR_SUCCESS)
363 goto done;
365 beg = end + 2;
368 done:
369 msi_free(cmd);
370 msi_free(codes);
372 MsiCloseHandle(info);
373 MsiCloseHandle(patch);
375 return r;
378 UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
379 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
381 FIXME("(%s, %d, %p): stub!\n", debugstr_a(szProductPackagePath),
382 cPatchInfo, pPatchInfo);
384 return ERROR_CALL_NOT_IMPLEMENTED;
387 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath,
388 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
390 FIXME("(%s, %d, %p): stub!\n", debugstr_w(szProductPackagePath),
391 cPatchInfo, pPatchInfo);
393 return ERROR_CALL_NOT_IMPLEMENTED;
396 static UINT msi_open_package(LPCWSTR product, MSIINSTALLCONTEXT context,
397 MSIPACKAGE **package)
399 UINT r;
400 DWORD sz;
401 HKEY props;
402 LPWSTR localpack;
403 WCHAR sourcepath[MAX_PATH];
404 WCHAR filename[MAX_PATH];
406 static const WCHAR szLocalPackage[] = {
407 'L','o','c','a','l','P','a','c','k','a','g','e',0};
409 if (context == MSIINSTALLCONTEXT_MACHINE)
410 r = MSIREG_OpenLocalSystemInstallProps(product, &props, FALSE);
411 else
412 r = MSIREG_OpenCurrentUserInstallProps(product, &props, FALSE);
414 if (r != ERROR_SUCCESS)
415 return ERROR_BAD_CONFIGURATION;
417 localpack = msi_reg_get_val_str(props, szLocalPackage);
418 if (localpack)
420 lstrcpyW(sourcepath, localpack);
421 msi_free(localpack);
424 if (!localpack || GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
426 sz = sizeof(sourcepath);
427 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
428 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
430 sz = sizeof(filename);
431 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
432 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
434 lstrcatW(sourcepath, filename);
437 if (GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
438 return ERROR_INSTALL_SOURCE_ABSENT;
440 return MSI_OpenPackageW(sourcepath, package);
443 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
444 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
446 MSIPACKAGE* package = NULL;
447 MSIINSTALLCONTEXT context;
448 UINT r;
449 DWORD sz;
450 WCHAR sourcepath[MAX_PATH];
451 LPWSTR commandline;
453 static const WCHAR szInstalled[] = {
454 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
455 static const WCHAR szRemoveAll[] = {
456 ' ','R','E','M','O','V','E','=','A','L','L',0};
457 static const WCHAR szMachine[] = {
458 ' ','A','L','L','U','S','E','R','S','=','1',0};
460 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
461 debugstr_w(szCommandLine));
463 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1)
464 return ERROR_INVALID_PARAMETER;
466 if (eInstallState == INSTALLSTATE_ADVERTISED ||
467 eInstallState == INSTALLSTATE_SOURCE)
469 FIXME("State %d not implemented\n", eInstallState);
470 return ERROR_CALL_NOT_IMPLEMENTED;
473 r = msi_locate_product(szProduct, &context);
474 if (r != ERROR_SUCCESS)
475 return r;
477 r = msi_open_package(szProduct, context, &package);
478 if (r != ERROR_SUCCESS)
479 return r;
481 sz = lstrlenW(szInstalled) + 1;
483 if (szCommandLine)
484 sz += lstrlenW(szCommandLine);
486 if (eInstallState == INSTALLSTATE_ABSENT)
487 sz += lstrlenW(szRemoveAll);
489 if (context == MSIINSTALLCONTEXT_MACHINE)
490 sz += lstrlenW(szMachine);
492 commandline = msi_alloc(sz * sizeof(WCHAR));
493 if (!commandline)
495 r = ERROR_OUTOFMEMORY;
496 goto end;
499 commandline[0] = 0;
500 if (szCommandLine)
501 lstrcpyW(commandline,szCommandLine);
503 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
504 lstrcatW(commandline,szInstalled);
506 if (eInstallState == INSTALLSTATE_ABSENT)
507 lstrcatW(commandline, szRemoveAll);
509 if (context == MSIINSTALLCONTEXT_MACHINE)
510 lstrcatW(commandline, szMachine);
512 r = MSI_InstallPackage( package, sourcepath, commandline );
514 msi_free(commandline);
516 end:
517 msiobj_release( &package->hdr );
519 return r;
522 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
523 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
525 LPWSTR szwProduct = NULL;
526 LPWSTR szwCommandLine = NULL;
527 UINT r = ERROR_OUTOFMEMORY;
529 if( szProduct )
531 szwProduct = strdupAtoW( szProduct );
532 if( !szwProduct )
533 goto end;
536 if( szCommandLine)
538 szwCommandLine = strdupAtoW( szCommandLine );
539 if( !szwCommandLine)
540 goto end;
543 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
544 szwCommandLine );
545 end:
546 msi_free( szwProduct );
547 msi_free( szwCommandLine);
549 return r;
552 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
553 INSTALLSTATE eInstallState)
555 LPWSTR szwProduct = NULL;
556 UINT r;
558 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
560 if( szProduct )
562 szwProduct = strdupAtoW( szProduct );
563 if( !szwProduct )
564 return ERROR_OUTOFMEMORY;
567 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
568 msi_free( szwProduct );
570 return r;
573 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
574 INSTALLSTATE eInstallState)
576 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
579 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
581 LPWSTR szwComponent = NULL;
582 UINT r;
583 WCHAR szwBuffer[GUID_SIZE];
585 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
587 if( szComponent )
589 szwComponent = strdupAtoW( szComponent );
590 if( !szwComponent )
591 return ERROR_OUTOFMEMORY;
594 *szwBuffer = '\0';
595 r = MsiGetProductCodeW( szwComponent, szwBuffer );
597 if(*szwBuffer)
598 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
600 msi_free( szwComponent );
602 return r;
605 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
607 UINT rc, index;
608 HKEY compkey, prodkey;
609 WCHAR squished_comp[GUID_SIZE];
610 WCHAR squished_prod[GUID_SIZE];
611 DWORD sz = GUID_SIZE;
613 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer);
615 if (!szComponent || !*szComponent)
616 return ERROR_INVALID_PARAMETER;
618 if (!squash_guid(szComponent, squished_comp))
619 return ERROR_INVALID_PARAMETER;
621 if (MSIREG_OpenUserDataComponentKey(szComponent, &compkey, FALSE) != ERROR_SUCCESS &&
622 MSIREG_OpenLocalSystemComponentKey(szComponent, &compkey, FALSE) != ERROR_SUCCESS)
624 return ERROR_UNKNOWN_COMPONENT;
627 rc = RegEnumValueW(compkey, 0, squished_prod, &sz, NULL, NULL, NULL, NULL);
628 if (rc != ERROR_SUCCESS)
630 RegCloseKey(compkey);
631 return ERROR_UNKNOWN_COMPONENT;
634 /* check simple case, only one product */
635 rc = RegEnumValueW(compkey, 1, squished_prod, &sz, NULL, NULL, NULL, NULL);
636 if (rc == ERROR_NO_MORE_ITEMS)
638 rc = ERROR_SUCCESS;
639 goto done;
642 index = 0;
643 while ((rc = RegEnumValueW(compkey, index, squished_prod, &sz,
644 NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS)
646 index++;
647 sz = GUID_SIZE;
648 unsquash_guid(squished_prod, szBuffer);
650 if (MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_USERMANAGED,
651 &prodkey, FALSE) == ERROR_SUCCESS ||
652 MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_USERUNMANAGED,
653 &prodkey, FALSE) == ERROR_SUCCESS ||
654 MSIREG_OpenProductKey(szBuffer, MSIINSTALLCONTEXT_MACHINE,
655 &prodkey, FALSE) == ERROR_SUCCESS)
657 RegCloseKey(prodkey);
658 rc = ERROR_SUCCESS;
659 goto done;
663 rc = ERROR_INSTALL_FAILURE;
665 done:
666 RegCloseKey(compkey);
667 unsquash_guid(squished_prod, szBuffer);
668 return rc;
671 static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
673 DWORD dval;
674 LONG res;
675 WCHAR temp[20];
677 static const WCHAR format[] = {'%','d',0};
679 res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL);
680 if (res != ERROR_SUCCESS)
681 return NULL;
683 if (*type == REG_SZ)
684 return msi_reg_get_val_str(hkey, name);
686 if (!msi_reg_get_val_dword(hkey, name, &dval))
687 return NULL;
689 sprintfW(temp, format, dval);
690 return strdupW(temp);
693 static UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
694 awstring *szValue, LPDWORD pcchValueBuf)
696 UINT r = ERROR_UNKNOWN_PROPERTY;
697 HKEY prodkey, userdata, source;
698 LPWSTR val = NULL;
699 WCHAR squished_pc[GUID_SIZE];
700 WCHAR packagecode[GUID_SIZE];
701 BOOL classes = FALSE;
702 BOOL badconfig = FALSE;
703 LONG res;
704 DWORD save, type = REG_NONE;
706 static WCHAR empty[] = {0};
707 static const WCHAR sourcelist[] = {
708 'S','o','u','r','c','e','L','i','s','t',0};
709 static const WCHAR display_name[] = {
710 'D','i','s','p','l','a','y','N','a','m','e',0};
711 static const WCHAR display_version[] = {
712 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
713 static const WCHAR assignment[] = {
714 'A','s','s','i','g','n','m','e','n','t',0};
716 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
717 debugstr_w(szAttribute), szValue, pcchValueBuf);
719 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
720 return ERROR_INVALID_PARAMETER;
722 if (!squash_guid(szProduct, squished_pc))
723 return ERROR_INVALID_PARAMETER;
725 if ((r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
726 &prodkey, FALSE)) != ERROR_SUCCESS &&
727 (r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
728 &prodkey, FALSE)) != ERROR_SUCCESS &&
729 (r = MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
730 &prodkey, FALSE)) == ERROR_SUCCESS)
732 classes = TRUE;
735 if (classes)
736 MSIREG_OpenLocalSystemProductKey(szProduct, &userdata, FALSE);
737 else
738 MSIREG_OpenCurrentUserInstallProps(szProduct, &userdata, FALSE);
740 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
741 !lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
742 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
743 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
744 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
745 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
746 !lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
747 !lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
748 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
749 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
750 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
751 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
752 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
753 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
754 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
755 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
757 if (!prodkey)
759 r = ERROR_UNKNOWN_PRODUCT;
760 goto done;
763 if (!userdata)
764 return ERROR_UNKNOWN_PROPERTY;
766 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
767 szAttribute = display_name;
768 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
769 szAttribute = display_version;
771 val = msi_reg_get_value(userdata, szAttribute, &type);
772 if (!val)
773 val = empty;
775 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
776 !lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
777 !lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
778 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
779 !lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
780 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
781 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
782 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
783 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
784 !lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
786 if (!prodkey)
788 r = ERROR_UNKNOWN_PRODUCT;
789 goto done;
792 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
793 szAttribute = assignment;
795 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
797 res = RegOpenKeyW(prodkey, sourcelist, &source);
798 if (res == ERROR_SUCCESS)
799 val = msi_reg_get_value(source, szAttribute, &type);
801 RegCloseKey(source);
803 else
805 val = msi_reg_get_value(prodkey, szAttribute, &type);
806 if (!val)
807 val = empty;
810 if (val != empty && type != REG_DWORD &&
811 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
813 if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
814 badconfig = TRUE;
815 else
817 unsquash_guid(val, packagecode);
818 msi_free(val);
819 val = strdupW(packagecode);
824 if (!val)
826 r = ERROR_UNKNOWN_PROPERTY;
827 goto done;
830 if (pcchValueBuf)
832 save = *pcchValueBuf;
834 if (strlenW(val) < *pcchValueBuf)
835 r = msi_strcpy_to_awstring(val, szValue, pcchValueBuf);
836 else if (szValue->str.a || szValue->str.w)
837 r = ERROR_MORE_DATA;
839 if (!badconfig)
840 *pcchValueBuf = lstrlenW(val);
841 else if (r == ERROR_SUCCESS)
843 *pcchValueBuf = save;
844 r = ERROR_BAD_CONFIGURATION;
847 else if (badconfig)
848 r = ERROR_BAD_CONFIGURATION;
850 if (val != empty)
851 msi_free(val);
853 done:
854 RegCloseKey(prodkey);
855 RegCloseKey(userdata);
856 return r;
859 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
860 LPSTR szBuffer, LPDWORD pcchValueBuf)
862 LPWSTR szwProduct, szwAttribute = NULL;
863 UINT r = ERROR_OUTOFMEMORY;
864 awstring buffer;
866 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
867 szBuffer, pcchValueBuf);
869 szwProduct = strdupAtoW( szProduct );
870 if( szProduct && !szwProduct )
871 goto end;
873 szwAttribute = strdupAtoW( szAttribute );
874 if( szAttribute && !szwAttribute )
875 goto end;
877 buffer.unicode = FALSE;
878 buffer.str.a = szBuffer;
880 r = MSI_GetProductInfo( szwProduct, szwAttribute,
881 &buffer, pcchValueBuf );
883 end:
884 msi_free( szwProduct );
885 msi_free( szwAttribute );
887 return r;
890 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
891 LPWSTR szBuffer, LPDWORD pcchValueBuf)
893 awstring buffer;
895 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
896 szBuffer, pcchValueBuf);
898 buffer.unicode = TRUE;
899 buffer.str.w = szBuffer;
901 return MSI_GetProductInfo( szProduct, szAttribute,
902 &buffer, pcchValueBuf );
905 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
906 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
907 LPSTR szValue, LPDWORD pcchValue)
909 LPWSTR product = NULL;
910 LPWSTR usersid = NULL;
911 LPWSTR property = NULL;
912 LPWSTR value = NULL;
913 DWORD len = 0;
914 UINT r;
916 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
917 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
918 szValue, pcchValue);
920 if (szValue && !pcchValue)
921 return ERROR_INVALID_PARAMETER;
923 if (szProductCode) product = strdupAtoW(szProductCode);
924 if (szUserSid) usersid = strdupAtoW(szUserSid);
925 if (szProperty) property = strdupAtoW(szProperty);
927 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
928 NULL, &len);
929 if (r != ERROR_SUCCESS)
930 goto done;
932 value = msi_alloc(++len * sizeof(WCHAR));
933 if (!value)
935 r = ERROR_OUTOFMEMORY;
936 goto done;
939 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
940 value, &len);
941 if (r != ERROR_SUCCESS)
942 goto done;
944 if (!pcchValue)
945 goto done;
947 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
948 if (*pcchValue >= len)
949 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
950 else if (szValue)
952 r = ERROR_MORE_DATA;
953 if (*pcchValue > 0)
954 *szValue = '\0';
957 if (*pcchValue <= len || !szValue)
958 len = len * sizeof(WCHAR) - 1;
960 *pcchValue = len - 1;
962 done:
963 msi_free(product);
964 msi_free(usersid);
965 msi_free(property);
966 msi_free(value);
968 return r;
971 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
973 UINT r;
975 if (!val)
976 return ERROR_UNKNOWN_PROPERTY;
978 if (out)
980 if (strlenW(val) >= *size)
982 r = ERROR_MORE_DATA;
983 if (*size > 0)
984 *out = '\0';
986 else
987 lstrcpyW(out, val);
990 if (size)
991 *size = lstrlenW(val);
993 return ERROR_SUCCESS;
996 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
997 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
998 LPWSTR szValue, LPDWORD pcchValue)
1000 WCHAR squished_pc[GUID_SIZE];
1001 LPWSTR val = NULL;
1002 LPCWSTR package = NULL;
1003 HKEY props = NULL, prod;
1004 HKEY classes = NULL, managed;
1005 HKEY hkey = NULL;
1006 DWORD type;
1007 UINT r = ERROR_UNKNOWN_PRODUCT;
1009 static const WCHAR one[] = {'1',0};
1010 static const WCHAR five[] = {'5',0};
1011 static const WCHAR empty[] = {0};
1012 static const WCHAR displayname[] = {
1013 'D','i','s','p','l','a','y','N','a','m','e',0};
1014 static const WCHAR displayversion[] = {
1015 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1016 static const WCHAR managed_local_package[] = {
1017 'M','a','n','a','g','e','d','L','o','c','a','l',
1018 'P','a','c','k','a','g','e',0};
1020 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
1021 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
1022 szValue, pcchValue);
1024 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1025 return ERROR_INVALID_PARAMETER;
1027 if (szValue && !pcchValue)
1028 return ERROR_INVALID_PARAMETER;
1030 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1031 dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1032 dwContext != MSIINSTALLCONTEXT_MACHINE)
1033 return ERROR_INVALID_PARAMETER;
1035 if (!szProperty || !*szProperty)
1036 return ERROR_INVALID_PARAMETER;
1038 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1039 return ERROR_INVALID_PARAMETER;
1041 MSIREG_OpenProductKey(szProductCode, MSIINSTALLCONTEXT_USERMANAGED,
1042 &managed, FALSE);
1043 MSIREG_OpenProductKey(szProductCode, MSIINSTALLCONTEXT_USERUNMANAGED,
1044 &prod, FALSE);
1046 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1048 package = INSTALLPROPERTY_LOCALPACKAGEW;
1049 MSIREG_OpenCurrentUserInstallProps(szProductCode, &props, FALSE);
1051 if (!props && !prod)
1052 goto done;
1054 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1056 package = managed_local_package;
1057 MSIREG_OpenCurrentUserInstallProps(szProductCode, &props, FALSE);
1059 if (!props && !managed)
1060 goto done;
1062 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1064 package = INSTALLPROPERTY_LOCALPACKAGEW;
1065 MSIREG_OpenLocalSystemProductKey(szProductCode, &props, FALSE);
1066 MSIREG_OpenProductKey(szProductCode, dwContext, &classes, FALSE);
1068 if (!props && !classes)
1069 goto done;
1072 if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
1073 !lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
1074 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
1075 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
1076 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
1077 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
1078 !lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
1079 !lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
1080 !lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
1081 !lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
1082 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
1083 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
1084 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
1085 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
1086 !lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
1087 !lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
1088 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
1090 val = msi_reg_get_value(props, package, &type);
1091 if (!val)
1093 if (prod || classes)
1094 r = ERROR_UNKNOWN_PROPERTY;
1096 goto done;
1099 msi_free(val);
1101 if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
1102 szProperty = displayname;
1103 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
1104 szProperty = displayversion;
1106 val = msi_reg_get_value(props, szProperty, &type);
1107 if (!val)
1108 val = strdupW(empty);
1110 r = msi_copy_outval(val, szValue, pcchValue);
1112 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
1113 !lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
1114 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
1115 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
1116 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
1117 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
1118 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
1119 !lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
1121 if (!prod && !classes)
1122 goto done;
1124 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1125 hkey = prod;
1126 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1127 hkey = managed;
1128 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1129 hkey = classes;
1131 val = msi_reg_get_value(hkey, szProperty, &type);
1132 if (!val)
1133 val = strdupW(empty);
1135 r = msi_copy_outval(val, szValue, pcchValue);
1137 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
1139 if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1141 if (props)
1143 val = msi_reg_get_value(props, package, &type);
1144 if (!val)
1145 goto done;
1147 msi_free(val);
1148 val = strdupW(five);
1150 else
1151 val = strdupW(one);
1153 r = msi_copy_outval(val, szValue, pcchValue);
1154 goto done;
1156 else if (props && (val = msi_reg_get_value(props, package, &type)))
1158 msi_free(val);
1159 val = strdupW(five);
1160 r = msi_copy_outval(val, szValue, pcchValue);
1161 goto done;
1164 if (prod || managed)
1165 val = strdupW(one);
1166 else
1167 goto done;
1169 r = msi_copy_outval(val, szValue, pcchValue);
1171 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
1173 if (!prod && !classes)
1174 goto done;
1176 /* FIXME */
1177 val = strdupW(empty);
1178 r = msi_copy_outval(val, szValue, pcchValue);
1180 else
1181 r = ERROR_UNKNOWN_PROPERTY;
1183 done:
1184 RegCloseKey(props);
1185 RegCloseKey(prod);
1186 RegCloseKey(managed);
1187 RegCloseKey(classes);
1188 msi_free(val);
1190 return r;
1193 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
1195 LPWSTR szwLogFile = NULL;
1196 UINT r;
1198 TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
1200 if( szLogFile )
1202 szwLogFile = strdupAtoW( szLogFile );
1203 if( !szwLogFile )
1204 return ERROR_OUTOFMEMORY;
1206 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
1207 msi_free( szwLogFile );
1208 return r;
1211 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
1213 HANDLE file = INVALID_HANDLE_VALUE;
1215 TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
1217 if (szLogFile)
1219 lstrcpyW(gszLogFile,szLogFile);
1220 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
1221 DeleteFileW(szLogFile);
1222 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
1223 FILE_ATTRIBUTE_NORMAL, NULL);
1224 if (file != INVALID_HANDLE_VALUE)
1225 CloseHandle(file);
1226 else
1227 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
1229 else
1230 gszLogFile[0] = '\0';
1232 return ERROR_SUCCESS;
1235 UINT WINAPI MsiEnumComponentCostsW(MSIHANDLE hInstall, LPCWSTR szComponent,
1236 DWORD dwIndex, INSTALLSTATE iState,
1237 LPWSTR lpDriveBuf, DWORD *pcchDriveBuf,
1238 int *piCost, int *pTempCost)
1240 FIXME("(%ld, %s, %d, %d, %p, %p, %p %p): stub!\n", hInstall,
1241 debugstr_w(szComponent), dwIndex, iState, lpDriveBuf,
1242 pcchDriveBuf, piCost, pTempCost);
1244 return ERROR_NO_MORE_ITEMS;
1247 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
1248 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1249 LPCSTR szComponent, INSTALLSTATE *pdwState)
1251 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL;
1252 UINT r;
1254 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode),
1255 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
1257 if (szProductCode && !(prodcode = strdupAtoW(szProductCode)))
1258 return ERROR_OUTOFMEMORY;
1260 if (szUserSid && !(usersid = strdupAtoW(szUserSid)))
1261 return ERROR_OUTOFMEMORY;
1263 if (szComponent && !(comp = strdupAtoW(szComponent)))
1264 return ERROR_OUTOFMEMORY;
1266 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState);
1268 msi_free(prodcode);
1269 msi_free(usersid);
1270 msi_free(comp);
1272 return r;
1275 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1277 UINT r;
1278 HKEY hkey;
1280 r = MSIREG_OpenProductKey(prodcode, context, &hkey, FALSE);
1281 RegCloseKey(hkey);
1282 return (r == ERROR_SUCCESS);
1285 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1287 LPCWSTR package;
1288 HKEY hkey;
1289 DWORD sz;
1290 LONG res;
1291 UINT r;
1293 static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
1294 static const WCHAR managed_local_package[] = {
1295 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
1298 if (context == MSIINSTALLCONTEXT_MACHINE)
1299 r = MSIREG_OpenLocalSystemProductKey(prodcode, &hkey, FALSE);
1300 else
1301 r = MSIREG_OpenCurrentUserInstallProps(prodcode, &hkey, FALSE);
1303 if (r != ERROR_SUCCESS)
1304 return FALSE;
1306 if (context == MSIINSTALLCONTEXT_USERMANAGED)
1307 package = managed_local_package;
1308 else
1309 package = local_package;
1311 sz = 0;
1312 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
1313 RegCloseKey(hkey);
1315 return (res == ERROR_SUCCESS);
1318 static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
1319 MSIINSTALLCONTEXT context,
1320 LPCWSTR comp, LPWSTR val, DWORD *sz)
1322 HKEY hkey;
1323 LONG res;
1324 UINT r;
1326 if (context == MSIINSTALLCONTEXT_MACHINE)
1327 r = MSIREG_OpenLocalSystemComponentKey(comp, &hkey, FALSE);
1328 else
1329 r = MSIREG_OpenUserDataComponentKey(comp, &hkey, FALSE);
1331 if (r != ERROR_SUCCESS)
1332 return FALSE;
1334 res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz);
1335 if (res != ERROR_SUCCESS)
1336 return FALSE;
1338 RegCloseKey(hkey);
1339 return TRUE;
1342 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
1343 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1344 LPCWSTR szComponent, INSTALLSTATE *pdwState)
1346 WCHAR squished_pc[GUID_SIZE];
1347 WCHAR val[MAX_PATH];
1348 BOOL found;
1349 DWORD sz;
1351 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
1352 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
1354 if (!pdwState)
1355 return ERROR_INVALID_PARAMETER;
1357 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1)
1358 return ERROR_INVALID_PARAMETER;
1360 if (!squash_guid(szProductCode, squished_pc))
1361 return ERROR_INVALID_PARAMETER;
1363 found = msi_comp_find_prod_key(szProductCode, dwContext);
1365 if (!msi_comp_find_package(szProductCode, dwContext))
1367 if (found)
1369 *pdwState = INSTALLSTATE_UNKNOWN;
1370 return ERROR_UNKNOWN_COMPONENT;
1373 return ERROR_UNKNOWN_PRODUCT;
1376 *pdwState = INSTALLSTATE_UNKNOWN;
1378 sz = MAX_PATH;
1379 if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))
1380 return ERROR_UNKNOWN_COMPONENT;
1382 if (sz == 0)
1383 *pdwState = INSTALLSTATE_NOTUSED;
1384 else
1386 if (lstrlenW(val) > 2 &&
1387 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9')
1389 *pdwState = INSTALLSTATE_SOURCE;
1391 else
1392 *pdwState = INSTALLSTATE_LOCAL;
1395 return ERROR_SUCCESS;
1398 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
1400 LPWSTR szwProduct = NULL;
1401 INSTALLSTATE r;
1403 if( szProduct )
1405 szwProduct = strdupAtoW( szProduct );
1406 if( !szwProduct )
1407 return ERROR_OUTOFMEMORY;
1409 r = MsiQueryProductStateW( szwProduct );
1410 msi_free( szwProduct );
1411 return r;
1414 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
1416 INSTALLSTATE state = INSTALLSTATE_ADVERTISED;
1417 HKEY prodkey = 0, userdata = 0;
1418 BOOL user = TRUE;
1419 DWORD val;
1420 UINT r;
1422 static const WCHAR szWindowsInstaller[] = {
1423 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1425 TRACE("%s\n", debugstr_w(szProduct));
1427 if (!szProduct || !*szProduct)
1428 return INSTALLSTATE_INVALIDARG;
1430 if (lstrlenW(szProduct) != GUID_SIZE - 1)
1431 return INSTALLSTATE_INVALIDARG;
1433 if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
1434 &prodkey, FALSE) != ERROR_SUCCESS &&
1435 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
1436 &prodkey, FALSE) != ERROR_SUCCESS &&
1437 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
1438 &prodkey, FALSE) == ERROR_SUCCESS)
1440 user = FALSE;
1443 if (user)
1445 r = MSIREG_OpenCurrentUserInstallProps(szProduct, &userdata, FALSE);
1446 if (r != ERROR_SUCCESS)
1447 goto done;
1449 else
1451 r = MSIREG_OpenLocalSystemInstallProps(szProduct, &userdata, FALSE);
1452 if (r != ERROR_SUCCESS)
1453 goto done;
1456 if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val))
1457 goto done;
1459 if (val)
1460 state = INSTALLSTATE_DEFAULT;
1461 else
1462 state = INSTALLSTATE_UNKNOWN;
1464 done:
1465 if (!prodkey)
1467 state = INSTALLSTATE_UNKNOWN;
1469 if (userdata)
1470 state = INSTALLSTATE_ABSENT;
1473 RegCloseKey(prodkey);
1474 RegCloseKey(userdata);
1475 return state;
1478 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
1480 INSTALLUILEVEL old = gUILevel;
1481 HWND oldwnd = gUIhwnd;
1483 TRACE("%08x %p\n", dwUILevel, phWnd);
1485 gUILevel = dwUILevel;
1486 if (phWnd)
1488 gUIhwnd = *phWnd;
1489 *phWnd = oldwnd;
1491 return old;
1494 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
1495 DWORD dwMessageFilter, LPVOID pvContext)
1497 INSTALLUI_HANDLERA prev = gUIHandlerA;
1499 TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
1500 gUIHandlerA = puiHandler;
1501 gUIFilter = dwMessageFilter;
1502 gUIContext = pvContext;
1504 return prev;
1507 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
1508 DWORD dwMessageFilter, LPVOID pvContext)
1510 INSTALLUI_HANDLERW prev = gUIHandlerW;
1512 TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
1513 gUIHandlerW = puiHandler;
1514 gUIFilter = dwMessageFilter;
1515 gUIContext = pvContext;
1517 return prev;
1520 /******************************************************************
1521 * MsiLoadStringW [MSI.@]
1523 * Loads a string from MSI's string resources.
1525 * PARAMS
1527 * handle [I] only -1 is handled currently
1528 * id [I] id of the string to be loaded
1529 * lpBuffer [O] buffer for the string to be written to
1530 * nBufferMax [I] maximum size of the buffer in characters
1531 * lang [I] the preferred language for the string
1533 * RETURNS
1535 * If successful, this function returns the language id of the string loaded
1536 * If the function fails, the function returns zero.
1538 * NOTES
1540 * The type of the first parameter is unknown. LoadString's prototype
1541 * suggests that it might be a module handle. I have made it an MSI handle
1542 * for starters, as -1 is an invalid MSI handle, but not an invalid module
1543 * handle. Maybe strings can be stored in an MSI database somehow.
1545 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
1546 int nBufferMax, LANGID lang )
1548 HRSRC hres;
1549 HGLOBAL hResData;
1550 LPWSTR p;
1551 DWORD i, len;
1553 TRACE("%ld %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
1555 if( handle != -1 )
1556 FIXME("don't know how to deal with handle = %08lx\n", handle);
1558 if( !lang )
1559 lang = GetUserDefaultLangID();
1561 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
1562 (LPWSTR)1, lang );
1563 if( !hres )
1564 return 0;
1565 hResData = LoadResource( msi_hInstance, hres );
1566 if( !hResData )
1567 return 0;
1568 p = LockResource( hResData );
1569 if( !p )
1570 return 0;
1572 for (i = 0; i < (id&0xf); i++)
1573 p += *p + 1;
1574 len = *p;
1576 if( nBufferMax <= len )
1577 return 0;
1579 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
1580 lpBuffer[ len ] = 0;
1582 TRACE("found -> %s\n", debugstr_w(lpBuffer));
1584 return lang;
1587 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
1588 int nBufferMax, LANGID lang )
1590 LPWSTR bufW;
1591 LANGID r;
1592 INT len;
1594 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
1595 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
1596 if( r )
1598 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
1599 if( len <= nBufferMax )
1600 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
1601 lpBuffer, nBufferMax, NULL, NULL );
1602 else
1603 r = 0;
1605 msi_free(bufW);
1606 return r;
1609 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
1610 LPDWORD pcchBuf)
1612 char szProduct[GUID_SIZE];
1614 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
1616 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
1617 return INSTALLSTATE_UNKNOWN;
1619 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
1622 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
1623 LPDWORD pcchBuf)
1625 WCHAR szProduct[GUID_SIZE];
1627 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
1629 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
1630 return INSTALLSTATE_UNKNOWN;
1632 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
1635 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
1636 WORD wLanguageId, DWORD f)
1638 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
1639 uType, wLanguageId, f);
1640 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
1643 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
1644 WORD wLanguageId, DWORD f)
1646 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
1647 uType, wLanguageId, f);
1648 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
1651 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
1652 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
1653 LPDWORD pcchPathBuf )
1655 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
1656 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
1657 pcchPathBuf);
1658 return ERROR_CALL_NOT_IMPLEMENTED;
1661 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
1662 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
1663 LPDWORD pcchPathBuf )
1665 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
1666 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
1667 pcchPathBuf);
1668 return ERROR_CALL_NOT_IMPLEMENTED;
1671 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
1672 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
1674 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
1675 return ERROR_CALL_NOT_IMPLEMENTED;
1678 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
1679 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
1681 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
1682 return ERROR_CALL_NOT_IMPLEMENTED;
1685 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
1686 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
1687 LPDWORD pcbHashData)
1689 FIXME("%s %08x %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
1690 ppcCertContext, pbHashData, pcbHashData);
1691 return ERROR_CALL_NOT_IMPLEMENTED;
1694 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
1695 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
1696 LPDWORD pcbHashData)
1698 FIXME("%s %08x %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
1699 ppcCertContext, pbHashData, pcbHashData);
1700 return ERROR_CALL_NOT_IMPLEMENTED;
1703 UINT WINAPI MsiGetProductPropertyA( MSIHANDLE hProduct, LPCSTR szProperty,
1704 LPSTR szValue, LPDWORD pccbValue )
1706 FIXME("%ld %s %p %p\n", hProduct, debugstr_a(szProperty), szValue, pccbValue);
1707 return ERROR_CALL_NOT_IMPLEMENTED;
1710 UINT WINAPI MsiGetProductPropertyW( MSIHANDLE hProduct, LPCWSTR szProperty,
1711 LPWSTR szValue, LPDWORD pccbValue )
1713 FIXME("%ld %s %p %p\n", hProduct, debugstr_w(szProperty), szValue, pccbValue);
1714 return ERROR_CALL_NOT_IMPLEMENTED;
1717 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
1719 UINT r;
1720 LPWSTR szPack = NULL;
1722 TRACE("%s\n", debugstr_a(szPackage) );
1724 if( szPackage )
1726 szPack = strdupAtoW( szPackage );
1727 if( !szPack )
1728 return ERROR_OUTOFMEMORY;
1731 r = MsiVerifyPackageW( szPack );
1733 msi_free( szPack );
1735 return r;
1738 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
1740 MSIHANDLE handle;
1741 UINT r;
1743 TRACE("%s\n", debugstr_w(szPackage) );
1745 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
1746 MsiCloseHandle( handle );
1748 return r;
1751 static INSTALLSTATE WINAPI MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
1752 awstring* lpPathBuf, LPDWORD pcchBuf)
1754 WCHAR squished_pc[GUID_SIZE];
1755 WCHAR squished_comp[GUID_SIZE];
1756 HKEY hkey;
1757 LPWSTR path = NULL;
1758 INSTALLSTATE state;
1759 DWORD version;
1761 static const WCHAR wininstaller[] = {
1762 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1764 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1765 debugstr_w(szComponent), lpPathBuf->str.w, pcchBuf);
1767 if (!szProduct || !szComponent)
1768 return INSTALLSTATE_INVALIDARG;
1770 if (lpPathBuf->str.w && !pcchBuf)
1771 return INSTALLSTATE_INVALIDARG;
1773 if (!squash_guid(szProduct, squished_pc) ||
1774 !squash_guid(szComponent, squished_comp))
1775 return INSTALLSTATE_INVALIDARG;
1777 state = INSTALLSTATE_UNKNOWN;
1779 if (MSIREG_OpenLocalSystemComponentKey(szComponent, &hkey, FALSE) == ERROR_SUCCESS ||
1780 MSIREG_OpenUserDataComponentKey(szComponent, &hkey, FALSE) == ERROR_SUCCESS)
1782 path = msi_reg_get_val_str(hkey, squished_pc);
1783 RegCloseKey(hkey);
1785 state = INSTALLSTATE_ABSENT;
1787 if ((MSIREG_OpenLocalSystemProductKey(szProduct, &hkey, FALSE) == ERROR_SUCCESS ||
1788 MSIREG_OpenUserDataProductKey(szProduct, &hkey, FALSE) == ERROR_SUCCESS) &&
1789 msi_reg_get_val_dword(hkey, wininstaller, &version) &&
1790 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
1792 RegCloseKey(hkey);
1793 state = INSTALLSTATE_LOCAL;
1797 if (state != INSTALLSTATE_LOCAL &&
1798 (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
1799 &hkey, FALSE) == ERROR_SUCCESS ||
1800 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
1801 &hkey, FALSE) == ERROR_SUCCESS))
1803 RegCloseKey(hkey);
1805 if (MSIREG_OpenLocalSystemComponentKey(szComponent, &hkey, FALSE) == ERROR_SUCCESS ||
1806 MSIREG_OpenUserDataComponentKey(szComponent, &hkey, FALSE) == ERROR_SUCCESS)
1808 msi_free(path);
1809 path = msi_reg_get_val_str(hkey, squished_pc);
1810 RegCloseKey(hkey);
1812 state = INSTALLSTATE_ABSENT;
1814 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
1815 state = INSTALLSTATE_LOCAL;
1819 if (!path)
1820 return INSTALLSTATE_UNKNOWN;
1822 if (state == INSTALLSTATE_LOCAL && !*path)
1823 state = INSTALLSTATE_NOTUSED;
1825 msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf);
1826 msi_free(path);
1827 return state;
1830 /******************************************************************
1831 * MsiGetComponentPathW [MSI.@]
1833 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1834 LPWSTR lpPathBuf, LPDWORD pcchBuf)
1836 awstring path;
1838 path.unicode = TRUE;
1839 path.str.w = lpPathBuf;
1841 return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
1844 /******************************************************************
1845 * MsiGetComponentPathA [MSI.@]
1847 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1848 LPSTR lpPathBuf, LPDWORD pcchBuf)
1850 LPWSTR szwProduct, szwComponent = NULL;
1851 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
1852 awstring path;
1854 szwProduct = strdupAtoW( szProduct );
1855 if( szProduct && !szwProduct)
1856 goto end;
1858 szwComponent = strdupAtoW( szComponent );
1859 if( szComponent && !szwComponent )
1860 goto end;
1862 path.unicode = FALSE;
1863 path.str.a = lpPathBuf;
1865 r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
1867 end:
1868 msi_free( szwProduct );
1869 msi_free( szwComponent );
1871 return r;
1874 /******************************************************************
1875 * MsiQueryFeatureStateA [MSI.@]
1877 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
1879 LPWSTR szwProduct = NULL, szwFeature= NULL;
1880 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
1882 szwProduct = strdupAtoW( szProduct );
1883 if ( szProduct && !szwProduct )
1884 goto end;
1886 szwFeature = strdupAtoW( szFeature );
1887 if ( szFeature && !szwFeature )
1888 goto end;
1890 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
1892 end:
1893 msi_free( szwProduct);
1894 msi_free( szwFeature);
1896 return rc;
1899 /******************************************************************
1900 * MsiQueryFeatureStateW [MSI.@]
1902 * Checks the state of a feature
1904 * PARAMS
1905 * szProduct [I] Product's GUID string
1906 * szFeature [I] Feature's GUID string
1908 * RETURNS
1909 * INSTALLSTATE_LOCAL Feature is installed and usable
1910 * INSTALLSTATE_ABSENT Feature is absent
1911 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
1912 * INSTALLSTATE_UNKNOWN An error occurred
1913 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
1916 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
1918 WCHAR squishProduct[33], comp[GUID_SIZE];
1919 GUID guid;
1920 LPWSTR components, p, parent_feature, path;
1921 UINT rc;
1922 HKEY hkey;
1923 INSTALLSTATE r;
1924 BOOL missing = FALSE;
1925 BOOL machine = FALSE;
1926 BOOL source = FALSE;
1928 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
1930 if (!szProduct || !szFeature)
1931 return INSTALLSTATE_INVALIDARG;
1933 if (!squash_guid( szProduct, squishProduct ))
1934 return INSTALLSTATE_INVALIDARG;
1936 if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
1937 &hkey, FALSE) != ERROR_SUCCESS &&
1938 MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
1939 &hkey, FALSE) != ERROR_SUCCESS)
1941 rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
1942 &hkey, FALSE);
1943 if (rc != ERROR_SUCCESS)
1944 return INSTALLSTATE_UNKNOWN;
1946 machine = TRUE;
1949 parent_feature = msi_reg_get_val_str( hkey, szFeature );
1950 RegCloseKey(hkey);
1952 if (!parent_feature)
1953 return INSTALLSTATE_UNKNOWN;
1955 r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
1956 msi_free(parent_feature);
1957 if (r == INSTALLSTATE_ABSENT)
1958 return r;
1960 if (machine)
1961 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
1962 MSIINSTALLCONTEXT_MACHINE,
1963 &hkey, FALSE);
1964 else
1965 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
1966 MSIINSTALLCONTEXT_USERUNMANAGED,
1967 &hkey, FALSE);
1969 if (rc != ERROR_SUCCESS)
1970 return INSTALLSTATE_ADVERTISED;
1972 components = msi_reg_get_val_str( hkey, szFeature );
1973 RegCloseKey(hkey);
1975 TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components));
1977 if (!components)
1978 return INSTALLSTATE_ADVERTISED;
1980 for( p = components; *p && *p != 2 ; p += 20)
1982 if (!decode_base85_guid( p, &guid ))
1984 if (p != components)
1985 break;
1987 msi_free(components);
1988 return INSTALLSTATE_BADCONFIG;
1991 StringFromGUID2(&guid, comp, GUID_SIZE);
1993 if (machine)
1994 rc = MSIREG_OpenLocalUserDataComponentKey(comp, &hkey, FALSE);
1995 else
1996 rc = MSIREG_OpenUserDataComponentKey(comp, &hkey, FALSE);
1998 if (rc != ERROR_SUCCESS)
2000 msi_free(components);
2001 return INSTALLSTATE_ADVERTISED;
2004 path = msi_reg_get_val_str(hkey, squishProduct);
2005 if (!path)
2006 missing = TRUE;
2007 else if (lstrlenW(path) > 2 &&
2008 path[0] >= '0' && path[0] <= '9' &&
2009 path[1] >= '0' && path[1] <= '9')
2011 source = TRUE;
2014 msi_free(path);
2017 TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
2018 msi_free(components);
2020 if (missing)
2021 return INSTALLSTATE_ADVERTISED;
2023 if (source)
2024 return INSTALLSTATE_SOURCE;
2026 return INSTALLSTATE_LOCAL;
2029 /******************************************************************
2030 * MsiGetFileVersionA [MSI.@]
2032 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
2033 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
2035 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
2036 UINT ret = ERROR_OUTOFMEMORY;
2038 if ((lpVersionBuf && !pcchVersionBuf) ||
2039 (lpLangBuf && !pcchLangBuf))
2040 return ERROR_INVALID_PARAMETER;
2042 if( szFilePath )
2044 szwFilePath = strdupAtoW( szFilePath );
2045 if( !szwFilePath )
2046 goto end;
2049 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
2051 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
2052 if( !lpwVersionBuff )
2053 goto end;
2056 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
2058 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
2059 if( !lpwLangBuff )
2060 goto end;
2063 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
2064 lpwLangBuff, pcchLangBuf);
2066 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
2067 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
2068 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
2069 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
2070 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
2071 lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
2073 end:
2074 msi_free(szwFilePath);
2075 msi_free(lpwVersionBuff);
2076 msi_free(lpwLangBuff);
2078 return ret;
2081 /******************************************************************
2082 * MsiGetFileVersionW [MSI.@]
2084 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
2085 LPDWORD pcchVersionBuf, LPWSTR lpLangBuf, LPDWORD pcchLangBuf)
2087 static const WCHAR szVersionResource[] = {'\\',0};
2088 static const WCHAR szVersionFormat[] = {
2089 '%','d','.','%','d','.','%','d','.','%','d',0};
2090 static const WCHAR szLangResource[] = {
2091 '\\','V','a','r','F','i','l','e','I','n','f','o','\\',
2092 'T','r','a','n','s','l','a','t','i','o','n',0};
2093 static const WCHAR szLangFormat[] = {'%','d',0};
2094 UINT ret = 0;
2095 DWORD dwVerLen, gle;
2096 LPVOID lpVer = NULL;
2097 VS_FIXEDFILEINFO *ffi;
2098 USHORT *lang;
2099 UINT puLen;
2100 WCHAR tmp[32];
2102 TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath),
2103 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
2104 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
2106 if ((lpVersionBuf && !pcchVersionBuf) ||
2107 (lpLangBuf && !pcchLangBuf))
2108 return ERROR_INVALID_PARAMETER;
2110 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
2111 if( !dwVerLen )
2113 gle = GetLastError();
2114 if (gle == ERROR_BAD_PATHNAME)
2115 return ERROR_FILE_NOT_FOUND;
2116 else if (gle == ERROR_RESOURCE_DATA_NOT_FOUND)
2117 return ERROR_FILE_INVALID;
2119 return gle;
2122 lpVer = msi_alloc(dwVerLen);
2123 if( !lpVer )
2125 ret = ERROR_OUTOFMEMORY;
2126 goto end;
2129 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
2131 ret = GetLastError();
2132 goto end;
2135 if (pcchVersionBuf)
2137 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
2138 (puLen > 0) )
2140 wsprintfW(tmp, szVersionFormat,
2141 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
2142 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
2143 if (lpVersionBuf) lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
2145 if (strlenW(tmp) >= *pcchVersionBuf)
2146 ret = ERROR_MORE_DATA;
2148 *pcchVersionBuf = lstrlenW(tmp);
2150 else
2152 if (lpVersionBuf) *lpVersionBuf = 0;
2153 *pcchVersionBuf = 0;
2157 if (pcchLangBuf)
2159 if (VerQueryValueW(lpVer, szLangResource, (LPVOID*)&lang, &puLen) &&
2160 (puLen > 0))
2162 wsprintfW(tmp, szLangFormat, *lang);
2163 if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
2165 if (strlenW(tmp) >= *pcchLangBuf)
2166 ret = ERROR_MORE_DATA;
2168 *pcchLangBuf = lstrlenW(tmp);
2170 else
2172 if (lpLangBuf) *lpLangBuf = 0;
2173 *pcchLangBuf = 0;
2177 end:
2178 msi_free(lpVer);
2179 return ret;
2182 /***********************************************************************
2183 * MsiGetFeatureUsageW [MSI.@]
2185 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
2186 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2188 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
2189 pdwUseCount, pwDateUsed);
2190 return ERROR_CALL_NOT_IMPLEMENTED;
2193 /***********************************************************************
2194 * MsiGetFeatureUsageA [MSI.@]
2196 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
2197 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2199 LPWSTR prod = NULL, feat = NULL;
2200 UINT ret = ERROR_OUTOFMEMORY;
2202 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
2203 pdwUseCount, pwDateUsed);
2205 prod = strdupAtoW( szProduct );
2206 if (szProduct && !prod)
2207 goto end;
2209 feat = strdupAtoW( szFeature );
2210 if (szFeature && !feat)
2211 goto end;
2213 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
2215 end:
2216 msi_free( prod );
2217 msi_free( feat );
2219 return ret;
2222 /***********************************************************************
2223 * MsiUseFeatureExW [MSI.@]
2225 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
2226 DWORD dwInstallMode, DWORD dwReserved )
2228 INSTALLSTATE state;
2230 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2231 dwInstallMode, dwReserved);
2233 state = MsiQueryFeatureStateW( szProduct, szFeature );
2235 if (dwReserved)
2236 return INSTALLSTATE_INVALIDARG;
2238 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
2240 FIXME("mark product %s feature %s as used\n",
2241 debugstr_w(szProduct), debugstr_w(szFeature) );
2244 return state;
2247 /***********************************************************************
2248 * MsiUseFeatureExA [MSI.@]
2250 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
2251 DWORD dwInstallMode, DWORD dwReserved )
2253 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
2254 LPWSTR prod = NULL, feat = NULL;
2256 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2257 dwInstallMode, dwReserved);
2259 prod = strdupAtoW( szProduct );
2260 if (szProduct && !prod)
2261 goto end;
2263 feat = strdupAtoW( szFeature );
2264 if (szFeature && !feat)
2265 goto end;
2267 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
2269 end:
2270 msi_free( prod );
2271 msi_free( feat );
2273 return ret;
2276 /***********************************************************************
2277 * MsiUseFeatureW [MSI.@]
2279 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
2281 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
2284 /***********************************************************************
2285 * MsiUseFeatureA [MSI.@]
2287 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
2289 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
2292 /***********************************************************************
2293 * MSI_ProvideQualifiedComponentEx [internal]
2295 static UINT WINAPI MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
2296 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2297 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
2298 LPDWORD pcchPathBuf)
2300 WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1],
2301 feature[MAX_FEATURE_CHARS+1];
2302 LPWSTR info;
2303 HKEY hkey;
2304 DWORD sz;
2305 UINT rc;
2307 TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent),
2308 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
2309 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2311 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
2312 if (rc != ERROR_SUCCESS)
2313 return ERROR_INDEX_ABSENT;
2315 info = msi_reg_get_val_str( hkey, szQualifier );
2316 RegCloseKey(hkey);
2318 if (!info)
2319 return ERROR_INDEX_ABSENT;
2321 MsiDecomposeDescriptorW(info, product, feature, component, &sz);
2323 if (!szProduct)
2324 rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf);
2325 else
2326 rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
2328 msi_free( info );
2330 if (rc != INSTALLSTATE_LOCAL)
2331 return ERROR_FILE_NOT_FOUND;
2333 return ERROR_SUCCESS;
2336 /***********************************************************************
2337 * MsiProvideQualifiedComponentExW [MSI.@]
2339 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
2340 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2341 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
2342 LPDWORD pcchPathBuf)
2344 awstring path;
2346 path.unicode = TRUE;
2347 path.str.w = lpPathBuf;
2349 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
2350 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
2353 /***********************************************************************
2354 * MsiProvideQualifiedComponentExA [MSI.@]
2356 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
2357 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct,
2358 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
2359 LPDWORD pcchPathBuf)
2361 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
2362 UINT r = ERROR_OUTOFMEMORY;
2363 awstring path;
2365 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
2366 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
2367 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2369 szwComponent = strdupAtoW( szComponent );
2370 if (szComponent && !szwComponent)
2371 goto end;
2373 szwQualifier = strdupAtoW( szQualifier );
2374 if (szQualifier && !szwQualifier)
2375 goto end;
2377 szwProduct = strdupAtoW( szProduct );
2378 if (szProduct && !szwProduct)
2379 goto end;
2381 path.unicode = FALSE;
2382 path.str.a = lpPathBuf;
2384 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
2385 dwInstallMode, szwProduct, Unused1,
2386 Unused2, &path, pcchPathBuf);
2387 end:
2388 msi_free(szwProduct);
2389 msi_free(szwComponent);
2390 msi_free(szwQualifier);
2392 return r;
2395 /***********************************************************************
2396 * MsiProvideQualifiedComponentW [MSI.@]
2398 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
2399 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
2400 LPDWORD pcchPathBuf)
2402 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
2403 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2406 /***********************************************************************
2407 * MsiProvideQualifiedComponentA [MSI.@]
2409 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
2410 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
2411 LPDWORD pcchPathBuf)
2413 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
2414 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2417 /***********************************************************************
2418 * MSI_GetUserInfo [internal]
2420 static USERINFOSTATE WINAPI MSI_GetUserInfo(LPCWSTR szProduct,
2421 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
2422 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2423 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
2425 WCHAR squished_pc[SQUISH_GUID_SIZE];
2426 LPWSTR user, org, serial;
2427 USERINFOSTATE state;
2428 HKEY hkey, props;
2429 LPCWSTR orgptr;
2430 UINT r;
2432 static const WCHAR szEmpty[] = {0};
2434 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
2435 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
2436 pcchSerialBuf);
2438 if (!szProduct || !squash_guid(szProduct, squished_pc))
2439 return USERINFOSTATE_INVALIDARG;
2441 if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2442 &hkey, FALSE) != ERROR_SUCCESS &&
2443 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2444 &hkey, FALSE) != ERROR_SUCCESS &&
2445 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2446 &hkey, FALSE) != ERROR_SUCCESS)
2448 return USERINFOSTATE_UNKNOWN;
2451 if (MSIREG_OpenCurrentUserInstallProps(szProduct, &props, FALSE) != ERROR_SUCCESS &&
2452 MSIREG_OpenLocalSystemInstallProps(szProduct, &props, FALSE) != ERROR_SUCCESS)
2454 RegCloseKey(hkey);
2455 return USERINFOSTATE_ABSENT;
2458 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
2459 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
2460 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
2461 state = USERINFOSTATE_ABSENT;
2463 RegCloseKey(hkey);
2464 RegCloseKey(props);
2466 if (user && serial)
2467 state = USERINFOSTATE_PRESENT;
2469 if (pcchUserNameBuf)
2471 if (lpUserNameBuf && !user)
2473 (*pcchUserNameBuf)--;
2474 goto done;
2477 r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf);
2478 if (r == ERROR_MORE_DATA)
2480 state = USERINFOSTATE_MOREDATA;
2481 goto done;
2485 if (pcchOrgNameBuf)
2487 orgptr = org;
2488 if (!orgptr) orgptr = szEmpty;
2490 r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf);
2491 if (r == ERROR_MORE_DATA)
2493 state = USERINFOSTATE_MOREDATA;
2494 goto done;
2498 if (pcchSerialBuf)
2500 if (!serial)
2502 (*pcchSerialBuf)--;
2503 goto done;
2506 r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf);
2507 if (r == ERROR_MORE_DATA)
2508 state = USERINFOSTATE_MOREDATA;
2511 done:
2512 msi_free(user);
2513 msi_free(org);
2514 msi_free(serial);
2516 return state;
2519 /***********************************************************************
2520 * MsiGetUserInfoW [MSI.@]
2522 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
2523 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2524 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2525 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
2527 awstring user, org, serial;
2529 if ((lpUserNameBuf && !pcchUserNameBuf) ||
2530 (lpOrgNameBuf && !pcchOrgNameBuf) ||
2531 (lpSerialBuf && !pcchSerialBuf))
2532 return USERINFOSTATE_INVALIDARG;
2534 user.unicode = TRUE;
2535 user.str.w = lpUserNameBuf;
2536 org.unicode = TRUE;
2537 org.str.w = lpOrgNameBuf;
2538 serial.unicode = TRUE;
2539 serial.str.w = lpSerialBuf;
2541 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
2542 &org, pcchOrgNameBuf,
2543 &serial, pcchSerialBuf );
2546 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
2547 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2548 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2549 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
2551 awstring user, org, serial;
2552 LPWSTR prod;
2553 UINT r;
2555 if ((lpUserNameBuf && !pcchUserNameBuf) ||
2556 (lpOrgNameBuf && !pcchOrgNameBuf) ||
2557 (lpSerialBuf && !pcchSerialBuf))
2558 return USERINFOSTATE_INVALIDARG;
2560 prod = strdupAtoW( szProduct );
2561 if (szProduct && !prod)
2562 return ERROR_OUTOFMEMORY;
2564 user.unicode = FALSE;
2565 user.str.a = lpUserNameBuf;
2566 org.unicode = FALSE;
2567 org.str.a = lpOrgNameBuf;
2568 serial.unicode = FALSE;
2569 serial.str.a = lpSerialBuf;
2571 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
2572 &org, pcchOrgNameBuf,
2573 &serial, pcchSerialBuf );
2575 msi_free( prod );
2577 return r;
2580 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
2582 MSIHANDLE handle;
2583 UINT rc;
2584 MSIPACKAGE *package;
2585 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
2587 TRACE("(%s)\n",debugstr_w(szProduct));
2589 rc = MsiOpenProductW(szProduct,&handle);
2590 if (rc != ERROR_SUCCESS)
2591 return ERROR_INVALID_PARAMETER;
2593 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
2594 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
2595 msiobj_release( &package->hdr );
2597 MsiCloseHandle(handle);
2599 return rc;
2602 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
2604 MSIHANDLE handle;
2605 UINT rc;
2606 MSIPACKAGE *package;
2607 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
2609 TRACE("(%s)\n",debugstr_a(szProduct));
2611 rc = MsiOpenProductA(szProduct,&handle);
2612 if (rc != ERROR_SUCCESS)
2613 return ERROR_INVALID_PARAMETER;
2615 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
2616 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
2617 msiobj_release( &package->hdr );
2619 MsiCloseHandle(handle);
2621 return rc;
2624 /***********************************************************************
2625 * MsiConfigureFeatureA [MSI.@]
2627 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
2629 LPWSTR prod, feat = NULL;
2630 UINT r = ERROR_OUTOFMEMORY;
2632 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
2634 prod = strdupAtoW( szProduct );
2635 if (szProduct && !prod)
2636 goto end;
2638 feat = strdupAtoW( szFeature );
2639 if (szFeature && !feat)
2640 goto end;
2642 r = MsiConfigureFeatureW(prod, feat, eInstallState);
2644 end:
2645 msi_free(feat);
2646 msi_free(prod);
2648 return r;
2651 /***********************************************************************
2652 * MsiConfigureFeatureW [MSI.@]
2654 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
2656 static const WCHAR szCostInit[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
2657 MSIPACKAGE *package = NULL;
2658 UINT r;
2659 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
2660 DWORD sz;
2662 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
2664 if (!szProduct || !szFeature)
2665 return ERROR_INVALID_PARAMETER;
2667 switch (eInstallState)
2669 case INSTALLSTATE_DEFAULT:
2670 /* FIXME: how do we figure out the default location? */
2671 eInstallState = INSTALLSTATE_LOCAL;
2672 break;
2673 case INSTALLSTATE_LOCAL:
2674 case INSTALLSTATE_SOURCE:
2675 case INSTALLSTATE_ABSENT:
2676 case INSTALLSTATE_ADVERTISED:
2677 break;
2678 default:
2679 return ERROR_INVALID_PARAMETER;
2682 r = MSI_OpenProductW( szProduct, &package );
2683 if (r != ERROR_SUCCESS)
2684 return r;
2686 sz = sizeof(sourcepath);
2687 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2688 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
2690 sz = sizeof(filename);
2691 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2692 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
2694 lstrcatW( sourcepath, filename );
2696 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
2698 r = ACTION_PerformUIAction( package, szCostInit, -1 );
2699 if (r != ERROR_SUCCESS)
2700 goto end;
2702 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
2703 if (r != ERROR_SUCCESS)
2704 goto end;
2706 r = MSI_InstallPackage( package, sourcepath, NULL );
2708 end:
2709 msiobj_release( &package->hdr );
2711 return r;
2714 /***********************************************************************
2715 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
2717 * Notes: undocumented
2719 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
2721 WCHAR path[MAX_PATH];
2723 TRACE("%d\n", dwReserved);
2725 if (dwReserved)
2727 FIXME("dwReserved=%d\n", dwReserved);
2728 return ERROR_INVALID_PARAMETER;
2731 if (!GetWindowsDirectoryW(path, MAX_PATH))
2732 return ERROR_FUNCTION_FAILED;
2734 lstrcatW(path, installerW);
2736 if (!CreateDirectoryW(path, NULL))
2737 return ERROR_FUNCTION_FAILED;
2739 return ERROR_SUCCESS;
2742 /***********************************************************************
2743 * MsiGetShortcutTargetA [MSI.@]
2745 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
2746 LPSTR szProductCode, LPSTR szFeatureId,
2747 LPSTR szComponentCode )
2749 LPWSTR target;
2750 const int len = MAX_FEATURE_CHARS+1;
2751 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
2752 UINT r;
2754 target = strdupAtoW( szShortcutTarget );
2755 if (szShortcutTarget && !target )
2756 return ERROR_OUTOFMEMORY;
2757 product[0] = 0;
2758 feature[0] = 0;
2759 component[0] = 0;
2760 r = MsiGetShortcutTargetW( target, product, feature, component );
2761 msi_free( target );
2762 if (r == ERROR_SUCCESS)
2764 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
2765 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
2766 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
2768 return r;
2771 /***********************************************************************
2772 * MsiGetShortcutTargetW [MSI.@]
2774 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
2775 LPWSTR szProductCode, LPWSTR szFeatureId,
2776 LPWSTR szComponentCode )
2778 IShellLinkDataList *dl = NULL;
2779 IPersistFile *pf = NULL;
2780 LPEXP_DARWIN_LINK darwin = NULL;
2781 HRESULT r, init;
2783 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
2784 szProductCode, szFeatureId, szComponentCode );
2786 init = CoInitialize(NULL);
2788 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
2789 &IID_IPersistFile, (LPVOID*) &pf );
2790 if( SUCCEEDED( r ) )
2792 r = IPersistFile_Load( pf, szShortcutTarget,
2793 STGM_READ | STGM_SHARE_DENY_WRITE );
2794 if( SUCCEEDED( r ) )
2796 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
2797 (LPVOID*) &dl );
2798 if( SUCCEEDED( r ) )
2800 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
2801 (LPVOID) &darwin );
2802 IShellLinkDataList_Release( dl );
2805 IPersistFile_Release( pf );
2808 if (SUCCEEDED(init))
2809 CoUninitialize();
2811 TRACE("darwin = %p\n", darwin);
2813 if (darwin)
2815 DWORD sz;
2816 UINT ret;
2818 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
2819 szProductCode, szFeatureId, szComponentCode, &sz );
2820 LocalFree( darwin );
2821 return ret;
2824 return ERROR_FUNCTION_FAILED;
2827 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
2828 DWORD dwReinstallMode )
2830 MSIPACKAGE* package = NULL;
2831 UINT r;
2832 WCHAR sourcepath[MAX_PATH];
2833 WCHAR filename[MAX_PATH];
2834 static const WCHAR szLogVerbose[] = {
2835 ' ','L','O','G','V','E','R','B','O','S','E',0 };
2836 static const WCHAR szInstalled[] = { 'I','n','s','t','a','l','l','e','d',0};
2837 static const WCHAR szReinstall[] = {'R','E','I','N','S','T','A','L','L',0};
2838 static const WCHAR szReinstallMode[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
2839 static const WCHAR szOne[] = {'1',0};
2840 WCHAR reinstallmode[11];
2841 LPWSTR ptr;
2842 DWORD sz;
2844 FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2845 dwReinstallMode);
2847 ptr = reinstallmode;
2849 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
2850 *ptr++ = 'p';
2851 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
2852 *ptr++ = 'o';
2853 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
2854 *ptr++ = 'w';
2855 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
2856 *ptr++ = 'd';
2857 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
2858 *ptr++ = 'c';
2859 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
2860 *ptr++ = 'a';
2861 if (dwReinstallMode & REINSTALLMODE_USERDATA)
2862 *ptr++ = 'u';
2863 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
2864 *ptr++ = 'm';
2865 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
2866 *ptr++ = 's';
2867 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
2868 *ptr++ = 'v';
2869 *ptr = 0;
2871 sz = sizeof(sourcepath);
2872 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2873 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
2875 sz = sizeof(filename);
2876 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2877 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
2879 lstrcatW( sourcepath, filename );
2881 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
2882 r = MSI_OpenPackageW( sourcepath, &package );
2883 else
2884 r = MSI_OpenProductW( szProduct, &package );
2886 if (r != ERROR_SUCCESS)
2887 return r;
2889 MSI_SetPropertyW( package, szReinstallMode, reinstallmode );
2890 MSI_SetPropertyW( package, szInstalled, szOne );
2891 MSI_SetPropertyW( package, szLogVerbose, szOne );
2892 MSI_SetPropertyW( package, szReinstall, szFeature );
2894 r = MSI_InstallPackage( package, sourcepath, NULL );
2896 msiobj_release( &package->hdr );
2898 return r;
2901 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
2902 DWORD dwReinstallMode )
2904 LPWSTR wszProduct;
2905 LPWSTR wszFeature;
2906 UINT rc;
2908 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2909 dwReinstallMode);
2911 wszProduct = strdupAtoW(szProduct);
2912 wszFeature = strdupAtoW(szFeature);
2914 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
2916 msi_free(wszProduct);
2917 msi_free(wszFeature);
2918 return rc;
2921 typedef struct
2923 unsigned int i[2];
2924 unsigned int buf[4];
2925 unsigned char in[64];
2926 unsigned char digest[16];
2927 } MD5_CTX;
2929 extern VOID WINAPI MD5Init( MD5_CTX *);
2930 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
2931 extern VOID WINAPI MD5Final( MD5_CTX *);
2933 /***********************************************************************
2934 * MsiGetFileHashW [MSI.@]
2936 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
2937 PMSIFILEHASHINFO pHash )
2939 HANDLE handle, mapping;
2940 void *p;
2941 DWORD length;
2942 UINT r = ERROR_FUNCTION_FAILED;
2944 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
2946 if (!szFilePath)
2947 return ERROR_INVALID_PARAMETER;
2949 if (!*szFilePath)
2950 return ERROR_PATH_NOT_FOUND;
2952 if (dwOptions)
2953 return ERROR_INVALID_PARAMETER;
2954 if (!pHash)
2955 return ERROR_INVALID_PARAMETER;
2956 if (pHash->dwFileHashInfoSize < sizeof *pHash)
2957 return ERROR_INVALID_PARAMETER;
2959 handle = CreateFileW( szFilePath, GENERIC_READ,
2960 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
2961 if (handle == INVALID_HANDLE_VALUE)
2962 return ERROR_FILE_NOT_FOUND;
2964 length = GetFileSize( handle, NULL );
2966 mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
2967 if (mapping)
2969 p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
2970 if (p)
2972 MD5_CTX ctx;
2974 MD5Init( &ctx );
2975 MD5Update( &ctx, p, length );
2976 MD5Final( &ctx );
2977 UnmapViewOfFile( p );
2979 memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData );
2980 r = ERROR_SUCCESS;
2982 CloseHandle( mapping );
2984 CloseHandle( handle );
2986 return r;
2989 /***********************************************************************
2990 * MsiGetFileHashA [MSI.@]
2992 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
2993 PMSIFILEHASHINFO pHash )
2995 LPWSTR file;
2996 UINT r;
2998 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
3000 file = strdupAtoW( szFilePath );
3001 if (szFilePath && !file)
3002 return ERROR_OUTOFMEMORY;
3004 r = MsiGetFileHashW( file, dwOptions, pHash );
3005 msi_free( file );
3006 return r;
3009 /***********************************************************************
3010 * MsiAdvertiseScriptW [MSI.@]
3012 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
3013 PHKEY phRegData, BOOL fRemoveItems )
3015 FIXME("%s %08x %p %d\n",
3016 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3017 return ERROR_CALL_NOT_IMPLEMENTED;
3020 /***********************************************************************
3021 * MsiAdvertiseScriptA [MSI.@]
3023 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
3024 PHKEY phRegData, BOOL fRemoveItems )
3026 FIXME("%s %08x %p %d\n",
3027 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3028 return ERROR_CALL_NOT_IMPLEMENTED;
3031 /***********************************************************************
3032 * MsiIsProductElevatedW [MSI.@]
3034 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
3036 FIXME("%s %p - stub\n",
3037 debugstr_w( szProduct ), pfElevated );
3038 *pfElevated = TRUE;
3039 return ERROR_SUCCESS;
3042 /***********************************************************************
3043 * MsiIsProductElevatedA [MSI.@]
3045 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
3047 FIXME("%s %p - stub\n",
3048 debugstr_a( szProduct ), pfElevated );
3049 *pfElevated = TRUE;
3050 return ERROR_SUCCESS;
3053 /***********************************************************************
3054 * MsiSetExternalUIRecord [MSI.@]
3056 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD puiHandler,
3057 DWORD dwMessageFilter, LPVOID pvContext,
3058 PINSTALLUI_HANDLER_RECORD ppuiPrevHandler)
3060 FIXME("%p %08x %p %p\n", puiHandler, dwMessageFilter ,pvContext,
3061 ppuiPrevHandler);
3062 return ERROR_CALL_NOT_IMPLEMENTED;
3065 /***********************************************************************
3066 * MsiInstallMissingComponentW [MSI.@]
3068 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState)
3070 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
3071 return ERROR_SUCCESS;