msvcrt: Use iob_func instead of p__iob on non-x86.
[wine/wine64.git] / dlls / msi / msi.c
blobef1b8718018b61ba016a350ea88646178ae4acde
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_OpenInstallProps(szProduct, szLocalSid, &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_OpenInstallProps(product, szLocalSid, &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, NULL, &compkey, FALSE) != ERROR_SUCCESS &&
622 MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &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 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_OpenInstallProps(szProduct, szLocalSid, &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_OpenInstallProps(szProductCode, szLocalSid, &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_OpenInstallProps(prodcode, szLocalSid, &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_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
1328 else
1329 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &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_OpenInstallProps(szProduct, szLocalSid, &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 /******************************************************************
1704 * MsiGetProductPropertyA [MSI.@]
1706 UINT WINAPI MsiGetProductPropertyA(MSIHANDLE hProduct, LPCSTR szProperty,
1707 LPSTR szValue, LPDWORD pccbValue)
1709 LPWSTR prop = NULL, val = NULL;
1710 DWORD len;
1711 UINT r;
1713 TRACE("(%ld, %s, %p, %p)\n", hProduct, debugstr_a(szProperty),
1714 szValue, pccbValue);
1716 if (szValue && !pccbValue)
1717 return ERROR_INVALID_PARAMETER;
1719 if (szProperty) prop = strdupAtoW(szProperty);
1721 len = 0;
1722 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len);
1723 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
1724 goto done;
1726 if (r == ERROR_SUCCESS)
1728 if (szValue) *szValue = '\0';
1729 if (pccbValue) *pccbValue = 0;
1730 goto done;
1733 val = msi_alloc(++len * sizeof(WCHAR));
1734 if (!val)
1736 r = ERROR_OUTOFMEMORY;
1737 goto done;
1740 r = MsiGetProductPropertyW(hProduct, prop, val, &len);
1741 if (r != ERROR_SUCCESS)
1742 goto done;
1744 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL);
1746 if (szValue)
1747 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue,
1748 *pccbValue, NULL, NULL);
1750 if (pccbValue)
1752 if (len > *pccbValue)
1753 r = ERROR_MORE_DATA;
1755 *pccbValue = len - 1;
1758 done:
1759 msi_free(prop);
1760 msi_free(val);
1762 return r;
1765 /******************************************************************
1766 * MsiGetProductPropertyW [MSI.@]
1768 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE hProduct, LPCWSTR szProperty,
1769 LPWSTR szValue, LPDWORD pccbValue)
1771 MSIPACKAGE *package;
1772 MSIQUERY *view = NULL;
1773 MSIRECORD *rec = NULL;
1774 LPCWSTR val;
1775 UINT r;
1777 static const WCHAR query[] = {
1778 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1779 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
1780 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
1782 TRACE("(%ld, %s, %p, %p)\n", hProduct, debugstr_w(szProperty),
1783 szValue, pccbValue);
1785 if (!szProperty)
1786 return ERROR_INVALID_PARAMETER;
1788 if (szValue && !pccbValue)
1789 return ERROR_INVALID_PARAMETER;
1791 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE);
1792 if (!package)
1793 return ERROR_INVALID_HANDLE;
1795 r = MSI_OpenQuery(package->db, &view, query, szProperty);
1796 if (r != ERROR_SUCCESS)
1797 goto done;
1799 r = MSI_ViewExecute(view, 0);
1800 if (r != ERROR_SUCCESS)
1801 goto done;
1803 r = MSI_ViewFetch(view, &rec);
1804 if (r != ERROR_SUCCESS)
1805 goto done;
1807 val = MSI_RecordGetString(rec, 2);
1808 if (!val)
1809 goto done;
1811 if (lstrlenW(val) >= *pccbValue)
1813 lstrcpynW(szValue, val, *pccbValue);
1814 *pccbValue = lstrlenW(val);
1815 r = ERROR_MORE_DATA;
1817 else
1819 lstrcpyW(szValue, val);
1820 *pccbValue = lstrlenW(val);
1821 r = ERROR_SUCCESS;
1824 done:
1825 if (view)
1827 MSI_ViewClose(view);
1828 msiobj_release(&view->hdr);
1829 if (rec) msiobj_release(&rec->hdr);
1832 if (!rec)
1834 if (szValue) *szValue = '\0';
1835 if (pccbValue) *pccbValue = 0;
1836 r = ERROR_SUCCESS;
1839 return r;
1842 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
1844 UINT r;
1845 LPWSTR szPack = NULL;
1847 TRACE("%s\n", debugstr_a(szPackage) );
1849 if( szPackage )
1851 szPack = strdupAtoW( szPackage );
1852 if( !szPack )
1853 return ERROR_OUTOFMEMORY;
1856 r = MsiVerifyPackageW( szPack );
1858 msi_free( szPack );
1860 return r;
1863 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
1865 MSIHANDLE handle;
1866 UINT r;
1868 TRACE("%s\n", debugstr_w(szPackage) );
1870 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
1871 MsiCloseHandle( handle );
1873 return r;
1876 static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
1877 awstring* lpPathBuf, LPDWORD pcchBuf)
1879 WCHAR squished_pc[GUID_SIZE];
1880 WCHAR squished_comp[GUID_SIZE];
1881 HKEY hkey;
1882 LPWSTR path = NULL;
1883 INSTALLSTATE state;
1884 DWORD version;
1886 static const WCHAR wininstaller[] = {
1887 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1889 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
1890 debugstr_w(szComponent), lpPathBuf->str.w, pcchBuf);
1892 if (!szProduct || !szComponent)
1893 return INSTALLSTATE_INVALIDARG;
1895 if (lpPathBuf->str.w && !pcchBuf)
1896 return INSTALLSTATE_INVALIDARG;
1898 if (!squash_guid(szProduct, squished_pc) ||
1899 !squash_guid(szComponent, squished_comp))
1900 return INSTALLSTATE_INVALIDARG;
1902 state = INSTALLSTATE_UNKNOWN;
1904 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
1905 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
1907 path = msi_reg_get_val_str(hkey, squished_pc);
1908 RegCloseKey(hkey);
1910 state = INSTALLSTATE_ABSENT;
1912 if ((MSIREG_OpenInstallProps(szProduct, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
1913 MSIREG_OpenUserDataProductKey(szProduct, NULL, &hkey, FALSE) == ERROR_SUCCESS) &&
1914 msi_reg_get_val_dword(hkey, wininstaller, &version) &&
1915 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
1917 RegCloseKey(hkey);
1918 state = INSTALLSTATE_LOCAL;
1922 if (state != INSTALLSTATE_LOCAL &&
1923 (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
1924 &hkey, FALSE) == ERROR_SUCCESS ||
1925 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
1926 &hkey, FALSE) == ERROR_SUCCESS))
1928 RegCloseKey(hkey);
1930 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
1931 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
1933 msi_free(path);
1934 path = msi_reg_get_val_str(hkey, squished_pc);
1935 RegCloseKey(hkey);
1937 state = INSTALLSTATE_ABSENT;
1939 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
1940 state = INSTALLSTATE_LOCAL;
1944 if (!path)
1945 return INSTALLSTATE_UNKNOWN;
1947 if (state == INSTALLSTATE_LOCAL && !*path)
1948 state = INSTALLSTATE_NOTUSED;
1950 msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf);
1951 msi_free(path);
1952 return state;
1955 /******************************************************************
1956 * MsiGetComponentPathW [MSI.@]
1958 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
1959 LPWSTR lpPathBuf, LPDWORD pcchBuf)
1961 awstring path;
1963 path.unicode = TRUE;
1964 path.str.w = lpPathBuf;
1966 return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
1969 /******************************************************************
1970 * MsiGetComponentPathA [MSI.@]
1972 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
1973 LPSTR lpPathBuf, LPDWORD pcchBuf)
1975 LPWSTR szwProduct, szwComponent = NULL;
1976 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
1977 awstring path;
1979 szwProduct = strdupAtoW( szProduct );
1980 if( szProduct && !szwProduct)
1981 goto end;
1983 szwComponent = strdupAtoW( szComponent );
1984 if( szComponent && !szwComponent )
1985 goto end;
1987 path.unicode = FALSE;
1988 path.str.a = lpPathBuf;
1990 r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
1992 end:
1993 msi_free( szwProduct );
1994 msi_free( szwComponent );
1996 return r;
1999 /******************************************************************
2000 * MsiQueryFeatureStateA [MSI.@]
2002 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
2004 LPWSTR szwProduct = NULL, szwFeature= NULL;
2005 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
2007 szwProduct = strdupAtoW( szProduct );
2008 if ( szProduct && !szwProduct )
2009 goto end;
2011 szwFeature = strdupAtoW( szFeature );
2012 if ( szFeature && !szwFeature )
2013 goto end;
2015 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
2017 end:
2018 msi_free( szwProduct);
2019 msi_free( szwFeature);
2021 return rc;
2024 /******************************************************************
2025 * MsiQueryFeatureStateW [MSI.@]
2027 * Checks the state of a feature
2029 * PARAMS
2030 * szProduct [I] Product's GUID string
2031 * szFeature [I] Feature's GUID string
2033 * RETURNS
2034 * INSTALLSTATE_LOCAL Feature is installed and usable
2035 * INSTALLSTATE_ABSENT Feature is absent
2036 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
2037 * INSTALLSTATE_UNKNOWN An error occurred
2038 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
2041 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
2043 WCHAR squishProduct[33], comp[GUID_SIZE];
2044 GUID guid;
2045 LPWSTR components, p, parent_feature, path;
2046 UINT rc;
2047 HKEY hkey;
2048 INSTALLSTATE r;
2049 BOOL missing = FALSE;
2050 BOOL machine = FALSE;
2051 BOOL source = FALSE;
2053 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
2055 if (!szProduct || !szFeature)
2056 return INSTALLSTATE_INVALIDARG;
2058 if (!squash_guid( szProduct, squishProduct ))
2059 return INSTALLSTATE_INVALIDARG;
2061 if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2062 &hkey, FALSE) != ERROR_SUCCESS &&
2063 MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2064 &hkey, FALSE) != ERROR_SUCCESS)
2066 rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2067 &hkey, FALSE);
2068 if (rc != ERROR_SUCCESS)
2069 return INSTALLSTATE_UNKNOWN;
2071 machine = TRUE;
2074 parent_feature = msi_reg_get_val_str( hkey, szFeature );
2075 RegCloseKey(hkey);
2077 if (!parent_feature)
2078 return INSTALLSTATE_UNKNOWN;
2080 r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
2081 msi_free(parent_feature);
2082 if (r == INSTALLSTATE_ABSENT)
2083 return r;
2085 if (machine)
2086 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2087 MSIINSTALLCONTEXT_MACHINE,
2088 &hkey, FALSE);
2089 else
2090 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2091 MSIINSTALLCONTEXT_USERUNMANAGED,
2092 &hkey, FALSE);
2094 if (rc != ERROR_SUCCESS)
2095 return INSTALLSTATE_ADVERTISED;
2097 components = msi_reg_get_val_str( hkey, szFeature );
2098 RegCloseKey(hkey);
2100 TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components));
2102 if (!components)
2103 return INSTALLSTATE_ADVERTISED;
2105 for( p = components; *p && *p != 2 ; p += 20)
2107 if (!decode_base85_guid( p, &guid ))
2109 if (p != components)
2110 break;
2112 msi_free(components);
2113 return INSTALLSTATE_BADCONFIG;
2116 StringFromGUID2(&guid, comp, GUID_SIZE);
2118 if (machine)
2119 rc = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
2120 else
2121 rc = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
2123 if (rc != ERROR_SUCCESS)
2125 msi_free(components);
2126 return INSTALLSTATE_ADVERTISED;
2129 path = msi_reg_get_val_str(hkey, squishProduct);
2130 if (!path)
2131 missing = TRUE;
2132 else if (lstrlenW(path) > 2 &&
2133 path[0] >= '0' && path[0] <= '9' &&
2134 path[1] >= '0' && path[1] <= '9')
2136 source = TRUE;
2139 msi_free(path);
2142 TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
2143 msi_free(components);
2145 if (missing)
2146 return INSTALLSTATE_ADVERTISED;
2148 if (source)
2149 return INSTALLSTATE_SOURCE;
2151 return INSTALLSTATE_LOCAL;
2154 /******************************************************************
2155 * MsiGetFileVersionA [MSI.@]
2157 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
2158 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
2160 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
2161 UINT ret = ERROR_OUTOFMEMORY;
2163 if ((lpVersionBuf && !pcchVersionBuf) ||
2164 (lpLangBuf && !pcchLangBuf))
2165 return ERROR_INVALID_PARAMETER;
2167 if( szFilePath )
2169 szwFilePath = strdupAtoW( szFilePath );
2170 if( !szwFilePath )
2171 goto end;
2174 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
2176 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
2177 if( !lpwVersionBuff )
2178 goto end;
2181 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
2183 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
2184 if( !lpwLangBuff )
2185 goto end;
2188 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
2189 lpwLangBuff, pcchLangBuf);
2191 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
2192 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
2193 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
2194 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
2195 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
2196 lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
2198 end:
2199 msi_free(szwFilePath);
2200 msi_free(lpwVersionBuff);
2201 msi_free(lpwLangBuff);
2203 return ret;
2206 /******************************************************************
2207 * MsiGetFileVersionW [MSI.@]
2209 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
2210 LPDWORD pcchVersionBuf, LPWSTR lpLangBuf, LPDWORD pcchLangBuf)
2212 static const WCHAR szVersionResource[] = {'\\',0};
2213 static const WCHAR szVersionFormat[] = {
2214 '%','d','.','%','d','.','%','d','.','%','d',0};
2215 static const WCHAR szLangResource[] = {
2216 '\\','V','a','r','F','i','l','e','I','n','f','o','\\',
2217 'T','r','a','n','s','l','a','t','i','o','n',0};
2218 static const WCHAR szLangFormat[] = {'%','d',0};
2219 UINT ret = 0;
2220 DWORD dwVerLen, gle;
2221 LPVOID lpVer = NULL;
2222 VS_FIXEDFILEINFO *ffi;
2223 USHORT *lang;
2224 UINT puLen;
2225 WCHAR tmp[32];
2227 TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath),
2228 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
2229 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
2231 if ((lpVersionBuf && !pcchVersionBuf) ||
2232 (lpLangBuf && !pcchLangBuf))
2233 return ERROR_INVALID_PARAMETER;
2235 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
2236 if( !dwVerLen )
2238 gle = GetLastError();
2239 if (gle == ERROR_BAD_PATHNAME)
2240 return ERROR_FILE_NOT_FOUND;
2241 else if (gle == ERROR_RESOURCE_DATA_NOT_FOUND)
2242 return ERROR_FILE_INVALID;
2244 return gle;
2247 lpVer = msi_alloc(dwVerLen);
2248 if( !lpVer )
2250 ret = ERROR_OUTOFMEMORY;
2251 goto end;
2254 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
2256 ret = GetLastError();
2257 goto end;
2260 if (pcchVersionBuf)
2262 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
2263 (puLen > 0) )
2265 wsprintfW(tmp, szVersionFormat,
2266 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
2267 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
2268 if (lpVersionBuf) lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
2270 if (strlenW(tmp) >= *pcchVersionBuf)
2271 ret = ERROR_MORE_DATA;
2273 *pcchVersionBuf = lstrlenW(tmp);
2275 else
2277 if (lpVersionBuf) *lpVersionBuf = 0;
2278 *pcchVersionBuf = 0;
2282 if (pcchLangBuf)
2284 if (VerQueryValueW(lpVer, szLangResource, (LPVOID*)&lang, &puLen) &&
2285 (puLen > 0))
2287 wsprintfW(tmp, szLangFormat, *lang);
2288 if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
2290 if (strlenW(tmp) >= *pcchLangBuf)
2291 ret = ERROR_MORE_DATA;
2293 *pcchLangBuf = lstrlenW(tmp);
2295 else
2297 if (lpLangBuf) *lpLangBuf = 0;
2298 *pcchLangBuf = 0;
2302 end:
2303 msi_free(lpVer);
2304 return ret;
2307 /***********************************************************************
2308 * MsiGetFeatureUsageW [MSI.@]
2310 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
2311 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2313 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
2314 pdwUseCount, pwDateUsed);
2315 return ERROR_CALL_NOT_IMPLEMENTED;
2318 /***********************************************************************
2319 * MsiGetFeatureUsageA [MSI.@]
2321 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
2322 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2324 LPWSTR prod = NULL, feat = NULL;
2325 UINT ret = ERROR_OUTOFMEMORY;
2327 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
2328 pdwUseCount, pwDateUsed);
2330 prod = strdupAtoW( szProduct );
2331 if (szProduct && !prod)
2332 goto end;
2334 feat = strdupAtoW( szFeature );
2335 if (szFeature && !feat)
2336 goto end;
2338 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
2340 end:
2341 msi_free( prod );
2342 msi_free( feat );
2344 return ret;
2347 /***********************************************************************
2348 * MsiUseFeatureExW [MSI.@]
2350 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
2351 DWORD dwInstallMode, DWORD dwReserved )
2353 INSTALLSTATE state;
2355 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2356 dwInstallMode, dwReserved);
2358 state = MsiQueryFeatureStateW( szProduct, szFeature );
2360 if (dwReserved)
2361 return INSTALLSTATE_INVALIDARG;
2363 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
2365 FIXME("mark product %s feature %s as used\n",
2366 debugstr_w(szProduct), debugstr_w(szFeature) );
2369 return state;
2372 /***********************************************************************
2373 * MsiUseFeatureExA [MSI.@]
2375 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
2376 DWORD dwInstallMode, DWORD dwReserved )
2378 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
2379 LPWSTR prod = NULL, feat = NULL;
2381 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2382 dwInstallMode, dwReserved);
2384 prod = strdupAtoW( szProduct );
2385 if (szProduct && !prod)
2386 goto end;
2388 feat = strdupAtoW( szFeature );
2389 if (szFeature && !feat)
2390 goto end;
2392 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
2394 end:
2395 msi_free( prod );
2396 msi_free( feat );
2398 return ret;
2401 /***********************************************************************
2402 * MsiUseFeatureW [MSI.@]
2404 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
2406 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
2409 /***********************************************************************
2410 * MsiUseFeatureA [MSI.@]
2412 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
2414 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
2417 /***********************************************************************
2418 * MSI_ProvideQualifiedComponentEx [internal]
2420 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
2421 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2422 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
2423 LPDWORD pcchPathBuf)
2425 WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1],
2426 feature[MAX_FEATURE_CHARS+1];
2427 LPWSTR info;
2428 HKEY hkey;
2429 DWORD sz;
2430 UINT rc;
2432 TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent),
2433 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
2434 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2436 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
2437 if (rc != ERROR_SUCCESS)
2438 return ERROR_INDEX_ABSENT;
2440 info = msi_reg_get_val_str( hkey, szQualifier );
2441 RegCloseKey(hkey);
2443 if (!info)
2444 return ERROR_INDEX_ABSENT;
2446 MsiDecomposeDescriptorW(info, product, feature, component, &sz);
2448 if (!szProduct)
2449 rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf);
2450 else
2451 rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
2453 msi_free( info );
2455 if (rc != INSTALLSTATE_LOCAL)
2456 return ERROR_FILE_NOT_FOUND;
2458 return ERROR_SUCCESS;
2461 /***********************************************************************
2462 * MsiProvideQualifiedComponentExW [MSI.@]
2464 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
2465 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2466 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
2467 LPDWORD pcchPathBuf)
2469 awstring path;
2471 path.unicode = TRUE;
2472 path.str.w = lpPathBuf;
2474 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
2475 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
2478 /***********************************************************************
2479 * MsiProvideQualifiedComponentExA [MSI.@]
2481 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
2482 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct,
2483 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
2484 LPDWORD pcchPathBuf)
2486 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
2487 UINT r = ERROR_OUTOFMEMORY;
2488 awstring path;
2490 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
2491 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
2492 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2494 szwComponent = strdupAtoW( szComponent );
2495 if (szComponent && !szwComponent)
2496 goto end;
2498 szwQualifier = strdupAtoW( szQualifier );
2499 if (szQualifier && !szwQualifier)
2500 goto end;
2502 szwProduct = strdupAtoW( szProduct );
2503 if (szProduct && !szwProduct)
2504 goto end;
2506 path.unicode = FALSE;
2507 path.str.a = lpPathBuf;
2509 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
2510 dwInstallMode, szwProduct, Unused1,
2511 Unused2, &path, pcchPathBuf);
2512 end:
2513 msi_free(szwProduct);
2514 msi_free(szwComponent);
2515 msi_free(szwQualifier);
2517 return r;
2520 /***********************************************************************
2521 * MsiProvideQualifiedComponentW [MSI.@]
2523 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
2524 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
2525 LPDWORD pcchPathBuf)
2527 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
2528 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2531 /***********************************************************************
2532 * MsiProvideQualifiedComponentA [MSI.@]
2534 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
2535 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
2536 LPDWORD pcchPathBuf)
2538 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
2539 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2542 /***********************************************************************
2543 * MSI_GetUserInfo [internal]
2545 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
2546 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
2547 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2548 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
2550 WCHAR squished_pc[SQUISH_GUID_SIZE];
2551 LPWSTR user, org, serial;
2552 USERINFOSTATE state;
2553 HKEY hkey, props;
2554 LPCWSTR orgptr;
2555 UINT r;
2557 static const WCHAR szEmpty[] = {0};
2559 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
2560 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
2561 pcchSerialBuf);
2563 if (!szProduct || !squash_guid(szProduct, squished_pc))
2564 return USERINFOSTATE_INVALIDARG;
2566 if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2567 &hkey, FALSE) != ERROR_SUCCESS &&
2568 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2569 &hkey, FALSE) != ERROR_SUCCESS &&
2570 MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2571 &hkey, FALSE) != ERROR_SUCCESS)
2573 return USERINFOSTATE_UNKNOWN;
2576 if (MSIREG_OpenCurrentUserInstallProps(szProduct, &props, FALSE) != ERROR_SUCCESS &&
2577 MSIREG_OpenInstallProps(szProduct, szLocalSid, &props, FALSE) != ERROR_SUCCESS)
2579 RegCloseKey(hkey);
2580 return USERINFOSTATE_ABSENT;
2583 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
2584 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
2585 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
2586 state = USERINFOSTATE_ABSENT;
2588 RegCloseKey(hkey);
2589 RegCloseKey(props);
2591 if (user && serial)
2592 state = USERINFOSTATE_PRESENT;
2594 if (pcchUserNameBuf)
2596 if (lpUserNameBuf && !user)
2598 (*pcchUserNameBuf)--;
2599 goto done;
2602 r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf);
2603 if (r == ERROR_MORE_DATA)
2605 state = USERINFOSTATE_MOREDATA;
2606 goto done;
2610 if (pcchOrgNameBuf)
2612 orgptr = org;
2613 if (!orgptr) orgptr = szEmpty;
2615 r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf);
2616 if (r == ERROR_MORE_DATA)
2618 state = USERINFOSTATE_MOREDATA;
2619 goto done;
2623 if (pcchSerialBuf)
2625 if (!serial)
2627 (*pcchSerialBuf)--;
2628 goto done;
2631 r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf);
2632 if (r == ERROR_MORE_DATA)
2633 state = USERINFOSTATE_MOREDATA;
2636 done:
2637 msi_free(user);
2638 msi_free(org);
2639 msi_free(serial);
2641 return state;
2644 /***********************************************************************
2645 * MsiGetUserInfoW [MSI.@]
2647 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
2648 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2649 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2650 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
2652 awstring user, org, serial;
2654 if ((lpUserNameBuf && !pcchUserNameBuf) ||
2655 (lpOrgNameBuf && !pcchOrgNameBuf) ||
2656 (lpSerialBuf && !pcchSerialBuf))
2657 return USERINFOSTATE_INVALIDARG;
2659 user.unicode = TRUE;
2660 user.str.w = lpUserNameBuf;
2661 org.unicode = TRUE;
2662 org.str.w = lpOrgNameBuf;
2663 serial.unicode = TRUE;
2664 serial.str.w = lpSerialBuf;
2666 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
2667 &org, pcchOrgNameBuf,
2668 &serial, pcchSerialBuf );
2671 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
2672 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2673 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2674 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
2676 awstring user, org, serial;
2677 LPWSTR prod;
2678 UINT r;
2680 if ((lpUserNameBuf && !pcchUserNameBuf) ||
2681 (lpOrgNameBuf && !pcchOrgNameBuf) ||
2682 (lpSerialBuf && !pcchSerialBuf))
2683 return USERINFOSTATE_INVALIDARG;
2685 prod = strdupAtoW( szProduct );
2686 if (szProduct && !prod)
2687 return ERROR_OUTOFMEMORY;
2689 user.unicode = FALSE;
2690 user.str.a = lpUserNameBuf;
2691 org.unicode = FALSE;
2692 org.str.a = lpOrgNameBuf;
2693 serial.unicode = FALSE;
2694 serial.str.a = lpSerialBuf;
2696 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
2697 &org, pcchOrgNameBuf,
2698 &serial, pcchSerialBuf );
2700 msi_free( prod );
2702 return r;
2705 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
2707 MSIHANDLE handle;
2708 UINT rc;
2709 MSIPACKAGE *package;
2710 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
2712 TRACE("(%s)\n",debugstr_w(szProduct));
2714 rc = MsiOpenProductW(szProduct,&handle);
2715 if (rc != ERROR_SUCCESS)
2716 return ERROR_INVALID_PARAMETER;
2718 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
2719 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
2720 msiobj_release( &package->hdr );
2722 MsiCloseHandle(handle);
2724 return rc;
2727 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
2729 MSIHANDLE handle;
2730 UINT rc;
2731 MSIPACKAGE *package;
2732 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
2734 TRACE("(%s)\n",debugstr_a(szProduct));
2736 rc = MsiOpenProductA(szProduct,&handle);
2737 if (rc != ERROR_SUCCESS)
2738 return ERROR_INVALID_PARAMETER;
2740 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
2741 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
2742 msiobj_release( &package->hdr );
2744 MsiCloseHandle(handle);
2746 return rc;
2749 /***********************************************************************
2750 * MsiConfigureFeatureA [MSI.@]
2752 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
2754 LPWSTR prod, feat = NULL;
2755 UINT r = ERROR_OUTOFMEMORY;
2757 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
2759 prod = strdupAtoW( szProduct );
2760 if (szProduct && !prod)
2761 goto end;
2763 feat = strdupAtoW( szFeature );
2764 if (szFeature && !feat)
2765 goto end;
2767 r = MsiConfigureFeatureW(prod, feat, eInstallState);
2769 end:
2770 msi_free(feat);
2771 msi_free(prod);
2773 return r;
2776 /***********************************************************************
2777 * MsiConfigureFeatureW [MSI.@]
2779 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
2781 static const WCHAR szCostInit[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
2782 MSIPACKAGE *package = NULL;
2783 UINT r;
2784 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
2785 DWORD sz;
2787 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
2789 if (!szProduct || !szFeature)
2790 return ERROR_INVALID_PARAMETER;
2792 switch (eInstallState)
2794 case INSTALLSTATE_DEFAULT:
2795 /* FIXME: how do we figure out the default location? */
2796 eInstallState = INSTALLSTATE_LOCAL;
2797 break;
2798 case INSTALLSTATE_LOCAL:
2799 case INSTALLSTATE_SOURCE:
2800 case INSTALLSTATE_ABSENT:
2801 case INSTALLSTATE_ADVERTISED:
2802 break;
2803 default:
2804 return ERROR_INVALID_PARAMETER;
2807 r = MSI_OpenProductW( szProduct, &package );
2808 if (r != ERROR_SUCCESS)
2809 return r;
2811 sz = sizeof(sourcepath);
2812 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2813 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
2815 sz = sizeof(filename);
2816 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2817 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
2819 lstrcatW( sourcepath, filename );
2821 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
2823 r = ACTION_PerformUIAction( package, szCostInit, -1 );
2824 if (r != ERROR_SUCCESS)
2825 goto end;
2827 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
2828 if (r != ERROR_SUCCESS)
2829 goto end;
2831 r = MSI_InstallPackage( package, sourcepath, NULL );
2833 end:
2834 msiobj_release( &package->hdr );
2836 return r;
2839 /***********************************************************************
2840 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
2842 * Notes: undocumented
2844 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
2846 WCHAR path[MAX_PATH];
2848 TRACE("%d\n", dwReserved);
2850 if (dwReserved)
2852 FIXME("dwReserved=%d\n", dwReserved);
2853 return ERROR_INVALID_PARAMETER;
2856 if (!GetWindowsDirectoryW(path, MAX_PATH))
2857 return ERROR_FUNCTION_FAILED;
2859 lstrcatW(path, installerW);
2861 if (!CreateDirectoryW(path, NULL))
2862 return ERROR_FUNCTION_FAILED;
2864 return ERROR_SUCCESS;
2867 /***********************************************************************
2868 * MsiGetShortcutTargetA [MSI.@]
2870 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
2871 LPSTR szProductCode, LPSTR szFeatureId,
2872 LPSTR szComponentCode )
2874 LPWSTR target;
2875 const int len = MAX_FEATURE_CHARS+1;
2876 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
2877 UINT r;
2879 target = strdupAtoW( szShortcutTarget );
2880 if (szShortcutTarget && !target )
2881 return ERROR_OUTOFMEMORY;
2882 product[0] = 0;
2883 feature[0] = 0;
2884 component[0] = 0;
2885 r = MsiGetShortcutTargetW( target, product, feature, component );
2886 msi_free( target );
2887 if (r == ERROR_SUCCESS)
2889 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
2890 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
2891 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
2893 return r;
2896 /***********************************************************************
2897 * MsiGetShortcutTargetW [MSI.@]
2899 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
2900 LPWSTR szProductCode, LPWSTR szFeatureId,
2901 LPWSTR szComponentCode )
2903 IShellLinkDataList *dl = NULL;
2904 IPersistFile *pf = NULL;
2905 LPEXP_DARWIN_LINK darwin = NULL;
2906 HRESULT r, init;
2908 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
2909 szProductCode, szFeatureId, szComponentCode );
2911 init = CoInitialize(NULL);
2913 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
2914 &IID_IPersistFile, (LPVOID*) &pf );
2915 if( SUCCEEDED( r ) )
2917 r = IPersistFile_Load( pf, szShortcutTarget,
2918 STGM_READ | STGM_SHARE_DENY_WRITE );
2919 if( SUCCEEDED( r ) )
2921 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
2922 (LPVOID*) &dl );
2923 if( SUCCEEDED( r ) )
2925 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
2926 (LPVOID) &darwin );
2927 IShellLinkDataList_Release( dl );
2930 IPersistFile_Release( pf );
2933 if (SUCCEEDED(init))
2934 CoUninitialize();
2936 TRACE("darwin = %p\n", darwin);
2938 if (darwin)
2940 DWORD sz;
2941 UINT ret;
2943 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
2944 szProductCode, szFeatureId, szComponentCode, &sz );
2945 LocalFree( darwin );
2946 return ret;
2949 return ERROR_FUNCTION_FAILED;
2952 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
2953 DWORD dwReinstallMode )
2955 MSIPACKAGE* package = NULL;
2956 UINT r;
2957 WCHAR sourcepath[MAX_PATH];
2958 WCHAR filename[MAX_PATH];
2959 static const WCHAR szLogVerbose[] = {
2960 ' ','L','O','G','V','E','R','B','O','S','E',0 };
2961 static const WCHAR szInstalled[] = { 'I','n','s','t','a','l','l','e','d',0};
2962 static const WCHAR szReinstall[] = {'R','E','I','N','S','T','A','L','L',0};
2963 static const WCHAR szReinstallMode[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
2964 static const WCHAR szOne[] = {'1',0};
2965 WCHAR reinstallmode[11];
2966 LPWSTR ptr;
2967 DWORD sz;
2969 FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2970 dwReinstallMode);
2972 ptr = reinstallmode;
2974 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
2975 *ptr++ = 'p';
2976 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
2977 *ptr++ = 'o';
2978 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
2979 *ptr++ = 'w';
2980 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
2981 *ptr++ = 'd';
2982 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
2983 *ptr++ = 'c';
2984 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
2985 *ptr++ = 'a';
2986 if (dwReinstallMode & REINSTALLMODE_USERDATA)
2987 *ptr++ = 'u';
2988 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
2989 *ptr++ = 'm';
2990 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
2991 *ptr++ = 's';
2992 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
2993 *ptr++ = 'v';
2994 *ptr = 0;
2996 sz = sizeof(sourcepath);
2997 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2998 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3000 sz = sizeof(filename);
3001 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3002 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3004 lstrcatW( sourcepath, filename );
3006 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
3007 r = MSI_OpenPackageW( sourcepath, &package );
3008 else
3009 r = MSI_OpenProductW( szProduct, &package );
3011 if (r != ERROR_SUCCESS)
3012 return r;
3014 MSI_SetPropertyW( package, szReinstallMode, reinstallmode );
3015 MSI_SetPropertyW( package, szInstalled, szOne );
3016 MSI_SetPropertyW( package, szLogVerbose, szOne );
3017 MSI_SetPropertyW( package, szReinstall, szFeature );
3019 r = MSI_InstallPackage( package, sourcepath, NULL );
3021 msiobj_release( &package->hdr );
3023 return r;
3026 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
3027 DWORD dwReinstallMode )
3029 LPWSTR wszProduct;
3030 LPWSTR wszFeature;
3031 UINT rc;
3033 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
3034 dwReinstallMode);
3036 wszProduct = strdupAtoW(szProduct);
3037 wszFeature = strdupAtoW(szFeature);
3039 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
3041 msi_free(wszProduct);
3042 msi_free(wszFeature);
3043 return rc;
3046 typedef struct
3048 unsigned int i[2];
3049 unsigned int buf[4];
3050 unsigned char in[64];
3051 unsigned char digest[16];
3052 } MD5_CTX;
3054 extern VOID WINAPI MD5Init( MD5_CTX *);
3055 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
3056 extern VOID WINAPI MD5Final( MD5_CTX *);
3058 /***********************************************************************
3059 * MsiGetFileHashW [MSI.@]
3061 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
3062 PMSIFILEHASHINFO pHash )
3064 HANDLE handle, mapping;
3065 void *p;
3066 DWORD length;
3067 UINT r = ERROR_FUNCTION_FAILED;
3069 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
3071 if (!szFilePath)
3072 return ERROR_INVALID_PARAMETER;
3074 if (!*szFilePath)
3075 return ERROR_PATH_NOT_FOUND;
3077 if (dwOptions)
3078 return ERROR_INVALID_PARAMETER;
3079 if (!pHash)
3080 return ERROR_INVALID_PARAMETER;
3081 if (pHash->dwFileHashInfoSize < sizeof *pHash)
3082 return ERROR_INVALID_PARAMETER;
3084 handle = CreateFileW( szFilePath, GENERIC_READ,
3085 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
3086 if (handle == INVALID_HANDLE_VALUE)
3087 return ERROR_FILE_NOT_FOUND;
3089 length = GetFileSize( handle, NULL );
3091 mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
3092 if (mapping)
3094 p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
3095 if (p)
3097 MD5_CTX ctx;
3099 MD5Init( &ctx );
3100 MD5Update( &ctx, p, length );
3101 MD5Final( &ctx );
3102 UnmapViewOfFile( p );
3104 memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData );
3105 r = ERROR_SUCCESS;
3107 CloseHandle( mapping );
3109 CloseHandle( handle );
3111 return r;
3114 /***********************************************************************
3115 * MsiGetFileHashA [MSI.@]
3117 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
3118 PMSIFILEHASHINFO pHash )
3120 LPWSTR file;
3121 UINT r;
3123 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
3125 file = strdupAtoW( szFilePath );
3126 if (szFilePath && !file)
3127 return ERROR_OUTOFMEMORY;
3129 r = MsiGetFileHashW( file, dwOptions, pHash );
3130 msi_free( file );
3131 return r;
3134 /***********************************************************************
3135 * MsiAdvertiseScriptW [MSI.@]
3137 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
3138 PHKEY phRegData, BOOL fRemoveItems )
3140 FIXME("%s %08x %p %d\n",
3141 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3142 return ERROR_CALL_NOT_IMPLEMENTED;
3145 /***********************************************************************
3146 * MsiAdvertiseScriptA [MSI.@]
3148 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
3149 PHKEY phRegData, BOOL fRemoveItems )
3151 FIXME("%s %08x %p %d\n",
3152 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3153 return ERROR_CALL_NOT_IMPLEMENTED;
3156 /***********************************************************************
3157 * MsiIsProductElevatedW [MSI.@]
3159 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
3161 FIXME("%s %p - stub\n",
3162 debugstr_w( szProduct ), pfElevated );
3163 *pfElevated = TRUE;
3164 return ERROR_SUCCESS;
3167 /***********************************************************************
3168 * MsiIsProductElevatedA [MSI.@]
3170 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
3172 FIXME("%s %p - stub\n",
3173 debugstr_a( szProduct ), pfElevated );
3174 *pfElevated = TRUE;
3175 return ERROR_SUCCESS;
3178 /***********************************************************************
3179 * MsiSetExternalUIRecord [MSI.@]
3181 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD puiHandler,
3182 DWORD dwMessageFilter, LPVOID pvContext,
3183 PINSTALLUI_HANDLER_RECORD ppuiPrevHandler)
3185 FIXME("%p %08x %p %p\n", puiHandler, dwMessageFilter ,pvContext,
3186 ppuiPrevHandler);
3187 return ERROR_CALL_NOT_IMPLEMENTED;
3190 /***********************************************************************
3191 * MsiInstallMissingComponentW [MSI.@]
3193 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState)
3195 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
3196 return ERROR_SUCCESS;