push 52cba0a224aad01bcbdb26d79e43229ba950650e
[wine/hacks.git] / dlls / msi / msi.c
blobbe1ad93bf9ff15ff8a489716762ec57aceb86413
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, NULL, MSIINSTALLCONTEXT_USERMANAGED,
55 &hkey, FALSE) == ERROR_SUCCESS)
56 *context = MSIINSTALLCONTEXT_USERMANAGED;
57 else if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
58 &hkey, FALSE) == ERROR_SUCCESS)
59 *context = MSIINSTALLCONTEXT_MACHINE;
60 else if (MSIREG_OpenProductKey(szProduct, NULL,
61 MSIINSTALLCONTEXT_USERUNMANAGED,
62 &hkey, FALSE) == ERROR_SUCCESS)
63 *context = MSIINSTALLCONTEXT_USERUNMANAGED;
65 RegCloseKey(hkey);
67 if (*context == MSIINSTALLCONTEXT_NONE)
68 return ERROR_UNKNOWN_PRODUCT;
70 return ERROR_SUCCESS;
73 UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
75 UINT r;
76 LPWSTR szwProd = NULL;
78 TRACE("%s %p\n",debugstr_a(szProduct), phProduct);
80 if( szProduct )
82 szwProd = strdupAtoW( szProduct );
83 if( !szwProd )
84 return ERROR_OUTOFMEMORY;
87 r = MsiOpenProductW( szwProd, phProduct );
89 msi_free( szwProd );
91 return r;
94 static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package)
96 UINT r;
97 HKEY props;
98 LPWSTR path;
99 MSIINSTALLCONTEXT context;
101 static const WCHAR managed[] = {
102 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
103 static const WCHAR local[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
105 TRACE("%s %p\n", debugstr_w(szProduct), package);
107 r = msi_locate_product(szProduct, &context);
108 if (r != ERROR_SUCCESS)
109 return r;
111 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &props, FALSE);
112 if (r != ERROR_SUCCESS)
113 return ERROR_UNKNOWN_PRODUCT;
115 if (context == MSIINSTALLCONTEXT_USERMANAGED)
116 path = msi_reg_get_val_str(props, managed);
117 else
118 path = msi_reg_get_val_str(props, local);
120 r = ERROR_UNKNOWN_PRODUCT;
122 if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
123 goto done;
125 if (PathIsRelativeW(path))
127 r = ERROR_INSTALL_PACKAGE_OPEN_FAILED;
128 goto done;
131 r = MSI_OpenPackageW(path, package);
133 done:
134 RegCloseKey(props);
135 msi_free(path);
136 return r;
139 UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct)
141 MSIPACKAGE *package = NULL;
142 WCHAR squished_pc[GUID_SIZE];
143 UINT r;
145 if (!szProduct || !squash_guid(szProduct, squished_pc))
146 return ERROR_INVALID_PARAMETER;
148 if (!phProduct)
149 return ERROR_INVALID_PARAMETER;
151 r = MSI_OpenProductW(szProduct, &package);
152 if (r != ERROR_SUCCESS)
153 return r;
155 *phProduct = alloc_msihandle(&package->hdr);
156 if (!*phProduct)
157 r = ERROR_NOT_ENOUGH_MEMORY;
159 msiobj_release(&package->hdr);
160 return r;
163 UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
164 LPCSTR szTransforms, LANGID lgidLanguage)
166 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath),
167 debugstr_a(szScriptfilePath), debugstr_a(szTransforms), lgidLanguage);
168 return ERROR_CALL_NOT_IMPLEMENTED;
171 UINT WINAPI MsiAdvertiseProductW(LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
172 LPCWSTR szTransforms, LANGID lgidLanguage)
174 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath),
175 debugstr_w(szScriptfilePath), debugstr_w(szTransforms), lgidLanguage);
176 return ERROR_CALL_NOT_IMPLEMENTED;
179 UINT WINAPI MsiAdvertiseProductExA(LPCSTR szPackagePath, LPCSTR szScriptfilePath,
180 LPCSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
182 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath),
183 debugstr_a(szScriptfilePath), debugstr_a(szTransforms),
184 lgidLanguage, dwPlatform, dwOptions);
185 return ERROR_CALL_NOT_IMPLEMENTED;
188 UINT WINAPI MsiAdvertiseProductExW( LPCWSTR szPackagePath, LPCWSTR szScriptfilePath,
189 LPCWSTR szTransforms, LANGID lgidLanguage, DWORD dwPlatform, DWORD dwOptions)
191 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath),
192 debugstr_w(szScriptfilePath), debugstr_w(szTransforms),
193 lgidLanguage, dwPlatform, dwOptions);
194 return ERROR_CALL_NOT_IMPLEMENTED;
197 UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
199 LPWSTR szwPath = NULL, szwCommand = NULL;
200 UINT r = ERROR_OUTOFMEMORY;
202 TRACE("%s %s\n",debugstr_a(szPackagePath), debugstr_a(szCommandLine));
204 if( szPackagePath )
206 szwPath = strdupAtoW( szPackagePath );
207 if( !szwPath )
208 goto end;
211 if( szCommandLine )
213 szwCommand = strdupAtoW( szCommandLine );
214 if( !szwCommand )
215 goto end;
218 r = MsiInstallProductW( szwPath, szwCommand );
220 end:
221 msi_free( szwPath );
222 msi_free( szwCommand );
224 return r;
227 UINT WINAPI MsiInstallProductW(LPCWSTR szPackagePath, LPCWSTR szCommandLine)
229 MSIPACKAGE *package = NULL;
230 UINT r;
232 TRACE("%s %s\n",debugstr_w(szPackagePath), debugstr_w(szCommandLine));
234 if (!szPackagePath)
235 return ERROR_INVALID_PARAMETER;
237 if (!*szPackagePath)
238 return ERROR_PATH_NOT_FOUND;
240 r = MSI_OpenPackageW( szPackagePath, &package );
241 if (r == ERROR_SUCCESS)
243 r = MSI_InstallPackage( package, szPackagePath, szCommandLine );
244 msiobj_release( &package->hdr );
247 return r;
250 UINT WINAPI MsiReinstallProductA(LPCSTR szProduct, DWORD dwReinstallMode)
252 LPWSTR wszProduct;
253 UINT rc;
255 TRACE("%s %08x\n", debugstr_a(szProduct), dwReinstallMode);
257 wszProduct = strdupAtoW(szProduct);
259 rc = MsiReinstallProductW(wszProduct, dwReinstallMode);
261 msi_free(wszProduct);
262 return rc;
265 UINT WINAPI MsiReinstallProductW(LPCWSTR szProduct, DWORD dwReinstallMode)
267 static const WCHAR szAll[] = {'A','L','L',0};
269 TRACE("%s %08x\n", debugstr_w(szProduct), dwReinstallMode);
271 return MsiReinstallFeatureW(szProduct, szAll, dwReinstallMode);
274 UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage,
275 INSTALLTYPE eInstallType, LPCSTR szCommandLine)
277 LPWSTR patch_package = NULL;
278 LPWSTR install_package = NULL;
279 LPWSTR command_line = NULL;
280 UINT r = ERROR_OUTOFMEMORY;
282 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage), debugstr_a(szInstallPackage),
283 eInstallType, debugstr_a(szCommandLine));
285 if (szPatchPackage && !(patch_package = strdupAtoW(szPatchPackage)))
286 goto done;
288 if (szInstallPackage && !(install_package = strdupAtoW(szInstallPackage)))
289 goto done;
291 if (szCommandLine && !(command_line = strdupAtoW(szCommandLine)))
292 goto done;
294 r = MsiApplyPatchW(patch_package, install_package, eInstallType, command_line);
296 done:
297 msi_free(patch_package);
298 msi_free(install_package);
299 msi_free(command_line);
301 return r;
304 static UINT MSI_ApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szProductCode, LPCWSTR szCommandLine)
306 MSIHANDLE patch = 0, info = 0;
307 UINT r = ERROR_SUCCESS, type;
308 DWORD size = 0;
309 LPCWSTR cmd_ptr = szCommandLine;
310 LPCWSTR product_code = szProductCode;
311 LPWSTR beg, end;
312 LPWSTR cmd = NULL, codes = NULL;
314 static const WCHAR space[] = {' ',0};
315 static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
316 static WCHAR empty[] = {0};
318 if (!szPatchPackage || !szPatchPackage[0])
319 return ERROR_INVALID_PARAMETER;
321 if (!szProductCode)
323 r = MsiOpenDatabaseW(szPatchPackage, MSIDBOPEN_READONLY, &patch);
324 if (r != ERROR_SUCCESS)
325 return r;
327 r = MsiGetSummaryInformationW(patch, NULL, 0, &info);
328 if (r != ERROR_SUCCESS)
329 goto done;
331 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, empty, &size);
332 if (r != ERROR_MORE_DATA || !size || type != VT_LPSTR)
334 ERR("Failed to read product codes from patch\n");
335 goto done;
338 codes = msi_alloc(++size * sizeof(WCHAR));
339 if (!codes)
341 r = ERROR_OUTOFMEMORY;
342 goto done;
345 r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
346 if (r != ERROR_SUCCESS)
347 goto done;
349 product_code = codes;
352 if (!szCommandLine)
353 cmd_ptr = empty;
355 size = lstrlenW(cmd_ptr) + lstrlenW(patcheq) + lstrlenW(szPatchPackage) + 1;
356 cmd = msi_alloc(size * sizeof(WCHAR));
357 if (!cmd)
359 r = ERROR_OUTOFMEMORY;
360 goto done;
363 lstrcpyW(cmd, cmd_ptr);
364 if (szCommandLine) lstrcatW(cmd, space);
365 lstrcatW(cmd, patcheq);
366 lstrcatW(cmd, szPatchPackage);
368 beg = codes;
369 while ((end = strchrW(beg, '}')))
371 *(end + 1) = '\0';
373 r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
374 if (r != ERROR_SUCCESS)
375 goto done;
377 beg = end + 2;
380 done:
381 msi_free(cmd);
382 msi_free(codes);
384 MsiCloseHandle(info);
385 MsiCloseHandle(patch);
387 return r;
390 UINT WINAPI MsiApplyPatchW(LPCWSTR szPatchPackage, LPCWSTR szInstallPackage,
391 INSTALLTYPE eInstallType, LPCWSTR szCommandLine)
393 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage), debugstr_w(szInstallPackage),
394 eInstallType, debugstr_w(szCommandLine));
396 if (szInstallPackage || eInstallType == INSTALLTYPE_NETWORK_IMAGE ||
397 eInstallType == INSTALLTYPE_SINGLE_INSTANCE)
399 FIXME("Only reading target products from patch\n");
400 return ERROR_CALL_NOT_IMPLEMENTED;
403 return MSI_ApplyPatchW(szPatchPackage, NULL, szCommandLine);
406 UINT WINAPI MsiApplyMultiplePatchesA(LPCSTR szPatchPackages,
407 LPCSTR szProductCode, LPCSTR szPropertiesList)
409 LPWSTR patch_packages = NULL;
410 LPWSTR product_code = NULL;
411 LPWSTR properties_list = NULL;
412 UINT r = ERROR_OUTOFMEMORY;
414 TRACE("%s %s %s\n", debugstr_a(szPatchPackages), debugstr_a(szProductCode),
415 debugstr_a(szPropertiesList));
417 if (!szPatchPackages || !szPatchPackages[0])
418 return ERROR_INVALID_PARAMETER;
420 if (!(patch_packages = strdupAtoW(szPatchPackages)))
421 return ERROR_OUTOFMEMORY;
423 if (szProductCode && !(product_code = strdupAtoW(szProductCode)))
424 goto done;
426 if (szPropertiesList && !(properties_list = strdupAtoW(szPropertiesList)))
427 goto done;
429 r = MsiApplyMultiplePatchesW(patch_packages, product_code, properties_list);
431 done:
432 msi_free(patch_packages);
433 msi_free(product_code);
434 msi_free(properties_list);
436 return r;
439 UINT WINAPI MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages,
440 LPCWSTR szProductCode, LPCWSTR szPropertiesList)
442 UINT r = ERROR_SUCCESS;
443 LPCWSTR beg, end;
445 TRACE("%s %s %s\n", debugstr_w(szPatchPackages), debugstr_w(szProductCode),
446 debugstr_w(szPropertiesList));
448 if (!szPatchPackages || !szPatchPackages[0])
449 return ERROR_INVALID_PARAMETER;
451 beg = end = szPatchPackages;
452 while (*beg)
454 DWORD len;
455 LPWSTR patch;
457 while (*beg == ' ') beg++;
458 while (*end && *end != ';') end++;
460 len = end - beg;
461 while (len && beg[len - 1] == ' ') len--;
463 if (!len) return ERROR_INVALID_NAME;
465 patch = msi_alloc((len + 1) * sizeof(WCHAR));
466 if (!patch)
467 return ERROR_OUTOFMEMORY;
469 memcpy(patch, beg, len * sizeof(WCHAR));
470 patch[len] = '\0';
472 r = MSI_ApplyPatchW(patch, szProductCode, szPropertiesList);
473 msi_free(patch);
475 if (r != ERROR_SUCCESS)
476 break;
478 beg = ++end;
480 return r;
483 UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
484 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
486 FIXME("(%s, %d, %p): stub!\n", debugstr_a(szProductPackagePath),
487 cPatchInfo, pPatchInfo);
489 return ERROR_CALL_NOT_IMPLEMENTED;
492 UINT WINAPI MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath,
493 DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
495 FIXME("(%s, %d, %p): stub!\n", debugstr_w(szProductPackagePath),
496 cPatchInfo, pPatchInfo);
498 return ERROR_CALL_NOT_IMPLEMENTED;
501 UINT WINAPI MsiDeterminePatchSequenceA(LPCSTR szProductCode, LPCSTR szUserSid,
502 MSIINSTALLCONTEXT dwContext, DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
504 FIXME("(%s, %s, %d, %d, %p): stub!\n", debugstr_a(szProductCode),
505 debugstr_a(szUserSid), dwContext, cPatchInfo, pPatchInfo);
507 return ERROR_CALL_NOT_IMPLEMENTED;
510 UINT WINAPI MsiDeterminePatchSequenceW(LPCWSTR szProductCode, LPCWSTR szUserSid,
511 MSIINSTALLCONTEXT dwContext, DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOW pPatchInfo)
513 FIXME("(%s, %s, %d, %d, %p): stub!\n", debugstr_w(szProductCode),
514 debugstr_w(szUserSid), dwContext, cPatchInfo, pPatchInfo);
516 return ERROR_CALL_NOT_IMPLEMENTED;
519 static UINT msi_open_package(LPCWSTR product, MSIINSTALLCONTEXT context,
520 MSIPACKAGE **package)
522 UINT r;
523 DWORD sz;
524 HKEY props;
525 LPWSTR localpack;
526 WCHAR sourcepath[MAX_PATH];
527 WCHAR filename[MAX_PATH];
529 static const WCHAR szLocalPackage[] = {
530 'L','o','c','a','l','P','a','c','k','a','g','e',0};
533 r = MSIREG_OpenInstallProps(product, context, NULL, &props, FALSE);
534 if (r != ERROR_SUCCESS)
535 return ERROR_BAD_CONFIGURATION;
537 localpack = msi_reg_get_val_str(props, szLocalPackage);
538 if (localpack)
540 lstrcpyW(sourcepath, localpack);
541 msi_free(localpack);
544 if (!localpack || GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
546 sz = sizeof(sourcepath);
547 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
548 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
550 sz = sizeof(filename);
551 MsiSourceListGetInfoW(product, NULL, context, MSICODE_PRODUCT,
552 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
554 lstrcatW(sourcepath, filename);
557 if (GetFileAttributesW(sourcepath) == INVALID_FILE_ATTRIBUTES)
558 return ERROR_INSTALL_SOURCE_ABSENT;
560 return MSI_OpenPackageW(sourcepath, package);
563 UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel,
564 INSTALLSTATE eInstallState, LPCWSTR szCommandLine)
566 MSIPACKAGE* package = NULL;
567 MSIINSTALLCONTEXT context;
568 UINT r;
569 DWORD sz;
570 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
571 LPWSTR commandline;
573 static const WCHAR szInstalled[] = {
574 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
575 static const WCHAR szRemoveAll[] = {
576 ' ','R','E','M','O','V','E','=','A','L','L',0};
577 static const WCHAR szMachine[] = {
578 ' ','A','L','L','U','S','E','R','S','=','1',0};
580 TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState,
581 debugstr_w(szCommandLine));
583 if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1)
584 return ERROR_INVALID_PARAMETER;
586 if (eInstallState == INSTALLSTATE_ADVERTISED ||
587 eInstallState == INSTALLSTATE_SOURCE)
589 FIXME("State %d not implemented\n", eInstallState);
590 return ERROR_CALL_NOT_IMPLEMENTED;
593 r = msi_locate_product(szProduct, &context);
594 if (r != ERROR_SUCCESS)
595 return r;
597 r = msi_open_package(szProduct, context, &package);
598 if (r != ERROR_SUCCESS)
599 return r;
601 sz = lstrlenW(szInstalled) + 1;
603 if (szCommandLine)
604 sz += lstrlenW(szCommandLine);
606 if (eInstallState == INSTALLSTATE_ABSENT)
607 sz += lstrlenW(szRemoveAll);
609 if (context == MSIINSTALLCONTEXT_MACHINE)
610 sz += lstrlenW(szMachine);
612 commandline = msi_alloc(sz * sizeof(WCHAR));
613 if (!commandline)
615 r = ERROR_OUTOFMEMORY;
616 goto end;
619 commandline[0] = 0;
620 if (szCommandLine)
621 lstrcpyW(commandline,szCommandLine);
623 if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN)
624 lstrcatW(commandline,szInstalled);
626 if (eInstallState == INSTALLSTATE_ABSENT)
627 lstrcatW(commandline, szRemoveAll);
629 if (context == MSIINSTALLCONTEXT_MACHINE)
630 lstrcatW(commandline, szMachine);
632 sz = sizeof(sourcepath);
633 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
634 INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
636 sz = sizeof(filename);
637 MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT,
638 INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
640 strcatW(sourcepath, filename);
642 r = MSI_InstallPackage( package, sourcepath, commandline );
644 msi_free(commandline);
646 end:
647 msiobj_release( &package->hdr );
649 return r;
652 UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel,
653 INSTALLSTATE eInstallState, LPCSTR szCommandLine)
655 LPWSTR szwProduct = NULL;
656 LPWSTR szwCommandLine = NULL;
657 UINT r = ERROR_OUTOFMEMORY;
659 if( szProduct )
661 szwProduct = strdupAtoW( szProduct );
662 if( !szwProduct )
663 goto end;
666 if( szCommandLine)
668 szwCommandLine = strdupAtoW( szCommandLine );
669 if( !szwCommandLine)
670 goto end;
673 r = MsiConfigureProductExW( szwProduct, iInstallLevel, eInstallState,
674 szwCommandLine );
675 end:
676 msi_free( szwProduct );
677 msi_free( szwCommandLine);
679 return r;
682 UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel,
683 INSTALLSTATE eInstallState)
685 LPWSTR szwProduct = NULL;
686 UINT r;
688 TRACE("%s %d %d\n",debugstr_a(szProduct), iInstallLevel, eInstallState);
690 if( szProduct )
692 szwProduct = strdupAtoW( szProduct );
693 if( !szwProduct )
694 return ERROR_OUTOFMEMORY;
697 r = MsiConfigureProductW( szwProduct, iInstallLevel, eInstallState );
698 msi_free( szwProduct );
700 return r;
703 UINT WINAPI MsiConfigureProductW(LPCWSTR szProduct, int iInstallLevel,
704 INSTALLSTATE eInstallState)
706 return MsiConfigureProductExW(szProduct, iInstallLevel, eInstallState, NULL);
709 UINT WINAPI MsiGetProductCodeA(LPCSTR szComponent, LPSTR szBuffer)
711 LPWSTR szwComponent = NULL;
712 UINT r;
713 WCHAR szwBuffer[GUID_SIZE];
715 TRACE("%s %s\n",debugstr_a(szComponent), debugstr_a(szBuffer));
717 if( szComponent )
719 szwComponent = strdupAtoW( szComponent );
720 if( !szwComponent )
721 return ERROR_OUTOFMEMORY;
724 *szwBuffer = '\0';
725 r = MsiGetProductCodeW( szwComponent, szwBuffer );
727 if(*szwBuffer)
728 WideCharToMultiByte(CP_ACP, 0, szwBuffer, -1, szBuffer, GUID_SIZE, NULL, NULL);
730 msi_free( szwComponent );
732 return r;
735 UINT WINAPI MsiGetProductCodeW(LPCWSTR szComponent, LPWSTR szBuffer)
737 UINT rc, index;
738 HKEY compkey, prodkey;
739 WCHAR squished_comp[GUID_SIZE];
740 WCHAR squished_prod[GUID_SIZE];
741 DWORD sz = GUID_SIZE;
743 TRACE("%s %p\n", debugstr_w(szComponent), szBuffer);
745 if (!szComponent || !*szComponent)
746 return ERROR_INVALID_PARAMETER;
748 if (!squash_guid(szComponent, squished_comp))
749 return ERROR_INVALID_PARAMETER;
751 if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &compkey, FALSE) != ERROR_SUCCESS &&
752 MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &compkey, FALSE) != ERROR_SUCCESS)
754 return ERROR_UNKNOWN_COMPONENT;
757 rc = RegEnumValueW(compkey, 0, squished_prod, &sz, NULL, NULL, NULL, NULL);
758 if (rc != ERROR_SUCCESS)
760 RegCloseKey(compkey);
761 return ERROR_UNKNOWN_COMPONENT;
764 /* check simple case, only one product */
765 rc = RegEnumValueW(compkey, 1, squished_prod, &sz, NULL, NULL, NULL, NULL);
766 if (rc == ERROR_NO_MORE_ITEMS)
768 rc = ERROR_SUCCESS;
769 goto done;
772 index = 0;
773 while ((rc = RegEnumValueW(compkey, index, squished_prod, &sz,
774 NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS)
776 index++;
777 sz = GUID_SIZE;
778 unsquash_guid(squished_prod, szBuffer);
780 if (MSIREG_OpenProductKey(szBuffer, NULL,
781 MSIINSTALLCONTEXT_USERMANAGED,
782 &prodkey, FALSE) == ERROR_SUCCESS ||
783 MSIREG_OpenProductKey(szBuffer, NULL,
784 MSIINSTALLCONTEXT_USERUNMANAGED,
785 &prodkey, FALSE) == ERROR_SUCCESS ||
786 MSIREG_OpenProductKey(szBuffer, NULL,
787 MSIINSTALLCONTEXT_MACHINE,
788 &prodkey, FALSE) == ERROR_SUCCESS)
790 RegCloseKey(prodkey);
791 rc = ERROR_SUCCESS;
792 goto done;
796 rc = ERROR_INSTALL_FAILURE;
798 done:
799 RegCloseKey(compkey);
800 unsquash_guid(squished_prod, szBuffer);
801 return rc;
804 static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
806 DWORD dval;
807 LONG res;
808 WCHAR temp[20];
810 static const WCHAR format[] = {'%','d',0};
812 res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL);
813 if (res != ERROR_SUCCESS)
814 return NULL;
816 if (*type == REG_SZ)
817 return msi_reg_get_val_str(hkey, name);
819 if (!msi_reg_get_val_dword(hkey, name, &dval))
820 return NULL;
822 sprintfW(temp, format, dval);
823 return strdupW(temp);
826 static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
827 awstring *szValue, LPDWORD pcchValueBuf)
829 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
830 UINT r = ERROR_UNKNOWN_PROPERTY;
831 HKEY prodkey, userdata, source;
832 LPWSTR val = NULL;
833 WCHAR squished_pc[GUID_SIZE];
834 WCHAR packagecode[GUID_SIZE];
835 BOOL badconfig = FALSE;
836 LONG res;
837 DWORD save, type = REG_NONE;
839 static WCHAR empty[] = {0};
840 static const WCHAR sourcelist[] = {
841 'S','o','u','r','c','e','L','i','s','t',0};
842 static const WCHAR display_name[] = {
843 'D','i','s','p','l','a','y','N','a','m','e',0};
844 static const WCHAR display_version[] = {
845 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
846 static const WCHAR assignment[] = {
847 'A','s','s','i','g','n','m','e','n','t',0};
849 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
850 debugstr_w(szAttribute), szValue, pcchValueBuf);
852 if ((szValue->str.w && !pcchValueBuf) || !szProduct || !szAttribute)
853 return ERROR_INVALID_PARAMETER;
855 if (!squash_guid(szProduct, squished_pc))
856 return ERROR_INVALID_PARAMETER;
858 if ((r = MSIREG_OpenProductKey(szProduct, NULL,
859 MSIINSTALLCONTEXT_USERMANAGED,
860 &prodkey, FALSE)) != ERROR_SUCCESS &&
861 (r = MSIREG_OpenProductKey(szProduct, NULL,
862 MSIINSTALLCONTEXT_USERUNMANAGED,
863 &prodkey, FALSE)) != ERROR_SUCCESS &&
864 (r = MSIREG_OpenProductKey(szProduct, NULL,
865 MSIINSTALLCONTEXT_MACHINE,
866 &prodkey, FALSE)) == ERROR_SUCCESS)
868 context = MSIINSTALLCONTEXT_MACHINE;
871 MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
873 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) ||
874 !lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) ||
875 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLDATEW) ||
876 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
877 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLLOCATIONW) ||
878 !lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLSOURCEW) ||
879 !lstrcmpW(szAttribute, INSTALLPROPERTY_LOCALPACKAGEW) ||
880 !lstrcmpW(szAttribute, INSTALLPROPERTY_PUBLISHERW) ||
881 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLINFOABOUTW) ||
882 !lstrcmpW(szAttribute, INSTALLPROPERTY_URLUPDATEINFOW) ||
883 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMINORW) ||
884 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONMAJORW) ||
885 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW) ||
886 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTIDW) ||
887 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGCOMPANYW) ||
888 !lstrcmpW(szAttribute, INSTALLPROPERTY_REGOWNERW))
890 if (!prodkey)
892 r = ERROR_UNKNOWN_PRODUCT;
893 goto done;
896 if (!userdata)
897 return ERROR_UNKNOWN_PROPERTY;
899 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
900 szAttribute = display_name;
901 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONSTRINGW))
902 szAttribute = display_version;
904 val = msi_reg_get_value(userdata, szAttribute, &type);
905 if (!val)
906 val = empty;
908 else if (!lstrcmpW(szAttribute, INSTALLPROPERTY_INSTANCETYPEW) ||
909 !lstrcmpW(szAttribute, INSTALLPROPERTY_TRANSFORMSW) ||
910 !lstrcmpW(szAttribute, INSTALLPROPERTY_LANGUAGEW) ||
911 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTNAMEW) ||
912 !lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW) ||
913 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW) ||
914 !lstrcmpW(szAttribute, INSTALLPROPERTY_VERSIONW) ||
915 !lstrcmpW(szAttribute, INSTALLPROPERTY_PRODUCTICONW) ||
916 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW) ||
917 !lstrcmpW(szAttribute, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
919 if (!prodkey)
921 r = ERROR_UNKNOWN_PRODUCT;
922 goto done;
925 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_ASSIGNMENTTYPEW))
926 szAttribute = assignment;
928 if (!lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGENAMEW))
930 res = RegOpenKeyW(prodkey, sourcelist, &source);
931 if (res != ERROR_SUCCESS)
933 r = ERROR_UNKNOWN_PRODUCT;
934 goto done;
937 val = msi_reg_get_value(source, szAttribute, &type);
938 if (!val)
939 val = empty;
941 RegCloseKey(source);
943 else
945 val = msi_reg_get_value(prodkey, szAttribute, &type);
946 if (!val)
947 val = empty;
950 if (val != empty && type != REG_DWORD &&
951 !lstrcmpW(szAttribute, INSTALLPROPERTY_PACKAGECODEW))
953 if (lstrlenW(val) != SQUISH_GUID_SIZE - 1)
954 badconfig = TRUE;
955 else
957 unsquash_guid(val, packagecode);
958 msi_free(val);
959 val = strdupW(packagecode);
964 if (!val)
966 r = ERROR_UNKNOWN_PROPERTY;
967 goto done;
970 if (pcchValueBuf)
972 save = *pcchValueBuf;
974 if (strlenW(val) < *pcchValueBuf)
975 r = msi_strcpy_to_awstring(val, szValue, pcchValueBuf);
976 else if (szValue->str.a || szValue->str.w)
977 r = ERROR_MORE_DATA;
979 if (!badconfig)
980 *pcchValueBuf = lstrlenW(val);
981 else if (r == ERROR_SUCCESS)
983 *pcchValueBuf = save;
984 r = ERROR_BAD_CONFIGURATION;
987 else if (badconfig)
988 r = ERROR_BAD_CONFIGURATION;
990 if (val != empty)
991 msi_free(val);
993 done:
994 RegCloseKey(prodkey);
995 RegCloseKey(userdata);
996 return r;
999 UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute,
1000 LPSTR szBuffer, LPDWORD pcchValueBuf)
1002 LPWSTR szwProduct, szwAttribute = NULL;
1003 UINT r = ERROR_OUTOFMEMORY;
1004 awstring buffer;
1006 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szAttribute),
1007 szBuffer, pcchValueBuf);
1009 szwProduct = strdupAtoW( szProduct );
1010 if( szProduct && !szwProduct )
1011 goto end;
1013 szwAttribute = strdupAtoW( szAttribute );
1014 if( szAttribute && !szwAttribute )
1015 goto end;
1017 buffer.unicode = FALSE;
1018 buffer.str.a = szBuffer;
1020 r = MSI_GetProductInfo( szwProduct, szwAttribute,
1021 &buffer, pcchValueBuf );
1023 end:
1024 msi_free( szwProduct );
1025 msi_free( szwAttribute );
1027 return r;
1030 UINT WINAPI MsiGetProductInfoW(LPCWSTR szProduct, LPCWSTR szAttribute,
1031 LPWSTR szBuffer, LPDWORD pcchValueBuf)
1033 awstring buffer;
1035 TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szAttribute),
1036 szBuffer, pcchValueBuf);
1038 buffer.unicode = TRUE;
1039 buffer.str.w = szBuffer;
1041 return MSI_GetProductInfo( szProduct, szAttribute,
1042 &buffer, pcchValueBuf );
1045 UINT WINAPI MsiGetProductInfoExA(LPCSTR szProductCode, LPCSTR szUserSid,
1046 MSIINSTALLCONTEXT dwContext, LPCSTR szProperty,
1047 LPSTR szValue, LPDWORD pcchValue)
1049 LPWSTR product = NULL;
1050 LPWSTR usersid = NULL;
1051 LPWSTR property = NULL;
1052 LPWSTR value = NULL;
1053 DWORD len = 0;
1054 UINT r;
1056 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode),
1057 debugstr_a(szUserSid), dwContext, debugstr_a(szProperty),
1058 szValue, pcchValue);
1060 if (szValue && !pcchValue)
1061 return ERROR_INVALID_PARAMETER;
1063 if (szProductCode) product = strdupAtoW(szProductCode);
1064 if (szUserSid) usersid = strdupAtoW(szUserSid);
1065 if (szProperty) property = strdupAtoW(szProperty);
1067 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1068 NULL, &len);
1069 if (r != ERROR_SUCCESS)
1070 goto done;
1072 value = msi_alloc(++len * sizeof(WCHAR));
1073 if (!value)
1075 r = ERROR_OUTOFMEMORY;
1076 goto done;
1079 r = MsiGetProductInfoExW(product, usersid, dwContext, property,
1080 value, &len);
1081 if (r != ERROR_SUCCESS)
1082 goto done;
1084 if (!pcchValue)
1085 goto done;
1087 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
1088 if (*pcchValue >= len)
1089 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
1090 else if (szValue)
1092 r = ERROR_MORE_DATA;
1093 if (*pcchValue > 0)
1094 *szValue = '\0';
1097 if (*pcchValue <= len || !szValue)
1098 len = len * sizeof(WCHAR) - 1;
1100 *pcchValue = len - 1;
1102 done:
1103 msi_free(product);
1104 msi_free(usersid);
1105 msi_free(property);
1106 msi_free(value);
1108 return r;
1111 static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
1113 UINT r;
1115 if (!val)
1116 return ERROR_UNKNOWN_PROPERTY;
1118 if (out)
1120 if (strlenW(val) >= *size)
1122 r = ERROR_MORE_DATA;
1123 if (*size > 0)
1124 *out = '\0';
1126 else
1127 lstrcpyW(out, val);
1130 if (size)
1131 *size = lstrlenW(val);
1133 return ERROR_SUCCESS;
1136 UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
1137 MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty,
1138 LPWSTR szValue, LPDWORD pcchValue)
1140 WCHAR squished_pc[GUID_SIZE];
1141 LPWSTR val = NULL;
1142 LPCWSTR package = NULL;
1143 HKEY props = NULL, prod;
1144 HKEY classes = NULL, managed;
1145 HKEY hkey = NULL;
1146 DWORD type;
1147 UINT r = ERROR_UNKNOWN_PRODUCT;
1149 static const WCHAR one[] = {'1',0};
1150 static const WCHAR five[] = {'5',0};
1151 static const WCHAR empty[] = {0};
1152 static const WCHAR displayname[] = {
1153 'D','i','s','p','l','a','y','N','a','m','e',0};
1154 static const WCHAR displayversion[] = {
1155 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1156 static const WCHAR managed_local_package[] = {
1157 'M','a','n','a','g','e','d','L','o','c','a','l',
1158 'P','a','c','k','a','g','e',0};
1160 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode),
1161 debugstr_w(szUserSid), dwContext, debugstr_w(szProperty),
1162 szValue, pcchValue);
1164 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1165 return ERROR_INVALID_PARAMETER;
1167 if (szValue && !pcchValue)
1168 return ERROR_INVALID_PARAMETER;
1170 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1171 dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1172 dwContext != MSIINSTALLCONTEXT_MACHINE)
1173 return ERROR_INVALID_PARAMETER;
1175 if (!szProperty || !*szProperty)
1176 return ERROR_INVALID_PARAMETER;
1178 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1179 return ERROR_INVALID_PARAMETER;
1181 /* FIXME: dwContext is provided, no need to search for it */
1182 MSIREG_OpenProductKey(szProductCode, NULL,MSIINSTALLCONTEXT_USERMANAGED,
1183 &managed, FALSE);
1184 MSIREG_OpenProductKey(szProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1185 &prod, FALSE);
1187 MSIREG_OpenInstallProps(szProductCode, dwContext, NULL, &props, FALSE);
1189 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1191 package = INSTALLPROPERTY_LOCALPACKAGEW;
1193 if (!props && !prod)
1194 goto done;
1196 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1198 package = managed_local_package;
1200 if (!props && !managed)
1201 goto done;
1203 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1205 package = INSTALLPROPERTY_LOCALPACKAGEW;
1206 MSIREG_OpenProductKey(szProductCode, NULL, dwContext, &classes, FALSE);
1208 if (!props && !classes)
1209 goto done;
1212 if (!lstrcmpW(szProperty, INSTALLPROPERTY_HELPLINKW) ||
1213 !lstrcmpW(szProperty, INSTALLPROPERTY_HELPTELEPHONEW) ||
1214 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW) ||
1215 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW) ||
1216 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLLOCATIONW) ||
1217 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLSOURCEW) ||
1218 !lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW) ||
1219 !lstrcmpW(szProperty, INSTALLPROPERTY_PUBLISHERW) ||
1220 !lstrcmpW(szProperty, INSTALLPROPERTY_URLINFOABOUTW) ||
1221 !lstrcmpW(szProperty, INSTALLPROPERTY_URLUPDATEINFOW) ||
1222 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMINORW) ||
1223 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONMAJORW) ||
1224 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW) ||
1225 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTIDW) ||
1226 !lstrcmpW(szProperty, INSTALLPROPERTY_REGCOMPANYW) ||
1227 !lstrcmpW(szProperty, INSTALLPROPERTY_REGOWNERW) ||
1228 !lstrcmpW(szProperty, INSTALLPROPERTY_INSTANCETYPEW))
1230 val = msi_reg_get_value(props, package, &type);
1231 if (!val)
1233 if (prod || classes)
1234 r = ERROR_UNKNOWN_PROPERTY;
1236 goto done;
1239 msi_free(val);
1241 if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW))
1242 szProperty = displayname;
1243 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONSTRINGW))
1244 szProperty = displayversion;
1246 val = msi_reg_get_value(props, szProperty, &type);
1247 if (!val)
1248 val = strdupW(empty);
1250 r = msi_copy_outval(val, szValue, pcchValue);
1252 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW) ||
1253 !lstrcmpW(szProperty, INSTALLPROPERTY_LANGUAGEW) ||
1254 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTNAMEW) ||
1255 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGECODEW) ||
1256 !lstrcmpW(szProperty, INSTALLPROPERTY_VERSIONW) ||
1257 !lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTICONW) ||
1258 !lstrcmpW(szProperty, INSTALLPROPERTY_PACKAGENAMEW) ||
1259 !lstrcmpW(szProperty, INSTALLPROPERTY_AUTHORIZED_LUA_APPW))
1261 if (!prod && !classes)
1262 goto done;
1264 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
1265 hkey = prod;
1266 else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1267 hkey = managed;
1268 else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1269 hkey = classes;
1271 val = msi_reg_get_value(hkey, szProperty, &type);
1272 if (!val)
1273 val = strdupW(empty);
1275 r = msi_copy_outval(val, szValue, pcchValue);
1277 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_PRODUCTSTATEW))
1279 if (dwContext == MSIINSTALLCONTEXT_MACHINE)
1281 if (props)
1283 val = msi_reg_get_value(props, package, &type);
1284 if (!val)
1285 goto done;
1287 msi_free(val);
1288 val = strdupW(five);
1290 else
1291 val = strdupW(one);
1293 r = msi_copy_outval(val, szValue, pcchValue);
1294 goto done;
1296 else if (props && (val = msi_reg_get_value(props, package, &type)))
1298 msi_free(val);
1299 val = strdupW(five);
1300 r = msi_copy_outval(val, szValue, pcchValue);
1301 goto done;
1304 if (prod || managed)
1305 val = strdupW(one);
1306 else
1307 goto done;
1309 r = msi_copy_outval(val, szValue, pcchValue);
1311 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_ASSIGNMENTTYPEW))
1313 if (!prod && !classes)
1314 goto done;
1316 /* FIXME */
1317 val = strdupW(empty);
1318 r = msi_copy_outval(val, szValue, pcchValue);
1320 else
1321 r = ERROR_UNKNOWN_PROPERTY;
1323 done:
1324 RegCloseKey(props);
1325 RegCloseKey(prod);
1326 RegCloseKey(managed);
1327 RegCloseKey(classes);
1328 msi_free(val);
1330 return r;
1333 UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode,
1334 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1335 LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
1337 LPWSTR patch = NULL, product = NULL, usersid = NULL;
1338 LPWSTR property = NULL, val = NULL;
1339 DWORD len;
1340 UINT r;
1342 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode),
1343 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext,
1344 debugstr_a(szProperty), lpValue, pcchValue);
1346 if (lpValue && !pcchValue)
1347 return ERROR_INVALID_PARAMETER;
1349 if (szPatchCode) patch = strdupAtoW(szPatchCode);
1350 if (szProductCode) product = strdupAtoW(szProductCode);
1351 if (szUserSid) usersid = strdupAtoW(szUserSid);
1352 if (szProperty) property = strdupAtoW(szProperty);
1354 len = 0;
1355 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1356 NULL, &len);
1357 if (r != ERROR_SUCCESS)
1358 goto done;
1360 val = msi_alloc(++len * sizeof(WCHAR));
1361 if (!val)
1363 r = ERROR_OUTOFMEMORY;
1364 goto done;
1367 r = MsiGetPatchInfoExW(patch, product, usersid, dwContext, property,
1368 val, &len);
1369 if (r != ERROR_SUCCESS || !pcchValue)
1370 goto done;
1372 if (lpValue)
1373 WideCharToMultiByte(CP_ACP, 0, val, -1, lpValue,
1374 *pcchValue - 1, NULL, NULL);
1376 len = lstrlenW(val);
1377 if ((*val && *pcchValue < len + 1) || !lpValue)
1379 if (lpValue)
1381 r = ERROR_MORE_DATA;
1382 lpValue[*pcchValue - 1] = '\0';
1385 *pcchValue = len * sizeof(WCHAR);
1387 else
1388 *pcchValue = len;
1390 done:
1391 msi_free(val);
1392 msi_free(patch);
1393 msi_free(product);
1394 msi_free(usersid);
1395 msi_free(property);
1397 return r;
1400 UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
1401 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1402 LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue)
1404 WCHAR squished_pc[GUID_SIZE];
1405 WCHAR squished_patch[GUID_SIZE];
1406 HKEY udprod = 0, prod = 0, props = 0;
1407 HKEY patch = 0, patches = 0;
1408 HKEY udpatch = 0, datakey = 0;
1409 HKEY prodpatches = 0;
1410 LPWSTR val = NULL;
1411 UINT r = ERROR_UNKNOWN_PRODUCT;
1412 DWORD len;
1413 LONG res;
1415 static const WCHAR szEmpty[] = {0};
1416 static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
1417 static const WCHAR szInstalled[] = {'I','n','s','t','a','l','l','e','d',0};
1418 static const WCHAR szManagedPackage[] = {'M','a','n','a','g','e','d',
1419 'L','o','c','a','l','P','a','c','k','a','g','e',0};
1421 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode),
1422 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext,
1423 debugstr_w(szProperty), lpValue, pcchValue);
1425 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1426 return ERROR_INVALID_PARAMETER;
1428 if (!szPatchCode || !squash_guid(szPatchCode, squished_patch))
1429 return ERROR_INVALID_PARAMETER;
1431 if (!szProperty)
1432 return ERROR_INVALID_PARAMETER;
1434 if (lpValue && !pcchValue)
1435 return ERROR_INVALID_PARAMETER;
1437 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
1438 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
1439 dwContext != MSIINSTALLCONTEXT_MACHINE)
1440 return ERROR_INVALID_PARAMETER;
1442 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
1443 return ERROR_INVALID_PARAMETER;
1445 if (!lstrcmpW(szUserSid, szLocalSid))
1446 return ERROR_INVALID_PARAMETER;
1448 if (MSIREG_OpenUserDataProductKey(szProductCode, dwContext, NULL,
1449 &udprod, FALSE) != ERROR_SUCCESS)
1450 goto done;
1452 if (MSIREG_OpenInstallProps(szProductCode, dwContext, NULL,
1453 &props, FALSE) != ERROR_SUCCESS)
1454 goto done;
1456 r = ERROR_UNKNOWN_PATCH;
1458 res = RegOpenKeyExW(udprod, szPatches, 0, KEY_READ, &patches);
1459 if (res != ERROR_SUCCESS)
1460 goto done;
1462 res = RegOpenKeyExW(patches, squished_patch, 0, KEY_READ, &patch);
1463 if (res != ERROR_SUCCESS)
1464 goto done;
1466 if (!lstrcmpW(szProperty, INSTALLPROPERTY_TRANSFORMSW))
1468 if (MSIREG_OpenProductKey(szProductCode, NULL, dwContext,
1469 &prod, FALSE) != ERROR_SUCCESS)
1470 goto done;
1472 res = RegOpenKeyExW(prod, szPatches, 0, KEY_ALL_ACCESS, &prodpatches);
1473 if (res != ERROR_SUCCESS)
1474 goto done;
1476 datakey = prodpatches;
1477 szProperty = squished_patch;
1479 else
1481 if (MSIREG_OpenUserDataPatchKey(szPatchCode, dwContext,
1482 &udpatch, FALSE) != ERROR_SUCCESS)
1483 goto done;
1485 if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
1487 if (dwContext == MSIINSTALLCONTEXT_USERMANAGED)
1488 szProperty = szManagedPackage;
1489 datakey = udpatch;
1491 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_INSTALLDATEW))
1493 datakey = patch;
1494 szProperty = szInstalled;
1496 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_LOCALPACKAGEW))
1498 datakey = udpatch;
1500 else if (!lstrcmpW(szProperty, INSTALLPROPERTY_UNINSTALLABLEW) ||
1501 !lstrcmpW(szProperty, INSTALLPROPERTY_PATCHSTATEW) ||
1502 !lstrcmpW(szProperty, INSTALLPROPERTY_DISPLAYNAMEW) ||
1503 !lstrcmpW(szProperty, INSTALLPROPERTY_MOREINFOURLW))
1505 datakey = patch;
1507 else
1509 r = ERROR_UNKNOWN_PROPERTY;
1510 goto done;
1514 val = msi_reg_get_val_str(datakey, szProperty);
1515 if (!val)
1516 val = strdupW(szEmpty);
1518 r = ERROR_SUCCESS;
1520 if (!pcchValue)
1521 goto done;
1523 if (lpValue)
1524 lstrcpynW(lpValue, val, *pcchValue);
1526 len = lstrlenW(val);
1527 if ((*val && *pcchValue < len + 1) || !lpValue)
1529 if (lpValue)
1530 r = ERROR_MORE_DATA;
1532 *pcchValue = len * sizeof(WCHAR);
1535 *pcchValue = len;
1537 done:
1538 msi_free(val);
1539 RegCloseKey(prodpatches);
1540 RegCloseKey(prod);
1541 RegCloseKey(patch);
1542 RegCloseKey(patches);
1543 RegCloseKey(udpatch);
1544 RegCloseKey(props);
1545 RegCloseKey(udprod);
1547 return r;
1550 UINT WINAPI MsiEnableLogA(DWORD dwLogMode, LPCSTR szLogFile, DWORD attributes)
1552 LPWSTR szwLogFile = NULL;
1553 UINT r;
1555 TRACE("%08x %s %08x\n", dwLogMode, debugstr_a(szLogFile), attributes);
1557 if( szLogFile )
1559 szwLogFile = strdupAtoW( szLogFile );
1560 if( !szwLogFile )
1561 return ERROR_OUTOFMEMORY;
1563 r = MsiEnableLogW( dwLogMode, szwLogFile, attributes );
1564 msi_free( szwLogFile );
1565 return r;
1568 UINT WINAPI MsiEnableLogW(DWORD dwLogMode, LPCWSTR szLogFile, DWORD attributes)
1570 HANDLE file = INVALID_HANDLE_VALUE;
1572 TRACE("%08x %s %08x\n", dwLogMode, debugstr_w(szLogFile), attributes);
1574 if (szLogFile)
1576 lstrcpyW(gszLogFile,szLogFile);
1577 if (!(attributes & INSTALLLOGATTRIBUTES_APPEND))
1578 DeleteFileW(szLogFile);
1579 file = CreateFileW(szLogFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
1580 FILE_ATTRIBUTE_NORMAL, NULL);
1581 if (file != INVALID_HANDLE_VALUE)
1582 CloseHandle(file);
1583 else
1584 ERR("Unable to enable log %s\n",debugstr_w(szLogFile));
1586 else
1587 gszLogFile[0] = '\0';
1589 return ERROR_SUCCESS;
1592 UINT WINAPI MsiEnumComponentCostsW(MSIHANDLE hInstall, LPCWSTR szComponent,
1593 DWORD dwIndex, INSTALLSTATE iState,
1594 LPWSTR lpDriveBuf, DWORD *pcchDriveBuf,
1595 int *piCost, int *pTempCost)
1597 FIXME("(%d, %s, %d, %d, %p, %p, %p %p): stub!\n", hInstall,
1598 debugstr_w(szComponent), dwIndex, iState, lpDriveBuf,
1599 pcchDriveBuf, piCost, pTempCost);
1601 return ERROR_NO_MORE_ITEMS;
1604 UINT WINAPI MsiQueryComponentStateA(LPCSTR szProductCode,
1605 LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1606 LPCSTR szComponent, INSTALLSTATE *pdwState)
1608 LPWSTR prodcode = NULL, usersid = NULL, comp = NULL;
1609 UINT r;
1611 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode),
1612 debugstr_a(szUserSid), dwContext, debugstr_a(szComponent), pdwState);
1614 if (szProductCode && !(prodcode = strdupAtoW(szProductCode)))
1615 return ERROR_OUTOFMEMORY;
1617 if (szUserSid && !(usersid = strdupAtoW(szUserSid)))
1618 return ERROR_OUTOFMEMORY;
1620 if (szComponent && !(comp = strdupAtoW(szComponent)))
1621 return ERROR_OUTOFMEMORY;
1623 r = MsiQueryComponentStateW(prodcode, usersid, dwContext, comp, pdwState);
1625 msi_free(prodcode);
1626 msi_free(usersid);
1627 msi_free(comp);
1629 return r;
1632 static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1634 UINT r;
1635 HKEY hkey;
1637 r = MSIREG_OpenProductKey(prodcode, NULL, context, &hkey, FALSE);
1638 RegCloseKey(hkey);
1639 return (r == ERROR_SUCCESS);
1642 static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
1644 LPCWSTR package;
1645 HKEY hkey;
1646 DWORD sz;
1647 LONG res;
1648 UINT r;
1650 static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
1651 static const WCHAR managed_local_package[] = {
1652 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
1655 r = MSIREG_OpenInstallProps(prodcode, context, NULL, &hkey, FALSE);
1656 if (r != ERROR_SUCCESS)
1657 return FALSE;
1659 if (context == MSIINSTALLCONTEXT_USERMANAGED)
1660 package = managed_local_package;
1661 else
1662 package = local_package;
1664 sz = 0;
1665 res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
1666 RegCloseKey(hkey);
1668 return (res == ERROR_SUCCESS);
1671 static BOOL msi_comp_find_prodcode(LPWSTR squished_pc,
1672 MSIINSTALLCONTEXT context,
1673 LPCWSTR comp, LPWSTR val, DWORD *sz)
1675 HKEY hkey;
1676 LONG res;
1677 UINT r;
1679 if (context == MSIINSTALLCONTEXT_MACHINE)
1680 r = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
1681 else
1682 r = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
1684 if (r != ERROR_SUCCESS)
1685 return FALSE;
1687 res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, (BYTE *)val, sz);
1688 if (res != ERROR_SUCCESS)
1689 return FALSE;
1691 RegCloseKey(hkey);
1692 return TRUE;
1695 UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
1696 LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
1697 LPCWSTR szComponent, INSTALLSTATE *pdwState)
1699 WCHAR squished_pc[GUID_SIZE];
1700 WCHAR val[MAX_PATH];
1701 BOOL found;
1702 DWORD sz;
1704 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
1705 debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
1707 if (!pdwState || !szComponent)
1708 return ERROR_INVALID_PARAMETER;
1710 if (!szProductCode || !*szProductCode || lstrlenW(szProductCode) != GUID_SIZE - 1)
1711 return ERROR_INVALID_PARAMETER;
1713 if (!squash_guid(szProductCode, squished_pc))
1714 return ERROR_INVALID_PARAMETER;
1716 found = msi_comp_find_prod_key(szProductCode, dwContext);
1718 if (!msi_comp_find_package(szProductCode, dwContext))
1720 if (found)
1722 *pdwState = INSTALLSTATE_UNKNOWN;
1723 return ERROR_UNKNOWN_COMPONENT;
1726 return ERROR_UNKNOWN_PRODUCT;
1729 *pdwState = INSTALLSTATE_UNKNOWN;
1731 sz = MAX_PATH;
1732 if (!msi_comp_find_prodcode(squished_pc, dwContext, szComponent, val, &sz))
1733 return ERROR_UNKNOWN_COMPONENT;
1735 if (sz == 0)
1736 *pdwState = INSTALLSTATE_NOTUSED;
1737 else
1739 if (lstrlenW(val) > 2 &&
1740 val[0] >= '0' && val[0] <= '9' && val[1] >= '0' && val[1] <= '9')
1742 *pdwState = INSTALLSTATE_SOURCE;
1744 else
1745 *pdwState = INSTALLSTATE_LOCAL;
1748 return ERROR_SUCCESS;
1751 INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct)
1753 LPWSTR szwProduct = NULL;
1754 INSTALLSTATE r;
1756 if( szProduct )
1758 szwProduct = strdupAtoW( szProduct );
1759 if( !szwProduct )
1760 return ERROR_OUTOFMEMORY;
1762 r = MsiQueryProductStateW( szwProduct );
1763 msi_free( szwProduct );
1764 return r;
1767 INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct)
1769 MSIINSTALLCONTEXT context = MSIINSTALLCONTEXT_USERUNMANAGED;
1770 INSTALLSTATE state = INSTALLSTATE_ADVERTISED;
1771 HKEY prodkey = 0, userdata = 0;
1772 DWORD val;
1773 UINT r;
1775 static const WCHAR szWindowsInstaller[] = {
1776 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1778 TRACE("%s\n", debugstr_w(szProduct));
1780 if (!szProduct || !*szProduct)
1781 return INSTALLSTATE_INVALIDARG;
1783 if (lstrlenW(szProduct) != GUID_SIZE - 1)
1784 return INSTALLSTATE_INVALIDARG;
1786 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
1787 &prodkey, FALSE) != ERROR_SUCCESS &&
1788 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1789 &prodkey, FALSE) != ERROR_SUCCESS &&
1790 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
1791 &prodkey, FALSE) == ERROR_SUCCESS)
1793 context = MSIINSTALLCONTEXT_MACHINE;
1796 r = MSIREG_OpenInstallProps(szProduct, context, NULL, &userdata, FALSE);
1797 if (r != ERROR_SUCCESS)
1798 goto done;
1800 if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val))
1801 goto done;
1803 if (val)
1804 state = INSTALLSTATE_DEFAULT;
1805 else
1806 state = INSTALLSTATE_UNKNOWN;
1808 done:
1809 if (!prodkey)
1811 state = INSTALLSTATE_UNKNOWN;
1813 if (userdata)
1814 state = INSTALLSTATE_ABSENT;
1817 RegCloseKey(prodkey);
1818 RegCloseKey(userdata);
1819 return state;
1822 INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
1824 INSTALLUILEVEL old = gUILevel;
1825 HWND oldwnd = gUIhwnd;
1827 TRACE("%08x %p\n", dwUILevel, phWnd);
1829 gUILevel = dwUILevel;
1830 if (phWnd)
1832 gUIhwnd = *phWnd;
1833 *phWnd = oldwnd;
1835 return old;
1838 INSTALLUI_HANDLERA WINAPI MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler,
1839 DWORD dwMessageFilter, LPVOID pvContext)
1841 INSTALLUI_HANDLERA prev = gUIHandlerA;
1843 TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
1844 gUIHandlerA = puiHandler;
1845 gUIFilter = dwMessageFilter;
1846 gUIContext = pvContext;
1848 return prev;
1851 INSTALLUI_HANDLERW WINAPI MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler,
1852 DWORD dwMessageFilter, LPVOID pvContext)
1854 INSTALLUI_HANDLERW prev = gUIHandlerW;
1856 TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
1857 gUIHandlerW = puiHandler;
1858 gUIFilter = dwMessageFilter;
1859 gUIContext = pvContext;
1861 return prev;
1864 /******************************************************************
1865 * MsiLoadStringW [MSI.@]
1867 * Loads a string from MSI's string resources.
1869 * PARAMS
1871 * handle [I] only -1 is handled currently
1872 * id [I] id of the string to be loaded
1873 * lpBuffer [O] buffer for the string to be written to
1874 * nBufferMax [I] maximum size of the buffer in characters
1875 * lang [I] the preferred language for the string
1877 * RETURNS
1879 * If successful, this function returns the language id of the string loaded
1880 * If the function fails, the function returns zero.
1882 * NOTES
1884 * The type of the first parameter is unknown. LoadString's prototype
1885 * suggests that it might be a module handle. I have made it an MSI handle
1886 * for starters, as -1 is an invalid MSI handle, but not an invalid module
1887 * handle. Maybe strings can be stored in an MSI database somehow.
1889 LANGID WINAPI MsiLoadStringW( MSIHANDLE handle, UINT id, LPWSTR lpBuffer,
1890 int nBufferMax, LANGID lang )
1892 HRSRC hres;
1893 HGLOBAL hResData;
1894 LPWSTR p;
1895 DWORD i, len;
1897 TRACE("%d %u %p %d %d\n", handle, id, lpBuffer, nBufferMax, lang);
1899 if( handle != -1 )
1900 FIXME("don't know how to deal with handle = %08x\n", handle);
1902 if( !lang )
1903 lang = GetUserDefaultLangID();
1905 hres = FindResourceExW( msi_hInstance, (LPCWSTR) RT_STRING,
1906 (LPWSTR)1, lang );
1907 if( !hres )
1908 return 0;
1909 hResData = LoadResource( msi_hInstance, hres );
1910 if( !hResData )
1911 return 0;
1912 p = LockResource( hResData );
1913 if( !p )
1914 return 0;
1916 for (i = 0; i < (id&0xf); i++)
1917 p += *p + 1;
1918 len = *p;
1920 if( nBufferMax <= len )
1921 return 0;
1923 memcpy( lpBuffer, p+1, len * sizeof(WCHAR));
1924 lpBuffer[ len ] = 0;
1926 TRACE("found -> %s\n", debugstr_w(lpBuffer));
1928 return lang;
1931 LANGID WINAPI MsiLoadStringA( MSIHANDLE handle, UINT id, LPSTR lpBuffer,
1932 int nBufferMax, LANGID lang )
1934 LPWSTR bufW;
1935 LANGID r;
1936 INT len;
1938 bufW = msi_alloc(nBufferMax*sizeof(WCHAR));
1939 r = MsiLoadStringW(handle, id, bufW, nBufferMax, lang);
1940 if( r )
1942 len = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL );
1943 if( len <= nBufferMax )
1944 WideCharToMultiByte( CP_ACP, 0, bufW, -1,
1945 lpBuffer, nBufferMax, NULL, NULL );
1946 else
1947 r = 0;
1949 msi_free(bufW);
1950 return r;
1953 INSTALLSTATE WINAPI MsiLocateComponentA(LPCSTR szComponent, LPSTR lpPathBuf,
1954 LPDWORD pcchBuf)
1956 char szProduct[GUID_SIZE];
1958 TRACE("%s %p %p\n", debugstr_a(szComponent), lpPathBuf, pcchBuf);
1960 if (MsiGetProductCodeA( szComponent, szProduct ) != ERROR_SUCCESS)
1961 return INSTALLSTATE_UNKNOWN;
1963 return MsiGetComponentPathA( szProduct, szComponent, lpPathBuf, pcchBuf );
1966 INSTALLSTATE WINAPI MsiLocateComponentW(LPCWSTR szComponent, LPWSTR lpPathBuf,
1967 LPDWORD pcchBuf)
1969 WCHAR szProduct[GUID_SIZE];
1971 TRACE("%s %p %p\n", debugstr_w(szComponent), lpPathBuf, pcchBuf);
1973 if (MsiGetProductCodeW( szComponent, szProduct ) != ERROR_SUCCESS)
1974 return INSTALLSTATE_UNKNOWN;
1976 return MsiGetComponentPathW( szProduct, szComponent, lpPathBuf, pcchBuf );
1979 UINT WINAPI MsiMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
1980 WORD wLanguageId, DWORD f)
1982 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_a(lpText), debugstr_a(lpCaption),
1983 uType, wLanguageId, f);
1984 return MessageBoxExA(hWnd,lpText,lpCaption,uType,wLanguageId);
1987 UINT WINAPI MsiMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
1988 WORD wLanguageId, DWORD f)
1990 FIXME("%p %s %s %u %08x %08x\n", hWnd, debugstr_w(lpText), debugstr_w(lpCaption),
1991 uType, wLanguageId, f);
1992 return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
1995 UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
1996 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
1997 LPDWORD pcchPathBuf )
1999 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName),
2000 debugstr_a(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2001 pcchPathBuf);
2002 return ERROR_CALL_NOT_IMPLEMENTED;
2005 UINT WINAPI MsiProvideAssemblyW( LPCWSTR szAssemblyName, LPCWSTR szAppContext,
2006 DWORD dwInstallMode, DWORD dwAssemblyInfo, LPWSTR lpPathBuf,
2007 LPDWORD pcchPathBuf )
2009 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName),
2010 debugstr_w(szAppContext), dwInstallMode, dwAssemblyInfo, lpPathBuf,
2011 pcchPathBuf);
2012 return ERROR_CALL_NOT_IMPLEMENTED;
2015 UINT WINAPI MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor,
2016 LPSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2018 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor), szPath, pcchPath, pcchArgs );
2019 return ERROR_CALL_NOT_IMPLEMENTED;
2022 UINT WINAPI MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor,
2023 LPWSTR szPath, LPDWORD pcchPath, LPDWORD pcchArgs )
2025 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor), szPath, pcchPath, pcchArgs );
2026 return ERROR_CALL_NOT_IMPLEMENTED;
2029 HRESULT WINAPI MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath,
2030 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
2031 LPDWORD pcbHashData)
2033 FIXME("%s %08x %p %p %p\n", debugstr_a(szSignedObjectPath), dwFlags,
2034 ppcCertContext, pbHashData, pcbHashData);
2035 return ERROR_CALL_NOT_IMPLEMENTED;
2038 HRESULT WINAPI MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath,
2039 DWORD dwFlags, PCCERT_CONTEXT* ppcCertContext, LPBYTE pbHashData,
2040 LPDWORD pcbHashData)
2042 FIXME("%s %08x %p %p %p\n", debugstr_w(szSignedObjectPath), dwFlags,
2043 ppcCertContext, pbHashData, pcbHashData);
2044 return ERROR_CALL_NOT_IMPLEMENTED;
2047 /******************************************************************
2048 * MsiGetProductPropertyA [MSI.@]
2050 UINT WINAPI MsiGetProductPropertyA(MSIHANDLE hProduct, LPCSTR szProperty,
2051 LPSTR szValue, LPDWORD pccbValue)
2053 LPWSTR prop = NULL, val = NULL;
2054 DWORD len;
2055 UINT r;
2057 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_a(szProperty),
2058 szValue, pccbValue);
2060 if (szValue && !pccbValue)
2061 return ERROR_INVALID_PARAMETER;
2063 if (szProperty) prop = strdupAtoW(szProperty);
2065 len = 0;
2066 r = MsiGetProductPropertyW(hProduct, prop, NULL, &len);
2067 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2068 goto done;
2070 if (r == ERROR_SUCCESS)
2072 if (szValue) *szValue = '\0';
2073 if (pccbValue) *pccbValue = 0;
2074 goto done;
2077 val = msi_alloc(++len * sizeof(WCHAR));
2078 if (!val)
2080 r = ERROR_OUTOFMEMORY;
2081 goto done;
2084 r = MsiGetProductPropertyW(hProduct, prop, val, &len);
2085 if (r != ERROR_SUCCESS)
2086 goto done;
2088 len = WideCharToMultiByte(CP_ACP, 0, val, -1, NULL, 0, NULL, NULL);
2090 if (szValue)
2091 WideCharToMultiByte(CP_ACP, 0, val, -1, szValue,
2092 *pccbValue, NULL, NULL);
2094 if (pccbValue)
2096 if (len > *pccbValue)
2097 r = ERROR_MORE_DATA;
2099 *pccbValue = len - 1;
2102 done:
2103 msi_free(prop);
2104 msi_free(val);
2106 return r;
2109 /******************************************************************
2110 * MsiGetProductPropertyW [MSI.@]
2112 UINT WINAPI MsiGetProductPropertyW(MSIHANDLE hProduct, LPCWSTR szProperty,
2113 LPWSTR szValue, LPDWORD pccbValue)
2115 MSIPACKAGE *package;
2116 MSIQUERY *view = NULL;
2117 MSIRECORD *rec = NULL;
2118 LPCWSTR val;
2119 UINT r;
2121 static const WCHAR query[] = {
2122 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
2123 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
2124 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
2126 TRACE("(%d, %s, %p, %p)\n", hProduct, debugstr_w(szProperty),
2127 szValue, pccbValue);
2129 if (!szProperty)
2130 return ERROR_INVALID_PARAMETER;
2132 if (szValue && !pccbValue)
2133 return ERROR_INVALID_PARAMETER;
2135 package = msihandle2msiinfo(hProduct, MSIHANDLETYPE_PACKAGE);
2136 if (!package)
2137 return ERROR_INVALID_HANDLE;
2139 r = MSI_OpenQuery(package->db, &view, query, szProperty);
2140 if (r != ERROR_SUCCESS)
2141 goto done;
2143 r = MSI_ViewExecute(view, 0);
2144 if (r != ERROR_SUCCESS)
2145 goto done;
2147 r = MSI_ViewFetch(view, &rec);
2148 if (r != ERROR_SUCCESS)
2149 goto done;
2151 val = MSI_RecordGetString(rec, 2);
2152 if (!val)
2153 goto done;
2155 if (lstrlenW(val) >= *pccbValue)
2157 lstrcpynW(szValue, val, *pccbValue);
2158 *pccbValue = lstrlenW(val);
2159 r = ERROR_MORE_DATA;
2161 else
2163 lstrcpyW(szValue, val);
2164 *pccbValue = lstrlenW(val);
2165 r = ERROR_SUCCESS;
2168 done:
2169 if (view)
2171 MSI_ViewClose(view);
2172 msiobj_release(&view->hdr);
2173 if (rec) msiobj_release(&rec->hdr);
2176 if (!rec)
2178 if (szValue) *szValue = '\0';
2179 if (pccbValue) *pccbValue = 0;
2180 r = ERROR_SUCCESS;
2183 return r;
2186 UINT WINAPI MsiVerifyPackageA( LPCSTR szPackage )
2188 UINT r;
2189 LPWSTR szPack = NULL;
2191 TRACE("%s\n", debugstr_a(szPackage) );
2193 if( szPackage )
2195 szPack = strdupAtoW( szPackage );
2196 if( !szPack )
2197 return ERROR_OUTOFMEMORY;
2200 r = MsiVerifyPackageW( szPack );
2202 msi_free( szPack );
2204 return r;
2207 UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
2209 MSIHANDLE handle;
2210 UINT r;
2212 TRACE("%s\n", debugstr_w(szPackage) );
2214 r = MsiOpenDatabaseW( szPackage, MSIDBOPEN_READONLY, &handle );
2215 MsiCloseHandle( handle );
2217 return r;
2220 static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
2221 awstring* lpPathBuf, LPDWORD pcchBuf)
2223 WCHAR squished_pc[GUID_SIZE];
2224 WCHAR squished_comp[GUID_SIZE];
2225 HKEY hkey;
2226 LPWSTR path = NULL;
2227 INSTALLSTATE state;
2228 DWORD version;
2230 static const WCHAR wininstaller[] = {
2231 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
2233 TRACE("%s %s %p %p\n", debugstr_w(szProduct),
2234 debugstr_w(szComponent), lpPathBuf->str.w, pcchBuf);
2236 if (!szProduct || !szComponent)
2237 return INSTALLSTATE_INVALIDARG;
2239 if (lpPathBuf->str.w && !pcchBuf)
2240 return INSTALLSTATE_INVALIDARG;
2242 if (!squash_guid(szProduct, squished_pc) ||
2243 !squash_guid(szComponent, squished_comp))
2244 return INSTALLSTATE_INVALIDARG;
2246 state = INSTALLSTATE_UNKNOWN;
2248 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
2249 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
2251 path = msi_reg_get_val_str(hkey, squished_pc);
2252 RegCloseKey(hkey);
2254 state = INSTALLSTATE_ABSENT;
2256 if ((MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL,
2257 &hkey, FALSE) == ERROR_SUCCESS ||
2258 MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2259 NULL, &hkey, FALSE) == ERROR_SUCCESS) &&
2260 msi_reg_get_val_dword(hkey, wininstaller, &version) &&
2261 GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2263 RegCloseKey(hkey);
2264 state = INSTALLSTATE_LOCAL;
2268 if (state != INSTALLSTATE_LOCAL &&
2269 (MSIREG_OpenProductKey(szProduct, NULL,
2270 MSIINSTALLCONTEXT_USERUNMANAGED,
2271 &hkey, FALSE) == ERROR_SUCCESS ||
2272 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2273 &hkey, FALSE) == ERROR_SUCCESS))
2275 RegCloseKey(hkey);
2277 if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
2278 MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
2280 msi_free(path);
2281 path = msi_reg_get_val_str(hkey, squished_pc);
2282 RegCloseKey(hkey);
2284 state = INSTALLSTATE_ABSENT;
2286 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
2287 state = INSTALLSTATE_LOCAL;
2291 if (!path)
2292 return INSTALLSTATE_UNKNOWN;
2294 if (state == INSTALLSTATE_LOCAL && !*path)
2295 state = INSTALLSTATE_NOTUSED;
2297 msi_strcpy_to_awstring(path, lpPathBuf, pcchBuf);
2298 msi_free(path);
2299 return state;
2302 /******************************************************************
2303 * MsiGetComponentPathW [MSI.@]
2305 INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
2306 LPWSTR lpPathBuf, LPDWORD pcchBuf)
2308 awstring path;
2310 path.unicode = TRUE;
2311 path.str.w = lpPathBuf;
2313 return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
2316 /******************************************************************
2317 * MsiGetComponentPathA [MSI.@]
2319 INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
2320 LPSTR lpPathBuf, LPDWORD pcchBuf)
2322 LPWSTR szwProduct, szwComponent = NULL;
2323 INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
2324 awstring path;
2326 szwProduct = strdupAtoW( szProduct );
2327 if( szProduct && !szwProduct)
2328 goto end;
2330 szwComponent = strdupAtoW( szComponent );
2331 if( szComponent && !szwComponent )
2332 goto end;
2334 path.unicode = FALSE;
2335 path.str.a = lpPathBuf;
2337 r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
2339 end:
2340 msi_free( szwProduct );
2341 msi_free( szwComponent );
2343 return r;
2346 /******************************************************************
2347 * MsiQueryFeatureStateA [MSI.@]
2349 INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR szProduct, LPCSTR szFeature)
2351 LPWSTR szwProduct = NULL, szwFeature= NULL;
2352 INSTALLSTATE rc = INSTALLSTATE_UNKNOWN;
2354 szwProduct = strdupAtoW( szProduct );
2355 if ( szProduct && !szwProduct )
2356 goto end;
2358 szwFeature = strdupAtoW( szFeature );
2359 if ( szFeature && !szwFeature )
2360 goto end;
2362 rc = MsiQueryFeatureStateW(szwProduct, szwFeature);
2364 end:
2365 msi_free( szwProduct);
2366 msi_free( szwFeature);
2368 return rc;
2371 /******************************************************************
2372 * MsiQueryFeatureStateW [MSI.@]
2374 * Checks the state of a feature
2376 * PARAMS
2377 * szProduct [I] Product's GUID string
2378 * szFeature [I] Feature's GUID string
2380 * RETURNS
2381 * INSTALLSTATE_LOCAL Feature is installed and usable
2382 * INSTALLSTATE_ABSENT Feature is absent
2383 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
2384 * INSTALLSTATE_UNKNOWN An error occurred
2385 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
2388 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature)
2390 WCHAR squishProduct[33], comp[GUID_SIZE];
2391 GUID guid;
2392 LPWSTR components, p, parent_feature, path;
2393 UINT rc;
2394 HKEY hkey;
2395 INSTALLSTATE r;
2396 BOOL missing = FALSE;
2397 BOOL machine = FALSE;
2398 BOOL source = FALSE;
2400 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature));
2402 if (!szProduct || !szFeature)
2403 return INSTALLSTATE_INVALIDARG;
2405 if (!squash_guid( szProduct, squishProduct ))
2406 return INSTALLSTATE_INVALIDARG;
2408 if (MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2409 &hkey, FALSE) != ERROR_SUCCESS &&
2410 MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2411 &hkey, FALSE) != ERROR_SUCCESS)
2413 rc = MSIREG_OpenFeaturesKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2414 &hkey, FALSE);
2415 if (rc != ERROR_SUCCESS)
2416 return INSTALLSTATE_UNKNOWN;
2418 machine = TRUE;
2421 parent_feature = msi_reg_get_val_str( hkey, szFeature );
2422 RegCloseKey(hkey);
2424 if (!parent_feature)
2425 return INSTALLSTATE_UNKNOWN;
2427 r = (parent_feature[0] == 6) ? INSTALLSTATE_ABSENT : INSTALLSTATE_LOCAL;
2428 msi_free(parent_feature);
2429 if (r == INSTALLSTATE_ABSENT)
2430 return r;
2432 if (machine)
2433 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2434 MSIINSTALLCONTEXT_MACHINE,
2435 &hkey, FALSE);
2436 else
2437 rc = MSIREG_OpenUserDataFeaturesKey(szProduct,
2438 MSIINSTALLCONTEXT_USERUNMANAGED,
2439 &hkey, FALSE);
2441 if (rc != ERROR_SUCCESS)
2442 return INSTALLSTATE_ADVERTISED;
2444 components = msi_reg_get_val_str( hkey, szFeature );
2445 RegCloseKey(hkey);
2447 TRACE("rc = %d buffer = %s\n", rc, debugstr_w(components));
2449 if (!components)
2450 return INSTALLSTATE_ADVERTISED;
2452 for( p = components; *p && *p != 2 ; p += 20)
2454 if (!decode_base85_guid( p, &guid ))
2456 if (p != components)
2457 break;
2459 msi_free(components);
2460 return INSTALLSTATE_BADCONFIG;
2463 StringFromGUID2(&guid, comp, GUID_SIZE);
2465 if (machine)
2466 rc = MSIREG_OpenUserDataComponentKey(comp, szLocalSid, &hkey, FALSE);
2467 else
2468 rc = MSIREG_OpenUserDataComponentKey(comp, NULL, &hkey, FALSE);
2470 if (rc != ERROR_SUCCESS)
2472 msi_free(components);
2473 return INSTALLSTATE_ADVERTISED;
2476 path = msi_reg_get_val_str(hkey, squishProduct);
2477 if (!path)
2478 missing = TRUE;
2479 else if (lstrlenW(path) > 2 &&
2480 path[0] >= '0' && path[0] <= '9' &&
2481 path[1] >= '0' && path[1] <= '9')
2483 source = TRUE;
2486 msi_free(path);
2489 TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r);
2490 msi_free(components);
2492 if (missing)
2493 return INSTALLSTATE_ADVERTISED;
2495 if (source)
2496 return INSTALLSTATE_SOURCE;
2498 return INSTALLSTATE_LOCAL;
2501 /******************************************************************
2502 * MsiGetFileVersionA [MSI.@]
2504 UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf,
2505 LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf)
2507 LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL;
2508 UINT ret = ERROR_OUTOFMEMORY;
2510 if ((lpVersionBuf && !pcchVersionBuf) ||
2511 (lpLangBuf && !pcchLangBuf))
2512 return ERROR_INVALID_PARAMETER;
2514 if( szFilePath )
2516 szwFilePath = strdupAtoW( szFilePath );
2517 if( !szwFilePath )
2518 goto end;
2521 if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf )
2523 lpwVersionBuff = msi_alloc(*pcchVersionBuf*sizeof(WCHAR));
2524 if( !lpwVersionBuff )
2525 goto end;
2528 if( lpLangBuf && pcchLangBuf && *pcchLangBuf )
2530 lpwLangBuff = msi_alloc(*pcchLangBuf*sizeof(WCHAR));
2531 if( !lpwLangBuff )
2532 goto end;
2535 ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf,
2536 lpwLangBuff, pcchLangBuf);
2538 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff )
2539 WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1,
2540 lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL);
2541 if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff )
2542 WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1,
2543 lpLangBuf, *pcchLangBuf + 1, NULL, NULL);
2545 end:
2546 msi_free(szwFilePath);
2547 msi_free(lpwVersionBuff);
2548 msi_free(lpwLangBuff);
2550 return ret;
2553 /******************************************************************
2554 * MsiGetFileVersionW [MSI.@]
2556 UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf,
2557 LPDWORD pcchVersionBuf, LPWSTR lpLangBuf, LPDWORD pcchLangBuf)
2559 static const WCHAR szVersionResource[] = {'\\',0};
2560 static const WCHAR szVersionFormat[] = {
2561 '%','d','.','%','d','.','%','d','.','%','d',0};
2562 static const WCHAR szLangResource[] = {
2563 '\\','V','a','r','F','i','l','e','I','n','f','o','\\',
2564 'T','r','a','n','s','l','a','t','i','o','n',0};
2565 static const WCHAR szLangFormat[] = {'%','d',0};
2566 UINT ret = 0;
2567 DWORD dwVerLen, gle;
2568 LPVOID lpVer = NULL;
2569 VS_FIXEDFILEINFO *ffi;
2570 USHORT *lang;
2571 UINT puLen;
2572 WCHAR tmp[32];
2574 TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath),
2575 lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
2576 lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
2578 if ((lpVersionBuf && !pcchVersionBuf) ||
2579 (lpLangBuf && !pcchLangBuf))
2580 return ERROR_INVALID_PARAMETER;
2582 dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
2583 if( !dwVerLen )
2585 gle = GetLastError();
2586 if (gle == ERROR_BAD_PATHNAME)
2587 return ERROR_FILE_NOT_FOUND;
2588 else if (gle == ERROR_RESOURCE_DATA_NOT_FOUND)
2589 return ERROR_FILE_INVALID;
2591 return gle;
2594 lpVer = msi_alloc(dwVerLen);
2595 if( !lpVer )
2597 ret = ERROR_OUTOFMEMORY;
2598 goto end;
2601 if( !GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer) )
2603 ret = GetLastError();
2604 goto end;
2607 if (pcchVersionBuf)
2609 if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) &&
2610 (puLen > 0) )
2612 wsprintfW(tmp, szVersionFormat,
2613 HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS),
2614 HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
2615 if (lpVersionBuf) lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
2617 if (strlenW(tmp) >= *pcchVersionBuf)
2618 ret = ERROR_MORE_DATA;
2620 *pcchVersionBuf = lstrlenW(tmp);
2622 else
2624 if (lpVersionBuf) *lpVersionBuf = 0;
2625 *pcchVersionBuf = 0;
2629 if (pcchLangBuf)
2631 if (VerQueryValueW(lpVer, szLangResource, (LPVOID*)&lang, &puLen) &&
2632 (puLen > 0))
2634 wsprintfW(tmp, szLangFormat, *lang);
2635 if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
2637 if (strlenW(tmp) >= *pcchLangBuf)
2638 ret = ERROR_MORE_DATA;
2640 *pcchLangBuf = lstrlenW(tmp);
2642 else
2644 if (lpLangBuf) *lpLangBuf = 0;
2645 *pcchLangBuf = 0;
2649 end:
2650 msi_free(lpVer);
2651 return ret;
2654 /***********************************************************************
2655 * MsiGetFeatureUsageW [MSI.@]
2657 UINT WINAPI MsiGetFeatureUsageW( LPCWSTR szProduct, LPCWSTR szFeature,
2658 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2660 FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature),
2661 pdwUseCount, pwDateUsed);
2662 return ERROR_CALL_NOT_IMPLEMENTED;
2665 /***********************************************************************
2666 * MsiGetFeatureUsageA [MSI.@]
2668 UINT WINAPI MsiGetFeatureUsageA( LPCSTR szProduct, LPCSTR szFeature,
2669 LPDWORD pdwUseCount, LPWORD pwDateUsed )
2671 LPWSTR prod = NULL, feat = NULL;
2672 UINT ret = ERROR_OUTOFMEMORY;
2674 TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature),
2675 pdwUseCount, pwDateUsed);
2677 prod = strdupAtoW( szProduct );
2678 if (szProduct && !prod)
2679 goto end;
2681 feat = strdupAtoW( szFeature );
2682 if (szFeature && !feat)
2683 goto end;
2685 ret = MsiGetFeatureUsageW( prod, feat, pdwUseCount, pwDateUsed );
2687 end:
2688 msi_free( prod );
2689 msi_free( feat );
2691 return ret;
2694 /***********************************************************************
2695 * MsiUseFeatureExW [MSI.@]
2697 INSTALLSTATE WINAPI MsiUseFeatureExW( LPCWSTR szProduct, LPCWSTR szFeature,
2698 DWORD dwInstallMode, DWORD dwReserved )
2700 INSTALLSTATE state;
2702 TRACE("%s %s %i %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
2703 dwInstallMode, dwReserved);
2705 state = MsiQueryFeatureStateW( szProduct, szFeature );
2707 if (dwReserved)
2708 return INSTALLSTATE_INVALIDARG;
2710 if (state == INSTALLSTATE_LOCAL && dwInstallMode != INSTALLMODE_NODETECTION)
2712 FIXME("mark product %s feature %s as used\n",
2713 debugstr_w(szProduct), debugstr_w(szFeature) );
2716 return state;
2719 /***********************************************************************
2720 * MsiUseFeatureExA [MSI.@]
2722 INSTALLSTATE WINAPI MsiUseFeatureExA( LPCSTR szProduct, LPCSTR szFeature,
2723 DWORD dwInstallMode, DWORD dwReserved )
2725 INSTALLSTATE ret = INSTALLSTATE_UNKNOWN;
2726 LPWSTR prod = NULL, feat = NULL;
2728 TRACE("%s %s %i %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
2729 dwInstallMode, dwReserved);
2731 prod = strdupAtoW( szProduct );
2732 if (szProduct && !prod)
2733 goto end;
2735 feat = strdupAtoW( szFeature );
2736 if (szFeature && !feat)
2737 goto end;
2739 ret = MsiUseFeatureExW( prod, feat, dwInstallMode, dwReserved );
2741 end:
2742 msi_free( prod );
2743 msi_free( feat );
2745 return ret;
2748 /***********************************************************************
2749 * MsiUseFeatureW [MSI.@]
2751 INSTALLSTATE WINAPI MsiUseFeatureW( LPCWSTR szProduct, LPCWSTR szFeature )
2753 return MsiUseFeatureExW(szProduct, szFeature, 0, 0);
2756 /***********************************************************************
2757 * MsiUseFeatureA [MSI.@]
2759 INSTALLSTATE WINAPI MsiUseFeatureA( LPCSTR szProduct, LPCSTR szFeature )
2761 return MsiUseFeatureExA(szProduct, szFeature, 0, 0);
2764 /***********************************************************************
2765 * MSI_ProvideQualifiedComponentEx [internal]
2767 static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
2768 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2769 DWORD Unused1, DWORD Unused2, awstring *lpPathBuf,
2770 LPDWORD pcchPathBuf)
2772 WCHAR product[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1],
2773 feature[MAX_FEATURE_CHARS+1];
2774 LPWSTR info;
2775 HKEY hkey;
2776 DWORD sz;
2777 UINT rc;
2779 TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent),
2780 debugstr_w(szQualifier), dwInstallMode, debugstr_w(szProduct),
2781 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2783 rc = MSIREG_OpenUserComponentsKey(szComponent, &hkey, FALSE);
2784 if (rc != ERROR_SUCCESS)
2785 return ERROR_INDEX_ABSENT;
2787 info = msi_reg_get_val_str( hkey, szQualifier );
2788 RegCloseKey(hkey);
2790 if (!info)
2791 return ERROR_INDEX_ABSENT;
2793 MsiDecomposeDescriptorW(info, product, feature, component, &sz);
2795 if (!szProduct)
2796 rc = MSI_GetComponentPath(product, component, lpPathBuf, pcchPathBuf);
2797 else
2798 rc = MSI_GetComponentPath(szProduct, component, lpPathBuf, pcchPathBuf);
2800 msi_free( info );
2802 if (rc != INSTALLSTATE_LOCAL)
2803 return ERROR_FILE_NOT_FOUND;
2805 return ERROR_SUCCESS;
2808 /***********************************************************************
2809 * MsiProvideQualifiedComponentExW [MSI.@]
2811 UINT WINAPI MsiProvideQualifiedComponentExW(LPCWSTR szComponent,
2812 LPCWSTR szQualifier, DWORD dwInstallMode, LPCWSTR szProduct,
2813 DWORD Unused1, DWORD Unused2, LPWSTR lpPathBuf,
2814 LPDWORD pcchPathBuf)
2816 awstring path;
2818 path.unicode = TRUE;
2819 path.str.w = lpPathBuf;
2821 return MSI_ProvideQualifiedComponentEx(szComponent, szQualifier,
2822 dwInstallMode, szProduct, Unused1, Unused2, &path, pcchPathBuf);
2825 /***********************************************************************
2826 * MsiProvideQualifiedComponentExA [MSI.@]
2828 UINT WINAPI MsiProvideQualifiedComponentExA(LPCSTR szComponent,
2829 LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct,
2830 DWORD Unused1, DWORD Unused2, LPSTR lpPathBuf,
2831 LPDWORD pcchPathBuf)
2833 LPWSTR szwComponent, szwQualifier = NULL, szwProduct = NULL;
2834 UINT r = ERROR_OUTOFMEMORY;
2835 awstring path;
2837 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent),
2838 debugstr_a(szQualifier), dwInstallMode, debugstr_a(szProduct),
2839 Unused1, Unused2, lpPathBuf, pcchPathBuf);
2841 szwComponent = strdupAtoW( szComponent );
2842 if (szComponent && !szwComponent)
2843 goto end;
2845 szwQualifier = strdupAtoW( szQualifier );
2846 if (szQualifier && !szwQualifier)
2847 goto end;
2849 szwProduct = strdupAtoW( szProduct );
2850 if (szProduct && !szwProduct)
2851 goto end;
2853 path.unicode = FALSE;
2854 path.str.a = lpPathBuf;
2856 r = MSI_ProvideQualifiedComponentEx(szwComponent, szwQualifier,
2857 dwInstallMode, szwProduct, Unused1,
2858 Unused2, &path, pcchPathBuf);
2859 end:
2860 msi_free(szwProduct);
2861 msi_free(szwComponent);
2862 msi_free(szwQualifier);
2864 return r;
2867 /***********************************************************************
2868 * MsiProvideQualifiedComponentW [MSI.@]
2870 UINT WINAPI MsiProvideQualifiedComponentW( LPCWSTR szComponent,
2871 LPCWSTR szQualifier, DWORD dwInstallMode, LPWSTR lpPathBuf,
2872 LPDWORD pcchPathBuf)
2874 return MsiProvideQualifiedComponentExW(szComponent, szQualifier,
2875 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2878 /***********************************************************************
2879 * MsiProvideQualifiedComponentA [MSI.@]
2881 UINT WINAPI MsiProvideQualifiedComponentA( LPCSTR szComponent,
2882 LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf,
2883 LPDWORD pcchPathBuf)
2885 return MsiProvideQualifiedComponentExA(szComponent, szQualifier,
2886 dwInstallMode, NULL, 0, 0, lpPathBuf, pcchPathBuf);
2889 /***********************************************************************
2890 * MSI_GetUserInfo [internal]
2892 static USERINFOSTATE MSI_GetUserInfo(LPCWSTR szProduct,
2893 awstring *lpUserNameBuf, LPDWORD pcchUserNameBuf,
2894 awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2895 awstring *lpSerialBuf, LPDWORD pcchSerialBuf)
2897 WCHAR squished_pc[SQUISH_GUID_SIZE];
2898 LPWSTR user, org, serial;
2899 USERINFOSTATE state;
2900 HKEY hkey, props;
2901 LPCWSTR orgptr;
2902 UINT r;
2904 static const WCHAR szEmpty[] = {0};
2906 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf,
2907 pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf,
2908 pcchSerialBuf);
2910 if (!szProduct || !squash_guid(szProduct, squished_pc))
2911 return USERINFOSTATE_INVALIDARG;
2913 if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
2914 &hkey, FALSE) != ERROR_SUCCESS &&
2915 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2916 &hkey, FALSE) != ERROR_SUCCESS &&
2917 MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2918 &hkey, FALSE) != ERROR_SUCCESS)
2920 return USERINFOSTATE_UNKNOWN;
2923 if (MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2924 NULL, &props, FALSE) != ERROR_SUCCESS &&
2925 MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE,
2926 NULL, &props, FALSE) != ERROR_SUCCESS)
2928 RegCloseKey(hkey);
2929 return USERINFOSTATE_ABSENT;
2932 user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW);
2933 org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW);
2934 serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW);
2935 state = USERINFOSTATE_ABSENT;
2937 RegCloseKey(hkey);
2938 RegCloseKey(props);
2940 if (user && serial)
2941 state = USERINFOSTATE_PRESENT;
2943 if (pcchUserNameBuf)
2945 if (lpUserNameBuf && !user)
2947 (*pcchUserNameBuf)--;
2948 goto done;
2951 r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf);
2952 if (r == ERROR_MORE_DATA)
2954 state = USERINFOSTATE_MOREDATA;
2955 goto done;
2959 if (pcchOrgNameBuf)
2961 orgptr = org;
2962 if (!orgptr) orgptr = szEmpty;
2964 r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf);
2965 if (r == ERROR_MORE_DATA)
2967 state = USERINFOSTATE_MOREDATA;
2968 goto done;
2972 if (pcchSerialBuf)
2974 if (!serial)
2976 (*pcchSerialBuf)--;
2977 goto done;
2980 r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf);
2981 if (r == ERROR_MORE_DATA)
2982 state = USERINFOSTATE_MOREDATA;
2985 done:
2986 msi_free(user);
2987 msi_free(org);
2988 msi_free(serial);
2990 return state;
2993 /***********************************************************************
2994 * MsiGetUserInfoW [MSI.@]
2996 USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct,
2997 LPWSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
2998 LPWSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
2999 LPWSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3001 awstring user, org, serial;
3003 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3004 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3005 (lpSerialBuf && !pcchSerialBuf))
3006 return USERINFOSTATE_INVALIDARG;
3008 user.unicode = TRUE;
3009 user.str.w = lpUserNameBuf;
3010 org.unicode = TRUE;
3011 org.str.w = lpOrgNameBuf;
3012 serial.unicode = TRUE;
3013 serial.str.w = lpSerialBuf;
3015 return MSI_GetUserInfo( szProduct, &user, pcchUserNameBuf,
3016 &org, pcchOrgNameBuf,
3017 &serial, pcchSerialBuf );
3020 USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct,
3021 LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf,
3022 LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf,
3023 LPSTR lpSerialBuf, LPDWORD pcchSerialBuf)
3025 awstring user, org, serial;
3026 LPWSTR prod;
3027 UINT r;
3029 if ((lpUserNameBuf && !pcchUserNameBuf) ||
3030 (lpOrgNameBuf && !pcchOrgNameBuf) ||
3031 (lpSerialBuf && !pcchSerialBuf))
3032 return USERINFOSTATE_INVALIDARG;
3034 prod = strdupAtoW( szProduct );
3035 if (szProduct && !prod)
3036 return ERROR_OUTOFMEMORY;
3038 user.unicode = FALSE;
3039 user.str.a = lpUserNameBuf;
3040 org.unicode = FALSE;
3041 org.str.a = lpOrgNameBuf;
3042 serial.unicode = FALSE;
3043 serial.str.a = lpSerialBuf;
3045 r = MSI_GetUserInfo( prod, &user, pcchUserNameBuf,
3046 &org, pcchOrgNameBuf,
3047 &serial, pcchSerialBuf );
3049 msi_free( prod );
3051 return r;
3054 UINT WINAPI MsiCollectUserInfoW(LPCWSTR szProduct)
3056 MSIHANDLE handle;
3057 UINT rc;
3058 MSIPACKAGE *package;
3059 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3061 TRACE("(%s)\n",debugstr_w(szProduct));
3063 rc = MsiOpenProductW(szProduct,&handle);
3064 if (rc != ERROR_SUCCESS)
3065 return ERROR_INVALID_PARAMETER;
3067 /* MsiCollectUserInfo cannot be called from a custom action. */
3068 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3069 if (!package)
3070 return ERROR_CALL_NOT_IMPLEMENTED;
3072 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
3073 msiobj_release( &package->hdr );
3075 MsiCloseHandle(handle);
3077 return rc;
3080 UINT WINAPI MsiCollectUserInfoA(LPCSTR szProduct)
3082 MSIHANDLE handle;
3083 UINT rc;
3084 MSIPACKAGE *package;
3085 static const WCHAR szFirstRun[] = {'F','i','r','s','t','R','u','n',0};
3087 TRACE("(%s)\n",debugstr_a(szProduct));
3089 rc = MsiOpenProductA(szProduct,&handle);
3090 if (rc != ERROR_SUCCESS)
3091 return ERROR_INVALID_PARAMETER;
3093 /* MsiCollectUserInfo cannot be called from a custom action. */
3094 package = msihandle2msiinfo(handle, MSIHANDLETYPE_PACKAGE);
3095 if (!package)
3096 return ERROR_CALL_NOT_IMPLEMENTED;
3098 rc = ACTION_PerformUIAction(package, szFirstRun, -1);
3099 msiobj_release( &package->hdr );
3101 MsiCloseHandle(handle);
3103 return rc;
3106 /***********************************************************************
3107 * MsiConfigureFeatureA [MSI.@]
3109 UINT WINAPI MsiConfigureFeatureA(LPCSTR szProduct, LPCSTR szFeature, INSTALLSTATE eInstallState)
3111 LPWSTR prod, feat = NULL;
3112 UINT r = ERROR_OUTOFMEMORY;
3114 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature), eInstallState);
3116 prod = strdupAtoW( szProduct );
3117 if (szProduct && !prod)
3118 goto end;
3120 feat = strdupAtoW( szFeature );
3121 if (szFeature && !feat)
3122 goto end;
3124 r = MsiConfigureFeatureW(prod, feat, eInstallState);
3126 end:
3127 msi_free(feat);
3128 msi_free(prod);
3130 return r;
3133 /***********************************************************************
3134 * MsiConfigureFeatureW [MSI.@]
3136 UINT WINAPI MsiConfigureFeatureW(LPCWSTR szProduct, LPCWSTR szFeature, INSTALLSTATE eInstallState)
3138 static const WCHAR szCostInit[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
3139 MSIPACKAGE *package = NULL;
3140 UINT r;
3141 WCHAR sourcepath[MAX_PATH], filename[MAX_PATH];
3142 DWORD sz;
3144 TRACE("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature), eInstallState);
3146 if (!szProduct || !szFeature)
3147 return ERROR_INVALID_PARAMETER;
3149 switch (eInstallState)
3151 case INSTALLSTATE_DEFAULT:
3152 /* FIXME: how do we figure out the default location? */
3153 eInstallState = INSTALLSTATE_LOCAL;
3154 break;
3155 case INSTALLSTATE_LOCAL:
3156 case INSTALLSTATE_SOURCE:
3157 case INSTALLSTATE_ABSENT:
3158 case INSTALLSTATE_ADVERTISED:
3159 break;
3160 default:
3161 return ERROR_INVALID_PARAMETER;
3164 r = MSI_OpenProductW( szProduct, &package );
3165 if (r != ERROR_SUCCESS)
3166 return r;
3168 sz = sizeof(sourcepath);
3169 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3170 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3172 sz = sizeof(filename);
3173 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3174 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3176 lstrcatW( sourcepath, filename );
3178 MsiSetInternalUI( INSTALLUILEVEL_BASIC, NULL );
3180 r = ACTION_PerformUIAction( package, szCostInit, -1 );
3181 if (r != ERROR_SUCCESS)
3182 goto end;
3184 r = MSI_SetFeatureStateW( package, szFeature, eInstallState);
3185 if (r != ERROR_SUCCESS)
3186 goto end;
3188 r = MSI_InstallPackage( package, sourcepath, NULL );
3190 end:
3191 msiobj_release( &package->hdr );
3193 return r;
3196 /***********************************************************************
3197 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3199 * Notes: undocumented
3201 UINT WINAPI MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved)
3203 WCHAR path[MAX_PATH];
3205 TRACE("%d\n", dwReserved);
3207 if (dwReserved)
3209 FIXME("dwReserved=%d\n", dwReserved);
3210 return ERROR_INVALID_PARAMETER;
3213 if (!GetWindowsDirectoryW(path, MAX_PATH))
3214 return ERROR_FUNCTION_FAILED;
3216 lstrcatW(path, installerW);
3218 if (!CreateDirectoryW(path, NULL))
3219 return ERROR_FUNCTION_FAILED;
3221 return ERROR_SUCCESS;
3224 /***********************************************************************
3225 * MsiGetShortcutTargetA [MSI.@]
3227 UINT WINAPI MsiGetShortcutTargetA( LPCSTR szShortcutTarget,
3228 LPSTR szProductCode, LPSTR szFeatureId,
3229 LPSTR szComponentCode )
3231 LPWSTR target;
3232 const int len = MAX_FEATURE_CHARS+1;
3233 WCHAR product[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1], component[MAX_FEATURE_CHARS+1];
3234 UINT r;
3236 target = strdupAtoW( szShortcutTarget );
3237 if (szShortcutTarget && !target )
3238 return ERROR_OUTOFMEMORY;
3239 product[0] = 0;
3240 feature[0] = 0;
3241 component[0] = 0;
3242 r = MsiGetShortcutTargetW( target, product, feature, component );
3243 msi_free( target );
3244 if (r == ERROR_SUCCESS)
3246 WideCharToMultiByte( CP_ACP, 0, product, -1, szProductCode, len, NULL, NULL );
3247 WideCharToMultiByte( CP_ACP, 0, feature, -1, szFeatureId, len, NULL, NULL );
3248 WideCharToMultiByte( CP_ACP, 0, component, -1, szComponentCode, len, NULL, NULL );
3250 return r;
3253 /***********************************************************************
3254 * MsiGetShortcutTargetW [MSI.@]
3256 UINT WINAPI MsiGetShortcutTargetW( LPCWSTR szShortcutTarget,
3257 LPWSTR szProductCode, LPWSTR szFeatureId,
3258 LPWSTR szComponentCode )
3260 IShellLinkDataList *dl = NULL;
3261 IPersistFile *pf = NULL;
3262 LPEXP_DARWIN_LINK darwin = NULL;
3263 HRESULT r, init;
3265 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget),
3266 szProductCode, szFeatureId, szComponentCode );
3268 init = CoInitialize(NULL);
3270 r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
3271 &IID_IPersistFile, (LPVOID*) &pf );
3272 if( SUCCEEDED( r ) )
3274 r = IPersistFile_Load( pf, szShortcutTarget,
3275 STGM_READ | STGM_SHARE_DENY_WRITE );
3276 if( SUCCEEDED( r ) )
3278 r = IPersistFile_QueryInterface( pf, &IID_IShellLinkDataList,
3279 (LPVOID*) &dl );
3280 if( SUCCEEDED( r ) )
3282 IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG,
3283 (LPVOID) &darwin );
3284 IShellLinkDataList_Release( dl );
3287 IPersistFile_Release( pf );
3290 if (SUCCEEDED(init))
3291 CoUninitialize();
3293 TRACE("darwin = %p\n", darwin);
3295 if (darwin)
3297 DWORD sz;
3298 UINT ret;
3300 ret = MsiDecomposeDescriptorW( darwin->szwDarwinID,
3301 szProductCode, szFeatureId, szComponentCode, &sz );
3302 LocalFree( darwin );
3303 return ret;
3306 return ERROR_FUNCTION_FAILED;
3309 UINT WINAPI MsiReinstallFeatureW( LPCWSTR szProduct, LPCWSTR szFeature,
3310 DWORD dwReinstallMode )
3312 MSIPACKAGE* package = NULL;
3313 UINT r;
3314 WCHAR sourcepath[MAX_PATH];
3315 WCHAR filename[MAX_PATH];
3316 static const WCHAR szLogVerbose[] = {
3317 ' ','L','O','G','V','E','R','B','O','S','E',0 };
3318 static const WCHAR szInstalled[] = { 'I','n','s','t','a','l','l','e','d',0};
3319 static const WCHAR szReinstall[] = {'R','E','I','N','S','T','A','L','L',0};
3320 static const WCHAR szReinstallMode[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
3321 static const WCHAR szOne[] = {'1',0};
3322 WCHAR reinstallmode[11];
3323 LPWSTR ptr;
3324 DWORD sz;
3326 FIXME("%s %s %i\n", debugstr_w(szProduct), debugstr_w(szFeature),
3327 dwReinstallMode);
3329 ptr = reinstallmode;
3331 if (dwReinstallMode & REINSTALLMODE_FILEMISSING)
3332 *ptr++ = 'p';
3333 if (dwReinstallMode & REINSTALLMODE_FILEOLDERVERSION)
3334 *ptr++ = 'o';
3335 if (dwReinstallMode & REINSTALLMODE_FILEEQUALVERSION)
3336 *ptr++ = 'w';
3337 if (dwReinstallMode & REINSTALLMODE_FILEEXACT)
3338 *ptr++ = 'd';
3339 if (dwReinstallMode & REINSTALLMODE_FILEVERIFY)
3340 *ptr++ = 'c';
3341 if (dwReinstallMode & REINSTALLMODE_FILEREPLACE)
3342 *ptr++ = 'a';
3343 if (dwReinstallMode & REINSTALLMODE_USERDATA)
3344 *ptr++ = 'u';
3345 if (dwReinstallMode & REINSTALLMODE_MACHINEDATA)
3346 *ptr++ = 'm';
3347 if (dwReinstallMode & REINSTALLMODE_SHORTCUT)
3348 *ptr++ = 's';
3349 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
3350 *ptr++ = 'v';
3351 *ptr = 0;
3353 sz = sizeof(sourcepath);
3354 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3355 MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz);
3357 sz = sizeof(filename);
3358 MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3359 MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz);
3361 lstrcatW( sourcepath, filename );
3363 if (dwReinstallMode & REINSTALLMODE_PACKAGE)
3364 r = MSI_OpenPackageW( sourcepath, &package );
3365 else
3366 r = MSI_OpenProductW( szProduct, &package );
3368 if (r != ERROR_SUCCESS)
3369 return r;
3371 MSI_SetPropertyW( package, szReinstallMode, reinstallmode );
3372 MSI_SetPropertyW( package, szInstalled, szOne );
3373 MSI_SetPropertyW( package, szLogVerbose, szOne );
3374 MSI_SetPropertyW( package, szReinstall, szFeature );
3376 r = MSI_InstallPackage( package, sourcepath, NULL );
3378 msiobj_release( &package->hdr );
3380 return r;
3383 UINT WINAPI MsiReinstallFeatureA( LPCSTR szProduct, LPCSTR szFeature,
3384 DWORD dwReinstallMode )
3386 LPWSTR wszProduct;
3387 LPWSTR wszFeature;
3388 UINT rc;
3390 TRACE("%s %s %i\n", debugstr_a(szProduct), debugstr_a(szFeature),
3391 dwReinstallMode);
3393 wszProduct = strdupAtoW(szProduct);
3394 wszFeature = strdupAtoW(szFeature);
3396 rc = MsiReinstallFeatureW(wszProduct, wszFeature, dwReinstallMode);
3398 msi_free(wszProduct);
3399 msi_free(wszFeature);
3400 return rc;
3403 typedef struct
3405 unsigned int i[2];
3406 unsigned int buf[4];
3407 unsigned char in[64];
3408 unsigned char digest[16];
3409 } MD5_CTX;
3411 extern VOID WINAPI MD5Init( MD5_CTX *);
3412 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
3413 extern VOID WINAPI MD5Final( MD5_CTX *);
3415 /***********************************************************************
3416 * MsiGetFileHashW [MSI.@]
3418 UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
3419 PMSIFILEHASHINFO pHash )
3421 HANDLE handle, mapping;
3422 void *p;
3423 DWORD length;
3424 UINT r = ERROR_FUNCTION_FAILED;
3426 TRACE("%s %08x %p\n", debugstr_w(szFilePath), dwOptions, pHash );
3428 if (!szFilePath)
3429 return ERROR_INVALID_PARAMETER;
3431 if (!*szFilePath)
3432 return ERROR_PATH_NOT_FOUND;
3434 if (dwOptions)
3435 return ERROR_INVALID_PARAMETER;
3436 if (!pHash)
3437 return ERROR_INVALID_PARAMETER;
3438 if (pHash->dwFileHashInfoSize < sizeof *pHash)
3439 return ERROR_INVALID_PARAMETER;
3441 handle = CreateFileW( szFilePath, GENERIC_READ,
3442 FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
3443 if (handle == INVALID_HANDLE_VALUE)
3444 return ERROR_FILE_NOT_FOUND;
3446 length = GetFileSize( handle, NULL );
3448 mapping = CreateFileMappingW( handle, NULL, PAGE_READONLY, 0, 0, NULL );
3449 if (mapping)
3451 p = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, length );
3452 if (p)
3454 MD5_CTX ctx;
3456 MD5Init( &ctx );
3457 MD5Update( &ctx, p, length );
3458 MD5Final( &ctx );
3459 UnmapViewOfFile( p );
3461 memcpy( pHash->dwData, ctx.digest, sizeof pHash->dwData );
3462 r = ERROR_SUCCESS;
3464 CloseHandle( mapping );
3466 CloseHandle( handle );
3468 return r;
3471 /***********************************************************************
3472 * MsiGetFileHashA [MSI.@]
3474 UINT WINAPI MsiGetFileHashA( LPCSTR szFilePath, DWORD dwOptions,
3475 PMSIFILEHASHINFO pHash )
3477 LPWSTR file;
3478 UINT r;
3480 TRACE("%s %08x %p\n", debugstr_a(szFilePath), dwOptions, pHash );
3482 file = strdupAtoW( szFilePath );
3483 if (szFilePath && !file)
3484 return ERROR_OUTOFMEMORY;
3486 r = MsiGetFileHashW( file, dwOptions, pHash );
3487 msi_free( file );
3488 return r;
3491 /***********************************************************************
3492 * MsiAdvertiseScriptW [MSI.@]
3494 UINT WINAPI MsiAdvertiseScriptW( LPCWSTR szScriptFile, DWORD dwFlags,
3495 PHKEY phRegData, BOOL fRemoveItems )
3497 FIXME("%s %08x %p %d\n",
3498 debugstr_w( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3499 return ERROR_CALL_NOT_IMPLEMENTED;
3502 /***********************************************************************
3503 * MsiAdvertiseScriptA [MSI.@]
3505 UINT WINAPI MsiAdvertiseScriptA( LPCSTR szScriptFile, DWORD dwFlags,
3506 PHKEY phRegData, BOOL fRemoveItems )
3508 FIXME("%s %08x %p %d\n",
3509 debugstr_a( szScriptFile ), dwFlags, phRegData, fRemoveItems );
3510 return ERROR_CALL_NOT_IMPLEMENTED;
3513 /***********************************************************************
3514 * MsiIsProductElevatedW [MSI.@]
3516 UINT WINAPI MsiIsProductElevatedW( LPCWSTR szProduct, BOOL *pfElevated )
3518 FIXME("%s %p - stub\n",
3519 debugstr_w( szProduct ), pfElevated );
3520 *pfElevated = TRUE;
3521 return ERROR_SUCCESS;
3524 /***********************************************************************
3525 * MsiIsProductElevatedA [MSI.@]
3527 UINT WINAPI MsiIsProductElevatedA( LPCSTR szProduct, BOOL *pfElevated )
3529 FIXME("%s %p - stub\n",
3530 debugstr_a( szProduct ), pfElevated );
3531 *pfElevated = TRUE;
3532 return ERROR_SUCCESS;
3535 /***********************************************************************
3536 * MsiSetExternalUIRecord [MSI.@]
3538 UINT WINAPI MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD puiHandler,
3539 DWORD dwMessageFilter, LPVOID pvContext,
3540 PINSTALLUI_HANDLER_RECORD ppuiPrevHandler)
3542 FIXME("%p %08x %p %p\n", puiHandler, dwMessageFilter ,pvContext,
3543 ppuiPrevHandler);
3544 return ERROR_CALL_NOT_IMPLEMENTED;
3547 /***********************************************************************
3548 * MsiInstallMissingComponentW [MSI.@]
3550 UINT WINAPI MsiInstallMissingComponentW(LPCWSTR szProduct, LPCWSTR szComponent, INSTALLSTATE eInstallState)
3552 FIXME("(%s %s %d\n", debugstr_w(szProduct), debugstr_w(szComponent), eInstallState);
3553 return ERROR_SUCCESS;