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
24 #define NONAMELESSUNION
31 #include "wine/debug.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
)
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
;
67 if (*context
== MSIINSTALLCONTEXT_NONE
)
68 return ERROR_UNKNOWN_PRODUCT
;
73 UINT WINAPI
MsiOpenProductA(LPCSTR szProduct
, MSIHANDLE
*phProduct
)
76 LPWSTR szwProd
= NULL
;
78 TRACE("%s %p\n",debugstr_a(szProduct
), phProduct
);
82 szwProd
= strdupAtoW( szProduct
);
84 return ERROR_OUTOFMEMORY
;
87 r
= MsiOpenProductW( szwProd
, phProduct
);
94 static UINT
MSI_OpenProductW(LPCWSTR szProduct
, MSIPACKAGE
**package
)
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
)
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
);
118 path
= msi_reg_get_val_str(props
, local
);
120 r
= ERROR_UNKNOWN_PRODUCT
;
122 if (!path
|| GetFileAttributesW(path
) == INVALID_FILE_ATTRIBUTES
)
125 if (PathIsRelativeW(path
))
127 r
= ERROR_INSTALL_PACKAGE_OPEN_FAILED
;
131 r
= MSI_OpenPackageW(path
, package
);
139 UINT WINAPI
MsiOpenProductW(LPCWSTR szProduct
, MSIHANDLE
*phProduct
)
141 MSIPACKAGE
*package
= NULL
;
142 WCHAR squished_pc
[GUID_SIZE
];
145 if (!szProduct
|| !squash_guid(szProduct
, squished_pc
))
146 return ERROR_INVALID_PARAMETER
;
149 return ERROR_INVALID_PARAMETER
;
151 r
= MSI_OpenProductW(szProduct
, &package
);
152 if (r
!= ERROR_SUCCESS
)
155 *phProduct
= alloc_msihandle(&package
->hdr
);
157 r
= ERROR_NOT_ENOUGH_MEMORY
;
159 msiobj_release(&package
->hdr
);
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
));
206 szwPath
= strdupAtoW( szPackagePath
);
213 szwCommand
= strdupAtoW( szCommandLine
);
218 r
= MsiInstallProductW( szwPath
, szwCommand
);
222 msi_free( szwCommand
);
227 UINT WINAPI
MsiInstallProductW(LPCWSTR szPackagePath
, LPCWSTR szCommandLine
)
229 MSIPACKAGE
*package
= NULL
;
232 TRACE("%s %s\n",debugstr_w(szPackagePath
), debugstr_w(szCommandLine
));
234 r
= MSI_OpenPackageW( szPackagePath
, &package
);
235 if (r
== ERROR_SUCCESS
)
237 r
= MSI_InstallPackage( package
, szPackagePath
, szCommandLine
);
238 msiobj_release( &package
->hdr
);
244 UINT WINAPI
MsiReinstallProductA(LPCSTR szProduct
, DWORD dwReinstallMode
)
246 FIXME("%s %08x\n", debugstr_a(szProduct
), dwReinstallMode
);
247 return ERROR_CALL_NOT_IMPLEMENTED
;
250 UINT WINAPI
MsiReinstallProductW(LPCWSTR szProduct
, DWORD dwReinstallMode
)
252 FIXME("%s %08x\n", debugstr_w(szProduct
), dwReinstallMode
);
253 return ERROR_CALL_NOT_IMPLEMENTED
;
256 UINT WINAPI
MsiApplyPatchA(LPCSTR szPatchPackage
, LPCSTR szInstallPackage
,
257 INSTALLTYPE eInstallType
, LPCSTR szCommandLine
)
259 LPWSTR patch_package
= NULL
;
260 LPWSTR install_package
= NULL
;
261 LPWSTR command_line
= NULL
;
262 UINT r
= ERROR_OUTOFMEMORY
;
264 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage
), debugstr_a(szInstallPackage
),
265 eInstallType
, debugstr_a(szCommandLine
));
267 if (szPatchPackage
&& !(patch_package
= strdupAtoW(szPatchPackage
)))
270 if (szInstallPackage
&& !(install_package
= strdupAtoW(szInstallPackage
)))
273 if (szCommandLine
&& !(command_line
= strdupAtoW(szCommandLine
)))
276 r
= MsiApplyPatchW(patch_package
, install_package
, eInstallType
, command_line
);
279 msi_free(patch_package
);
280 msi_free(install_package
);
281 msi_free(command_line
);
286 UINT WINAPI
MsiApplyPatchW(LPCWSTR szPatchPackage
, LPCWSTR szInstallPackage
,
287 INSTALLTYPE eInstallType
, LPCWSTR szCommandLine
)
289 MSIHANDLE patch
, info
;
292 LPCWSTR cmd_ptr
= szCommandLine
;
294 LPWSTR cmd
= NULL
, codes
= NULL
;
296 static const WCHAR space
[] = {' ',0};
297 static const WCHAR patcheq
[] = {'P','A','T','C','H','=',0};
298 static WCHAR empty
[] = {0};
300 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage
), debugstr_w(szInstallPackage
),
301 eInstallType
, debugstr_w(szCommandLine
));
303 if (szInstallPackage
|| eInstallType
== INSTALLTYPE_NETWORK_IMAGE
||
304 eInstallType
== INSTALLTYPE_SINGLE_INSTANCE
)
306 FIXME("Only reading target products from patch\n");
307 return ERROR_CALL_NOT_IMPLEMENTED
;
310 r
= MsiOpenDatabaseW(szPatchPackage
, MSIDBOPEN_READONLY
, &patch
);
311 if (r
!= ERROR_SUCCESS
)
314 r
= MsiGetSummaryInformationW(patch
, NULL
, 0, &info
);
315 if (r
!= ERROR_SUCCESS
)
318 r
= MsiSummaryInfoGetPropertyW(info
, PID_TEMPLATE
, &type
, NULL
, NULL
, empty
, &size
);
319 if (r
!= ERROR_MORE_DATA
|| !size
|| type
!= VT_LPSTR
)
321 ERR("Failed to read product codes from patch\n");
325 codes
= msi_alloc(++size
* sizeof(WCHAR
));
328 r
= ERROR_OUTOFMEMORY
;
332 r
= MsiSummaryInfoGetPropertyW(info
, PID_TEMPLATE
, &type
, NULL
, NULL
, codes
, &size
);
333 if (r
!= ERROR_SUCCESS
)
339 size
= lstrlenW(cmd_ptr
) + lstrlenW(patcheq
) + lstrlenW(szPatchPackage
) + 1;
340 cmd
= msi_alloc(size
* sizeof(WCHAR
));
343 r
= ERROR_OUTOFMEMORY
;
347 lstrcpyW(cmd
, cmd_ptr
);
348 if (szCommandLine
) lstrcatW(cmd
, space
);
349 lstrcatW(cmd
, patcheq
);
350 lstrcatW(cmd
, szPatchPackage
);
353 while ((end
= strchrW(beg
, '}')))
357 r
= MsiConfigureProductExW(beg
, INSTALLLEVEL_DEFAULT
, INSTALLSTATE_DEFAULT
, cmd
);
358 if (r
!= ERROR_SUCCESS
)
368 MsiCloseHandle(info
);
369 MsiCloseHandle(patch
);
374 UINT WINAPI
MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath
,
375 DWORD cPatchInfo
, PMSIPATCHSEQUENCEINFOA pPatchInfo
)
377 FIXME("(%s, %d, %p): stub!\n", debugstr_a(szProductPackagePath
),
378 cPatchInfo
, pPatchInfo
);
380 return ERROR_CALL_NOT_IMPLEMENTED
;
383 UINT WINAPI
MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath
,
384 DWORD cPatchInfo
, PMSIPATCHSEQUENCEINFOW pPatchInfo
)
386 FIXME("(%s, %d, %p): stub!\n", debugstr_w(szProductPackagePath
),
387 cPatchInfo
, pPatchInfo
);
389 return ERROR_CALL_NOT_IMPLEMENTED
;
392 static UINT
msi_open_package(LPCWSTR product
, MSIINSTALLCONTEXT context
,
393 MSIPACKAGE
**package
)
399 WCHAR sourcepath
[MAX_PATH
];
400 WCHAR filename
[MAX_PATH
];
402 static const WCHAR szLocalPackage
[] = {
403 'L','o','c','a','l','P','a','c','k','a','g','e',0};
406 r
= MSIREG_OpenInstallProps(product
, context
, NULL
, &props
, FALSE
);
407 if (r
!= ERROR_SUCCESS
)
408 return ERROR_BAD_CONFIGURATION
;
410 localpack
= msi_reg_get_val_str(props
, szLocalPackage
);
413 lstrcpyW(sourcepath
, localpack
);
417 if (!localpack
|| GetFileAttributesW(sourcepath
) == INVALID_FILE_ATTRIBUTES
)
419 sz
= sizeof(sourcepath
);
420 MsiSourceListGetInfoW(product
, NULL
, context
, MSICODE_PRODUCT
,
421 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
423 sz
= sizeof(filename
);
424 MsiSourceListGetInfoW(product
, NULL
, context
, MSICODE_PRODUCT
,
425 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
427 lstrcatW(sourcepath
, filename
);
430 if (GetFileAttributesW(sourcepath
) == INVALID_FILE_ATTRIBUTES
)
431 return ERROR_INSTALL_SOURCE_ABSENT
;
433 return MSI_OpenPackageW(sourcepath
, package
);
436 UINT WINAPI
MsiConfigureProductExW(LPCWSTR szProduct
, int iInstallLevel
,
437 INSTALLSTATE eInstallState
, LPCWSTR szCommandLine
)
439 MSIPACKAGE
* package
= NULL
;
440 MSIINSTALLCONTEXT context
;
443 WCHAR sourcepath
[MAX_PATH
];
446 static const WCHAR szInstalled
[] = {
447 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
448 static const WCHAR szRemoveAll
[] = {
449 ' ','R','E','M','O','V','E','=','A','L','L',0};
450 static const WCHAR szMachine
[] = {
451 ' ','A','L','L','U','S','E','R','S','=','1',0};
453 TRACE("%s %d %d %s\n",debugstr_w(szProduct
), iInstallLevel
, eInstallState
,
454 debugstr_w(szCommandLine
));
456 if (!szProduct
|| lstrlenW(szProduct
) != GUID_SIZE
- 1)
457 return ERROR_INVALID_PARAMETER
;
459 if (eInstallState
== INSTALLSTATE_ADVERTISED
||
460 eInstallState
== INSTALLSTATE_SOURCE
)
462 FIXME("State %d not implemented\n", eInstallState
);
463 return ERROR_CALL_NOT_IMPLEMENTED
;
466 r
= msi_locate_product(szProduct
, &context
);
467 if (r
!= ERROR_SUCCESS
)
470 r
= msi_open_package(szProduct
, context
, &package
);
471 if (r
!= ERROR_SUCCESS
)
474 sz
= lstrlenW(szInstalled
) + 1;
477 sz
+= lstrlenW(szCommandLine
);
479 if (eInstallState
== INSTALLSTATE_ABSENT
)
480 sz
+= lstrlenW(szRemoveAll
);
482 if (context
== MSIINSTALLCONTEXT_MACHINE
)
483 sz
+= lstrlenW(szMachine
);
485 commandline
= msi_alloc(sz
* sizeof(WCHAR
));
488 r
= ERROR_OUTOFMEMORY
;
494 lstrcpyW(commandline
,szCommandLine
);
496 if (MsiQueryProductStateW(szProduct
) != INSTALLSTATE_UNKNOWN
)
497 lstrcatW(commandline
,szInstalled
);
499 if (eInstallState
== INSTALLSTATE_ABSENT
)
500 lstrcatW(commandline
, szRemoveAll
);
502 if (context
== MSIINSTALLCONTEXT_MACHINE
)
503 lstrcatW(commandline
, szMachine
);
505 r
= MSI_InstallPackage( package
, sourcepath
, commandline
);
507 msi_free(commandline
);
510 msiobj_release( &package
->hdr
);
515 UINT WINAPI
MsiConfigureProductExA(LPCSTR szProduct
, int iInstallLevel
,
516 INSTALLSTATE eInstallState
, LPCSTR szCommandLine
)
518 LPWSTR szwProduct
= NULL
;
519 LPWSTR szwCommandLine
= NULL
;
520 UINT r
= ERROR_OUTOFMEMORY
;
524 szwProduct
= strdupAtoW( szProduct
);
531 szwCommandLine
= strdupAtoW( szCommandLine
);
536 r
= MsiConfigureProductExW( szwProduct
, iInstallLevel
, eInstallState
,
539 msi_free( szwProduct
);
540 msi_free( szwCommandLine
);
545 UINT WINAPI
MsiConfigureProductA(LPCSTR szProduct
, int iInstallLevel
,
546 INSTALLSTATE eInstallState
)
548 LPWSTR szwProduct
= NULL
;
551 TRACE("%s %d %d\n",debugstr_a(szProduct
), iInstallLevel
, eInstallState
);
555 szwProduct
= strdupAtoW( szProduct
);
557 return ERROR_OUTOFMEMORY
;
560 r
= MsiConfigureProductW( szwProduct
, iInstallLevel
, eInstallState
);
561 msi_free( szwProduct
);
566 UINT WINAPI
MsiConfigureProductW(LPCWSTR szProduct
, int iInstallLevel
,
567 INSTALLSTATE eInstallState
)
569 return MsiConfigureProductExW(szProduct
, iInstallLevel
, eInstallState
, NULL
);
572 UINT WINAPI
MsiGetProductCodeA(LPCSTR szComponent
, LPSTR szBuffer
)
574 LPWSTR szwComponent
= NULL
;
576 WCHAR szwBuffer
[GUID_SIZE
];
578 TRACE("%s %s\n",debugstr_a(szComponent
), debugstr_a(szBuffer
));
582 szwComponent
= strdupAtoW( szComponent
);
584 return ERROR_OUTOFMEMORY
;
588 r
= MsiGetProductCodeW( szwComponent
, szwBuffer
);
591 WideCharToMultiByte(CP_ACP
, 0, szwBuffer
, -1, szBuffer
, GUID_SIZE
, NULL
, NULL
);
593 msi_free( szwComponent
);
598 UINT WINAPI
MsiGetProductCodeW(LPCWSTR szComponent
, LPWSTR szBuffer
)
601 HKEY compkey
, prodkey
;
602 WCHAR squished_comp
[GUID_SIZE
];
603 WCHAR squished_prod
[GUID_SIZE
];
604 DWORD sz
= GUID_SIZE
;
606 TRACE("%s %p\n", debugstr_w(szComponent
), szBuffer
);
608 if (!szComponent
|| !*szComponent
)
609 return ERROR_INVALID_PARAMETER
;
611 if (!squash_guid(szComponent
, squished_comp
))
612 return ERROR_INVALID_PARAMETER
;
614 if (MSIREG_OpenUserDataComponentKey(szComponent
, NULL
, &compkey
, FALSE
) != ERROR_SUCCESS
&&
615 MSIREG_OpenUserDataComponentKey(szComponent
, szLocalSid
, &compkey
, FALSE
) != ERROR_SUCCESS
)
617 return ERROR_UNKNOWN_COMPONENT
;
620 rc
= RegEnumValueW(compkey
, 0, squished_prod
, &sz
, NULL
, NULL
, NULL
, NULL
);
621 if (rc
!= ERROR_SUCCESS
)
623 RegCloseKey(compkey
);
624 return ERROR_UNKNOWN_COMPONENT
;
627 /* check simple case, only one product */
628 rc
= RegEnumValueW(compkey
, 1, squished_prod
, &sz
, NULL
, NULL
, NULL
, NULL
);
629 if (rc
== ERROR_NO_MORE_ITEMS
)
636 while ((rc
= RegEnumValueW(compkey
, index
, squished_prod
, &sz
,
637 NULL
, NULL
, NULL
, NULL
)) != ERROR_NO_MORE_ITEMS
)
641 unsquash_guid(squished_prod
, szBuffer
);
643 if (MSIREG_OpenProductKey(szBuffer
, NULL
,
644 MSIINSTALLCONTEXT_USERMANAGED
,
645 &prodkey
, FALSE
) == ERROR_SUCCESS
||
646 MSIREG_OpenProductKey(szBuffer
, NULL
,
647 MSIINSTALLCONTEXT_USERUNMANAGED
,
648 &prodkey
, FALSE
) == ERROR_SUCCESS
||
649 MSIREG_OpenProductKey(szBuffer
, NULL
,
650 MSIINSTALLCONTEXT_MACHINE
,
651 &prodkey
, FALSE
) == ERROR_SUCCESS
)
653 RegCloseKey(prodkey
);
659 rc
= ERROR_INSTALL_FAILURE
;
662 RegCloseKey(compkey
);
663 unsquash_guid(squished_prod
, szBuffer
);
667 static LPWSTR
msi_reg_get_value(HKEY hkey
, LPCWSTR name
, DWORD
*type
)
673 static const WCHAR format
[] = {'%','d',0};
675 res
= RegQueryValueExW(hkey
, name
, NULL
, type
, NULL
, NULL
);
676 if (res
!= ERROR_SUCCESS
)
680 return msi_reg_get_val_str(hkey
, name
);
682 if (!msi_reg_get_val_dword(hkey
, name
, &dval
))
685 sprintfW(temp
, format
, dval
);
686 return strdupW(temp
);
689 static UINT
MSI_GetProductInfo(LPCWSTR szProduct
, LPCWSTR szAttribute
,
690 awstring
*szValue
, LPDWORD pcchValueBuf
)
692 MSIINSTALLCONTEXT context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
693 UINT r
= ERROR_UNKNOWN_PROPERTY
;
694 HKEY prodkey
, userdata
, source
;
696 WCHAR squished_pc
[GUID_SIZE
];
697 WCHAR packagecode
[GUID_SIZE
];
698 BOOL badconfig
= FALSE
;
700 DWORD save
, type
= REG_NONE
;
702 static WCHAR empty
[] = {0};
703 static const WCHAR sourcelist
[] = {
704 'S','o','u','r','c','e','L','i','s','t',0};
705 static const WCHAR display_name
[] = {
706 'D','i','s','p','l','a','y','N','a','m','e',0};
707 static const WCHAR display_version
[] = {
708 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
709 static const WCHAR assignment
[] = {
710 'A','s','s','i','g','n','m','e','n','t',0};
712 TRACE("%s %s %p %p\n", debugstr_w(szProduct
),
713 debugstr_w(szAttribute
), szValue
, pcchValueBuf
);
715 if ((szValue
->str
.w
&& !pcchValueBuf
) || !szProduct
|| !szAttribute
)
716 return ERROR_INVALID_PARAMETER
;
718 if (!squash_guid(szProduct
, squished_pc
))
719 return ERROR_INVALID_PARAMETER
;
721 if ((r
= MSIREG_OpenProductKey(szProduct
, NULL
,
722 MSIINSTALLCONTEXT_USERMANAGED
,
723 &prodkey
, FALSE
)) != ERROR_SUCCESS
&&
724 (r
= MSIREG_OpenProductKey(szProduct
, NULL
,
725 MSIINSTALLCONTEXT_USERUNMANAGED
,
726 &prodkey
, FALSE
)) != ERROR_SUCCESS
&&
727 (r
= MSIREG_OpenProductKey(szProduct
, NULL
,
728 MSIINSTALLCONTEXT_MACHINE
,
729 &prodkey
, FALSE
)) == ERROR_SUCCESS
)
731 context
= MSIINSTALLCONTEXT_MACHINE
;
734 MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &userdata
, FALSE
);
736 if (!lstrcmpW(szAttribute
, INSTALLPROPERTY_HELPLINKW
) ||
737 !lstrcmpW(szAttribute
, INSTALLPROPERTY_HELPTELEPHONEW
) ||
738 !lstrcmpW(szAttribute
, INSTALLPROPERTY_INSTALLDATEW
) ||
739 !lstrcmpW(szAttribute
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
) ||
740 !lstrcmpW(szAttribute
, INSTALLPROPERTY_INSTALLLOCATIONW
) ||
741 !lstrcmpW(szAttribute
, INSTALLPROPERTY_INSTALLSOURCEW
) ||
742 !lstrcmpW(szAttribute
, INSTALLPROPERTY_LOCALPACKAGEW
) ||
743 !lstrcmpW(szAttribute
, INSTALLPROPERTY_PUBLISHERW
) ||
744 !lstrcmpW(szAttribute
, INSTALLPROPERTY_URLINFOABOUTW
) ||
745 !lstrcmpW(szAttribute
, INSTALLPROPERTY_URLUPDATEINFOW
) ||
746 !lstrcmpW(szAttribute
, INSTALLPROPERTY_VERSIONMINORW
) ||
747 !lstrcmpW(szAttribute
, INSTALLPROPERTY_VERSIONMAJORW
) ||
748 !lstrcmpW(szAttribute
, INSTALLPROPERTY_VERSIONSTRINGW
) ||
749 !lstrcmpW(szAttribute
, INSTALLPROPERTY_PRODUCTIDW
) ||
750 !lstrcmpW(szAttribute
, INSTALLPROPERTY_REGCOMPANYW
) ||
751 !lstrcmpW(szAttribute
, INSTALLPROPERTY_REGOWNERW
))
755 r
= ERROR_UNKNOWN_PRODUCT
;
760 return ERROR_UNKNOWN_PROPERTY
;
762 if (!lstrcmpW(szAttribute
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
))
763 szAttribute
= display_name
;
764 else if (!lstrcmpW(szAttribute
, INSTALLPROPERTY_VERSIONSTRINGW
))
765 szAttribute
= display_version
;
767 val
= msi_reg_get_value(userdata
, szAttribute
, &type
);
771 else if (!lstrcmpW(szAttribute
, INSTALLPROPERTY_INSTANCETYPEW
) ||
772 !lstrcmpW(szAttribute
, INSTALLPROPERTY_TRANSFORMSW
) ||
773 !lstrcmpW(szAttribute
, INSTALLPROPERTY_LANGUAGEW
) ||
774 !lstrcmpW(szAttribute
, INSTALLPROPERTY_PRODUCTNAMEW
) ||
775 !lstrcmpW(szAttribute
, INSTALLPROPERTY_ASSIGNMENTTYPEW
) ||
776 !lstrcmpW(szAttribute
, INSTALLPROPERTY_PACKAGECODEW
) ||
777 !lstrcmpW(szAttribute
, INSTALLPROPERTY_VERSIONW
) ||
778 !lstrcmpW(szAttribute
, INSTALLPROPERTY_PRODUCTICONW
) ||
779 !lstrcmpW(szAttribute
, INSTALLPROPERTY_PACKAGENAMEW
) ||
780 !lstrcmpW(szAttribute
, INSTALLPROPERTY_AUTHORIZED_LUA_APPW
))
784 r
= ERROR_UNKNOWN_PRODUCT
;
788 if (!lstrcmpW(szAttribute
, INSTALLPROPERTY_ASSIGNMENTTYPEW
))
789 szAttribute
= assignment
;
791 if (!lstrcmpW(szAttribute
, INSTALLPROPERTY_PACKAGENAMEW
))
793 res
= RegOpenKeyW(prodkey
, sourcelist
, &source
);
794 if (res
!= ERROR_SUCCESS
)
796 r
= ERROR_UNKNOWN_PRODUCT
;
800 val
= msi_reg_get_value(source
, szAttribute
, &type
);
808 val
= msi_reg_get_value(prodkey
, szAttribute
, &type
);
813 if (val
!= empty
&& type
!= REG_DWORD
&&
814 !lstrcmpW(szAttribute
, INSTALLPROPERTY_PACKAGECODEW
))
816 if (lstrlenW(val
) != SQUISH_GUID_SIZE
- 1)
820 unsquash_guid(val
, packagecode
);
822 val
= strdupW(packagecode
);
829 r
= ERROR_UNKNOWN_PROPERTY
;
835 save
= *pcchValueBuf
;
837 if (strlenW(val
) < *pcchValueBuf
)
838 r
= msi_strcpy_to_awstring(val
, szValue
, pcchValueBuf
);
839 else if (szValue
->str
.a
|| szValue
->str
.w
)
843 *pcchValueBuf
= lstrlenW(val
);
844 else if (r
== ERROR_SUCCESS
)
846 *pcchValueBuf
= save
;
847 r
= ERROR_BAD_CONFIGURATION
;
851 r
= ERROR_BAD_CONFIGURATION
;
857 RegCloseKey(prodkey
);
858 RegCloseKey(userdata
);
862 UINT WINAPI
MsiGetProductInfoA(LPCSTR szProduct
, LPCSTR szAttribute
,
863 LPSTR szBuffer
, LPDWORD pcchValueBuf
)
865 LPWSTR szwProduct
, szwAttribute
= NULL
;
866 UINT r
= ERROR_OUTOFMEMORY
;
869 TRACE("%s %s %p %p\n", debugstr_a(szProduct
), debugstr_a(szAttribute
),
870 szBuffer
, pcchValueBuf
);
872 szwProduct
= strdupAtoW( szProduct
);
873 if( szProduct
&& !szwProduct
)
876 szwAttribute
= strdupAtoW( szAttribute
);
877 if( szAttribute
&& !szwAttribute
)
880 buffer
.unicode
= FALSE
;
881 buffer
.str
.a
= szBuffer
;
883 r
= MSI_GetProductInfo( szwProduct
, szwAttribute
,
884 &buffer
, pcchValueBuf
);
887 msi_free( szwProduct
);
888 msi_free( szwAttribute
);
893 UINT WINAPI
MsiGetProductInfoW(LPCWSTR szProduct
, LPCWSTR szAttribute
,
894 LPWSTR szBuffer
, LPDWORD pcchValueBuf
)
898 TRACE("%s %s %p %p\n", debugstr_w(szProduct
), debugstr_w(szAttribute
),
899 szBuffer
, pcchValueBuf
);
901 buffer
.unicode
= TRUE
;
902 buffer
.str
.w
= szBuffer
;
904 return MSI_GetProductInfo( szProduct
, szAttribute
,
905 &buffer
, pcchValueBuf
);
908 UINT WINAPI
MsiGetProductInfoExA(LPCSTR szProductCode
, LPCSTR szUserSid
,
909 MSIINSTALLCONTEXT dwContext
, LPCSTR szProperty
,
910 LPSTR szValue
, LPDWORD pcchValue
)
912 LPWSTR product
= NULL
;
913 LPWSTR usersid
= NULL
;
914 LPWSTR property
= NULL
;
919 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode
),
920 debugstr_a(szUserSid
), dwContext
, debugstr_a(szProperty
),
923 if (szValue
&& !pcchValue
)
924 return ERROR_INVALID_PARAMETER
;
926 if (szProductCode
) product
= strdupAtoW(szProductCode
);
927 if (szUserSid
) usersid
= strdupAtoW(szUserSid
);
928 if (szProperty
) property
= strdupAtoW(szProperty
);
930 r
= MsiGetProductInfoExW(product
, usersid
, dwContext
, property
,
932 if (r
!= ERROR_SUCCESS
)
935 value
= msi_alloc(++len
* sizeof(WCHAR
));
938 r
= ERROR_OUTOFMEMORY
;
942 r
= MsiGetProductInfoExW(product
, usersid
, dwContext
, property
,
944 if (r
!= ERROR_SUCCESS
)
950 len
= WideCharToMultiByte(CP_ACP
, 0, value
, -1, NULL
, 0, NULL
, NULL
);
951 if (*pcchValue
>= len
)
952 WideCharToMultiByte(CP_ACP
, 0, value
, -1, szValue
, len
, NULL
, NULL
);
960 if (*pcchValue
<= len
|| !szValue
)
961 len
= len
* sizeof(WCHAR
) - 1;
963 *pcchValue
= len
- 1;
974 static UINT
msi_copy_outval(LPWSTR val
, LPWSTR out
, LPDWORD size
)
979 return ERROR_UNKNOWN_PROPERTY
;
983 if (strlenW(val
) >= *size
)
994 *size
= lstrlenW(val
);
996 return ERROR_SUCCESS
;
999 UINT WINAPI
MsiGetProductInfoExW(LPCWSTR szProductCode
, LPCWSTR szUserSid
,
1000 MSIINSTALLCONTEXT dwContext
, LPCWSTR szProperty
,
1001 LPWSTR szValue
, LPDWORD pcchValue
)
1003 WCHAR squished_pc
[GUID_SIZE
];
1005 LPCWSTR package
= NULL
;
1006 HKEY props
= NULL
, prod
;
1007 HKEY classes
= NULL
, managed
;
1010 UINT r
= ERROR_UNKNOWN_PRODUCT
;
1012 static const WCHAR one
[] = {'1',0};
1013 static const WCHAR five
[] = {'5',0};
1014 static const WCHAR empty
[] = {0};
1015 static const WCHAR displayname
[] = {
1016 'D','i','s','p','l','a','y','N','a','m','e',0};
1017 static const WCHAR displayversion
[] = {
1018 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1019 static const WCHAR managed_local_package
[] = {
1020 'M','a','n','a','g','e','d','L','o','c','a','l',
1021 'P','a','c','k','a','g','e',0};
1023 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode
),
1024 debugstr_w(szUserSid
), dwContext
, debugstr_w(szProperty
),
1025 szValue
, pcchValue
);
1027 if (!szProductCode
|| !squash_guid(szProductCode
, squished_pc
))
1028 return ERROR_INVALID_PARAMETER
;
1030 if (szValue
&& !pcchValue
)
1031 return ERROR_INVALID_PARAMETER
;
1033 if (dwContext
!= MSIINSTALLCONTEXT_USERUNMANAGED
&&
1034 dwContext
!= MSIINSTALLCONTEXT_USERMANAGED
&&
1035 dwContext
!= MSIINSTALLCONTEXT_MACHINE
)
1036 return ERROR_INVALID_PARAMETER
;
1038 if (!szProperty
|| !*szProperty
)
1039 return ERROR_INVALID_PARAMETER
;
1041 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
&& szUserSid
)
1042 return ERROR_INVALID_PARAMETER
;
1044 /* FIXME: dwContext is provided, no need to search for it */
1045 MSIREG_OpenProductKey(szProductCode
, NULL
,MSIINSTALLCONTEXT_USERMANAGED
,
1047 MSIREG_OpenProductKey(szProductCode
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
1050 MSIREG_OpenInstallProps(szProductCode
, dwContext
, NULL
, &props
, FALSE
);
1052 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
1054 package
= INSTALLPROPERTY_LOCALPACKAGEW
;
1056 if (!props
&& !prod
)
1059 else if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1061 package
= managed_local_package
;
1063 if (!props
&& !managed
)
1066 else if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1068 package
= INSTALLPROPERTY_LOCALPACKAGEW
;
1069 MSIREG_OpenProductKey(szProductCode
, NULL
, dwContext
, &classes
, FALSE
);
1071 if (!props
&& !classes
)
1075 if (!lstrcmpW(szProperty
, INSTALLPROPERTY_HELPLINKW
) ||
1076 !lstrcmpW(szProperty
, INSTALLPROPERTY_HELPTELEPHONEW
) ||
1077 !lstrcmpW(szProperty
, INSTALLPROPERTY_INSTALLDATEW
) ||
1078 !lstrcmpW(szProperty
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
) ||
1079 !lstrcmpW(szProperty
, INSTALLPROPERTY_INSTALLLOCATIONW
) ||
1080 !lstrcmpW(szProperty
, INSTALLPROPERTY_INSTALLSOURCEW
) ||
1081 !lstrcmpW(szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
) ||
1082 !lstrcmpW(szProperty
, INSTALLPROPERTY_PUBLISHERW
) ||
1083 !lstrcmpW(szProperty
, INSTALLPROPERTY_URLINFOABOUTW
) ||
1084 !lstrcmpW(szProperty
, INSTALLPROPERTY_URLUPDATEINFOW
) ||
1085 !lstrcmpW(szProperty
, INSTALLPROPERTY_VERSIONMINORW
) ||
1086 !lstrcmpW(szProperty
, INSTALLPROPERTY_VERSIONMAJORW
) ||
1087 !lstrcmpW(szProperty
, INSTALLPROPERTY_VERSIONSTRINGW
) ||
1088 !lstrcmpW(szProperty
, INSTALLPROPERTY_PRODUCTIDW
) ||
1089 !lstrcmpW(szProperty
, INSTALLPROPERTY_REGCOMPANYW
) ||
1090 !lstrcmpW(szProperty
, INSTALLPROPERTY_REGOWNERW
) ||
1091 !lstrcmpW(szProperty
, INSTALLPROPERTY_INSTANCETYPEW
))
1093 val
= msi_reg_get_value(props
, package
, &type
);
1096 if (prod
|| classes
)
1097 r
= ERROR_UNKNOWN_PROPERTY
;
1104 if (!lstrcmpW(szProperty
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
))
1105 szProperty
= displayname
;
1106 else if (!lstrcmpW(szProperty
, INSTALLPROPERTY_VERSIONSTRINGW
))
1107 szProperty
= displayversion
;
1109 val
= msi_reg_get_value(props
, szProperty
, &type
);
1111 val
= strdupW(empty
);
1113 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1115 else if (!lstrcmpW(szProperty
, INSTALLPROPERTY_TRANSFORMSW
) ||
1116 !lstrcmpW(szProperty
, INSTALLPROPERTY_LANGUAGEW
) ||
1117 !lstrcmpW(szProperty
, INSTALLPROPERTY_PRODUCTNAMEW
) ||
1118 !lstrcmpW(szProperty
, INSTALLPROPERTY_PACKAGECODEW
) ||
1119 !lstrcmpW(szProperty
, INSTALLPROPERTY_VERSIONW
) ||
1120 !lstrcmpW(szProperty
, INSTALLPROPERTY_PRODUCTICONW
) ||
1121 !lstrcmpW(szProperty
, INSTALLPROPERTY_PACKAGENAMEW
) ||
1122 !lstrcmpW(szProperty
, INSTALLPROPERTY_AUTHORIZED_LUA_APPW
))
1124 if (!prod
&& !classes
)
1127 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
1129 else if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1131 else if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1134 val
= msi_reg_get_value(hkey
, szProperty
, &type
);
1136 val
= strdupW(empty
);
1138 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1140 else if (!lstrcmpW(szProperty
, INSTALLPROPERTY_PRODUCTSTATEW
))
1142 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1146 val
= msi_reg_get_value(props
, package
, &type
);
1151 val
= strdupW(five
);
1156 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1159 else if (props
&& (val
= msi_reg_get_value(props
, package
, &type
)))
1162 val
= strdupW(five
);
1163 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1167 if (prod
|| managed
)
1172 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1174 else if (!lstrcmpW(szProperty
, INSTALLPROPERTY_ASSIGNMENTTYPEW
))
1176 if (!prod
&& !classes
)
1180 val
= strdupW(empty
);
1181 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1184 r
= ERROR_UNKNOWN_PROPERTY
;
1189 RegCloseKey(managed
);
1190 RegCloseKey(classes
);
1196 UINT WINAPI
MsiGetPatchInfoExA(LPCSTR szPatchCode
, LPCSTR szProductCode
,
1197 LPCSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1198 LPCSTR szProperty
, LPSTR lpValue
, DWORD
*pcchValue
)
1200 LPWSTR patch
= NULL
, product
= NULL
, usersid
= NULL
;
1201 LPWSTR property
= NULL
, val
= NULL
;
1205 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode
),
1206 debugstr_a(szProductCode
), debugstr_a(szUserSid
), dwContext
,
1207 debugstr_a(szProperty
), lpValue
, pcchValue
);
1209 if (lpValue
&& !pcchValue
)
1210 return ERROR_INVALID_PARAMETER
;
1212 if (szPatchCode
) patch
= strdupAtoW(szPatchCode
);
1213 if (szProductCode
) product
= strdupAtoW(szProductCode
);
1214 if (szUserSid
) usersid
= strdupAtoW(szUserSid
);
1215 if (szProperty
) property
= strdupAtoW(szProperty
);
1218 r
= MsiGetPatchInfoExW(patch
, product
, usersid
, dwContext
, property
,
1220 if (r
!= ERROR_SUCCESS
)
1223 val
= msi_alloc(++len
* sizeof(WCHAR
));
1226 r
= ERROR_OUTOFMEMORY
;
1230 r
= MsiGetPatchInfoExW(patch
, product
, usersid
, dwContext
, property
,
1232 if (r
!= ERROR_SUCCESS
|| !pcchValue
)
1236 WideCharToMultiByte(CP_ACP
, 0, val
, -1, lpValue
,
1237 *pcchValue
- 1, NULL
, NULL
);
1239 len
= lstrlenW(val
);
1240 if ((*val
&& *pcchValue
< len
+ 1) || !lpValue
)
1244 r
= ERROR_MORE_DATA
;
1245 lpValue
[*pcchValue
- 1] = '\0';
1248 *pcchValue
= len
* sizeof(WCHAR
);
1263 UINT WINAPI
MsiGetPatchInfoExW(LPCWSTR szPatchCode
, LPCWSTR szProductCode
,
1264 LPCWSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1265 LPCWSTR szProperty
, LPWSTR lpValue
, DWORD
*pcchValue
)
1267 WCHAR squished_pc
[GUID_SIZE
];
1268 WCHAR squished_patch
[GUID_SIZE
];
1269 HKEY udprod
= 0, prod
= 0, props
= 0;
1270 HKEY patch
= 0, patches
= 0;
1271 HKEY udpatch
= 0, datakey
= 0;
1272 HKEY prodpatches
= 0;
1274 UINT r
= ERROR_UNKNOWN_PRODUCT
;
1278 static const WCHAR szEmpty
[] = {0};
1279 static const WCHAR szPatches
[] = {'P','a','t','c','h','e','s',0};
1280 static const WCHAR szInstalled
[] = {'I','n','s','t','a','l','l','e','d',0};
1281 static const WCHAR szManagedPackage
[] = {'M','a','n','a','g','e','d',
1282 'L','o','c','a','l','P','a','c','k','a','g','e',0};
1284 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode
),
1285 debugstr_w(szProductCode
), debugstr_w(szUserSid
), dwContext
,
1286 debugstr_w(szProperty
), lpValue
, pcchValue
);
1288 if (!szProductCode
|| !squash_guid(szProductCode
, squished_pc
))
1289 return ERROR_INVALID_PARAMETER
;
1291 if (!szPatchCode
|| !squash_guid(szPatchCode
, squished_patch
))
1292 return ERROR_INVALID_PARAMETER
;
1295 return ERROR_INVALID_PARAMETER
;
1297 if (lpValue
&& !pcchValue
)
1298 return ERROR_INVALID_PARAMETER
;
1300 if (dwContext
!= MSIINSTALLCONTEXT_USERMANAGED
&&
1301 dwContext
!= MSIINSTALLCONTEXT_USERUNMANAGED
&&
1302 dwContext
!= MSIINSTALLCONTEXT_MACHINE
)
1303 return ERROR_INVALID_PARAMETER
;
1305 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
&& szUserSid
)
1306 return ERROR_INVALID_PARAMETER
;
1308 if (!lstrcmpW(szUserSid
, szLocalSid
))
1309 return ERROR_INVALID_PARAMETER
;
1311 if (MSIREG_OpenUserDataProductKey(szProductCode
, dwContext
, NULL
,
1312 &udprod
, FALSE
) != ERROR_SUCCESS
)
1315 if (MSIREG_OpenInstallProps(szProductCode
, dwContext
, NULL
,
1316 &props
, FALSE
) != ERROR_SUCCESS
)
1319 r
= ERROR_UNKNOWN_PATCH
;
1321 res
= RegOpenKeyExW(udprod
, szPatches
, 0, KEY_READ
, &patches
);
1322 if (res
!= ERROR_SUCCESS
)
1325 res
= RegOpenKeyExW(patches
, squished_patch
, 0, KEY_READ
, &patch
);
1326 if (res
!= ERROR_SUCCESS
)
1329 if (!lstrcmpW(szProperty
, INSTALLPROPERTY_TRANSFORMSW
))
1331 if (MSIREG_OpenProductKey(szProductCode
, NULL
, dwContext
,
1332 &prod
, FALSE
) != ERROR_SUCCESS
)
1335 res
= RegOpenKeyExW(prod
, szPatches
, 0, KEY_ALL_ACCESS
, &prodpatches
);
1336 if (res
!= ERROR_SUCCESS
)
1339 datakey
= prodpatches
;
1340 szProperty
= squished_patch
;
1344 if (MSIREG_OpenUserDataPatchKey(szPatchCode
, dwContext
,
1345 &udpatch
, FALSE
) != ERROR_SUCCESS
)
1348 if (!lstrcmpW(szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
))
1350 if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1351 szProperty
= szManagedPackage
;
1354 else if (!lstrcmpW(szProperty
, INSTALLPROPERTY_INSTALLDATEW
))
1357 szProperty
= szInstalled
;
1359 else if (!lstrcmpW(szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
))
1363 else if (!lstrcmpW(szProperty
, INSTALLPROPERTY_UNINSTALLABLEW
) ||
1364 !lstrcmpW(szProperty
, INSTALLPROPERTY_PATCHSTATEW
) ||
1365 !lstrcmpW(szProperty
, INSTALLPROPERTY_DISPLAYNAMEW
) ||
1366 !lstrcmpW(szProperty
, INSTALLPROPERTY_MOREINFOURLW
))
1372 r
= ERROR_UNKNOWN_PROPERTY
;
1377 val
= msi_reg_get_val_str(datakey
, szProperty
);
1379 val
= strdupW(szEmpty
);
1387 lstrcpynW(lpValue
, val
, *pcchValue
);
1389 len
= lstrlenW(val
);
1390 if ((*val
&& *pcchValue
< len
+ 1) || !lpValue
)
1393 r
= ERROR_MORE_DATA
;
1395 *pcchValue
= len
* sizeof(WCHAR
);
1402 RegCloseKey(prodpatches
);
1405 RegCloseKey(patches
);
1406 RegCloseKey(udpatch
);
1408 RegCloseKey(udprod
);
1413 UINT WINAPI
MsiEnableLogA(DWORD dwLogMode
, LPCSTR szLogFile
, DWORD attributes
)
1415 LPWSTR szwLogFile
= NULL
;
1418 TRACE("%08x %s %08x\n", dwLogMode
, debugstr_a(szLogFile
), attributes
);
1422 szwLogFile
= strdupAtoW( szLogFile
);
1424 return ERROR_OUTOFMEMORY
;
1426 r
= MsiEnableLogW( dwLogMode
, szwLogFile
, attributes
);
1427 msi_free( szwLogFile
);
1431 UINT WINAPI
MsiEnableLogW(DWORD dwLogMode
, LPCWSTR szLogFile
, DWORD attributes
)
1433 HANDLE file
= INVALID_HANDLE_VALUE
;
1435 TRACE("%08x %s %08x\n", dwLogMode
, debugstr_w(szLogFile
), attributes
);
1439 lstrcpyW(gszLogFile
,szLogFile
);
1440 if (!(attributes
& INSTALLLOGATTRIBUTES_APPEND
))
1441 DeleteFileW(szLogFile
);
1442 file
= CreateFileW(szLogFile
, GENERIC_WRITE
, 0, NULL
, OPEN_ALWAYS
,
1443 FILE_ATTRIBUTE_NORMAL
, NULL
);
1444 if (file
!= INVALID_HANDLE_VALUE
)
1447 ERR("Unable to enable log %s\n",debugstr_w(szLogFile
));
1450 gszLogFile
[0] = '\0';
1452 return ERROR_SUCCESS
;
1455 UINT WINAPI
MsiEnumComponentCostsW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
1456 DWORD dwIndex
, INSTALLSTATE iState
,
1457 LPWSTR lpDriveBuf
, DWORD
*pcchDriveBuf
,
1458 int *piCost
, int *pTempCost
)
1460 FIXME("(%d, %s, %d, %d, %p, %p, %p %p): stub!\n", hInstall
,
1461 debugstr_w(szComponent
), dwIndex
, iState
, lpDriveBuf
,
1462 pcchDriveBuf
, piCost
, pTempCost
);
1464 return ERROR_NO_MORE_ITEMS
;
1467 UINT WINAPI
MsiQueryComponentStateA(LPCSTR szProductCode
,
1468 LPCSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1469 LPCSTR szComponent
, INSTALLSTATE
*pdwState
)
1471 LPWSTR prodcode
= NULL
, usersid
= NULL
, comp
= NULL
;
1474 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode
),
1475 debugstr_a(szUserSid
), dwContext
, debugstr_a(szComponent
), pdwState
);
1477 if (szProductCode
&& !(prodcode
= strdupAtoW(szProductCode
)))
1478 return ERROR_OUTOFMEMORY
;
1480 if (szUserSid
&& !(usersid
= strdupAtoW(szUserSid
)))
1481 return ERROR_OUTOFMEMORY
;
1483 if (szComponent
&& !(comp
= strdupAtoW(szComponent
)))
1484 return ERROR_OUTOFMEMORY
;
1486 r
= MsiQueryComponentStateW(prodcode
, usersid
, dwContext
, comp
, pdwState
);
1495 static BOOL
msi_comp_find_prod_key(LPCWSTR prodcode
, MSIINSTALLCONTEXT context
)
1500 r
= MSIREG_OpenProductKey(prodcode
, NULL
, context
, &hkey
, FALSE
);
1502 return (r
== ERROR_SUCCESS
);
1505 static BOOL
msi_comp_find_package(LPCWSTR prodcode
, MSIINSTALLCONTEXT context
)
1513 static const WCHAR local_package
[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
1514 static const WCHAR managed_local_package
[] = {
1515 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
1518 r
= MSIREG_OpenInstallProps(prodcode
, context
, NULL
, &hkey
, FALSE
);
1519 if (r
!= ERROR_SUCCESS
)
1522 if (context
== MSIINSTALLCONTEXT_USERMANAGED
)
1523 package
= managed_local_package
;
1525 package
= local_package
;
1528 res
= RegQueryValueExW(hkey
, package
, NULL
, NULL
, NULL
, &sz
);
1531 return (res
== ERROR_SUCCESS
);
1534 static BOOL
msi_comp_find_prodcode(LPWSTR squished_pc
,
1535 MSIINSTALLCONTEXT context
,
1536 LPCWSTR comp
, LPWSTR val
, DWORD
*sz
)
1542 if (context
== MSIINSTALLCONTEXT_MACHINE
)
1543 r
= MSIREG_OpenUserDataComponentKey(comp
, szLocalSid
, &hkey
, FALSE
);
1545 r
= MSIREG_OpenUserDataComponentKey(comp
, NULL
, &hkey
, FALSE
);
1547 if (r
!= ERROR_SUCCESS
)
1550 res
= RegQueryValueExW(hkey
, squished_pc
, NULL
, NULL
, (BYTE
*)val
, sz
);
1551 if (res
!= ERROR_SUCCESS
)
1558 UINT WINAPI
MsiQueryComponentStateW(LPCWSTR szProductCode
,
1559 LPCWSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1560 LPCWSTR szComponent
, INSTALLSTATE
*pdwState
)
1562 WCHAR squished_pc
[GUID_SIZE
];
1563 WCHAR val
[MAX_PATH
];
1567 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode
),
1568 debugstr_w(szUserSid
), dwContext
, debugstr_w(szComponent
), pdwState
);
1570 if (!pdwState
|| !szComponent
)
1571 return ERROR_INVALID_PARAMETER
;
1573 if (!szProductCode
|| !*szProductCode
|| lstrlenW(szProductCode
) != GUID_SIZE
- 1)
1574 return ERROR_INVALID_PARAMETER
;
1576 if (!squash_guid(szProductCode
, squished_pc
))
1577 return ERROR_INVALID_PARAMETER
;
1579 found
= msi_comp_find_prod_key(szProductCode
, dwContext
);
1581 if (!msi_comp_find_package(szProductCode
, dwContext
))
1585 *pdwState
= INSTALLSTATE_UNKNOWN
;
1586 return ERROR_UNKNOWN_COMPONENT
;
1589 return ERROR_UNKNOWN_PRODUCT
;
1592 *pdwState
= INSTALLSTATE_UNKNOWN
;
1595 if (!msi_comp_find_prodcode(squished_pc
, dwContext
, szComponent
, val
, &sz
))
1596 return ERROR_UNKNOWN_COMPONENT
;
1599 *pdwState
= INSTALLSTATE_NOTUSED
;
1602 if (lstrlenW(val
) > 2 &&
1603 val
[0] >= '0' && val
[0] <= '9' && val
[1] >= '0' && val
[1] <= '9')
1605 *pdwState
= INSTALLSTATE_SOURCE
;
1608 *pdwState
= INSTALLSTATE_LOCAL
;
1611 return ERROR_SUCCESS
;
1614 INSTALLSTATE WINAPI
MsiQueryProductStateA(LPCSTR szProduct
)
1616 LPWSTR szwProduct
= NULL
;
1621 szwProduct
= strdupAtoW( szProduct
);
1623 return ERROR_OUTOFMEMORY
;
1625 r
= MsiQueryProductStateW( szwProduct
);
1626 msi_free( szwProduct
);
1630 INSTALLSTATE WINAPI
MsiQueryProductStateW(LPCWSTR szProduct
)
1632 MSIINSTALLCONTEXT context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
1633 INSTALLSTATE state
= INSTALLSTATE_ADVERTISED
;
1634 HKEY prodkey
= 0, userdata
= 0;
1638 static const WCHAR szWindowsInstaller
[] = {
1639 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
1641 TRACE("%s\n", debugstr_w(szProduct
));
1643 if (!szProduct
|| !*szProduct
)
1644 return INSTALLSTATE_INVALIDARG
;
1646 if (lstrlenW(szProduct
) != GUID_SIZE
- 1)
1647 return INSTALLSTATE_INVALIDARG
;
1649 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
1650 &prodkey
, FALSE
) != ERROR_SUCCESS
&&
1651 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
1652 &prodkey
, FALSE
) != ERROR_SUCCESS
&&
1653 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
1654 &prodkey
, FALSE
) == ERROR_SUCCESS
)
1656 context
= MSIINSTALLCONTEXT_MACHINE
;
1659 r
= MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &userdata
, FALSE
);
1660 if (r
!= ERROR_SUCCESS
)
1663 if (!msi_reg_get_val_dword(userdata
, szWindowsInstaller
, &val
))
1667 state
= INSTALLSTATE_DEFAULT
;
1669 state
= INSTALLSTATE_UNKNOWN
;
1674 state
= INSTALLSTATE_UNKNOWN
;
1677 state
= INSTALLSTATE_ABSENT
;
1680 RegCloseKey(prodkey
);
1681 RegCloseKey(userdata
);
1685 INSTALLUILEVEL WINAPI
MsiSetInternalUI(INSTALLUILEVEL dwUILevel
, HWND
*phWnd
)
1687 INSTALLUILEVEL old
= gUILevel
;
1688 HWND oldwnd
= gUIhwnd
;
1690 TRACE("%08x %p\n", dwUILevel
, phWnd
);
1692 gUILevel
= dwUILevel
;
1701 INSTALLUI_HANDLERA WINAPI
MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler
,
1702 DWORD dwMessageFilter
, LPVOID pvContext
)
1704 INSTALLUI_HANDLERA prev
= gUIHandlerA
;
1706 TRACE("%p %x %p\n",puiHandler
, dwMessageFilter
,pvContext
);
1707 gUIHandlerA
= puiHandler
;
1708 gUIFilter
= dwMessageFilter
;
1709 gUIContext
= pvContext
;
1714 INSTALLUI_HANDLERW WINAPI
MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler
,
1715 DWORD dwMessageFilter
, LPVOID pvContext
)
1717 INSTALLUI_HANDLERW prev
= gUIHandlerW
;
1719 TRACE("%p %x %p\n",puiHandler
,dwMessageFilter
,pvContext
);
1720 gUIHandlerW
= puiHandler
;
1721 gUIFilter
= dwMessageFilter
;
1722 gUIContext
= pvContext
;
1727 /******************************************************************
1728 * MsiLoadStringW [MSI.@]
1730 * Loads a string from MSI's string resources.
1734 * handle [I] only -1 is handled currently
1735 * id [I] id of the string to be loaded
1736 * lpBuffer [O] buffer for the string to be written to
1737 * nBufferMax [I] maximum size of the buffer in characters
1738 * lang [I] the preferred language for the string
1742 * If successful, this function returns the language id of the string loaded
1743 * If the function fails, the function returns zero.
1747 * The type of the first parameter is unknown. LoadString's prototype
1748 * suggests that it might be a module handle. I have made it an MSI handle
1749 * for starters, as -1 is an invalid MSI handle, but not an invalid module
1750 * handle. Maybe strings can be stored in an MSI database somehow.
1752 LANGID WINAPI
MsiLoadStringW( MSIHANDLE handle
, UINT id
, LPWSTR lpBuffer
,
1753 int nBufferMax
, LANGID lang
)
1760 TRACE("%d %u %p %d %d\n", handle
, id
, lpBuffer
, nBufferMax
, lang
);
1763 FIXME("don't know how to deal with handle = %08x\n", handle
);
1766 lang
= GetUserDefaultLangID();
1768 hres
= FindResourceExW( msi_hInstance
, (LPCWSTR
) RT_STRING
,
1772 hResData
= LoadResource( msi_hInstance
, hres
);
1775 p
= LockResource( hResData
);
1779 for (i
= 0; i
< (id
&0xf); i
++)
1783 if( nBufferMax
<= len
)
1786 memcpy( lpBuffer
, p
+1, len
* sizeof(WCHAR
));
1787 lpBuffer
[ len
] = 0;
1789 TRACE("found -> %s\n", debugstr_w(lpBuffer
));
1794 LANGID WINAPI
MsiLoadStringA( MSIHANDLE handle
, UINT id
, LPSTR lpBuffer
,
1795 int nBufferMax
, LANGID lang
)
1801 bufW
= msi_alloc(nBufferMax
*sizeof(WCHAR
));
1802 r
= MsiLoadStringW(handle
, id
, bufW
, nBufferMax
, lang
);
1805 len
= WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, NULL
, 0, NULL
, NULL
);
1806 if( len
<= nBufferMax
)
1807 WideCharToMultiByte( CP_ACP
, 0, bufW
, -1,
1808 lpBuffer
, nBufferMax
, NULL
, NULL
);
1816 INSTALLSTATE WINAPI
MsiLocateComponentA(LPCSTR szComponent
, LPSTR lpPathBuf
,
1819 char szProduct
[GUID_SIZE
];
1821 TRACE("%s %p %p\n", debugstr_a(szComponent
), lpPathBuf
, pcchBuf
);
1823 if (MsiGetProductCodeA( szComponent
, szProduct
) != ERROR_SUCCESS
)
1824 return INSTALLSTATE_UNKNOWN
;
1826 return MsiGetComponentPathA( szProduct
, szComponent
, lpPathBuf
, pcchBuf
);
1829 INSTALLSTATE WINAPI
MsiLocateComponentW(LPCWSTR szComponent
, LPWSTR lpPathBuf
,
1832 WCHAR szProduct
[GUID_SIZE
];
1834 TRACE("%s %p %p\n", debugstr_w(szComponent
), lpPathBuf
, pcchBuf
);
1836 if (MsiGetProductCodeW( szComponent
, szProduct
) != ERROR_SUCCESS
)
1837 return INSTALLSTATE_UNKNOWN
;
1839 return MsiGetComponentPathW( szProduct
, szComponent
, lpPathBuf
, pcchBuf
);
1842 UINT WINAPI
MsiMessageBoxA(HWND hWnd
, LPCSTR lpText
, LPCSTR lpCaption
, UINT uType
,
1843 WORD wLanguageId
, DWORD f
)
1845 FIXME("%p %s %s %u %08x %08x\n", hWnd
, debugstr_a(lpText
), debugstr_a(lpCaption
),
1846 uType
, wLanguageId
, f
);
1847 return MessageBoxExA(hWnd
,lpText
,lpCaption
,uType
,wLanguageId
);
1850 UINT WINAPI
MsiMessageBoxW(HWND hWnd
, LPCWSTR lpText
, LPCWSTR lpCaption
, UINT uType
,
1851 WORD wLanguageId
, DWORD f
)
1853 FIXME("%p %s %s %u %08x %08x\n", hWnd
, debugstr_w(lpText
), debugstr_w(lpCaption
),
1854 uType
, wLanguageId
, f
);
1855 return MessageBoxExW(hWnd
,lpText
,lpCaption
,uType
,wLanguageId
);
1858 UINT WINAPI
MsiProvideAssemblyA( LPCSTR szAssemblyName
, LPCSTR szAppContext
,
1859 DWORD dwInstallMode
, DWORD dwAssemblyInfo
, LPSTR lpPathBuf
,
1860 LPDWORD pcchPathBuf
)
1862 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName
),
1863 debugstr_a(szAppContext
), dwInstallMode
, dwAssemblyInfo
, lpPathBuf
,
1865 return ERROR_CALL_NOT_IMPLEMENTED
;
1868 UINT WINAPI
MsiProvideAssemblyW( LPCWSTR szAssemblyName
, LPCWSTR szAppContext
,
1869 DWORD dwInstallMode
, DWORD dwAssemblyInfo
, LPWSTR lpPathBuf
,
1870 LPDWORD pcchPathBuf
)
1872 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName
),
1873 debugstr_w(szAppContext
), dwInstallMode
, dwAssemblyInfo
, lpPathBuf
,
1875 return ERROR_CALL_NOT_IMPLEMENTED
;
1878 UINT WINAPI
MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor
,
1879 LPSTR szPath
, LPDWORD pcchPath
, LPDWORD pcchArgs
)
1881 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor
), szPath
, pcchPath
, pcchArgs
);
1882 return ERROR_CALL_NOT_IMPLEMENTED
;
1885 UINT WINAPI
MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor
,
1886 LPWSTR szPath
, LPDWORD pcchPath
, LPDWORD pcchArgs
)
1888 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor
), szPath
, pcchPath
, pcchArgs
);
1889 return ERROR_CALL_NOT_IMPLEMENTED
;
1892 HRESULT WINAPI
MsiGetFileSignatureInformationA( LPCSTR szSignedObjectPath
,
1893 DWORD dwFlags
, PCCERT_CONTEXT
* ppcCertContext
, LPBYTE pbHashData
,
1894 LPDWORD pcbHashData
)
1896 FIXME("%s %08x %p %p %p\n", debugstr_a(szSignedObjectPath
), dwFlags
,
1897 ppcCertContext
, pbHashData
, pcbHashData
);
1898 return ERROR_CALL_NOT_IMPLEMENTED
;
1901 HRESULT WINAPI
MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath
,
1902 DWORD dwFlags
, PCCERT_CONTEXT
* ppcCertContext
, LPBYTE pbHashData
,
1903 LPDWORD pcbHashData
)
1905 FIXME("%s %08x %p %p %p\n", debugstr_w(szSignedObjectPath
), dwFlags
,
1906 ppcCertContext
, pbHashData
, pcbHashData
);
1907 return ERROR_CALL_NOT_IMPLEMENTED
;
1910 /******************************************************************
1911 * MsiGetProductPropertyA [MSI.@]
1913 UINT WINAPI
MsiGetProductPropertyA(MSIHANDLE hProduct
, LPCSTR szProperty
,
1914 LPSTR szValue
, LPDWORD pccbValue
)
1916 LPWSTR prop
= NULL
, val
= NULL
;
1920 TRACE("(%d, %s, %p, %p)\n", hProduct
, debugstr_a(szProperty
),
1921 szValue
, pccbValue
);
1923 if (szValue
&& !pccbValue
)
1924 return ERROR_INVALID_PARAMETER
;
1926 if (szProperty
) prop
= strdupAtoW(szProperty
);
1929 r
= MsiGetProductPropertyW(hProduct
, prop
, NULL
, &len
);
1930 if (r
!= ERROR_SUCCESS
&& r
!= ERROR_MORE_DATA
)
1933 if (r
== ERROR_SUCCESS
)
1935 if (szValue
) *szValue
= '\0';
1936 if (pccbValue
) *pccbValue
= 0;
1940 val
= msi_alloc(++len
* sizeof(WCHAR
));
1943 r
= ERROR_OUTOFMEMORY
;
1947 r
= MsiGetProductPropertyW(hProduct
, prop
, val
, &len
);
1948 if (r
!= ERROR_SUCCESS
)
1951 len
= WideCharToMultiByte(CP_ACP
, 0, val
, -1, NULL
, 0, NULL
, NULL
);
1954 WideCharToMultiByte(CP_ACP
, 0, val
, -1, szValue
,
1955 *pccbValue
, NULL
, NULL
);
1959 if (len
> *pccbValue
)
1960 r
= ERROR_MORE_DATA
;
1962 *pccbValue
= len
- 1;
1972 /******************************************************************
1973 * MsiGetProductPropertyW [MSI.@]
1975 UINT WINAPI
MsiGetProductPropertyW(MSIHANDLE hProduct
, LPCWSTR szProperty
,
1976 LPWSTR szValue
, LPDWORD pccbValue
)
1978 MSIPACKAGE
*package
;
1979 MSIQUERY
*view
= NULL
;
1980 MSIRECORD
*rec
= NULL
;
1984 static const WCHAR query
[] = {
1985 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
1986 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
1987 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
1989 TRACE("(%d, %s, %p, %p)\n", hProduct
, debugstr_w(szProperty
),
1990 szValue
, pccbValue
);
1993 return ERROR_INVALID_PARAMETER
;
1995 if (szValue
&& !pccbValue
)
1996 return ERROR_INVALID_PARAMETER
;
1998 package
= msihandle2msiinfo(hProduct
, MSIHANDLETYPE_PACKAGE
);
2000 return ERROR_INVALID_HANDLE
;
2002 r
= MSI_OpenQuery(package
->db
, &view
, query
, szProperty
);
2003 if (r
!= ERROR_SUCCESS
)
2006 r
= MSI_ViewExecute(view
, 0);
2007 if (r
!= ERROR_SUCCESS
)
2010 r
= MSI_ViewFetch(view
, &rec
);
2011 if (r
!= ERROR_SUCCESS
)
2014 val
= MSI_RecordGetString(rec
, 2);
2018 if (lstrlenW(val
) >= *pccbValue
)
2020 lstrcpynW(szValue
, val
, *pccbValue
);
2021 *pccbValue
= lstrlenW(val
);
2022 r
= ERROR_MORE_DATA
;
2026 lstrcpyW(szValue
, val
);
2027 *pccbValue
= lstrlenW(val
);
2034 MSI_ViewClose(view
);
2035 msiobj_release(&view
->hdr
);
2036 if (rec
) msiobj_release(&rec
->hdr
);
2041 if (szValue
) *szValue
= '\0';
2042 if (pccbValue
) *pccbValue
= 0;
2049 UINT WINAPI
MsiVerifyPackageA( LPCSTR szPackage
)
2052 LPWSTR szPack
= NULL
;
2054 TRACE("%s\n", debugstr_a(szPackage
) );
2058 szPack
= strdupAtoW( szPackage
);
2060 return ERROR_OUTOFMEMORY
;
2063 r
= MsiVerifyPackageW( szPack
);
2070 UINT WINAPI
MsiVerifyPackageW( LPCWSTR szPackage
)
2075 TRACE("%s\n", debugstr_w(szPackage
) );
2077 r
= MsiOpenDatabaseW( szPackage
, MSIDBOPEN_READONLY
, &handle
);
2078 MsiCloseHandle( handle
);
2083 static INSTALLSTATE
MSI_GetComponentPath(LPCWSTR szProduct
, LPCWSTR szComponent
,
2084 awstring
* lpPathBuf
, LPDWORD pcchBuf
)
2086 WCHAR squished_pc
[GUID_SIZE
];
2087 WCHAR squished_comp
[GUID_SIZE
];
2093 static const WCHAR wininstaller
[] = {
2094 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
2096 TRACE("%s %s %p %p\n", debugstr_w(szProduct
),
2097 debugstr_w(szComponent
), lpPathBuf
->str
.w
, pcchBuf
);
2099 if (!szProduct
|| !szComponent
)
2100 return INSTALLSTATE_INVALIDARG
;
2102 if (lpPathBuf
->str
.w
&& !pcchBuf
)
2103 return INSTALLSTATE_INVALIDARG
;
2105 if (!squash_guid(szProduct
, squished_pc
) ||
2106 !squash_guid(szComponent
, squished_comp
))
2107 return INSTALLSTATE_INVALIDARG
;
2109 state
= INSTALLSTATE_UNKNOWN
;
2111 if (MSIREG_OpenUserDataComponentKey(szComponent
, szLocalSid
, &hkey
, FALSE
) == ERROR_SUCCESS
||
2112 MSIREG_OpenUserDataComponentKey(szComponent
, NULL
, &hkey
, FALSE
) == ERROR_SUCCESS
)
2114 path
= msi_reg_get_val_str(hkey
, squished_pc
);
2117 state
= INSTALLSTATE_ABSENT
;
2119 if ((MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_MACHINE
, NULL
,
2120 &hkey
, FALSE
) == ERROR_SUCCESS
||
2121 MSIREG_OpenUserDataProductKey(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
,
2122 NULL
, &hkey
, FALSE
) == ERROR_SUCCESS
) &&
2123 msi_reg_get_val_dword(hkey
, wininstaller
, &version
) &&
2124 GetFileAttributesW(path
) != INVALID_FILE_ATTRIBUTES
)
2127 state
= INSTALLSTATE_LOCAL
;
2131 if (state
!= INSTALLSTATE_LOCAL
&&
2132 (MSIREG_OpenProductKey(szProduct
, NULL
,
2133 MSIINSTALLCONTEXT_USERUNMANAGED
,
2134 &hkey
, FALSE
) == ERROR_SUCCESS
||
2135 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
2136 &hkey
, FALSE
) == ERROR_SUCCESS
))
2140 if (MSIREG_OpenUserDataComponentKey(szComponent
, szLocalSid
, &hkey
, FALSE
) == ERROR_SUCCESS
||
2141 MSIREG_OpenUserDataComponentKey(szComponent
, NULL
, &hkey
, FALSE
) == ERROR_SUCCESS
)
2144 path
= msi_reg_get_val_str(hkey
, squished_pc
);
2147 state
= INSTALLSTATE_ABSENT
;
2149 if (GetFileAttributesW(path
) != INVALID_FILE_ATTRIBUTES
)
2150 state
= INSTALLSTATE_LOCAL
;
2155 return INSTALLSTATE_UNKNOWN
;
2157 if (state
== INSTALLSTATE_LOCAL
&& !*path
)
2158 state
= INSTALLSTATE_NOTUSED
;
2160 msi_strcpy_to_awstring(path
, lpPathBuf
, pcchBuf
);
2165 /******************************************************************
2166 * MsiGetComponentPathW [MSI.@]
2168 INSTALLSTATE WINAPI
MsiGetComponentPathW(LPCWSTR szProduct
, LPCWSTR szComponent
,
2169 LPWSTR lpPathBuf
, LPDWORD pcchBuf
)
2173 path
.unicode
= TRUE
;
2174 path
.str
.w
= lpPathBuf
;
2176 return MSI_GetComponentPath( szProduct
, szComponent
, &path
, pcchBuf
);
2179 /******************************************************************
2180 * MsiGetComponentPathA [MSI.@]
2182 INSTALLSTATE WINAPI
MsiGetComponentPathA(LPCSTR szProduct
, LPCSTR szComponent
,
2183 LPSTR lpPathBuf
, LPDWORD pcchBuf
)
2185 LPWSTR szwProduct
, szwComponent
= NULL
;
2186 INSTALLSTATE r
= INSTALLSTATE_UNKNOWN
;
2189 szwProduct
= strdupAtoW( szProduct
);
2190 if( szProduct
&& !szwProduct
)
2193 szwComponent
= strdupAtoW( szComponent
);
2194 if( szComponent
&& !szwComponent
)
2197 path
.unicode
= FALSE
;
2198 path
.str
.a
= lpPathBuf
;
2200 r
= MSI_GetComponentPath( szwProduct
, szwComponent
, &path
, pcchBuf
);
2203 msi_free( szwProduct
);
2204 msi_free( szwComponent
);
2209 /******************************************************************
2210 * MsiQueryFeatureStateA [MSI.@]
2212 INSTALLSTATE WINAPI
MsiQueryFeatureStateA(LPCSTR szProduct
, LPCSTR szFeature
)
2214 LPWSTR szwProduct
= NULL
, szwFeature
= NULL
;
2215 INSTALLSTATE rc
= INSTALLSTATE_UNKNOWN
;
2217 szwProduct
= strdupAtoW( szProduct
);
2218 if ( szProduct
&& !szwProduct
)
2221 szwFeature
= strdupAtoW( szFeature
);
2222 if ( szFeature
&& !szwFeature
)
2225 rc
= MsiQueryFeatureStateW(szwProduct
, szwFeature
);
2228 msi_free( szwProduct
);
2229 msi_free( szwFeature
);
2234 /******************************************************************
2235 * MsiQueryFeatureStateW [MSI.@]
2237 * Checks the state of a feature
2240 * szProduct [I] Product's GUID string
2241 * szFeature [I] Feature's GUID string
2244 * INSTALLSTATE_LOCAL Feature is installed and usable
2245 * INSTALLSTATE_ABSENT Feature is absent
2246 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
2247 * INSTALLSTATE_UNKNOWN An error occurred
2248 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
2251 INSTALLSTATE WINAPI
MsiQueryFeatureStateW(LPCWSTR szProduct
, LPCWSTR szFeature
)
2253 WCHAR squishProduct
[33], comp
[GUID_SIZE
];
2255 LPWSTR components
, p
, parent_feature
, path
;
2259 BOOL missing
= FALSE
;
2260 BOOL machine
= FALSE
;
2261 BOOL source
= FALSE
;
2263 TRACE("%s %s\n", debugstr_w(szProduct
), debugstr_w(szFeature
));
2265 if (!szProduct
|| !szFeature
)
2266 return INSTALLSTATE_INVALIDARG
;
2268 if (!squash_guid( szProduct
, squishProduct
))
2269 return INSTALLSTATE_INVALIDARG
;
2271 if (MSIREG_OpenFeaturesKey(szProduct
, MSIINSTALLCONTEXT_USERMANAGED
,
2272 &hkey
, FALSE
) != ERROR_SUCCESS
&&
2273 MSIREG_OpenFeaturesKey(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
,
2274 &hkey
, FALSE
) != ERROR_SUCCESS
)
2276 rc
= MSIREG_OpenFeaturesKey(szProduct
, MSIINSTALLCONTEXT_MACHINE
,
2278 if (rc
!= ERROR_SUCCESS
)
2279 return INSTALLSTATE_UNKNOWN
;
2284 parent_feature
= msi_reg_get_val_str( hkey
, szFeature
);
2287 if (!parent_feature
)
2288 return INSTALLSTATE_UNKNOWN
;
2290 r
= (parent_feature
[0] == 6) ? INSTALLSTATE_ABSENT
: INSTALLSTATE_LOCAL
;
2291 msi_free(parent_feature
);
2292 if (r
== INSTALLSTATE_ABSENT
)
2296 rc
= MSIREG_OpenUserDataFeaturesKey(szProduct
,
2297 MSIINSTALLCONTEXT_MACHINE
,
2300 rc
= MSIREG_OpenUserDataFeaturesKey(szProduct
,
2301 MSIINSTALLCONTEXT_USERUNMANAGED
,
2304 if (rc
!= ERROR_SUCCESS
)
2305 return INSTALLSTATE_ADVERTISED
;
2307 components
= msi_reg_get_val_str( hkey
, szFeature
);
2310 TRACE("rc = %d buffer = %s\n", rc
, debugstr_w(components
));
2313 return INSTALLSTATE_ADVERTISED
;
2315 for( p
= components
; *p
&& *p
!= 2 ; p
+= 20)
2317 if (!decode_base85_guid( p
, &guid
))
2319 if (p
!= components
)
2322 msi_free(components
);
2323 return INSTALLSTATE_BADCONFIG
;
2326 StringFromGUID2(&guid
, comp
, GUID_SIZE
);
2329 rc
= MSIREG_OpenUserDataComponentKey(comp
, szLocalSid
, &hkey
, FALSE
);
2331 rc
= MSIREG_OpenUserDataComponentKey(comp
, NULL
, &hkey
, FALSE
);
2333 if (rc
!= ERROR_SUCCESS
)
2335 msi_free(components
);
2336 return INSTALLSTATE_ADVERTISED
;
2339 path
= msi_reg_get_val_str(hkey
, squishProduct
);
2342 else if (lstrlenW(path
) > 2 &&
2343 path
[0] >= '0' && path
[0] <= '9' &&
2344 path
[1] >= '0' && path
[1] <= '9')
2352 TRACE("%s %s -> %d\n", debugstr_w(szProduct
), debugstr_w(szFeature
), r
);
2353 msi_free(components
);
2356 return INSTALLSTATE_ADVERTISED
;
2359 return INSTALLSTATE_SOURCE
;
2361 return INSTALLSTATE_LOCAL
;
2364 /******************************************************************
2365 * MsiGetFileVersionA [MSI.@]
2367 UINT WINAPI
MsiGetFileVersionA(LPCSTR szFilePath
, LPSTR lpVersionBuf
,
2368 LPDWORD pcchVersionBuf
, LPSTR lpLangBuf
, LPDWORD pcchLangBuf
)
2370 LPWSTR szwFilePath
= NULL
, lpwVersionBuff
= NULL
, lpwLangBuff
= NULL
;
2371 UINT ret
= ERROR_OUTOFMEMORY
;
2373 if ((lpVersionBuf
&& !pcchVersionBuf
) ||
2374 (lpLangBuf
&& !pcchLangBuf
))
2375 return ERROR_INVALID_PARAMETER
;
2379 szwFilePath
= strdupAtoW( szFilePath
);
2384 if( lpVersionBuf
&& pcchVersionBuf
&& *pcchVersionBuf
)
2386 lpwVersionBuff
= msi_alloc(*pcchVersionBuf
*sizeof(WCHAR
));
2387 if( !lpwVersionBuff
)
2391 if( lpLangBuf
&& pcchLangBuf
&& *pcchLangBuf
)
2393 lpwLangBuff
= msi_alloc(*pcchLangBuf
*sizeof(WCHAR
));
2398 ret
= MsiGetFileVersionW(szwFilePath
, lpwVersionBuff
, pcchVersionBuf
,
2399 lpwLangBuff
, pcchLangBuf
);
2401 if( (ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) && lpwVersionBuff
)
2402 WideCharToMultiByte(CP_ACP
, 0, lpwVersionBuff
, -1,
2403 lpVersionBuf
, *pcchVersionBuf
+ 1, NULL
, NULL
);
2404 if( (ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) && lpwLangBuff
)
2405 WideCharToMultiByte(CP_ACP
, 0, lpwLangBuff
, -1,
2406 lpLangBuf
, *pcchLangBuf
+ 1, NULL
, NULL
);
2409 msi_free(szwFilePath
);
2410 msi_free(lpwVersionBuff
);
2411 msi_free(lpwLangBuff
);
2416 /******************************************************************
2417 * MsiGetFileVersionW [MSI.@]
2419 UINT WINAPI
MsiGetFileVersionW(LPCWSTR szFilePath
, LPWSTR lpVersionBuf
,
2420 LPDWORD pcchVersionBuf
, LPWSTR lpLangBuf
, LPDWORD pcchLangBuf
)
2422 static const WCHAR szVersionResource
[] = {'\\',0};
2423 static const WCHAR szVersionFormat
[] = {
2424 '%','d','.','%','d','.','%','d','.','%','d',0};
2425 static const WCHAR szLangResource
[] = {
2426 '\\','V','a','r','F','i','l','e','I','n','f','o','\\',
2427 'T','r','a','n','s','l','a','t','i','o','n',0};
2428 static const WCHAR szLangFormat
[] = {'%','d',0};
2430 DWORD dwVerLen
, gle
;
2431 LPVOID lpVer
= NULL
;
2432 VS_FIXEDFILEINFO
*ffi
;
2437 TRACE("%s %p %d %p %d\n", debugstr_w(szFilePath
),
2438 lpVersionBuf
, pcchVersionBuf
?*pcchVersionBuf
:0,
2439 lpLangBuf
, pcchLangBuf
?*pcchLangBuf
:0);
2441 if ((lpVersionBuf
&& !pcchVersionBuf
) ||
2442 (lpLangBuf
&& !pcchLangBuf
))
2443 return ERROR_INVALID_PARAMETER
;
2445 dwVerLen
= GetFileVersionInfoSizeW(szFilePath
, NULL
);
2448 gle
= GetLastError();
2449 if (gle
== ERROR_BAD_PATHNAME
)
2450 return ERROR_FILE_NOT_FOUND
;
2451 else if (gle
== ERROR_RESOURCE_DATA_NOT_FOUND
)
2452 return ERROR_FILE_INVALID
;
2457 lpVer
= msi_alloc(dwVerLen
);
2460 ret
= ERROR_OUTOFMEMORY
;
2464 if( !GetFileVersionInfoW(szFilePath
, 0, dwVerLen
, lpVer
) )
2466 ret
= GetLastError();
2472 if( VerQueryValueW(lpVer
, szVersionResource
, (LPVOID
*)&ffi
, &puLen
) &&
2475 wsprintfW(tmp
, szVersionFormat
,
2476 HIWORD(ffi
->dwFileVersionMS
), LOWORD(ffi
->dwFileVersionMS
),
2477 HIWORD(ffi
->dwFileVersionLS
), LOWORD(ffi
->dwFileVersionLS
));
2478 if (lpVersionBuf
) lstrcpynW(lpVersionBuf
, tmp
, *pcchVersionBuf
);
2480 if (strlenW(tmp
) >= *pcchVersionBuf
)
2481 ret
= ERROR_MORE_DATA
;
2483 *pcchVersionBuf
= lstrlenW(tmp
);
2487 if (lpVersionBuf
) *lpVersionBuf
= 0;
2488 *pcchVersionBuf
= 0;
2494 if (VerQueryValueW(lpVer
, szLangResource
, (LPVOID
*)&lang
, &puLen
) &&
2497 wsprintfW(tmp
, szLangFormat
, *lang
);
2498 if (lpLangBuf
) lstrcpynW(lpLangBuf
, tmp
, *pcchLangBuf
);
2500 if (strlenW(tmp
) >= *pcchLangBuf
)
2501 ret
= ERROR_MORE_DATA
;
2503 *pcchLangBuf
= lstrlenW(tmp
);
2507 if (lpLangBuf
) *lpLangBuf
= 0;
2517 /***********************************************************************
2518 * MsiGetFeatureUsageW [MSI.@]
2520 UINT WINAPI
MsiGetFeatureUsageW( LPCWSTR szProduct
, LPCWSTR szFeature
,
2521 LPDWORD pdwUseCount
, LPWORD pwDateUsed
)
2523 FIXME("%s %s %p %p\n",debugstr_w(szProduct
), debugstr_w(szFeature
),
2524 pdwUseCount
, pwDateUsed
);
2525 return ERROR_CALL_NOT_IMPLEMENTED
;
2528 /***********************************************************************
2529 * MsiGetFeatureUsageA [MSI.@]
2531 UINT WINAPI
MsiGetFeatureUsageA( LPCSTR szProduct
, LPCSTR szFeature
,
2532 LPDWORD pdwUseCount
, LPWORD pwDateUsed
)
2534 LPWSTR prod
= NULL
, feat
= NULL
;
2535 UINT ret
= ERROR_OUTOFMEMORY
;
2537 TRACE("%s %s %p %p\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
2538 pdwUseCount
, pwDateUsed
);
2540 prod
= strdupAtoW( szProduct
);
2541 if (szProduct
&& !prod
)
2544 feat
= strdupAtoW( szFeature
);
2545 if (szFeature
&& !feat
)
2548 ret
= MsiGetFeatureUsageW( prod
, feat
, pdwUseCount
, pwDateUsed
);
2557 /***********************************************************************
2558 * MsiUseFeatureExW [MSI.@]
2560 INSTALLSTATE WINAPI
MsiUseFeatureExW( LPCWSTR szProduct
, LPCWSTR szFeature
,
2561 DWORD dwInstallMode
, DWORD dwReserved
)
2565 TRACE("%s %s %i %i\n", debugstr_w(szProduct
), debugstr_w(szFeature
),
2566 dwInstallMode
, dwReserved
);
2568 state
= MsiQueryFeatureStateW( szProduct
, szFeature
);
2571 return INSTALLSTATE_INVALIDARG
;
2573 if (state
== INSTALLSTATE_LOCAL
&& dwInstallMode
!= INSTALLMODE_NODETECTION
)
2575 FIXME("mark product %s feature %s as used\n",
2576 debugstr_w(szProduct
), debugstr_w(szFeature
) );
2582 /***********************************************************************
2583 * MsiUseFeatureExA [MSI.@]
2585 INSTALLSTATE WINAPI
MsiUseFeatureExA( LPCSTR szProduct
, LPCSTR szFeature
,
2586 DWORD dwInstallMode
, DWORD dwReserved
)
2588 INSTALLSTATE ret
= INSTALLSTATE_UNKNOWN
;
2589 LPWSTR prod
= NULL
, feat
= NULL
;
2591 TRACE("%s %s %i %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
2592 dwInstallMode
, dwReserved
);
2594 prod
= strdupAtoW( szProduct
);
2595 if (szProduct
&& !prod
)
2598 feat
= strdupAtoW( szFeature
);
2599 if (szFeature
&& !feat
)
2602 ret
= MsiUseFeatureExW( prod
, feat
, dwInstallMode
, dwReserved
);
2611 /***********************************************************************
2612 * MsiUseFeatureW [MSI.@]
2614 INSTALLSTATE WINAPI
MsiUseFeatureW( LPCWSTR szProduct
, LPCWSTR szFeature
)
2616 return MsiUseFeatureExW(szProduct
, szFeature
, 0, 0);
2619 /***********************************************************************
2620 * MsiUseFeatureA [MSI.@]
2622 INSTALLSTATE WINAPI
MsiUseFeatureA( LPCSTR szProduct
, LPCSTR szFeature
)
2624 return MsiUseFeatureExA(szProduct
, szFeature
, 0, 0);
2627 /***********************************************************************
2628 * MSI_ProvideQualifiedComponentEx [internal]
2630 static UINT
MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent
,
2631 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPCWSTR szProduct
,
2632 DWORD Unused1
, DWORD Unused2
, awstring
*lpPathBuf
,
2633 LPDWORD pcchPathBuf
)
2635 WCHAR product
[MAX_FEATURE_CHARS
+1], component
[MAX_FEATURE_CHARS
+1],
2636 feature
[MAX_FEATURE_CHARS
+1];
2642 TRACE("%s %s %i %s %i %i %p %p\n", debugstr_w(szComponent
),
2643 debugstr_w(szQualifier
), dwInstallMode
, debugstr_w(szProduct
),
2644 Unused1
, Unused2
, lpPathBuf
, pcchPathBuf
);
2646 rc
= MSIREG_OpenUserComponentsKey(szComponent
, &hkey
, FALSE
);
2647 if (rc
!= ERROR_SUCCESS
)
2648 return ERROR_INDEX_ABSENT
;
2650 info
= msi_reg_get_val_str( hkey
, szQualifier
);
2654 return ERROR_INDEX_ABSENT
;
2656 MsiDecomposeDescriptorW(info
, product
, feature
, component
, &sz
);
2659 rc
= MSI_GetComponentPath(product
, component
, lpPathBuf
, pcchPathBuf
);
2661 rc
= MSI_GetComponentPath(szProduct
, component
, lpPathBuf
, pcchPathBuf
);
2665 if (rc
!= INSTALLSTATE_LOCAL
)
2666 return ERROR_FILE_NOT_FOUND
;
2668 return ERROR_SUCCESS
;
2671 /***********************************************************************
2672 * MsiProvideQualifiedComponentExW [MSI.@]
2674 UINT WINAPI
MsiProvideQualifiedComponentExW(LPCWSTR szComponent
,
2675 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPCWSTR szProduct
,
2676 DWORD Unused1
, DWORD Unused2
, LPWSTR lpPathBuf
,
2677 LPDWORD pcchPathBuf
)
2681 path
.unicode
= TRUE
;
2682 path
.str
.w
= lpPathBuf
;
2684 return MSI_ProvideQualifiedComponentEx(szComponent
, szQualifier
,
2685 dwInstallMode
, szProduct
, Unused1
, Unused2
, &path
, pcchPathBuf
);
2688 /***********************************************************************
2689 * MsiProvideQualifiedComponentExA [MSI.@]
2691 UINT WINAPI
MsiProvideQualifiedComponentExA(LPCSTR szComponent
,
2692 LPCSTR szQualifier
, DWORD dwInstallMode
, LPCSTR szProduct
,
2693 DWORD Unused1
, DWORD Unused2
, LPSTR lpPathBuf
,
2694 LPDWORD pcchPathBuf
)
2696 LPWSTR szwComponent
, szwQualifier
= NULL
, szwProduct
= NULL
;
2697 UINT r
= ERROR_OUTOFMEMORY
;
2700 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent
),
2701 debugstr_a(szQualifier
), dwInstallMode
, debugstr_a(szProduct
),
2702 Unused1
, Unused2
, lpPathBuf
, pcchPathBuf
);
2704 szwComponent
= strdupAtoW( szComponent
);
2705 if (szComponent
&& !szwComponent
)
2708 szwQualifier
= strdupAtoW( szQualifier
);
2709 if (szQualifier
&& !szwQualifier
)
2712 szwProduct
= strdupAtoW( szProduct
);
2713 if (szProduct
&& !szwProduct
)
2716 path
.unicode
= FALSE
;
2717 path
.str
.a
= lpPathBuf
;
2719 r
= MSI_ProvideQualifiedComponentEx(szwComponent
, szwQualifier
,
2720 dwInstallMode
, szwProduct
, Unused1
,
2721 Unused2
, &path
, pcchPathBuf
);
2723 msi_free(szwProduct
);
2724 msi_free(szwComponent
);
2725 msi_free(szwQualifier
);
2730 /***********************************************************************
2731 * MsiProvideQualifiedComponentW [MSI.@]
2733 UINT WINAPI
MsiProvideQualifiedComponentW( LPCWSTR szComponent
,
2734 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPWSTR lpPathBuf
,
2735 LPDWORD pcchPathBuf
)
2737 return MsiProvideQualifiedComponentExW(szComponent
, szQualifier
,
2738 dwInstallMode
, NULL
, 0, 0, lpPathBuf
, pcchPathBuf
);
2741 /***********************************************************************
2742 * MsiProvideQualifiedComponentA [MSI.@]
2744 UINT WINAPI
MsiProvideQualifiedComponentA( LPCSTR szComponent
,
2745 LPCSTR szQualifier
, DWORD dwInstallMode
, LPSTR lpPathBuf
,
2746 LPDWORD pcchPathBuf
)
2748 return MsiProvideQualifiedComponentExA(szComponent
, szQualifier
,
2749 dwInstallMode
, NULL
, 0, 0, lpPathBuf
, pcchPathBuf
);
2752 /***********************************************************************
2753 * MSI_GetUserInfo [internal]
2755 static USERINFOSTATE
MSI_GetUserInfo(LPCWSTR szProduct
,
2756 awstring
*lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
2757 awstring
*lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
2758 awstring
*lpSerialBuf
, LPDWORD pcchSerialBuf
)
2760 WCHAR squished_pc
[SQUISH_GUID_SIZE
];
2761 LPWSTR user
, org
, serial
;
2762 USERINFOSTATE state
;
2767 static const WCHAR szEmpty
[] = {0};
2769 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct
), lpUserNameBuf
,
2770 pcchUserNameBuf
, lpOrgNameBuf
, pcchOrgNameBuf
, lpSerialBuf
,
2773 if (!szProduct
|| !squash_guid(szProduct
, squished_pc
))
2774 return USERINFOSTATE_INVALIDARG
;
2776 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
2777 &hkey
, FALSE
) != ERROR_SUCCESS
&&
2778 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
2779 &hkey
, FALSE
) != ERROR_SUCCESS
&&
2780 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
2781 &hkey
, FALSE
) != ERROR_SUCCESS
)
2783 return USERINFOSTATE_UNKNOWN
;
2786 if (MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
,
2787 NULL
, &props
, FALSE
) != ERROR_SUCCESS
&&
2788 MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_MACHINE
,
2789 NULL
, &props
, FALSE
) != ERROR_SUCCESS
)
2792 return USERINFOSTATE_ABSENT
;
2795 user
= msi_reg_get_val_str(props
, INSTALLPROPERTY_REGOWNERW
);
2796 org
= msi_reg_get_val_str(props
, INSTALLPROPERTY_REGCOMPANYW
);
2797 serial
= msi_reg_get_val_str(props
, INSTALLPROPERTY_PRODUCTIDW
);
2798 state
= USERINFOSTATE_ABSENT
;
2804 state
= USERINFOSTATE_PRESENT
;
2806 if (pcchUserNameBuf
)
2808 if (lpUserNameBuf
&& !user
)
2810 (*pcchUserNameBuf
)--;
2814 r
= msi_strcpy_to_awstring(user
, lpUserNameBuf
, pcchUserNameBuf
);
2815 if (r
== ERROR_MORE_DATA
)
2817 state
= USERINFOSTATE_MOREDATA
;
2825 if (!orgptr
) orgptr
= szEmpty
;
2827 r
= msi_strcpy_to_awstring(orgptr
, lpOrgNameBuf
, pcchOrgNameBuf
);
2828 if (r
== ERROR_MORE_DATA
)
2830 state
= USERINFOSTATE_MOREDATA
;
2843 r
= msi_strcpy_to_awstring(serial
, lpSerialBuf
, pcchSerialBuf
);
2844 if (r
== ERROR_MORE_DATA
)
2845 state
= USERINFOSTATE_MOREDATA
;
2856 /***********************************************************************
2857 * MsiGetUserInfoW [MSI.@]
2859 USERINFOSTATE WINAPI
MsiGetUserInfoW(LPCWSTR szProduct
,
2860 LPWSTR lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
2861 LPWSTR lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
2862 LPWSTR lpSerialBuf
, LPDWORD pcchSerialBuf
)
2864 awstring user
, org
, serial
;
2866 if ((lpUserNameBuf
&& !pcchUserNameBuf
) ||
2867 (lpOrgNameBuf
&& !pcchOrgNameBuf
) ||
2868 (lpSerialBuf
&& !pcchSerialBuf
))
2869 return USERINFOSTATE_INVALIDARG
;
2871 user
.unicode
= TRUE
;
2872 user
.str
.w
= lpUserNameBuf
;
2874 org
.str
.w
= lpOrgNameBuf
;
2875 serial
.unicode
= TRUE
;
2876 serial
.str
.w
= lpSerialBuf
;
2878 return MSI_GetUserInfo( szProduct
, &user
, pcchUserNameBuf
,
2879 &org
, pcchOrgNameBuf
,
2880 &serial
, pcchSerialBuf
);
2883 USERINFOSTATE WINAPI
MsiGetUserInfoA(LPCSTR szProduct
,
2884 LPSTR lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
2885 LPSTR lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
2886 LPSTR lpSerialBuf
, LPDWORD pcchSerialBuf
)
2888 awstring user
, org
, serial
;
2892 if ((lpUserNameBuf
&& !pcchUserNameBuf
) ||
2893 (lpOrgNameBuf
&& !pcchOrgNameBuf
) ||
2894 (lpSerialBuf
&& !pcchSerialBuf
))
2895 return USERINFOSTATE_INVALIDARG
;
2897 prod
= strdupAtoW( szProduct
);
2898 if (szProduct
&& !prod
)
2899 return ERROR_OUTOFMEMORY
;
2901 user
.unicode
= FALSE
;
2902 user
.str
.a
= lpUserNameBuf
;
2903 org
.unicode
= FALSE
;
2904 org
.str
.a
= lpOrgNameBuf
;
2905 serial
.unicode
= FALSE
;
2906 serial
.str
.a
= lpSerialBuf
;
2908 r
= MSI_GetUserInfo( prod
, &user
, pcchUserNameBuf
,
2909 &org
, pcchOrgNameBuf
,
2910 &serial
, pcchSerialBuf
);
2917 UINT WINAPI
MsiCollectUserInfoW(LPCWSTR szProduct
)
2921 MSIPACKAGE
*package
;
2922 static const WCHAR szFirstRun
[] = {'F','i','r','s','t','R','u','n',0};
2924 TRACE("(%s)\n",debugstr_w(szProduct
));
2926 rc
= MsiOpenProductW(szProduct
,&handle
);
2927 if (rc
!= ERROR_SUCCESS
)
2928 return ERROR_INVALID_PARAMETER
;
2930 package
= msihandle2msiinfo(handle
, MSIHANDLETYPE_PACKAGE
);
2931 rc
= ACTION_PerformUIAction(package
, szFirstRun
, -1);
2932 msiobj_release( &package
->hdr
);
2934 MsiCloseHandle(handle
);
2939 UINT WINAPI
MsiCollectUserInfoA(LPCSTR szProduct
)
2943 MSIPACKAGE
*package
;
2944 static const WCHAR szFirstRun
[] = {'F','i','r','s','t','R','u','n',0};
2946 TRACE("(%s)\n",debugstr_a(szProduct
));
2948 rc
= MsiOpenProductA(szProduct
,&handle
);
2949 if (rc
!= ERROR_SUCCESS
)
2950 return ERROR_INVALID_PARAMETER
;
2952 package
= msihandle2msiinfo(handle
, MSIHANDLETYPE_PACKAGE
);
2953 rc
= ACTION_PerformUIAction(package
, szFirstRun
, -1);
2954 msiobj_release( &package
->hdr
);
2956 MsiCloseHandle(handle
);
2961 /***********************************************************************
2962 * MsiConfigureFeatureA [MSI.@]
2964 UINT WINAPI
MsiConfigureFeatureA(LPCSTR szProduct
, LPCSTR szFeature
, INSTALLSTATE eInstallState
)
2966 LPWSTR prod
, feat
= NULL
;
2967 UINT r
= ERROR_OUTOFMEMORY
;
2969 TRACE("%s %s %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
), eInstallState
);
2971 prod
= strdupAtoW( szProduct
);
2972 if (szProduct
&& !prod
)
2975 feat
= strdupAtoW( szFeature
);
2976 if (szFeature
&& !feat
)
2979 r
= MsiConfigureFeatureW(prod
, feat
, eInstallState
);
2988 /***********************************************************************
2989 * MsiConfigureFeatureW [MSI.@]
2991 UINT WINAPI
MsiConfigureFeatureW(LPCWSTR szProduct
, LPCWSTR szFeature
, INSTALLSTATE eInstallState
)
2993 static const WCHAR szCostInit
[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
2994 MSIPACKAGE
*package
= NULL
;
2996 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
2999 TRACE("%s %s %i\n", debugstr_w(szProduct
), debugstr_w(szFeature
), eInstallState
);
3001 if (!szProduct
|| !szFeature
)
3002 return ERROR_INVALID_PARAMETER
;
3004 switch (eInstallState
)
3006 case INSTALLSTATE_DEFAULT
:
3007 /* FIXME: how do we figure out the default location? */
3008 eInstallState
= INSTALLSTATE_LOCAL
;
3010 case INSTALLSTATE_LOCAL
:
3011 case INSTALLSTATE_SOURCE
:
3012 case INSTALLSTATE_ABSENT
:
3013 case INSTALLSTATE_ADVERTISED
:
3016 return ERROR_INVALID_PARAMETER
;
3019 r
= MSI_OpenProductW( szProduct
, &package
);
3020 if (r
!= ERROR_SUCCESS
)
3023 sz
= sizeof(sourcepath
);
3024 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3025 MSICODE_PRODUCT
, INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
3027 sz
= sizeof(filename
);
3028 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3029 MSICODE_PRODUCT
, INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
3031 lstrcatW( sourcepath
, filename
);
3033 MsiSetInternalUI( INSTALLUILEVEL_BASIC
, NULL
);
3035 r
= ACTION_PerformUIAction( package
, szCostInit
, -1 );
3036 if (r
!= ERROR_SUCCESS
)
3039 r
= MSI_SetFeatureStateW( package
, szFeature
, eInstallState
);
3040 if (r
!= ERROR_SUCCESS
)
3043 r
= MSI_InstallPackage( package
, sourcepath
, NULL
);
3046 msiobj_release( &package
->hdr
);
3051 /***********************************************************************
3052 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3054 * Notes: undocumented
3056 UINT WINAPI
MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved
)
3058 WCHAR path
[MAX_PATH
];
3060 TRACE("%d\n", dwReserved
);
3064 FIXME("dwReserved=%d\n", dwReserved
);
3065 return ERROR_INVALID_PARAMETER
;
3068 if (!GetWindowsDirectoryW(path
, MAX_PATH
))
3069 return ERROR_FUNCTION_FAILED
;
3071 lstrcatW(path
, installerW
);
3073 if (!CreateDirectoryW(path
, NULL
))
3074 return ERROR_FUNCTION_FAILED
;
3076 return ERROR_SUCCESS
;
3079 /***********************************************************************
3080 * MsiGetShortcutTargetA [MSI.@]
3082 UINT WINAPI
MsiGetShortcutTargetA( LPCSTR szShortcutTarget
,
3083 LPSTR szProductCode
, LPSTR szFeatureId
,
3084 LPSTR szComponentCode
)
3087 const int len
= MAX_FEATURE_CHARS
+1;
3088 WCHAR product
[MAX_FEATURE_CHARS
+1], feature
[MAX_FEATURE_CHARS
+1], component
[MAX_FEATURE_CHARS
+1];
3091 target
= strdupAtoW( szShortcutTarget
);
3092 if (szShortcutTarget
&& !target
)
3093 return ERROR_OUTOFMEMORY
;
3097 r
= MsiGetShortcutTargetW( target
, product
, feature
, component
);
3099 if (r
== ERROR_SUCCESS
)
3101 WideCharToMultiByte( CP_ACP
, 0, product
, -1, szProductCode
, len
, NULL
, NULL
);
3102 WideCharToMultiByte( CP_ACP
, 0, feature
, -1, szFeatureId
, len
, NULL
, NULL
);
3103 WideCharToMultiByte( CP_ACP
, 0, component
, -1, szComponentCode
, len
, NULL
, NULL
);
3108 /***********************************************************************
3109 * MsiGetShortcutTargetW [MSI.@]
3111 UINT WINAPI
MsiGetShortcutTargetW( LPCWSTR szShortcutTarget
,
3112 LPWSTR szProductCode
, LPWSTR szFeatureId
,
3113 LPWSTR szComponentCode
)
3115 IShellLinkDataList
*dl
= NULL
;
3116 IPersistFile
*pf
= NULL
;
3117 LPEXP_DARWIN_LINK darwin
= NULL
;
3120 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget
),
3121 szProductCode
, szFeatureId
, szComponentCode
);
3123 init
= CoInitialize(NULL
);
3125 r
= CoCreateInstance( &CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
3126 &IID_IPersistFile
, (LPVOID
*) &pf
);
3127 if( SUCCEEDED( r
) )
3129 r
= IPersistFile_Load( pf
, szShortcutTarget
,
3130 STGM_READ
| STGM_SHARE_DENY_WRITE
);
3131 if( SUCCEEDED( r
) )
3133 r
= IPersistFile_QueryInterface( pf
, &IID_IShellLinkDataList
,
3135 if( SUCCEEDED( r
) )
3137 IShellLinkDataList_CopyDataBlock( dl
, EXP_DARWIN_ID_SIG
,
3139 IShellLinkDataList_Release( dl
);
3142 IPersistFile_Release( pf
);
3145 if (SUCCEEDED(init
))
3148 TRACE("darwin = %p\n", darwin
);
3155 ret
= MsiDecomposeDescriptorW( darwin
->szwDarwinID
,
3156 szProductCode
, szFeatureId
, szComponentCode
, &sz
);
3157 LocalFree( darwin
);
3161 return ERROR_FUNCTION_FAILED
;
3164 UINT WINAPI
MsiReinstallFeatureW( LPCWSTR szProduct
, LPCWSTR szFeature
,
3165 DWORD dwReinstallMode
)
3167 MSIPACKAGE
* package
= NULL
;
3169 WCHAR sourcepath
[MAX_PATH
];
3170 WCHAR filename
[MAX_PATH
];
3171 static const WCHAR szLogVerbose
[] = {
3172 ' ','L','O','G','V','E','R','B','O','S','E',0 };
3173 static const WCHAR szInstalled
[] = { 'I','n','s','t','a','l','l','e','d',0};
3174 static const WCHAR szReinstall
[] = {'R','E','I','N','S','T','A','L','L',0};
3175 static const WCHAR szReinstallMode
[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0};
3176 static const WCHAR szOne
[] = {'1',0};
3177 WCHAR reinstallmode
[11];
3181 FIXME("%s %s %i\n", debugstr_w(szProduct
), debugstr_w(szFeature
),
3184 ptr
= reinstallmode
;
3186 if (dwReinstallMode
& REINSTALLMODE_FILEMISSING
)
3188 if (dwReinstallMode
& REINSTALLMODE_FILEOLDERVERSION
)
3190 if (dwReinstallMode
& REINSTALLMODE_FILEEQUALVERSION
)
3192 if (dwReinstallMode
& REINSTALLMODE_FILEEXACT
)
3194 if (dwReinstallMode
& REINSTALLMODE_FILEVERIFY
)
3196 if (dwReinstallMode
& REINSTALLMODE_FILEREPLACE
)
3198 if (dwReinstallMode
& REINSTALLMODE_USERDATA
)
3200 if (dwReinstallMode
& REINSTALLMODE_MACHINEDATA
)
3202 if (dwReinstallMode
& REINSTALLMODE_SHORTCUT
)
3204 if (dwReinstallMode
& REINSTALLMODE_PACKAGE
)
3208 sz
= sizeof(sourcepath
);
3209 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3210 MSICODE_PRODUCT
, INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
3212 sz
= sizeof(filename
);
3213 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3214 MSICODE_PRODUCT
, INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
3216 lstrcatW( sourcepath
, filename
);
3218 if (dwReinstallMode
& REINSTALLMODE_PACKAGE
)
3219 r
= MSI_OpenPackageW( sourcepath
, &package
);
3221 r
= MSI_OpenProductW( szProduct
, &package
);
3223 if (r
!= ERROR_SUCCESS
)
3226 MSI_SetPropertyW( package
, szReinstallMode
, reinstallmode
);
3227 MSI_SetPropertyW( package
, szInstalled
, szOne
);
3228 MSI_SetPropertyW( package
, szLogVerbose
, szOne
);
3229 MSI_SetPropertyW( package
, szReinstall
, szFeature
);
3231 r
= MSI_InstallPackage( package
, sourcepath
, NULL
);
3233 msiobj_release( &package
->hdr
);
3238 UINT WINAPI
MsiReinstallFeatureA( LPCSTR szProduct
, LPCSTR szFeature
,
3239 DWORD dwReinstallMode
)
3245 TRACE("%s %s %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
3248 wszProduct
= strdupAtoW(szProduct
);
3249 wszFeature
= strdupAtoW(szFeature
);
3251 rc
= MsiReinstallFeatureW(wszProduct
, wszFeature
, dwReinstallMode
);
3253 msi_free(wszProduct
);
3254 msi_free(wszFeature
);
3261 unsigned int buf
[4];
3262 unsigned char in
[64];
3263 unsigned char digest
[16];
3266 extern VOID WINAPI
MD5Init( MD5_CTX
*);
3267 extern VOID WINAPI
MD5Update( MD5_CTX
*, const unsigned char *, unsigned int );
3268 extern VOID WINAPI
MD5Final( MD5_CTX
*);
3270 /***********************************************************************
3271 * MsiGetFileHashW [MSI.@]
3273 UINT WINAPI
MsiGetFileHashW( LPCWSTR szFilePath
, DWORD dwOptions
,
3274 PMSIFILEHASHINFO pHash
)
3276 HANDLE handle
, mapping
;
3279 UINT r
= ERROR_FUNCTION_FAILED
;
3281 TRACE("%s %08x %p\n", debugstr_w(szFilePath
), dwOptions
, pHash
);
3284 return ERROR_INVALID_PARAMETER
;
3287 return ERROR_PATH_NOT_FOUND
;
3290 return ERROR_INVALID_PARAMETER
;
3292 return ERROR_INVALID_PARAMETER
;
3293 if (pHash
->dwFileHashInfoSize
< sizeof *pHash
)
3294 return ERROR_INVALID_PARAMETER
;
3296 handle
= CreateFileW( szFilePath
, GENERIC_READ
,
3297 FILE_SHARE_READ
| FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, 0, NULL
);
3298 if (handle
== INVALID_HANDLE_VALUE
)
3299 return ERROR_FILE_NOT_FOUND
;
3301 length
= GetFileSize( handle
, NULL
);
3303 mapping
= CreateFileMappingW( handle
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3306 p
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, length
);
3312 MD5Update( &ctx
, p
, length
);
3314 UnmapViewOfFile( p
);
3316 memcpy( pHash
->dwData
, ctx
.digest
, sizeof pHash
->dwData
);
3319 CloseHandle( mapping
);
3321 CloseHandle( handle
);
3326 /***********************************************************************
3327 * MsiGetFileHashA [MSI.@]
3329 UINT WINAPI
MsiGetFileHashA( LPCSTR szFilePath
, DWORD dwOptions
,
3330 PMSIFILEHASHINFO pHash
)
3335 TRACE("%s %08x %p\n", debugstr_a(szFilePath
), dwOptions
, pHash
);
3337 file
= strdupAtoW( szFilePath
);
3338 if (szFilePath
&& !file
)
3339 return ERROR_OUTOFMEMORY
;
3341 r
= MsiGetFileHashW( file
, dwOptions
, pHash
);
3346 /***********************************************************************
3347 * MsiAdvertiseScriptW [MSI.@]
3349 UINT WINAPI
MsiAdvertiseScriptW( LPCWSTR szScriptFile
, DWORD dwFlags
,
3350 PHKEY phRegData
, BOOL fRemoveItems
)
3352 FIXME("%s %08x %p %d\n",
3353 debugstr_w( szScriptFile
), dwFlags
, phRegData
, fRemoveItems
);
3354 return ERROR_CALL_NOT_IMPLEMENTED
;
3357 /***********************************************************************
3358 * MsiAdvertiseScriptA [MSI.@]
3360 UINT WINAPI
MsiAdvertiseScriptA( LPCSTR szScriptFile
, DWORD dwFlags
,
3361 PHKEY phRegData
, BOOL fRemoveItems
)
3363 FIXME("%s %08x %p %d\n",
3364 debugstr_a( szScriptFile
), dwFlags
, phRegData
, fRemoveItems
);
3365 return ERROR_CALL_NOT_IMPLEMENTED
;
3368 /***********************************************************************
3369 * MsiIsProductElevatedW [MSI.@]
3371 UINT WINAPI
MsiIsProductElevatedW( LPCWSTR szProduct
, BOOL
*pfElevated
)
3373 FIXME("%s %p - stub\n",
3374 debugstr_w( szProduct
), pfElevated
);
3376 return ERROR_SUCCESS
;
3379 /***********************************************************************
3380 * MsiIsProductElevatedA [MSI.@]
3382 UINT WINAPI
MsiIsProductElevatedA( LPCSTR szProduct
, BOOL
*pfElevated
)
3384 FIXME("%s %p - stub\n",
3385 debugstr_a( szProduct
), pfElevated
);
3387 return ERROR_SUCCESS
;
3390 /***********************************************************************
3391 * MsiSetExternalUIRecord [MSI.@]
3393 UINT WINAPI
MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD puiHandler
,
3394 DWORD dwMessageFilter
, LPVOID pvContext
,
3395 PINSTALLUI_HANDLER_RECORD ppuiPrevHandler
)
3397 FIXME("%p %08x %p %p\n", puiHandler
, dwMessageFilter
,pvContext
,
3399 return ERROR_CALL_NOT_IMPLEMENTED
;
3402 /***********************************************************************
3403 * MsiInstallMissingComponentW [MSI.@]
3405 UINT WINAPI
MsiInstallMissingComponentW(LPCWSTR szProduct
, LPCWSTR szComponent
, INSTALLSTATE eInstallState
)
3407 FIXME("(%s %s %d\n", debugstr_w(szProduct
), debugstr_w(szComponent
), eInstallState
);
3408 return ERROR_SUCCESS
;