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
49 #include "wine/debug.h"
50 #include "wine/exception.h"
51 #include "wine/unicode.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
55 static const WCHAR installerW
[] = {'\\','I','n','s','t','a','l','l','e','r',0};
57 UINT
msi_locate_product(LPCWSTR szProduct
, MSIINSTALLCONTEXT
*context
)
61 *context
= MSIINSTALLCONTEXT_NONE
;
62 if (!szProduct
) return ERROR_UNKNOWN_PRODUCT
;
64 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
65 &hkey
, FALSE
) == ERROR_SUCCESS
)
66 *context
= MSIINSTALLCONTEXT_USERMANAGED
;
67 else if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
68 &hkey
, FALSE
) == ERROR_SUCCESS
)
69 *context
= MSIINSTALLCONTEXT_MACHINE
;
70 else if (MSIREG_OpenProductKey(szProduct
, NULL
,
71 MSIINSTALLCONTEXT_USERUNMANAGED
,
72 &hkey
, FALSE
) == ERROR_SUCCESS
)
73 *context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
77 if (*context
== MSIINSTALLCONTEXT_NONE
)
78 return ERROR_UNKNOWN_PRODUCT
;
83 UINT WINAPI
MsiOpenProductA(LPCSTR szProduct
, MSIHANDLE
*phProduct
)
86 LPWSTR szwProd
= NULL
;
88 TRACE("%s %p\n",debugstr_a(szProduct
), phProduct
);
92 szwProd
= strdupAtoW( szProduct
);
94 return ERROR_OUTOFMEMORY
;
97 r
= MsiOpenProductW( szwProd
, phProduct
);
104 static UINT
MSI_OpenProductW(LPCWSTR szProduct
, MSIPACKAGE
**package
)
109 MSIINSTALLCONTEXT context
;
111 static const WCHAR managed
[] = {
112 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
113 static const WCHAR local
[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
115 TRACE("%s %p\n", debugstr_w(szProduct
), package
);
117 r
= msi_locate_product(szProduct
, &context
);
118 if (r
!= ERROR_SUCCESS
)
121 r
= MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &props
, FALSE
);
122 if (r
!= ERROR_SUCCESS
)
123 return ERROR_UNKNOWN_PRODUCT
;
125 if (context
== MSIINSTALLCONTEXT_USERMANAGED
)
126 path
= msi_reg_get_val_str(props
, managed
);
128 path
= msi_reg_get_val_str(props
, local
);
130 r
= ERROR_UNKNOWN_PRODUCT
;
132 if (!path
|| GetFileAttributesW(path
) == INVALID_FILE_ATTRIBUTES
)
135 if (PathIsRelativeW(path
))
137 r
= ERROR_INSTALL_PACKAGE_OPEN_FAILED
;
141 r
= MSI_OpenPackageW(path
, 0, package
);
149 UINT WINAPI
MsiOpenProductW(LPCWSTR szProduct
, MSIHANDLE
*phProduct
)
151 MSIPACKAGE
*package
= NULL
;
152 WCHAR squashed_pc
[SQUASHED_GUID_SIZE
];
155 if (!szProduct
|| !squash_guid( szProduct
, squashed_pc
))
156 return ERROR_INVALID_PARAMETER
;
159 return ERROR_INVALID_PARAMETER
;
161 r
= MSI_OpenProductW(szProduct
, &package
);
162 if (r
!= ERROR_SUCCESS
)
165 *phProduct
= alloc_msihandle(&package
->hdr
);
167 r
= ERROR_NOT_ENOUGH_MEMORY
;
169 msiobj_release(&package
->hdr
);
173 UINT WINAPI
MsiAdvertiseProductA(LPCSTR szPackagePath
, LPCSTR szScriptfilePath
,
174 LPCSTR szTransforms
, LANGID lgidLanguage
)
176 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath
),
177 debugstr_a(szScriptfilePath
), debugstr_a(szTransforms
), lgidLanguage
);
178 return ERROR_CALL_NOT_IMPLEMENTED
;
181 UINT WINAPI
MsiAdvertiseProductW(LPCWSTR szPackagePath
, LPCWSTR szScriptfilePath
,
182 LPCWSTR szTransforms
, LANGID lgidLanguage
)
184 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath
),
185 debugstr_w(szScriptfilePath
), debugstr_w(szTransforms
), lgidLanguage
);
186 return ERROR_CALL_NOT_IMPLEMENTED
;
189 UINT WINAPI
MsiAdvertiseProductExA(LPCSTR szPackagePath
, LPCSTR szScriptfilePath
,
190 LPCSTR szTransforms
, LANGID lgidLanguage
, DWORD dwPlatform
, DWORD dwOptions
)
192 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath
),
193 debugstr_a(szScriptfilePath
), debugstr_a(szTransforms
),
194 lgidLanguage
, dwPlatform
, dwOptions
);
195 return ERROR_CALL_NOT_IMPLEMENTED
;
198 UINT WINAPI
MsiAdvertiseProductExW( LPCWSTR szPackagePath
, LPCWSTR szScriptfilePath
,
199 LPCWSTR szTransforms
, LANGID lgidLanguage
, DWORD dwPlatform
, DWORD dwOptions
)
201 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath
),
202 debugstr_w(szScriptfilePath
), debugstr_w(szTransforms
),
203 lgidLanguage
, dwPlatform
, dwOptions
);
204 return ERROR_CALL_NOT_IMPLEMENTED
;
207 UINT WINAPI
MsiInstallProductA(LPCSTR szPackagePath
, LPCSTR szCommandLine
)
209 LPWSTR szwPath
= NULL
, szwCommand
= NULL
;
210 UINT r
= ERROR_OUTOFMEMORY
;
212 TRACE("%s %s\n",debugstr_a(szPackagePath
), debugstr_a(szCommandLine
));
216 szwPath
= strdupAtoW( szPackagePath
);
223 szwCommand
= strdupAtoW( szCommandLine
);
228 r
= MsiInstallProductW( szwPath
, szwCommand
);
232 msi_free( szwCommand
);
237 UINT WINAPI
MsiInstallProductW(LPCWSTR szPackagePath
, LPCWSTR szCommandLine
)
239 MSIPACKAGE
*package
= NULL
;
240 const WCHAR
*reinstallmode
;
244 TRACE("%s %s\n",debugstr_w(szPackagePath
), debugstr_w(szCommandLine
));
247 return ERROR_INVALID_PARAMETER
;
250 return ERROR_PATH_NOT_FOUND
;
252 reinstallmode
= msi_get_command_line_option(szCommandLine
, szReinstallMode
, &len
);
257 if (reinstallmode
[--len
] == 'v' || reinstallmode
[len
] == 'V')
259 options
|= WINE_OPENPACKAGEFLAGS_RECACHE
;
265 r
= MSI_OpenPackageW( szPackagePath
, options
, &package
);
266 if (r
== ERROR_SUCCESS
)
268 r
= MSI_InstallPackage( package
, szPackagePath
, szCommandLine
);
269 msiobj_release( &package
->hdr
);
275 UINT WINAPI
MsiReinstallProductA(LPCSTR szProduct
, DWORD dwReinstallMode
)
280 TRACE("%s %08x\n", debugstr_a(szProduct
), dwReinstallMode
);
282 wszProduct
= strdupAtoW(szProduct
);
284 rc
= MsiReinstallProductW(wszProduct
, dwReinstallMode
);
286 msi_free(wszProduct
);
290 UINT WINAPI
MsiReinstallProductW(LPCWSTR szProduct
, DWORD dwReinstallMode
)
292 TRACE("%s %08x\n", debugstr_w(szProduct
), dwReinstallMode
);
294 return MsiReinstallFeatureW(szProduct
, szAll
, dwReinstallMode
);
297 UINT WINAPI
MsiApplyPatchA(LPCSTR szPatchPackage
, LPCSTR szInstallPackage
,
298 INSTALLTYPE eInstallType
, LPCSTR szCommandLine
)
300 LPWSTR patch_package
= NULL
;
301 LPWSTR install_package
= NULL
;
302 LPWSTR command_line
= NULL
;
303 UINT r
= ERROR_OUTOFMEMORY
;
305 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage
), debugstr_a(szInstallPackage
),
306 eInstallType
, debugstr_a(szCommandLine
));
308 if (szPatchPackage
&& !(patch_package
= strdupAtoW(szPatchPackage
)))
311 if (szInstallPackage
&& !(install_package
= strdupAtoW(szInstallPackage
)))
314 if (szCommandLine
&& !(command_line
= strdupAtoW(szCommandLine
)))
317 r
= MsiApplyPatchW(patch_package
, install_package
, eInstallType
, command_line
);
320 msi_free(patch_package
);
321 msi_free(install_package
);
322 msi_free(command_line
);
327 static UINT
get_patch_product_codes( LPCWSTR szPatchPackage
, WCHAR
***product_codes
)
329 MSIHANDLE patch
, info
= 0;
332 static WCHAR empty
[] = {0};
335 r
= MsiOpenDatabaseW( szPatchPackage
, MSIDBOPEN_READONLY
, &patch
);
336 if (r
!= ERROR_SUCCESS
)
339 r
= MsiGetSummaryInformationW( patch
, NULL
, 0, &info
);
340 if (r
!= ERROR_SUCCESS
)
344 r
= MsiSummaryInfoGetPropertyW( info
, PID_TEMPLATE
, &type
, NULL
, NULL
, empty
, &size
);
345 if (r
!= ERROR_MORE_DATA
|| !size
|| type
!= VT_LPSTR
)
347 ERR("Failed to read product codes from patch\n");
348 r
= ERROR_FUNCTION_FAILED
;
352 codes
= msi_alloc( ++size
* sizeof(WCHAR
) );
355 r
= ERROR_OUTOFMEMORY
;
359 r
= MsiSummaryInfoGetPropertyW( info
, PID_TEMPLATE
, &type
, NULL
, NULL
, codes
, &size
);
360 if (r
== ERROR_SUCCESS
)
361 *product_codes
= msi_split_string( codes
, ';' );
364 MsiCloseHandle( info
);
365 MsiCloseHandle( patch
);
370 static UINT
MSI_ApplyPatchW(LPCWSTR szPatchPackage
, LPCWSTR szProductCode
, LPCWSTR szCommandLine
)
372 UINT i
, r
= ERROR_FUNCTION_FAILED
;
374 LPCWSTR cmd_ptr
= szCommandLine
;
375 LPWSTR cmd
, *codes
= NULL
;
376 BOOL succeeded
= FALSE
;
378 static const WCHAR fmt
[] = {'%','s',' ','P','A','T','C','H','=','"','%','s','"',0};
379 static const WCHAR empty
[] = {0};
381 if (!szPatchPackage
|| !szPatchPackage
[0])
382 return ERROR_INVALID_PARAMETER
;
384 if (!szProductCode
&& (r
= get_patch_product_codes( szPatchPackage
, &codes
)))
390 size
= strlenW(cmd_ptr
) + strlenW(fmt
) + strlenW(szPatchPackage
) + 1;
391 cmd
= msi_alloc(size
* sizeof(WCHAR
));
395 return ERROR_OUTOFMEMORY
;
397 sprintfW(cmd
, fmt
, cmd_ptr
, szPatchPackage
);
400 r
= MsiConfigureProductExW(szProductCode
, INSTALLLEVEL_DEFAULT
, INSTALLSTATE_DEFAULT
, cmd
);
403 for (i
= 0; codes
[i
]; i
++)
405 r
= MsiConfigureProductExW(codes
[i
], INSTALLLEVEL_DEFAULT
, INSTALLSTATE_DEFAULT
, cmd
);
406 if (r
== ERROR_SUCCESS
)
408 TRACE("patch applied\n");
422 UINT WINAPI
MsiApplyPatchW(LPCWSTR szPatchPackage
, LPCWSTR szInstallPackage
,
423 INSTALLTYPE eInstallType
, LPCWSTR szCommandLine
)
425 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage
), debugstr_w(szInstallPackage
),
426 eInstallType
, debugstr_w(szCommandLine
));
428 if (szInstallPackage
|| eInstallType
== INSTALLTYPE_NETWORK_IMAGE
||
429 eInstallType
== INSTALLTYPE_SINGLE_INSTANCE
)
431 FIXME("Only reading target products from patch\n");
432 return ERROR_CALL_NOT_IMPLEMENTED
;
435 return MSI_ApplyPatchW(szPatchPackage
, NULL
, szCommandLine
);
438 UINT WINAPI
MsiApplyMultiplePatchesA(LPCSTR szPatchPackages
,
439 LPCSTR szProductCode
, LPCSTR szPropertiesList
)
441 LPWSTR patch_packages
= NULL
;
442 LPWSTR product_code
= NULL
;
443 LPWSTR properties_list
= NULL
;
444 UINT r
= ERROR_OUTOFMEMORY
;
446 TRACE("%s %s %s\n", debugstr_a(szPatchPackages
), debugstr_a(szProductCode
),
447 debugstr_a(szPropertiesList
));
449 if (!szPatchPackages
|| !szPatchPackages
[0])
450 return ERROR_INVALID_PARAMETER
;
452 if (!(patch_packages
= strdupAtoW(szPatchPackages
)))
453 return ERROR_OUTOFMEMORY
;
455 if (szProductCode
&& !(product_code
= strdupAtoW(szProductCode
)))
458 if (szPropertiesList
&& !(properties_list
= strdupAtoW(szPropertiesList
)))
461 r
= MsiApplyMultiplePatchesW(patch_packages
, product_code
, properties_list
);
464 msi_free(patch_packages
);
465 msi_free(product_code
);
466 msi_free(properties_list
);
471 UINT WINAPI
MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages
,
472 LPCWSTR szProductCode
, LPCWSTR szPropertiesList
)
474 UINT r
= ERROR_SUCCESS
;
477 TRACE("%s %s %s\n", debugstr_w(szPatchPackages
), debugstr_w(szProductCode
),
478 debugstr_w(szPropertiesList
));
480 if (!szPatchPackages
|| !szPatchPackages
[0])
481 return ERROR_INVALID_PARAMETER
;
483 beg
= end
= szPatchPackages
;
489 while (*beg
== ' ') beg
++;
490 while (*end
&& *end
!= ';') end
++;
493 while (len
&& beg
[len
- 1] == ' ') len
--;
495 if (!len
) return ERROR_INVALID_NAME
;
497 patch
= msi_alloc((len
+ 1) * sizeof(WCHAR
));
499 return ERROR_OUTOFMEMORY
;
501 memcpy(patch
, beg
, len
* sizeof(WCHAR
));
504 r
= MSI_ApplyPatchW(patch
, szProductCode
, szPropertiesList
);
507 if (r
!= ERROR_SUCCESS
|| !*end
)
515 static void free_patchinfo( DWORD count
, MSIPATCHSEQUENCEINFOW
*info
)
518 for (i
= 0; i
< count
; i
++) msi_free( (WCHAR
*)info
[i
].szPatchData
);
522 static MSIPATCHSEQUENCEINFOW
*patchinfoAtoW( DWORD count
, const MSIPATCHSEQUENCEINFOA
*info
)
525 MSIPATCHSEQUENCEINFOW
*ret
;
527 if (!(ret
= msi_alloc( count
* sizeof(MSIPATCHSEQUENCEINFOW
) ))) return NULL
;
528 for (i
= 0; i
< count
; i
++)
530 if (info
[i
].szPatchData
&& !(ret
[i
].szPatchData
= strdupAtoW( info
[i
].szPatchData
)))
532 free_patchinfo( i
, ret
);
535 ret
[i
].ePatchDataType
= info
[i
].ePatchDataType
;
536 ret
[i
].dwOrder
= info
[i
].dwOrder
;
537 ret
[i
].uStatus
= info
[i
].uStatus
;
542 UINT WINAPI
MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath
,
543 DWORD cPatchInfo
, PMSIPATCHSEQUENCEINFOA pPatchInfo
)
546 WCHAR
*package_path
= NULL
;
547 MSIPATCHSEQUENCEINFOW
*psi
;
549 TRACE("%s, %u, %p\n", debugstr_a(szProductPackagePath
), cPatchInfo
, pPatchInfo
);
551 if (szProductPackagePath
&& !(package_path
= strdupAtoW( szProductPackagePath
)))
552 return ERROR_OUTOFMEMORY
;
554 if (!(psi
= patchinfoAtoW( cPatchInfo
, pPatchInfo
)))
556 msi_free( package_path
);
557 return ERROR_OUTOFMEMORY
;
559 r
= MsiDetermineApplicablePatchesW( package_path
, cPatchInfo
, psi
);
560 if (r
== ERROR_SUCCESS
)
562 for (i
= 0; i
< cPatchInfo
; i
++)
564 pPatchInfo
[i
].dwOrder
= psi
[i
].dwOrder
;
565 pPatchInfo
[i
].uStatus
= psi
[i
].uStatus
;
568 msi_free( package_path
);
569 free_patchinfo( cPatchInfo
, psi
);
573 static UINT
MSI_ApplicablePatchW( MSIPACKAGE
*package
, LPCWSTR patch
)
576 MSIDATABASE
*patch_db
;
579 r
= MSI_OpenDatabaseW( patch
, MSIDBOPEN_READONLY
, &patch_db
);
580 if (r
!= ERROR_SUCCESS
)
582 WARN("failed to open patch file %s\n", debugstr_w(patch
));
586 r
= msi_get_suminfo( patch_db
->storage
, 0, &si
);
587 if (r
!= ERROR_SUCCESS
)
589 msiobj_release( &patch_db
->hdr
);
590 return ERROR_FUNCTION_FAILED
;
593 r
= msi_check_patch_applicable( package
, si
);
594 if (r
!= ERROR_SUCCESS
)
595 TRACE("patch not applicable\n");
597 msiobj_release( &patch_db
->hdr
);
598 msiobj_release( &si
->hdr
);
602 /* IXMLDOMDocument should be set to XPath mode already */
603 static UINT
MSI_ApplicablePatchXML( MSIPACKAGE
*package
, IXMLDOMDocument
*desc
)
605 static const WCHAR queryW
[] = {'M','s','i','P','a','t','c','h','/',
606 'T','a','r','g','e','t','P','r','o','d','u','c','t','/',
607 'T','a','r','g','e','t','P','r','o','d','u','c','t','C','o','d','e',0};
608 UINT r
= ERROR_FUNCTION_FAILED
;
609 IXMLDOMNodeList
*list
;
615 product_code
= msi_dup_property( package
->db
, szProductCode
);
618 /* FIXME: the property ProductCode should be written into the DB somewhere */
619 ERR("no product code to check\n");
620 return ERROR_SUCCESS
;
623 s
= SysAllocString(queryW
);
624 hr
= IXMLDOMDocument_selectNodes( desc
, s
, &list
);
627 return ERROR_INVALID_PATCH_XML
;
629 while (IXMLDOMNodeList_nextNode( list
, &node
) == S_OK
&& r
!= ERROR_SUCCESS
)
631 hr
= IXMLDOMNode_get_text( node
, &s
);
632 IXMLDOMNode_Release( node
);
635 if (!strcmpW( s
, product_code
)) r
= ERROR_SUCCESS
;
639 IXMLDOMNodeList_Release( list
);
641 if (r
!= ERROR_SUCCESS
)
642 TRACE("patch not applicable\n");
644 msi_free( product_code
);
648 static UINT
determine_patch_sequence( MSIPACKAGE
*package
, DWORD count
, MSIPATCHSEQUENCEINFOW
*info
)
650 IXMLDOMDocument
*desc
= NULL
;
654 FIXME("patch ordering not supported\n");
656 for (i
= 0; i
< count
; i
++)
658 switch (info
[i
].ePatchDataType
)
660 case MSIPATCH_DATATYPE_PATCHFILE
:
662 if (MSI_ApplicablePatchW( package
, info
[i
].szPatchData
) != ERROR_SUCCESS
)
664 info
[i
].dwOrder
= ~0u;
665 info
[i
].uStatus
= ERROR_PATCH_TARGET_NOT_FOUND
;
670 info
[i
].uStatus
= ERROR_SUCCESS
;
674 case MSIPATCH_DATATYPE_XMLPATH
:
675 case MSIPATCH_DATATYPE_XMLBLOB
:
683 hr
= CoCreateInstance( &CLSID_DOMDocument30
, NULL
, CLSCTX_INPROC_SERVER
,
684 &IID_IXMLDOMDocument
, (void**)&desc
);
687 ERR("failed to create DOMDocument30 instance, 0x%08x\n", hr
);
688 return ERROR_FUNCTION_FAILED
;
692 s
= SysAllocString( info
[i
].szPatchData
);
693 if (info
[i
].ePatchDataType
== MSIPATCH_DATATYPE_XMLPATH
)
697 V_VT(&src
) = VT_BSTR
;
699 hr
= IXMLDOMDocument_load( desc
, src
, &b
);
702 hr
= IXMLDOMDocument_loadXML( desc
, s
, &b
);
706 ERR("failed to parse patch description\n");
707 IXMLDOMDocument_Release( desc
);
711 if (MSI_ApplicablePatchXML( package
, desc
) != ERROR_SUCCESS
)
713 info
[i
].dwOrder
= ~0u;
714 info
[i
].uStatus
= ERROR_PATCH_TARGET_NOT_FOUND
;
719 info
[i
].uStatus
= ERROR_SUCCESS
;
725 FIXME("unknown patch data type %u\n", info
[i
].ePatchDataType
);
727 info
[i
].uStatus
= ERROR_SUCCESS
;
732 TRACE("szPatchData: %s\n", debugstr_w(info
[i
].szPatchData
));
733 TRACE("ePatchDataType: %u\n", info
[i
].ePatchDataType
);
734 TRACE("dwOrder: %u\n", info
[i
].dwOrder
);
735 TRACE("uStatus: %u\n", info
[i
].uStatus
);
738 if (desc
) IXMLDOMDocument_Release( desc
);
740 return ERROR_SUCCESS
;
743 UINT WINAPI
MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath
,
744 DWORD cPatchInfo
, PMSIPATCHSEQUENCEINFOW pPatchInfo
)
749 TRACE("%s, %u, %p\n", debugstr_w(szProductPackagePath
), cPatchInfo
, pPatchInfo
);
751 r
= MSI_OpenPackageW( szProductPackagePath
, 0, &package
);
752 if (r
!= ERROR_SUCCESS
)
754 ERR("failed to open package %u\n", r
);
757 r
= determine_patch_sequence( package
, cPatchInfo
, pPatchInfo
);
758 msiobj_release( &package
->hdr
);
762 UINT WINAPI
MsiDeterminePatchSequenceA( LPCSTR product
, LPCSTR usersid
,
763 MSIINSTALLCONTEXT context
, DWORD count
, PMSIPATCHSEQUENCEINFOA patchinfo
)
766 WCHAR
*productW
, *usersidW
= NULL
;
767 MSIPATCHSEQUENCEINFOW
*patchinfoW
;
769 TRACE("%s, %s, %d, %d, %p\n", debugstr_a(product
), debugstr_a(usersid
),
770 context
, count
, patchinfo
);
772 if (!product
) return ERROR_INVALID_PARAMETER
;
773 if (!(productW
= strdupAtoW( product
))) return ERROR_OUTOFMEMORY
;
774 if (usersid
&& !(usersidW
= strdupAtoW( usersid
)))
776 msi_free( productW
);
777 return ERROR_OUTOFMEMORY
;
779 if (!(patchinfoW
= patchinfoAtoW( count
, patchinfo
)))
781 msi_free( productW
);
782 msi_free( usersidW
);
783 return ERROR_OUTOFMEMORY
;
785 r
= MsiDeterminePatchSequenceW( productW
, usersidW
, context
, count
, patchinfoW
);
786 if (r
== ERROR_SUCCESS
)
788 for (i
= 0; i
< count
; i
++)
790 patchinfo
[i
].dwOrder
= patchinfoW
[i
].dwOrder
;
791 patchinfo
[i
].uStatus
= patchinfoW
[i
].uStatus
;
794 msi_free( productW
);
795 msi_free( usersidW
);
796 free_patchinfo( count
, patchinfoW
);
800 static UINT
open_package( const WCHAR
*product
, const WCHAR
*usersid
,
801 MSIINSTALLCONTEXT context
, MSIPACKAGE
**package
)
805 WCHAR
*localpath
, sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
807 r
= MSIREG_OpenInstallProps( product
, context
, usersid
, &props
, FALSE
);
808 if (r
!= ERROR_SUCCESS
) return ERROR_BAD_CONFIGURATION
;
810 if ((localpath
= msi_reg_get_val_str( props
, szLocalPackage
)))
812 strcpyW( sourcepath
, localpath
);
813 msi_free( localpath
);
815 RegCloseKey( props
);
816 if (!localpath
|| GetFileAttributesW( sourcepath
) == INVALID_FILE_ATTRIBUTES
)
818 DWORD sz
= sizeof(sourcepath
);
819 MsiSourceListGetInfoW( product
, usersid
, context
, MSICODE_PRODUCT
,
820 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
821 sz
= sizeof(filename
);
822 MsiSourceListGetInfoW( product
, usersid
, context
, MSICODE_PRODUCT
,
823 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
824 strcatW( sourcepath
, filename
);
826 if (GetFileAttributesW( sourcepath
) == INVALID_FILE_ATTRIBUTES
)
827 return ERROR_INSTALL_SOURCE_ABSENT
;
829 return MSI_OpenPackageW( sourcepath
, 0, package
);
832 UINT WINAPI
MsiDeterminePatchSequenceW( LPCWSTR product
, LPCWSTR usersid
,
833 MSIINSTALLCONTEXT context
, DWORD count
, PMSIPATCHSEQUENCEINFOW patchinfo
)
838 TRACE("%s, %s, %d, %d, %p\n", debugstr_w(product
), debugstr_w(usersid
),
839 context
, count
, patchinfo
);
841 if (!product
) return ERROR_INVALID_PARAMETER
;
842 r
= open_package( product
, usersid
, context
, &package
);
843 if (r
!= ERROR_SUCCESS
) return r
;
845 r
= determine_patch_sequence( package
, count
, patchinfo
);
846 msiobj_release( &package
->hdr
);
850 UINT WINAPI
MsiConfigureProductExW(LPCWSTR szProduct
, int iInstallLevel
,
851 INSTALLSTATE eInstallState
, LPCWSTR szCommandLine
)
853 MSIPACKAGE
* package
= NULL
;
854 MSIINSTALLCONTEXT context
;
857 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
860 static const WCHAR szInstalled
[] = {
861 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
862 static const WCHAR szMaxInstallLevel
[] = {
863 ' ','I','N','S','T','A','L','L','L','E','V','E','L','=','3','2','7','6','7',0};
864 static const WCHAR szRemoveAll
[] = {
865 ' ','R','E','M','O','V','E','=','A','L','L',0};
866 static const WCHAR szMachine
[] = {
867 ' ','A','L','L','U','S','E','R','S','=','1',0};
869 TRACE("%s %d %d %s\n",debugstr_w(szProduct
), iInstallLevel
, eInstallState
,
870 debugstr_w(szCommandLine
));
872 if (!szProduct
|| lstrlenW(szProduct
) != GUID_SIZE
- 1)
873 return ERROR_INVALID_PARAMETER
;
875 if (eInstallState
== INSTALLSTATE_ADVERTISED
||
876 eInstallState
== INSTALLSTATE_SOURCE
)
878 FIXME("State %d not implemented\n", eInstallState
);
879 return ERROR_CALL_NOT_IMPLEMENTED
;
882 r
= msi_locate_product(szProduct
, &context
);
883 if (r
!= ERROR_SUCCESS
)
886 r
= open_package(szProduct
, NULL
, context
, &package
);
887 if (r
!= ERROR_SUCCESS
)
890 sz
= lstrlenW(szInstalled
) + 1;
893 sz
+= lstrlenW(szCommandLine
);
895 if (eInstallState
!= INSTALLSTATE_DEFAULT
)
896 sz
+= lstrlenW(szMaxInstallLevel
);
898 if (eInstallState
== INSTALLSTATE_ABSENT
)
899 sz
+= lstrlenW(szRemoveAll
);
901 if (context
== MSIINSTALLCONTEXT_MACHINE
)
902 sz
+= lstrlenW(szMachine
);
904 commandline
= msi_alloc(sz
* sizeof(WCHAR
));
907 r
= ERROR_OUTOFMEMORY
;
913 lstrcpyW(commandline
,szCommandLine
);
915 if (eInstallState
!= INSTALLSTATE_DEFAULT
)
916 lstrcatW(commandline
, szMaxInstallLevel
);
918 if (eInstallState
== INSTALLSTATE_ABSENT
)
919 lstrcatW(commandline
, szRemoveAll
);
921 if (context
== MSIINSTALLCONTEXT_MACHINE
)
922 lstrcatW(commandline
, szMachine
);
924 sz
= sizeof(sourcepath
);
925 MsiSourceListGetInfoW(szProduct
, NULL
, context
, MSICODE_PRODUCT
,
926 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
928 sz
= sizeof(filename
);
929 MsiSourceListGetInfoW(szProduct
, NULL
, context
, MSICODE_PRODUCT
,
930 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
932 strcatW(sourcepath
, filename
);
934 r
= MSI_InstallPackage( package
, sourcepath
, commandline
);
936 msi_free(commandline
);
939 msiobj_release( &package
->hdr
);
944 UINT WINAPI
MsiConfigureProductExA(LPCSTR szProduct
, int iInstallLevel
,
945 INSTALLSTATE eInstallState
, LPCSTR szCommandLine
)
947 LPWSTR szwProduct
= NULL
;
948 LPWSTR szwCommandLine
= NULL
;
949 UINT r
= ERROR_OUTOFMEMORY
;
953 szwProduct
= strdupAtoW( szProduct
);
960 szwCommandLine
= strdupAtoW( szCommandLine
);
965 r
= MsiConfigureProductExW( szwProduct
, iInstallLevel
, eInstallState
,
968 msi_free( szwProduct
);
969 msi_free( szwCommandLine
);
974 UINT WINAPI
MsiConfigureProductA(LPCSTR szProduct
, int iInstallLevel
,
975 INSTALLSTATE eInstallState
)
977 LPWSTR szwProduct
= NULL
;
980 TRACE("%s %d %d\n",debugstr_a(szProduct
), iInstallLevel
, eInstallState
);
984 szwProduct
= strdupAtoW( szProduct
);
986 return ERROR_OUTOFMEMORY
;
989 r
= MsiConfigureProductW( szwProduct
, iInstallLevel
, eInstallState
);
990 msi_free( szwProduct
);
995 UINT WINAPI
MsiConfigureProductW(LPCWSTR szProduct
, int iInstallLevel
,
996 INSTALLSTATE eInstallState
)
998 return MsiConfigureProductExW(szProduct
, iInstallLevel
, eInstallState
, NULL
);
1001 UINT WINAPI
MsiGetProductCodeA(LPCSTR szComponent
, LPSTR szBuffer
)
1003 LPWSTR szwComponent
= NULL
;
1005 WCHAR szwBuffer
[GUID_SIZE
];
1007 TRACE("%s %p\n", debugstr_a(szComponent
), szBuffer
);
1011 szwComponent
= strdupAtoW( szComponent
);
1013 return ERROR_OUTOFMEMORY
;
1017 r
= MsiGetProductCodeW( szwComponent
, szwBuffer
);
1020 WideCharToMultiByte(CP_ACP
, 0, szwBuffer
, -1, szBuffer
, GUID_SIZE
, NULL
, NULL
);
1022 msi_free( szwComponent
);
1027 UINT WINAPI
MsiGetProductCodeW(LPCWSTR szComponent
, LPWSTR szBuffer
)
1030 HKEY compkey
, prodkey
;
1031 WCHAR squashed_comp
[SQUASHED_GUID_SIZE
], squashed_prod
[SQUASHED_GUID_SIZE
];
1032 DWORD sz
= ARRAY_SIZE(squashed_prod
);
1034 TRACE("%s %p\n", debugstr_w(szComponent
), szBuffer
);
1036 if (!szComponent
|| !*szComponent
)
1037 return ERROR_INVALID_PARAMETER
;
1039 if (!squash_guid( szComponent
, squashed_comp
))
1040 return ERROR_INVALID_PARAMETER
;
1042 if (MSIREG_OpenUserDataComponentKey(szComponent
, NULL
, &compkey
, FALSE
) != ERROR_SUCCESS
&&
1043 MSIREG_OpenUserDataComponentKey(szComponent
, szLocalSid
, &compkey
, FALSE
) != ERROR_SUCCESS
)
1045 return ERROR_UNKNOWN_COMPONENT
;
1048 rc
= RegEnumValueW( compkey
, 0, squashed_prod
, &sz
, NULL
, NULL
, NULL
, NULL
);
1049 if (rc
!= ERROR_SUCCESS
)
1051 RegCloseKey(compkey
);
1052 return ERROR_UNKNOWN_COMPONENT
;
1055 /* check simple case, only one product */
1056 rc
= RegEnumValueW( compkey
, 1, squashed_prod
, &sz
, NULL
, NULL
, NULL
, NULL
);
1057 if (rc
== ERROR_NO_MORE_ITEMS
)
1064 while ((rc
= RegEnumValueW( compkey
, index
, squashed_prod
, &sz
, NULL
, NULL
, NULL
, NULL
)) !=
1065 ERROR_NO_MORE_ITEMS
)
1069 unsquash_guid( squashed_prod
, szBuffer
);
1071 if (MSIREG_OpenProductKey(szBuffer
, NULL
,
1072 MSIINSTALLCONTEXT_USERMANAGED
,
1073 &prodkey
, FALSE
) == ERROR_SUCCESS
||
1074 MSIREG_OpenProductKey(szBuffer
, NULL
,
1075 MSIINSTALLCONTEXT_USERUNMANAGED
,
1076 &prodkey
, FALSE
) == ERROR_SUCCESS
||
1077 MSIREG_OpenProductKey(szBuffer
, NULL
,
1078 MSIINSTALLCONTEXT_MACHINE
,
1079 &prodkey
, FALSE
) == ERROR_SUCCESS
)
1081 RegCloseKey(prodkey
);
1087 rc
= ERROR_INSTALL_FAILURE
;
1090 RegCloseKey(compkey
);
1091 unsquash_guid( squashed_prod
, szBuffer
);
1095 static WCHAR
*reg_get_value( HKEY hkey
, const WCHAR
*name
, DWORD
*type
)
1099 if ((res
= RegQueryValueExW( hkey
, name
, NULL
, type
, NULL
, NULL
)) != ERROR_SUCCESS
) return NULL
;
1101 if (*type
== REG_SZ
) return msi_reg_get_val_str( hkey
, name
);
1102 if (*type
== REG_DWORD
)
1104 static const WCHAR fmt
[] = {'%','u',0};
1108 if (!msi_reg_get_val_dword( hkey
, name
, &val
)) return NULL
;
1109 sprintfW( temp
, fmt
, val
);
1110 return strdupW( temp
);
1113 ERR( "unhandled value type %u\n", *type
);
1117 static UINT
MSI_GetProductInfo(LPCWSTR szProduct
, LPCWSTR szAttribute
,
1118 awstring
*szValue
, LPDWORD pcchValueBuf
)
1120 static WCHAR empty
[] = {0};
1121 static const WCHAR sourcelist
[] = {'S','o','u','r','c','e','L','i','s','t',0};
1122 static const WCHAR display_name
[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
1123 static const WCHAR display_version
[] = {'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1124 static const WCHAR assignment
[] = {'A','s','s','i','g','n','m','e','n','t',0};
1125 MSIINSTALLCONTEXT context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
1126 UINT r
= ERROR_UNKNOWN_PROPERTY
;
1127 HKEY prodkey
, userdata
, source
;
1128 WCHAR
*val
= NULL
, squashed_pc
[SQUASHED_GUID_SIZE
], packagecode
[GUID_SIZE
];
1129 BOOL badconfig
= FALSE
;
1131 DWORD type
= REG_NONE
;
1133 TRACE("%s %s %p %p\n", debugstr_w(szProduct
),
1134 debugstr_w(szAttribute
), szValue
, pcchValueBuf
);
1136 if ((szValue
->str
.w
&& !pcchValueBuf
) || !szProduct
|| !szAttribute
)
1137 return ERROR_INVALID_PARAMETER
;
1139 if (!squash_guid( szProduct
, squashed_pc
))
1140 return ERROR_INVALID_PARAMETER
;
1142 if ((r
= MSIREG_OpenProductKey(szProduct
, NULL
,
1143 MSIINSTALLCONTEXT_USERMANAGED
,
1144 &prodkey
, FALSE
)) != ERROR_SUCCESS
&&
1145 (r
= MSIREG_OpenProductKey(szProduct
, NULL
,
1146 MSIINSTALLCONTEXT_USERUNMANAGED
,
1147 &prodkey
, FALSE
)) != ERROR_SUCCESS
&&
1148 (r
= MSIREG_OpenProductKey(szProduct
, NULL
,
1149 MSIINSTALLCONTEXT_MACHINE
,
1150 &prodkey
, FALSE
)) == ERROR_SUCCESS
)
1152 context
= MSIINSTALLCONTEXT_MACHINE
;
1155 if (!strcmpW( szAttribute
, INSTALLPROPERTY_HELPLINKW
) ||
1156 !strcmpW( szAttribute
, INSTALLPROPERTY_HELPTELEPHONEW
) ||
1157 !strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLDATEW
) ||
1158 !strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
) ||
1159 !strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLLOCATIONW
) ||
1160 !strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLSOURCEW
) ||
1161 !strcmpW( szAttribute
, INSTALLPROPERTY_LOCALPACKAGEW
) ||
1162 !strcmpW( szAttribute
, INSTALLPROPERTY_PUBLISHERW
) ||
1163 !strcmpW( szAttribute
, INSTALLPROPERTY_URLINFOABOUTW
) ||
1164 !strcmpW( szAttribute
, INSTALLPROPERTY_URLUPDATEINFOW
) ||
1165 !strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONMINORW
) ||
1166 !strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONMAJORW
) ||
1167 !strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONSTRINGW
) ||
1168 !strcmpW( szAttribute
, INSTALLPROPERTY_PRODUCTIDW
) ||
1169 !strcmpW( szAttribute
, INSTALLPROPERTY_REGCOMPANYW
) ||
1170 !strcmpW( szAttribute
, INSTALLPROPERTY_REGOWNERW
))
1174 r
= ERROR_UNKNOWN_PRODUCT
;
1177 if (MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &userdata
, FALSE
))
1179 r
= ERROR_UNKNOWN_PROPERTY
;
1183 if (!strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
))
1184 szAttribute
= display_name
;
1185 else if (!strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONSTRINGW
))
1186 szAttribute
= display_version
;
1188 val
= reg_get_value(userdata
, szAttribute
, &type
);
1191 RegCloseKey(userdata
);
1193 else if (!strcmpW( szAttribute
, INSTALLPROPERTY_INSTANCETYPEW
) ||
1194 !strcmpW( szAttribute
, INSTALLPROPERTY_TRANSFORMSW
) ||
1195 !strcmpW( szAttribute
, INSTALLPROPERTY_LANGUAGEW
) ||
1196 !strcmpW( szAttribute
, INSTALLPROPERTY_PRODUCTNAMEW
) ||
1197 !strcmpW( szAttribute
, INSTALLPROPERTY_ASSIGNMENTTYPEW
) ||
1198 !strcmpW( szAttribute
, INSTALLPROPERTY_PACKAGECODEW
) ||
1199 !strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONW
) ||
1200 !strcmpW( szAttribute
, INSTALLPROPERTY_PRODUCTICONW
) ||
1201 !strcmpW( szAttribute
, INSTALLPROPERTY_PACKAGENAMEW
) ||
1202 !strcmpW( szAttribute
, INSTALLPROPERTY_AUTHORIZED_LUA_APPW
))
1206 r
= ERROR_UNKNOWN_PRODUCT
;
1210 if (!strcmpW( szAttribute
, INSTALLPROPERTY_ASSIGNMENTTYPEW
))
1211 szAttribute
= assignment
;
1213 if (!strcmpW( szAttribute
, INSTALLPROPERTY_PACKAGENAMEW
))
1215 res
= RegOpenKeyW(prodkey
, sourcelist
, &source
);
1216 if (res
!= ERROR_SUCCESS
)
1218 r
= ERROR_UNKNOWN_PRODUCT
;
1222 val
= reg_get_value(source
, szAttribute
, &type
);
1226 RegCloseKey(source
);
1230 val
= reg_get_value(prodkey
, szAttribute
, &type
);
1235 if (val
!= empty
&& type
!= REG_DWORD
&&
1236 !strcmpW( szAttribute
, INSTALLPROPERTY_PACKAGECODEW
))
1238 if (lstrlenW( val
) != SQUASHED_GUID_SIZE
- 1)
1242 unsquash_guid(val
, packagecode
);
1244 val
= strdupW(packagecode
);
1251 r
= ERROR_UNKNOWN_PROPERTY
;
1257 int len
= strlenW( val
);
1259 /* If szBuffer (szValue->str) is NULL, there's no need to copy the value
1260 * out. Also, *pcchValueBuf may be uninitialized in this case, so we
1261 * can't rely on its value.
1263 if (szValue
->str
.a
|| szValue
->str
.w
)
1265 DWORD size
= *pcchValueBuf
;
1267 r
= msi_strcpy_to_awstring( val
, len
, szValue
, &size
);
1269 r
= ERROR_MORE_DATA
;
1273 *pcchValueBuf
= len
;
1277 r
= ERROR_BAD_CONFIGURATION
;
1283 RegCloseKey(prodkey
);
1287 UINT WINAPI
MsiGetProductInfoA(LPCSTR szProduct
, LPCSTR szAttribute
,
1288 LPSTR szBuffer
, LPDWORD pcchValueBuf
)
1290 LPWSTR szwProduct
, szwAttribute
= NULL
;
1291 UINT r
= ERROR_OUTOFMEMORY
;
1294 TRACE("%s %s %p %p\n", debugstr_a(szProduct
), debugstr_a(szAttribute
),
1295 szBuffer
, pcchValueBuf
);
1297 szwProduct
= strdupAtoW( szProduct
);
1298 if( szProduct
&& !szwProduct
)
1301 szwAttribute
= strdupAtoW( szAttribute
);
1302 if( szAttribute
&& !szwAttribute
)
1305 buffer
.unicode
= FALSE
;
1306 buffer
.str
.a
= szBuffer
;
1308 r
= MSI_GetProductInfo( szwProduct
, szwAttribute
,
1309 &buffer
, pcchValueBuf
);
1312 msi_free( szwProduct
);
1313 msi_free( szwAttribute
);
1318 UINT WINAPI
MsiGetProductInfoW(LPCWSTR szProduct
, LPCWSTR szAttribute
,
1319 LPWSTR szBuffer
, LPDWORD pcchValueBuf
)
1323 TRACE("%s %s %p %p\n", debugstr_w(szProduct
), debugstr_w(szAttribute
),
1324 szBuffer
, pcchValueBuf
);
1326 buffer
.unicode
= TRUE
;
1327 buffer
.str
.w
= szBuffer
;
1329 return MSI_GetProductInfo( szProduct
, szAttribute
,
1330 &buffer
, pcchValueBuf
);
1333 UINT WINAPI
MsiGetProductInfoExA(LPCSTR szProductCode
, LPCSTR szUserSid
,
1334 MSIINSTALLCONTEXT dwContext
, LPCSTR szProperty
,
1335 LPSTR szValue
, LPDWORD pcchValue
)
1337 LPWSTR product
= NULL
;
1338 LPWSTR usersid
= NULL
;
1339 LPWSTR property
= NULL
;
1340 LPWSTR value
= NULL
;
1344 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode
),
1345 debugstr_a(szUserSid
), dwContext
, debugstr_a(szProperty
),
1346 szValue
, pcchValue
);
1348 if (szValue
&& !pcchValue
)
1349 return ERROR_INVALID_PARAMETER
;
1351 if (szProductCode
) product
= strdupAtoW(szProductCode
);
1352 if (szUserSid
) usersid
= strdupAtoW(szUserSid
);
1353 if (szProperty
) property
= strdupAtoW(szProperty
);
1355 r
= MsiGetProductInfoExW(product
, usersid
, dwContext
, property
,
1357 if (r
!= ERROR_SUCCESS
)
1360 value
= msi_alloc(++len
* sizeof(WCHAR
));
1363 r
= ERROR_OUTOFMEMORY
;
1367 r
= MsiGetProductInfoExW(product
, usersid
, dwContext
, property
,
1369 if (r
!= ERROR_SUCCESS
)
1375 len
= WideCharToMultiByte(CP_ACP
, 0, value
, -1, NULL
, 0, NULL
, NULL
);
1376 if (*pcchValue
>= len
)
1377 WideCharToMultiByte(CP_ACP
, 0, value
, -1, szValue
, len
, NULL
, NULL
);
1380 r
= ERROR_MORE_DATA
;
1385 if (*pcchValue
<= len
|| !szValue
)
1386 len
= len
* sizeof(WCHAR
) - 1;
1388 *pcchValue
= len
- 1;
1399 static UINT
msi_copy_outval(LPWSTR val
, LPWSTR out
, LPDWORD size
)
1401 UINT r
= ERROR_SUCCESS
;
1404 return ERROR_UNKNOWN_PROPERTY
;
1408 if (strlenW(val
) >= *size
)
1410 r
= ERROR_MORE_DATA
;
1419 *size
= lstrlenW(val
);
1424 UINT WINAPI
MsiGetProductInfoExW(LPCWSTR szProductCode
, LPCWSTR szUserSid
,
1425 MSIINSTALLCONTEXT dwContext
, LPCWSTR szProperty
,
1426 LPWSTR szValue
, LPDWORD pcchValue
)
1428 static const WCHAR five
[] = {'5',0};
1429 static const WCHAR displayname
[] = {
1430 'D','i','s','p','l','a','y','N','a','m','e',0};
1431 static const WCHAR displayversion
[] = {
1432 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1433 static const WCHAR managed_local_package
[] = {
1434 'M','a','n','a','g','e','d','L','o','c','a','l',
1435 'P','a','c','k','a','g','e',0};
1436 WCHAR
*val
= NULL
, squashed_pc
[SQUASHED_GUID_SIZE
];
1437 LPCWSTR package
= NULL
;
1438 HKEY props
= NULL
, prod
, classes
= NULL
, managed
, hkey
= NULL
;
1440 UINT r
= ERROR_UNKNOWN_PRODUCT
;
1442 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode
),
1443 debugstr_w(szUserSid
), dwContext
, debugstr_w(szProperty
),
1444 szValue
, pcchValue
);
1446 if (!szProductCode
|| !squash_guid( szProductCode
, squashed_pc
))
1447 return ERROR_INVALID_PARAMETER
;
1449 if (szValue
&& !pcchValue
)
1450 return ERROR_INVALID_PARAMETER
;
1452 if (dwContext
!= MSIINSTALLCONTEXT_USERUNMANAGED
&&
1453 dwContext
!= MSIINSTALLCONTEXT_USERMANAGED
&&
1454 dwContext
!= MSIINSTALLCONTEXT_MACHINE
)
1455 return ERROR_INVALID_PARAMETER
;
1457 if (!szProperty
|| !*szProperty
)
1458 return ERROR_INVALID_PARAMETER
;
1460 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
&& szUserSid
)
1461 return ERROR_INVALID_PARAMETER
;
1463 /* FIXME: dwContext is provided, no need to search for it */
1464 MSIREG_OpenProductKey(szProductCode
, NULL
,MSIINSTALLCONTEXT_USERMANAGED
,
1466 MSIREG_OpenProductKey(szProductCode
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
1469 MSIREG_OpenInstallProps(szProductCode
, dwContext
, NULL
, &props
, FALSE
);
1471 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
1473 package
= INSTALLPROPERTY_LOCALPACKAGEW
;
1475 if (!props
&& !prod
)
1478 else if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1480 package
= managed_local_package
;
1482 if (!props
&& !managed
)
1485 else if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1487 package
= INSTALLPROPERTY_LOCALPACKAGEW
;
1488 MSIREG_OpenProductKey(szProductCode
, NULL
, dwContext
, &classes
, FALSE
);
1490 if (!props
&& !classes
)
1494 if (!strcmpW( szProperty
, INSTALLPROPERTY_HELPLINKW
) ||
1495 !strcmpW( szProperty
, INSTALLPROPERTY_HELPTELEPHONEW
) ||
1496 !strcmpW( szProperty
, INSTALLPROPERTY_INSTALLDATEW
) ||
1497 !strcmpW( szProperty
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
) ||
1498 !strcmpW( szProperty
, INSTALLPROPERTY_INSTALLLOCATIONW
) ||
1499 !strcmpW( szProperty
, INSTALLPROPERTY_INSTALLSOURCEW
) ||
1500 !strcmpW( szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
) ||
1501 !strcmpW( szProperty
, INSTALLPROPERTY_PUBLISHERW
) ||
1502 !strcmpW( szProperty
, INSTALLPROPERTY_URLINFOABOUTW
) ||
1503 !strcmpW( szProperty
, INSTALLPROPERTY_URLUPDATEINFOW
) ||
1504 !strcmpW( szProperty
, INSTALLPROPERTY_VERSIONMINORW
) ||
1505 !strcmpW( szProperty
, INSTALLPROPERTY_VERSIONMAJORW
) ||
1506 !strcmpW( szProperty
, INSTALLPROPERTY_VERSIONSTRINGW
) ||
1507 !strcmpW( szProperty
, INSTALLPROPERTY_PRODUCTIDW
) ||
1508 !strcmpW( szProperty
, INSTALLPROPERTY_REGCOMPANYW
) ||
1509 !strcmpW( szProperty
, INSTALLPROPERTY_REGOWNERW
) ||
1510 !strcmpW( szProperty
, INSTALLPROPERTY_INSTANCETYPEW
))
1512 val
= reg_get_value(props
, package
, &type
);
1515 if (prod
|| classes
)
1516 r
= ERROR_UNKNOWN_PROPERTY
;
1523 if (!strcmpW( szProperty
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
))
1524 szProperty
= displayname
;
1525 else if (!strcmpW( szProperty
, INSTALLPROPERTY_VERSIONSTRINGW
))
1526 szProperty
= displayversion
;
1528 val
= reg_get_value(props
, szProperty
, &type
);
1530 val
= strdupW(szEmpty
);
1532 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1534 else if (!strcmpW( szProperty
, INSTALLPROPERTY_TRANSFORMSW
) ||
1535 !strcmpW( szProperty
, INSTALLPROPERTY_LANGUAGEW
) ||
1536 !strcmpW( szProperty
, INSTALLPROPERTY_PRODUCTNAMEW
) ||
1537 !strcmpW( szProperty
, INSTALLPROPERTY_PACKAGECODEW
) ||
1538 !strcmpW( szProperty
, INSTALLPROPERTY_VERSIONW
) ||
1539 !strcmpW( szProperty
, INSTALLPROPERTY_PRODUCTICONW
) ||
1540 !strcmpW( szProperty
, INSTALLPROPERTY_PACKAGENAMEW
) ||
1541 !strcmpW( szProperty
, INSTALLPROPERTY_AUTHORIZED_LUA_APPW
))
1543 if (!prod
&& !classes
)
1546 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
1548 else if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1550 else if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1553 val
= reg_get_value(hkey
, szProperty
, &type
);
1555 val
= strdupW(szEmpty
);
1557 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1559 else if (!strcmpW( szProperty
, INSTALLPROPERTY_PRODUCTSTATEW
))
1561 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1565 val
= reg_get_value(props
, package
, &type
);
1570 val
= strdupW(five
);
1573 val
= strdupW(szOne
);
1575 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1578 else if (props
&& (val
= reg_get_value(props
, package
, &type
)))
1581 val
= strdupW(five
);
1582 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1586 if (prod
|| managed
)
1587 val
= strdupW(szOne
);
1591 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1593 else if (!strcmpW( szProperty
, INSTALLPROPERTY_ASSIGNMENTTYPEW
))
1595 if (!prod
&& !classes
)
1599 val
= strdupW(szEmpty
);
1600 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1603 r
= ERROR_UNKNOWN_PROPERTY
;
1608 RegCloseKey(managed
);
1609 RegCloseKey(classes
);
1615 UINT WINAPI
MsiGetPatchFileListA(LPCSTR szProductCode
, LPCSTR szPatchList
,
1616 LPDWORD pcFiles
, MSIHANDLE
**pphFileRecords
)
1618 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_a(szProductCode
),
1619 debugstr_a(szPatchList
), pcFiles
, pphFileRecords
);
1620 return ERROR_FUNCTION_FAILED
;
1623 UINT WINAPI
MsiGetPatchFileListW(LPCWSTR szProductCode
, LPCWSTR szPatchList
,
1624 LPDWORD pcFiles
, MSIHANDLE
**pphFileRecords
)
1626 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_w(szProductCode
),
1627 debugstr_w(szPatchList
), pcFiles
, pphFileRecords
);
1628 return ERROR_FUNCTION_FAILED
;
1631 UINT WINAPI
MsiGetPatchInfoExA(LPCSTR szPatchCode
, LPCSTR szProductCode
,
1632 LPCSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1633 LPCSTR szProperty
, LPSTR lpValue
, DWORD
*pcchValue
)
1635 LPWSTR patch
= NULL
, product
= NULL
, usersid
= NULL
;
1636 LPWSTR property
= NULL
, val
= NULL
;
1640 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode
),
1641 debugstr_a(szProductCode
), debugstr_a(szUserSid
), dwContext
,
1642 debugstr_a(szProperty
), lpValue
, pcchValue
);
1644 if (lpValue
&& !pcchValue
)
1645 return ERROR_INVALID_PARAMETER
;
1647 if (szPatchCode
) patch
= strdupAtoW(szPatchCode
);
1648 if (szProductCode
) product
= strdupAtoW(szProductCode
);
1649 if (szUserSid
) usersid
= strdupAtoW(szUserSid
);
1650 if (szProperty
) property
= strdupAtoW(szProperty
);
1653 r
= MsiGetPatchInfoExW(patch
, product
, usersid
, dwContext
, property
,
1655 if (r
!= ERROR_SUCCESS
)
1658 val
= msi_alloc(++len
* sizeof(WCHAR
));
1661 r
= ERROR_OUTOFMEMORY
;
1665 r
= MsiGetPatchInfoExW(patch
, product
, usersid
, dwContext
, property
,
1667 if (r
!= ERROR_SUCCESS
|| !pcchValue
)
1671 WideCharToMultiByte(CP_ACP
, 0, val
, -1, lpValue
,
1672 *pcchValue
- 1, NULL
, NULL
);
1674 len
= lstrlenW(val
);
1675 if ((*val
&& *pcchValue
< len
+ 1) || !lpValue
)
1679 r
= ERROR_MORE_DATA
;
1680 lpValue
[*pcchValue
- 1] = '\0';
1683 *pcchValue
= len
* sizeof(WCHAR
);
1698 UINT WINAPI
MsiGetPatchInfoExW(LPCWSTR szPatchCode
, LPCWSTR szProductCode
,
1699 LPCWSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1700 LPCWSTR szProperty
, LPWSTR lpValue
, DWORD
*pcchValue
)
1702 static const WCHAR szManagedPackage
[] =
1703 {'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
1704 WCHAR
*val
= NULL
, squashed_pc
[SQUASHED_GUID_SIZE
], squashed_patch
[SQUASHED_GUID_SIZE
];
1705 HKEY udprod
= 0, prod
= 0, props
= 0;
1706 HKEY patch
= 0, patches
= 0;
1707 HKEY udpatch
= 0, datakey
= 0;
1708 HKEY prodpatches
= 0;
1709 UINT r
= ERROR_UNKNOWN_PRODUCT
;
1713 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode
),
1714 debugstr_w(szProductCode
), debugstr_w(szUserSid
), dwContext
,
1715 debugstr_w(szProperty
), lpValue
, pcchValue
);
1717 if (!szProductCode
|| !squash_guid( szProductCode
, squashed_pc
))
1718 return ERROR_INVALID_PARAMETER
;
1720 if (!szPatchCode
|| !squash_guid( szPatchCode
, squashed_patch
))
1721 return ERROR_INVALID_PARAMETER
;
1724 return ERROR_INVALID_PARAMETER
;
1726 if (lpValue
&& !pcchValue
)
1727 return ERROR_INVALID_PARAMETER
;
1729 if (dwContext
!= MSIINSTALLCONTEXT_USERMANAGED
&&
1730 dwContext
!= MSIINSTALLCONTEXT_USERUNMANAGED
&&
1731 dwContext
!= MSIINSTALLCONTEXT_MACHINE
)
1732 return ERROR_INVALID_PARAMETER
;
1734 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
&& szUserSid
)
1735 return ERROR_INVALID_PARAMETER
;
1737 if (szUserSid
&& !strcmpW( szUserSid
, szLocalSid
))
1738 return ERROR_INVALID_PARAMETER
;
1740 if (MSIREG_OpenUserDataProductKey(szProductCode
, dwContext
, NULL
,
1741 &udprod
, FALSE
) != ERROR_SUCCESS
)
1744 if (MSIREG_OpenInstallProps(szProductCode
, dwContext
, NULL
,
1745 &props
, FALSE
) != ERROR_SUCCESS
)
1748 r
= ERROR_UNKNOWN_PATCH
;
1750 res
= RegOpenKeyExW(udprod
, szPatches
, 0, KEY_WOW64_64KEY
|KEY_READ
, &patches
);
1751 if (res
!= ERROR_SUCCESS
)
1754 res
= RegOpenKeyExW( patches
, squashed_patch
, 0, KEY_WOW64_64KEY
|KEY_READ
, &patch
);
1755 if (res
!= ERROR_SUCCESS
)
1758 if (!strcmpW( szProperty
, INSTALLPROPERTY_TRANSFORMSW
))
1760 if (MSIREG_OpenProductKey(szProductCode
, NULL
, dwContext
,
1761 &prod
, FALSE
) != ERROR_SUCCESS
)
1764 res
= RegOpenKeyExW(prod
, szPatches
, 0, KEY_WOW64_64KEY
|KEY_ALL_ACCESS
, &prodpatches
);
1765 if (res
!= ERROR_SUCCESS
)
1768 datakey
= prodpatches
;
1769 szProperty
= squashed_patch
;
1773 if (MSIREG_OpenUserDataPatchKey(szPatchCode
, dwContext
,
1774 &udpatch
, FALSE
) != ERROR_SUCCESS
)
1777 if (!strcmpW( szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
))
1779 if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1780 szProperty
= szManagedPackage
;
1783 else if (!strcmpW( szProperty
, INSTALLPROPERTY_INSTALLDATEW
))
1786 szProperty
= szInstalled
;
1788 else if (!strcmpW( szProperty
, INSTALLPROPERTY_UNINSTALLABLEW
) ||
1789 !strcmpW( szProperty
, INSTALLPROPERTY_PATCHSTATEW
) ||
1790 !strcmpW( szProperty
, INSTALLPROPERTY_DISPLAYNAMEW
) ||
1791 !strcmpW( szProperty
, INSTALLPROPERTY_MOREINFOURLW
))
1797 r
= ERROR_UNKNOWN_PROPERTY
;
1802 val
= reg_get_value(datakey
, szProperty
, &type
);
1804 val
= strdupW(szEmpty
);
1812 lstrcpynW(lpValue
, val
, *pcchValue
);
1814 len
= lstrlenW(val
);
1815 if ((*val
&& *pcchValue
< len
+ 1) || !lpValue
)
1818 r
= ERROR_MORE_DATA
;
1820 *pcchValue
= len
* sizeof(WCHAR
);
1827 RegCloseKey(prodpatches
);
1830 RegCloseKey(patches
);
1831 RegCloseKey(udpatch
);
1833 RegCloseKey(udprod
);
1838 UINT WINAPI
MsiGetPatchInfoA( LPCSTR patch
, LPCSTR attr
, LPSTR buffer
, LPDWORD buflen
)
1840 UINT r
= ERROR_OUTOFMEMORY
;
1842 LPWSTR patchW
= NULL
, attrW
= NULL
, bufferW
= NULL
;
1844 TRACE("%s %s %p %p\n", debugstr_a(patch
), debugstr_a(attr
), buffer
, buflen
);
1846 if (!patch
|| !attr
)
1847 return ERROR_INVALID_PARAMETER
;
1849 if (!(patchW
= strdupAtoW( patch
)))
1852 if (!(attrW
= strdupAtoW( attr
)))
1856 r
= MsiGetPatchInfoW( patchW
, attrW
, NULL
, &size
);
1857 if (r
!= ERROR_SUCCESS
)
1861 if (!(bufferW
= msi_alloc( size
* sizeof(WCHAR
) )))
1863 r
= ERROR_OUTOFMEMORY
;
1867 r
= MsiGetPatchInfoW( patchW
, attrW
, bufferW
, &size
);
1868 if (r
== ERROR_SUCCESS
)
1870 int len
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1872 r
= ERROR_MORE_DATA
;
1874 WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, buffer
, *buflen
, NULL
, NULL
);
1882 msi_free( bufferW
);
1886 UINT WINAPI
MsiGetPatchInfoW( LPCWSTR patch
, LPCWSTR attr
, LPWSTR buffer
, LPDWORD buflen
)
1889 WCHAR product
[GUID_SIZE
];
1892 TRACE("%s %s %p %p\n", debugstr_w(patch
), debugstr_w(attr
), buffer
, buflen
);
1894 if (!patch
|| !attr
)
1895 return ERROR_INVALID_PARAMETER
;
1897 if (strcmpW( INSTALLPROPERTY_LOCALPACKAGEW
, attr
))
1898 return ERROR_UNKNOWN_PROPERTY
;
1903 r
= MsiEnumProductsW( index
, product
);
1904 if (r
!= ERROR_SUCCESS
)
1907 r
= MsiGetPatchInfoExW( patch
, product
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
, attr
, buffer
, buflen
);
1908 if (r
== ERROR_SUCCESS
|| r
== ERROR_MORE_DATA
)
1911 r
= MsiGetPatchInfoExW( patch
, product
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
, attr
, buffer
, buflen
);
1912 if (r
== ERROR_SUCCESS
|| r
== ERROR_MORE_DATA
)
1915 r
= MsiGetPatchInfoExW( patch
, product
, NULL
, MSIINSTALLCONTEXT_MACHINE
, attr
, buffer
, buflen
);
1916 if (r
== ERROR_SUCCESS
|| r
== ERROR_MORE_DATA
)
1922 return ERROR_UNKNOWN_PRODUCT
;
1925 UINT WINAPI
MsiEnableLogA(DWORD dwLogMode
, LPCSTR szLogFile
, DWORD attributes
)
1927 LPWSTR szwLogFile
= NULL
;
1930 TRACE("%08x %s %08x\n", dwLogMode
, debugstr_a(szLogFile
), attributes
);
1934 szwLogFile
= strdupAtoW( szLogFile
);
1936 return ERROR_OUTOFMEMORY
;
1938 r
= MsiEnableLogW( dwLogMode
, szwLogFile
, attributes
);
1939 msi_free( szwLogFile
);
1943 UINT WINAPI
MsiEnableLogW(DWORD dwLogMode
, LPCWSTR szLogFile
, DWORD attributes
)
1945 TRACE("%08x %s %08x\n", dwLogMode
, debugstr_w(szLogFile
), attributes
);
1947 msi_free(gszLogFile
);
1953 if (!(attributes
& INSTALLLOGATTRIBUTES_APPEND
))
1954 DeleteFileW(szLogFile
);
1955 file
= CreateFileW(szLogFile
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
, OPEN_ALWAYS
,
1956 FILE_ATTRIBUTE_NORMAL
, NULL
);
1957 if (file
!= INVALID_HANDLE_VALUE
)
1959 gszLogFile
= strdupW(szLogFile
);
1963 ERR("Unable to enable log %s (%u)\n", debugstr_w(szLogFile
), GetLastError());
1966 return ERROR_SUCCESS
;
1969 UINT WINAPI
MsiEnumComponentCostsA( MSIHANDLE handle
, LPCSTR component
, DWORD index
,
1970 INSTALLSTATE state
, LPSTR drive
, DWORD
*buflen
,
1971 int *cost
, int *temp
)
1975 WCHAR
*driveW
, *componentW
= NULL
;
1977 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle
, debugstr_a(component
), index
,
1978 state
, drive
, buflen
, cost
, temp
);
1980 if (!drive
|| !buflen
) return ERROR_INVALID_PARAMETER
;
1981 if (component
&& !(componentW
= strdupAtoW( component
))) return ERROR_OUTOFMEMORY
;
1984 if (!(driveW
= msi_alloc( len
* sizeof(WCHAR
) )))
1986 msi_free( componentW
);
1987 return ERROR_OUTOFMEMORY
;
1989 r
= MsiEnumComponentCostsW( handle
, componentW
, index
, state
, driveW
, buflen
, cost
, temp
);
1992 WideCharToMultiByte( CP_ACP
, 0, driveW
, -1, drive
, len
, NULL
, NULL
);
1994 msi_free( componentW
);
1999 static UINT
set_drive( WCHAR
*buffer
, WCHAR letter
)
2007 UINT WINAPI
MsiEnumComponentCostsW( MSIHANDLE handle
, LPCWSTR component
, DWORD index
,
2008 INSTALLSTATE state
, LPWSTR drive
, DWORD
*buflen
,
2009 int *cost
, int *temp
)
2011 UINT r
= ERROR_NO_MORE_ITEMS
;
2012 MSICOMPONENT
*comp
= NULL
;
2013 MSIPACKAGE
*package
;
2016 WCHAR path
[MAX_PATH
];
2018 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle
, debugstr_w(component
), index
,
2019 state
, drive
, buflen
, cost
, temp
);
2021 if (!drive
|| !buflen
|| !cost
|| !temp
) return ERROR_INVALID_PARAMETER
;
2022 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
2027 if (!(remote
= msi_get_remote(handle
)))
2028 return ERROR_INVALID_HANDLE
;
2032 r
= remote_EnumComponentCosts(remote
, component
, index
, state
, buffer
, cost
, temp
);
2034 __EXCEPT(rpc_filter
)
2036 r
= GetExceptionCode();
2040 if (r
== ERROR_SUCCESS
)
2042 lstrcpynW(drive
, buffer
, *buflen
);
2044 r
= ERROR_MORE_DATA
;
2050 if (!msi_get_property_int( package
->db
, szCostingComplete
, 0 ))
2052 msiobj_release( &package
->hdr
);
2053 return ERROR_FUNCTION_NOT_CALLED
;
2055 if (component
&& component
[0] && !(comp
= msi_get_loaded_component( package
, component
)))
2057 msiobj_release( &package
->hdr
);
2058 return ERROR_UNKNOWN_COMPONENT
;
2063 msiobj_release( &package
->hdr
);
2064 return ERROR_MORE_DATA
;
2068 msiobj_release( &package
->hdr
);
2069 return ERROR_NO_MORE_ITEMS
;
2074 GetWindowsDirectoryW( path
, MAX_PATH
);
2075 if (component
&& component
[0])
2077 if (msi_is_global_assembly( comp
)) *temp
= comp
->Cost
;
2078 if (!comp
->Enabled
|| !comp
->KeyPath
)
2081 *buflen
= set_drive( drive
, path
[0] );
2084 else if ((file
= msi_get_loaded_file( package
, comp
->KeyPath
)))
2086 *cost
= max( 8, comp
->Cost
/ 512 );
2087 *buflen
= set_drive( drive
, file
->TargetPath
[0] );
2091 else if (IStorage_Stat( package
->db
->storage
, &stat
, STATFLAG_NONAME
) == S_OK
)
2093 *temp
= max( 8, stat
.cbSize
.QuadPart
/ 512 );
2094 *buflen
= set_drive( drive
, path
[0] );
2097 msiobj_release( &package
->hdr
);
2101 UINT WINAPI
MsiQueryComponentStateA(LPCSTR szProductCode
,
2102 LPCSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
2103 LPCSTR szComponent
, INSTALLSTATE
*pdwState
)
2105 LPWSTR prodcode
= NULL
, usersid
= NULL
, comp
= NULL
;
2108 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode
),
2109 debugstr_a(szUserSid
), dwContext
, debugstr_a(szComponent
), pdwState
);
2111 if (szProductCode
&& !(prodcode
= strdupAtoW(szProductCode
)))
2112 return ERROR_OUTOFMEMORY
;
2114 if (szUserSid
&& !(usersid
= strdupAtoW(szUserSid
)))
2115 return ERROR_OUTOFMEMORY
;
2117 if (szComponent
&& !(comp
= strdupAtoW(szComponent
)))
2118 return ERROR_OUTOFMEMORY
;
2120 r
= MsiQueryComponentStateW(prodcode
, usersid
, dwContext
, comp
, pdwState
);
2129 static BOOL
msi_comp_find_prod_key(LPCWSTR prodcode
, MSIINSTALLCONTEXT context
)
2134 r
= MSIREG_OpenProductKey(prodcode
, NULL
, context
, &hkey
, FALSE
);
2136 return (r
== ERROR_SUCCESS
);
2139 static BOOL
msi_comp_find_package(LPCWSTR prodcode
, MSIINSTALLCONTEXT context
)
2147 static const WCHAR local_package
[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
2148 static const WCHAR managed_local_package
[] = {
2149 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
2152 r
= MSIREG_OpenInstallProps(prodcode
, context
, NULL
, &hkey
, FALSE
);
2153 if (r
!= ERROR_SUCCESS
)
2156 if (context
== MSIINSTALLCONTEXT_USERMANAGED
)
2157 package
= managed_local_package
;
2159 package
= local_package
;
2162 res
= RegQueryValueExW(hkey
, package
, NULL
, NULL
, NULL
, &sz
);
2165 return (res
== ERROR_SUCCESS
);
2168 static UINT
msi_comp_find_prodcode(WCHAR
*squashed_pc
,
2169 MSIINSTALLCONTEXT context
,
2170 LPCWSTR comp
, LPWSTR val
, DWORD
*sz
)
2176 if (context
== MSIINSTALLCONTEXT_MACHINE
)
2177 r
= MSIREG_OpenUserDataComponentKey(comp
, szLocalSid
, &hkey
, FALSE
);
2179 r
= MSIREG_OpenUserDataComponentKey(comp
, NULL
, &hkey
, FALSE
);
2181 if (r
!= ERROR_SUCCESS
)
2184 res
= RegQueryValueExW( hkey
, squashed_pc
, NULL
, NULL
, (BYTE
*)val
, sz
);
2185 if (res
!= ERROR_SUCCESS
)
2192 UINT WINAPI
MsiQueryComponentStateW(LPCWSTR szProductCode
,
2193 LPCWSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
2194 LPCWSTR szComponent
, INSTALLSTATE
*pdwState
)
2196 WCHAR squashed_pc
[SQUASHED_GUID_SIZE
];
2200 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode
),
2201 debugstr_w(szUserSid
), dwContext
, debugstr_w(szComponent
), pdwState
);
2203 if (!pdwState
|| !szComponent
)
2204 return ERROR_INVALID_PARAMETER
;
2206 if (!szProductCode
|| !*szProductCode
|| lstrlenW(szProductCode
) != GUID_SIZE
- 1)
2207 return ERROR_INVALID_PARAMETER
;
2209 if (!squash_guid( szProductCode
, squashed_pc
))
2210 return ERROR_INVALID_PARAMETER
;
2212 found
= msi_comp_find_prod_key(szProductCode
, dwContext
);
2214 if (!msi_comp_find_package(szProductCode
, dwContext
))
2218 *pdwState
= INSTALLSTATE_UNKNOWN
;
2219 return ERROR_UNKNOWN_COMPONENT
;
2222 return ERROR_UNKNOWN_PRODUCT
;
2225 *pdwState
= INSTALLSTATE_UNKNOWN
;
2228 if (msi_comp_find_prodcode( squashed_pc
, dwContext
, szComponent
, NULL
, &sz
))
2229 return ERROR_UNKNOWN_COMPONENT
;
2232 *pdwState
= INSTALLSTATE_NOTUSED
;
2238 if (!(val
= msi_alloc( sz
))) return ERROR_OUTOFMEMORY
;
2239 if ((r
= msi_comp_find_prodcode( squashed_pc
, dwContext
, szComponent
, val
, &sz
)))
2245 if (lstrlenW(val
) > 2 &&
2246 val
[0] >= '0' && val
[0] <= '9' && val
[1] >= '0' && val
[1] <= '9' && val
[2] != ':')
2248 *pdwState
= INSTALLSTATE_SOURCE
;
2251 *pdwState
= INSTALLSTATE_LOCAL
;
2255 TRACE("-> %d\n", *pdwState
);
2256 return ERROR_SUCCESS
;
2259 INSTALLSTATE WINAPI
MsiQueryProductStateA(LPCSTR szProduct
)
2261 LPWSTR szwProduct
= NULL
;
2266 szwProduct
= strdupAtoW( szProduct
);
2268 return ERROR_OUTOFMEMORY
;
2270 r
= MsiQueryProductStateW( szwProduct
);
2271 msi_free( szwProduct
);
2275 INSTALLSTATE WINAPI
MsiQueryProductStateW(LPCWSTR szProduct
)
2277 MSIINSTALLCONTEXT context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
2278 INSTALLSTATE state
= INSTALLSTATE_ADVERTISED
;
2279 HKEY prodkey
= 0, userdata
= 0;
2283 TRACE("%s\n", debugstr_w(szProduct
));
2285 if (!szProduct
|| !*szProduct
)
2286 return INSTALLSTATE_INVALIDARG
;
2288 if (lstrlenW(szProduct
) != GUID_SIZE
- 1)
2289 return INSTALLSTATE_INVALIDARG
;
2291 if (szProduct
[0] != '{' || szProduct
[37] != '}')
2292 return INSTALLSTATE_UNKNOWN
;
2294 SetLastError( ERROR_SUCCESS
);
2296 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
2297 &prodkey
, FALSE
) != ERROR_SUCCESS
&&
2298 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
2299 &prodkey
, FALSE
) != ERROR_SUCCESS
&&
2300 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
2301 &prodkey
, FALSE
) == ERROR_SUCCESS
)
2303 context
= MSIINSTALLCONTEXT_MACHINE
;
2306 r
= MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &userdata
, FALSE
);
2307 if (r
!= ERROR_SUCCESS
)
2310 if (!msi_reg_get_val_dword(userdata
, szWindowsInstaller
, &val
))
2314 state
= INSTALLSTATE_DEFAULT
;
2316 state
= INSTALLSTATE_UNKNOWN
;
2321 state
= INSTALLSTATE_UNKNOWN
;
2324 state
= INSTALLSTATE_ABSENT
;
2327 RegCloseKey(prodkey
);
2328 RegCloseKey(userdata
);
2329 TRACE("-> %d\n", state
);
2333 INSTALLUILEVEL WINAPI
MsiSetInternalUI(INSTALLUILEVEL dwUILevel
, HWND
*phWnd
)
2335 INSTALLUILEVEL old
= gUILevel
;
2336 HWND oldwnd
= gUIhwnd
;
2338 TRACE("%08x %p\n", dwUILevel
, phWnd
);
2340 if (dwUILevel
& ~(INSTALLUILEVEL_MASK
|INSTALLUILEVEL_HIDECANCEL
|INSTALLUILEVEL_PROGRESSONLY
|
2341 INSTALLUILEVEL_ENDDIALOG
|INSTALLUILEVEL_SOURCERESONLY
))
2343 FIXME("Unrecognized flags %08x\n", dwUILevel
);
2344 return INSTALLUILEVEL_NOCHANGE
;
2347 if (dwUILevel
!= INSTALLUILEVEL_NOCHANGE
)
2348 gUILevel
= dwUILevel
;
2358 INSTALLUI_HANDLERA WINAPI
MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler
,
2359 DWORD dwMessageFilter
, LPVOID pvContext
)
2361 INSTALLUI_HANDLERA prev
= gUIHandlerA
;
2363 TRACE("%p %08x %p\n", puiHandler
, dwMessageFilter
, pvContext
);
2365 gUIHandlerA
= puiHandler
;
2367 gUIFilter
= dwMessageFilter
;
2368 gUIContext
= pvContext
;
2373 INSTALLUI_HANDLERW WINAPI
MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler
,
2374 DWORD dwMessageFilter
, LPVOID pvContext
)
2376 INSTALLUI_HANDLERW prev
= gUIHandlerW
;
2378 TRACE("%p %08x %p\n", puiHandler
, dwMessageFilter
, pvContext
);
2381 gUIHandlerW
= puiHandler
;
2382 gUIFilter
= dwMessageFilter
;
2383 gUIContext
= pvContext
;
2388 /******************************************************************
2389 * MsiLoadStringW [MSI.@]
2391 * Loads a string from MSI's string resources.
2395 * handle [I] only -1 is handled currently
2396 * id [I] id of the string to be loaded
2397 * lpBuffer [O] buffer for the string to be written to
2398 * nBufferMax [I] maximum size of the buffer in characters
2399 * lang [I] the preferred language for the string
2403 * If successful, this function returns the language id of the string loaded
2404 * If the function fails, the function returns zero.
2408 * The type of the first parameter is unknown. LoadString's prototype
2409 * suggests that it might be a module handle. I have made it an MSI handle
2410 * for starters, as -1 is an invalid MSI handle, but not an invalid module
2411 * handle. Maybe strings can be stored in an MSI database somehow.
2413 LANGID WINAPI
MsiLoadStringW( MSIHANDLE handle
, UINT id
, LPWSTR lpBuffer
,
2414 int nBufferMax
, LANGID lang
)
2421 TRACE("%d %u %p %d %d\n", handle
, id
, lpBuffer
, nBufferMax
, lang
);
2424 FIXME("don't know how to deal with handle = %08x\n", handle
);
2427 lang
= GetUserDefaultLangID();
2429 hres
= FindResourceExW( msi_hInstance
, (LPCWSTR
) RT_STRING
,
2433 hResData
= LoadResource( msi_hInstance
, hres
);
2436 p
= LockResource( hResData
);
2440 for (i
= 0; i
< (id
& 0xf); i
++) p
+= *p
+ 1;
2443 if( nBufferMax
<= len
)
2446 memcpy( lpBuffer
, p
+1, len
* sizeof(WCHAR
));
2447 lpBuffer
[ len
] = 0;
2449 TRACE("found -> %s\n", debugstr_w(lpBuffer
));
2453 LANGID WINAPI
MsiLoadStringA( MSIHANDLE handle
, UINT id
, LPSTR lpBuffer
,
2454 int nBufferMax
, LANGID lang
)
2460 bufW
= msi_alloc(nBufferMax
*sizeof(WCHAR
));
2461 r
= MsiLoadStringW(handle
, id
, bufW
, nBufferMax
, lang
);
2464 len
= WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, NULL
, 0, NULL
, NULL
);
2465 if( len
<= nBufferMax
)
2466 WideCharToMultiByte( CP_ACP
, 0, bufW
, -1,
2467 lpBuffer
, nBufferMax
, NULL
, NULL
);
2475 INSTALLSTATE WINAPI
MsiLocateComponentA(LPCSTR szComponent
, LPSTR lpPathBuf
,
2478 char szProduct
[GUID_SIZE
];
2480 TRACE("%s %p %p\n", debugstr_a(szComponent
), lpPathBuf
, pcchBuf
);
2482 if (!szComponent
|| !pcchBuf
)
2483 return INSTALLSTATE_INVALIDARG
;
2485 if (MsiGetProductCodeA( szComponent
, szProduct
) != ERROR_SUCCESS
)
2486 return INSTALLSTATE_UNKNOWN
;
2488 return MsiGetComponentPathA( szProduct
, szComponent
, lpPathBuf
, pcchBuf
);
2491 INSTALLSTATE WINAPI
MsiLocateComponentW(LPCWSTR szComponent
, LPWSTR lpPathBuf
,
2494 WCHAR szProduct
[GUID_SIZE
];
2496 TRACE("%s %p %p\n", debugstr_w(szComponent
), lpPathBuf
, pcchBuf
);
2498 if (!szComponent
|| !pcchBuf
)
2499 return INSTALLSTATE_INVALIDARG
;
2501 if (MsiGetProductCodeW( szComponent
, szProduct
) != ERROR_SUCCESS
)
2502 return INSTALLSTATE_UNKNOWN
;
2504 return MsiGetComponentPathW( szProduct
, szComponent
, lpPathBuf
, pcchBuf
);
2507 UINT WINAPI
MsiMessageBoxA(HWND hWnd
, LPCSTR lpText
, LPCSTR lpCaption
, UINT uType
,
2508 WORD wLanguageId
, DWORD f
)
2510 FIXME("%p %s %s %u %08x %08x\n", hWnd
, debugstr_a(lpText
), debugstr_a(lpCaption
),
2511 uType
, wLanguageId
, f
);
2512 return MessageBoxExA(hWnd
,lpText
,lpCaption
,uType
,wLanguageId
);
2515 UINT WINAPI
MsiMessageBoxW(HWND hWnd
, LPCWSTR lpText
, LPCWSTR lpCaption
, UINT uType
,
2516 WORD wLanguageId
, DWORD f
)
2518 FIXME("%p %s %s %u %08x %08x\n", hWnd
, debugstr_w(lpText
), debugstr_w(lpCaption
),
2519 uType
, wLanguageId
, f
);
2520 return MessageBoxExW(hWnd
,lpText
,lpCaption
,uType
,wLanguageId
);
2523 UINT WINAPI
MsiMessageBoxExA(HWND hWnd
, LPCSTR lpText
, LPCSTR lpCaption
, UINT uType
,
2524 DWORD unknown
, WORD wLanguageId
, DWORD f
)
2526 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd
, debugstr_a(lpText
),
2527 debugstr_a(lpCaption
), uType
, unknown
, wLanguageId
, f
);
2528 return MessageBoxExA(hWnd
, lpText
, lpCaption
, uType
, wLanguageId
);
2531 UINT WINAPI
MsiMessageBoxExW(HWND hWnd
, LPCWSTR lpText
, LPCWSTR lpCaption
, UINT uType
,
2532 DWORD unknown
, WORD wLanguageId
, DWORD f
)
2534 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd
, debugstr_w(lpText
),
2535 debugstr_w(lpCaption
), uType
, unknown
, wLanguageId
, f
);
2536 return MessageBoxExW(hWnd
, lpText
, lpCaption
, uType
, wLanguageId
);
2539 UINT WINAPI
MsiProvideAssemblyA( LPCSTR szAssemblyName
, LPCSTR szAppContext
,
2540 DWORD dwInstallMode
, DWORD dwAssemblyInfo
, LPSTR lpPathBuf
,
2541 LPDWORD pcchPathBuf
)
2543 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName
),
2544 debugstr_a(szAppContext
), dwInstallMode
, dwAssemblyInfo
, lpPathBuf
,
2546 return ERROR_CALL_NOT_IMPLEMENTED
;
2549 UINT WINAPI
MsiProvideAssemblyW( LPCWSTR szAssemblyName
, LPCWSTR szAppContext
,
2550 DWORD dwInstallMode
, DWORD dwAssemblyInfo
, LPWSTR lpPathBuf
,
2551 LPDWORD pcchPathBuf
)
2553 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName
),
2554 debugstr_w(szAppContext
), dwInstallMode
, dwAssemblyInfo
, lpPathBuf
,
2556 return ERROR_CALL_NOT_IMPLEMENTED
;
2559 UINT WINAPI
MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor
,
2560 LPSTR szPath
, LPDWORD pcchPath
, LPDWORD pcchArgs
)
2562 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor
), szPath
, pcchPath
, pcchArgs
);
2563 return ERROR_CALL_NOT_IMPLEMENTED
;
2566 UINT WINAPI
MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor
,
2567 LPWSTR szPath
, LPDWORD pcchPath
, LPDWORD pcchArgs
)
2569 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor
), szPath
, pcchPath
, pcchArgs
);
2570 return ERROR_CALL_NOT_IMPLEMENTED
;
2573 HRESULT WINAPI
MsiGetFileSignatureInformationA( LPCSTR path
, DWORD flags
, PCCERT_CONTEXT
*cert
,
2574 LPBYTE hash
, LPDWORD hashlen
)
2577 WCHAR
*pathW
= NULL
;
2579 TRACE("%s %08x %p %p %p\n", debugstr_a(path
), flags
, cert
, hash
, hashlen
);
2581 if (path
&& !(pathW
= strdupAtoW( path
))) return E_OUTOFMEMORY
;
2582 r
= MsiGetFileSignatureInformationW( pathW
, flags
, cert
, hash
, hashlen
);
2587 HRESULT WINAPI
MsiGetFileSignatureInformationW( LPCWSTR path
, DWORD flags
, PCCERT_CONTEXT
*cert
,
2588 LPBYTE hash
, LPDWORD hashlen
)
2590 static GUID generic_verify_v2
= WINTRUST_ACTION_GENERIC_VERIFY_V2
;
2593 WINTRUST_FILE_INFO info
;
2594 CRYPT_PROVIDER_SGNR
*signer
;
2595 CRYPT_PROVIDER_CERT
*provider
;
2597 TRACE("%s %08x %p %p %p\n", debugstr_w(path
), flags
, cert
, hash
, hashlen
);
2599 if (!path
|| !cert
) return E_INVALIDARG
;
2601 info
.cbStruct
= sizeof(info
);
2602 info
.pcwszFilePath
= path
;
2604 info
.pgKnownSubject
= NULL
;
2606 data
.cbStruct
= sizeof(data
);
2607 data
.pPolicyCallbackData
= NULL
;
2608 data
.pSIPClientData
= NULL
;
2609 data
.dwUIChoice
= WTD_UI_NONE
;
2610 data
.fdwRevocationChecks
= WTD_REVOKE_WHOLECHAIN
;
2611 data
.dwUnionChoice
= WTD_CHOICE_FILE
;
2612 data
.u
.pFile
= &info
;
2613 data
.dwStateAction
= WTD_STATEACTION_VERIFY
;
2614 data
.hWVTStateData
= NULL
;
2615 data
.pwszURLReference
= NULL
;
2616 data
.dwProvFlags
= 0;
2617 data
.dwUIContext
= WTD_UICONTEXT_INSTALL
;
2618 hr
= WinVerifyTrustEx( INVALID_HANDLE_VALUE
, &generic_verify_v2
, &data
);
2620 if (FAILED(hr
)) goto done
;
2622 if (!(signer
= WTHelperGetProvSignerFromChain( data
.hWVTStateData
, 0, FALSE
, 0 )))
2624 hr
= TRUST_E_NOSIGNATURE
;
2629 DWORD len
= signer
->psSigner
->EncryptedHash
.cbData
;
2633 hr
= HRESULT_FROM_WIN32(ERROR_MORE_DATA
);
2636 memcpy( hash
, signer
->psSigner
->EncryptedHash
.pbData
, len
);
2639 if (!(provider
= WTHelperGetProvCertFromChain( signer
, 0 )))
2641 hr
= TRUST_E_PROVIDER_UNKNOWN
;
2644 *cert
= CertDuplicateCertificateContext( provider
->pCert
);
2647 data
.dwStateAction
= WTD_STATEACTION_CLOSE
;
2648 WinVerifyTrustEx( INVALID_HANDLE_VALUE
, &generic_verify_v2
, &data
);
2652 /******************************************************************
2653 * MsiGetProductPropertyA [MSI.@]
2655 UINT WINAPI
MsiGetProductPropertyA(MSIHANDLE hProduct
, LPCSTR szProperty
,
2656 LPSTR szValue
, LPDWORD pccbValue
)
2658 LPWSTR prop
= NULL
, val
= NULL
;
2662 TRACE("(%d, %s, %p, %p)\n", hProduct
, debugstr_a(szProperty
),
2663 szValue
, pccbValue
);
2665 if (szValue
&& !pccbValue
)
2666 return ERROR_INVALID_PARAMETER
;
2668 if (szProperty
) prop
= strdupAtoW(szProperty
);
2671 r
= MsiGetProductPropertyW(hProduct
, prop
, NULL
, &len
);
2672 if (r
!= ERROR_SUCCESS
&& r
!= ERROR_MORE_DATA
)
2675 if (r
== ERROR_SUCCESS
)
2677 if (szValue
) *szValue
= '\0';
2678 if (pccbValue
) *pccbValue
= 0;
2682 val
= msi_alloc(++len
* sizeof(WCHAR
));
2685 r
= ERROR_OUTOFMEMORY
;
2689 r
= MsiGetProductPropertyW(hProduct
, prop
, val
, &len
);
2690 if (r
!= ERROR_SUCCESS
)
2693 len
= WideCharToMultiByte(CP_ACP
, 0, val
, -1, NULL
, 0, NULL
, NULL
);
2696 WideCharToMultiByte(CP_ACP
, 0, val
, -1, szValue
,
2697 *pccbValue
, NULL
, NULL
);
2701 if (len
> *pccbValue
)
2702 r
= ERROR_MORE_DATA
;
2704 *pccbValue
= len
- 1;
2714 /******************************************************************
2715 * MsiGetProductPropertyW [MSI.@]
2717 UINT WINAPI
MsiGetProductPropertyW(MSIHANDLE hProduct
, LPCWSTR szProperty
,
2718 LPWSTR szValue
, LPDWORD pccbValue
)
2720 MSIPACKAGE
*package
;
2721 MSIQUERY
*view
= NULL
;
2722 MSIRECORD
*rec
= NULL
;
2726 static const WCHAR query
[] = {
2727 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
2728 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
2729 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
2731 TRACE("(%d, %s, %p, %p)\n", hProduct
, debugstr_w(szProperty
),
2732 szValue
, pccbValue
);
2735 return ERROR_INVALID_PARAMETER
;
2737 if (szValue
&& !pccbValue
)
2738 return ERROR_INVALID_PARAMETER
;
2740 package
= msihandle2msiinfo(hProduct
, MSIHANDLETYPE_PACKAGE
);
2742 return ERROR_INVALID_HANDLE
;
2744 r
= MSI_OpenQuery(package
->db
, &view
, query
, szProperty
);
2745 if (r
!= ERROR_SUCCESS
)
2748 r
= MSI_ViewExecute(view
, 0);
2749 if (r
!= ERROR_SUCCESS
)
2752 r
= MSI_ViewFetch(view
, &rec
);
2753 if (r
!= ERROR_SUCCESS
)
2756 val
= MSI_RecordGetString(rec
, 2);
2760 if (lstrlenW(val
) >= *pccbValue
)
2762 if (szValue
) lstrcpynW(szValue
, val
, *pccbValue
);
2763 r
= ERROR_MORE_DATA
;
2767 if (szValue
) lstrcpyW(szValue
, val
);
2771 *pccbValue
= lstrlenW(val
);
2776 MSI_ViewClose(view
);
2777 msiobj_release(&view
->hdr
);
2778 if (rec
) msiobj_release(&rec
->hdr
);
2783 if (szValue
) *szValue
= '\0';
2784 if (pccbValue
) *pccbValue
= 0;
2788 msiobj_release(&package
->hdr
);
2792 UINT WINAPI
MsiVerifyPackageA( LPCSTR szPackage
)
2795 LPWSTR szPack
= NULL
;
2797 TRACE("%s\n", debugstr_a(szPackage
) );
2801 szPack
= strdupAtoW( szPackage
);
2803 return ERROR_OUTOFMEMORY
;
2806 r
= MsiVerifyPackageW( szPack
);
2813 UINT WINAPI
MsiVerifyPackageW( LPCWSTR szPackage
)
2818 TRACE("%s\n", debugstr_w(szPackage
) );
2820 r
= MsiOpenDatabaseW( szPackage
, MSIDBOPEN_READONLY
, &handle
);
2821 MsiCloseHandle( handle
);
2826 static BOOL
open_userdata_comp_key( const WCHAR
*comp
, const WCHAR
*usersid
, MSIINSTALLCONTEXT ctx
,
2829 if (ctx
& MSIINSTALLCONTEXT_MACHINE
)
2831 if (!MSIREG_OpenUserDataComponentKey( comp
, szLocalSid
, hkey
, FALSE
)) return TRUE
;
2833 if (ctx
& (MSIINSTALLCONTEXT_USERMANAGED
|MSIINSTALLCONTEXT_USERUNMANAGED
))
2835 if (usersid
&& !strcmpiW( usersid
, szAllSid
))
2837 FIXME( "only looking at the current user\n" );
2840 if (!MSIREG_OpenUserDataComponentKey( comp
, usersid
, hkey
, FALSE
)) return TRUE
;
2845 static INSTALLSTATE
MSI_GetComponentPath( const WCHAR
*szProduct
, const WCHAR
*szComponent
,
2846 const WCHAR
*szUserSid
, MSIINSTALLCONTEXT ctx
,
2847 awstring
*lpPathBuf
, DWORD
*pcchBuf
)
2849 static const WCHAR wininstaller
[] =
2850 {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
2851 WCHAR
*path
= NULL
, squashed_pc
[SQUASHED_GUID_SIZE
], squashed_comp
[SQUASHED_GUID_SIZE
];
2856 if (!szProduct
|| !szComponent
)
2857 return INSTALLSTATE_INVALIDARG
;
2859 if (lpPathBuf
->str
.w
&& !pcchBuf
)
2860 return INSTALLSTATE_INVALIDARG
;
2862 if (!squash_guid( szProduct
, squashed_pc
) || !squash_guid( szComponent
, squashed_comp
))
2863 return INSTALLSTATE_INVALIDARG
;
2865 if (szUserSid
&& ctx
== MSIINSTALLCONTEXT_MACHINE
)
2866 return INSTALLSTATE_INVALIDARG
;
2868 state
= INSTALLSTATE_UNKNOWN
;
2870 if (open_userdata_comp_key( szComponent
, szUserSid
, ctx
, &hkey
))
2872 path
= msi_reg_get_val_str( hkey
, squashed_pc
);
2875 state
= INSTALLSTATE_ABSENT
;
2877 if ((!MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_MACHINE
, NULL
, &hkey
, FALSE
) ||
2878 !MSIREG_OpenUserDataProductKey(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
, NULL
, &hkey
, FALSE
)) &&
2879 msi_reg_get_val_dword(hkey
, wininstaller
, &version
) &&
2880 GetFileAttributesW(path
) != INVALID_FILE_ATTRIBUTES
)
2883 state
= INSTALLSTATE_LOCAL
;
2887 if (state
!= INSTALLSTATE_LOCAL
&&
2888 (!MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
, &hkey
, FALSE
) ||
2889 !MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
, &hkey
, FALSE
)))
2893 if (open_userdata_comp_key( szComponent
, szUserSid
, ctx
, &hkey
))
2896 path
= msi_reg_get_val_str( hkey
, squashed_pc
);
2899 state
= INSTALLSTATE_ABSENT
;
2901 if (GetFileAttributesW(path
) != INVALID_FILE_ATTRIBUTES
)
2902 state
= INSTALLSTATE_LOCAL
;
2907 return INSTALLSTATE_UNKNOWN
;
2909 if (state
== INSTALLSTATE_LOCAL
&& !*path
)
2910 state
= INSTALLSTATE_NOTUSED
;
2912 if (msi_strcpy_to_awstring(path
, -1, lpPathBuf
, pcchBuf
) == ERROR_MORE_DATA
)
2913 state
= INSTALLSTATE_MOREDATA
;
2919 /******************************************************************
2920 * MsiGetComponentPathExW [MSI.@]
2922 INSTALLSTATE WINAPI
MsiGetComponentPathExW( LPCWSTR product
, LPCWSTR comp
, LPCWSTR usersid
,
2923 MSIINSTALLCONTEXT ctx
, LPWSTR buf
, LPDWORD buflen
)
2927 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_w(product
), debugstr_w(comp
), debugstr_w(usersid
),
2930 path
.unicode
= TRUE
;
2933 return MSI_GetComponentPath( product
, comp
, usersid
, ctx
, &path
, buflen
);
2936 INSTALLSTATE WINAPI
MsiGetComponentPathExA( LPCSTR product
, LPCSTR comp
, LPCSTR usersid
,
2937 MSIINSTALLCONTEXT ctx
, LPSTR buf
, LPDWORD buflen
)
2939 WCHAR
*productW
= NULL
, *compW
= NULL
, *usersidW
= NULL
;
2940 INSTALLSTATE r
= INSTALLSTATE_UNKNOWN
;
2943 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_a(product
), debugstr_a(comp
), debugstr_a(usersid
),
2946 if (product
&& !(productW
= strdupAtoW( product
))) return INSTALLSTATE_UNKNOWN
;
2947 if (comp
&& !(compW
= strdupAtoW( comp
))) goto end
;
2948 if (usersid
&& !(usersidW
= strdupAtoW( usersid
))) goto end
;
2950 path
.unicode
= FALSE
;
2953 r
= MSI_GetComponentPath( productW
, compW
, usersidW
, ctx
, &path
, buflen
);
2956 msi_free( productW
);
2958 msi_free( usersidW
);
2963 /******************************************************************
2964 * MsiGetComponentPathW [MSI.@]
2966 INSTALLSTATE WINAPI
MsiGetComponentPathW( LPCWSTR product
, LPCWSTR comp
, LPWSTR buf
, LPDWORD buflen
)
2968 return MsiGetComponentPathExW( product
, comp
, szAllSid
, MSIINSTALLCONTEXT_ALL
, buf
, buflen
);
2971 /******************************************************************
2972 * MsiGetComponentPathA [MSI.@]
2974 INSTALLSTATE WINAPI
MsiGetComponentPathA( LPCSTR product
, LPCSTR comp
, LPSTR buf
, LPDWORD buflen
)
2976 return MsiGetComponentPathExA( product
, comp
, "s-1-1-0", MSIINSTALLCONTEXT_ALL
, buf
, buflen
);
2979 static UINT
query_feature_state( const WCHAR
*product
, const WCHAR
*squashed
, const WCHAR
*usersid
,
2980 MSIINSTALLCONTEXT ctx
, const WCHAR
*feature
, INSTALLSTATE
*state
)
2984 WCHAR
*parent
, *components
, *path
;
2986 BOOL missing
= FALSE
, source
= FALSE
;
2987 WCHAR comp
[GUID_SIZE
];
2990 if (ctx
!= MSIINSTALLCONTEXT_MACHINE
) SetLastError( ERROR_SUCCESS
);
2992 if (MSIREG_OpenFeaturesKey( product
, usersid
, ctx
, &hkey
, FALSE
)) return ERROR_UNKNOWN_PRODUCT
;
2994 parent
= msi_reg_get_val_str( hkey
, feature
);
2995 RegCloseKey( hkey
);
2996 if (!parent
) return ERROR_UNKNOWN_FEATURE
;
2998 *state
= (parent
[0] == 6) ? INSTALLSTATE_ABSENT
: INSTALLSTATE_LOCAL
;
3000 if (*state
== INSTALLSTATE_ABSENT
)
3001 return ERROR_SUCCESS
;
3003 r
= MSIREG_OpenUserDataFeaturesKey( product
, usersid
, ctx
, &hkey
, FALSE
);
3004 if (r
!= ERROR_SUCCESS
)
3006 *state
= INSTALLSTATE_ADVERTISED
;
3007 return ERROR_SUCCESS
;
3009 components
= msi_reg_get_val_str( hkey
, feature
);
3010 RegCloseKey( hkey
);
3012 TRACE("buffer = %s\n", debugstr_w(components
));
3016 *state
= INSTALLSTATE_ADVERTISED
;
3017 return ERROR_SUCCESS
;
3019 for (p
= components
; *p
&& *p
!= 2 ; p
+= 20)
3021 if (!decode_base85_guid( p
, &guid
))
3023 if (p
!= components
) break;
3024 msi_free( components
);
3025 *state
= INSTALLSTATE_BADCONFIG
;
3026 return ERROR_BAD_CONFIGURATION
;
3028 StringFromGUID2( &guid
, comp
, GUID_SIZE
);
3029 if (ctx
== MSIINSTALLCONTEXT_MACHINE
)
3030 r
= MSIREG_OpenUserDataComponentKey( comp
, szLocalSid
, &hkey
, FALSE
);
3032 r
= MSIREG_OpenUserDataComponentKey( comp
, usersid
, &hkey
, FALSE
);
3034 if (r
!= ERROR_SUCCESS
)
3036 msi_free( components
);
3037 *state
= INSTALLSTATE_ADVERTISED
;
3038 return ERROR_SUCCESS
;
3040 path
= msi_reg_get_val_str( hkey
, squashed
);
3041 if (!path
) missing
= TRUE
;
3042 else if (strlenW( path
) > 2 &&
3043 path
[0] >= '0' && path
[0] <= '9' &&
3044 path
[1] >= '0' && path
[1] <= '9')
3050 msi_free( components
);
3053 *state
= INSTALLSTATE_ADVERTISED
;
3055 *state
= INSTALLSTATE_SOURCE
;
3057 *state
= INSTALLSTATE_LOCAL
;
3059 TRACE("returning state %d\n", *state
);
3060 return ERROR_SUCCESS
;
3063 UINT WINAPI
MsiQueryFeatureStateExA( LPCSTR product
, LPCSTR usersid
, MSIINSTALLCONTEXT ctx
,
3064 LPCSTR feature
, INSTALLSTATE
*state
)
3067 WCHAR
*productW
= NULL
, *usersidW
= NULL
, *featureW
= NULL
;
3069 if (product
&& !(productW
= strdupAtoW( product
))) return ERROR_OUTOFMEMORY
;
3070 if (usersid
&& !(usersidW
= strdupAtoW( usersid
)))
3072 msi_free( productW
);
3073 return ERROR_OUTOFMEMORY
;
3075 if (feature
&& !(featureW
= strdupAtoW( feature
)))
3077 msi_free( productW
);
3078 msi_free( usersidW
);
3079 return ERROR_OUTOFMEMORY
;
3081 r
= MsiQueryFeatureStateExW( productW
, usersidW
, ctx
, featureW
, state
);
3082 msi_free( productW
);
3083 msi_free( usersidW
);
3084 msi_free( featureW
);
3088 UINT WINAPI
MsiQueryFeatureStateExW( LPCWSTR product
, LPCWSTR usersid
, MSIINSTALLCONTEXT ctx
,
3089 LPCWSTR feature
, INSTALLSTATE
*state
)
3092 if (!squash_guid( product
, squashed
)) return ERROR_INVALID_PARAMETER
;
3093 return query_feature_state( product
, squashed
, usersid
, ctx
, feature
, state
);
3096 /******************************************************************
3097 * MsiQueryFeatureStateA [MSI.@]
3099 INSTALLSTATE WINAPI
MsiQueryFeatureStateA(LPCSTR szProduct
, LPCSTR szFeature
)
3101 LPWSTR szwProduct
= NULL
, szwFeature
= NULL
;
3102 INSTALLSTATE rc
= INSTALLSTATE_UNKNOWN
;
3104 szwProduct
= strdupAtoW( szProduct
);
3105 if ( szProduct
&& !szwProduct
)
3108 szwFeature
= strdupAtoW( szFeature
);
3109 if ( szFeature
&& !szwFeature
)
3112 rc
= MsiQueryFeatureStateW(szwProduct
, szwFeature
);
3115 msi_free( szwProduct
);
3116 msi_free( szwFeature
);
3121 /******************************************************************
3122 * MsiQueryFeatureStateW [MSI.@]
3124 * Checks the state of a feature
3127 * szProduct [I] Product's GUID string
3128 * szFeature [I] Feature's GUID string
3131 * INSTALLSTATE_LOCAL Feature is installed and usable
3132 * INSTALLSTATE_ABSENT Feature is absent
3133 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
3134 * INSTALLSTATE_UNKNOWN An error occurred
3135 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
3138 INSTALLSTATE WINAPI
MsiQueryFeatureStateW(LPCWSTR szProduct
, LPCWSTR szFeature
)
3144 TRACE("%s %s\n", debugstr_w(szProduct
), debugstr_w(szFeature
));
3146 if (!szProduct
|| !szFeature
|| !squash_guid( szProduct
, squashed
))
3147 return INSTALLSTATE_INVALIDARG
;
3149 r
= query_feature_state( szProduct
, squashed
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
, szFeature
, &state
);
3150 if (r
== ERROR_SUCCESS
|| r
== ERROR_BAD_CONFIGURATION
) return state
;
3152 r
= query_feature_state( szProduct
, squashed
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
, szFeature
, &state
);
3153 if (r
== ERROR_SUCCESS
|| r
== ERROR_BAD_CONFIGURATION
) return state
;
3155 r
= query_feature_state( szProduct
, squashed
, NULL
, MSIINSTALLCONTEXT_MACHINE
, szFeature
, &state
);
3156 if (r
== ERROR_SUCCESS
|| r
== ERROR_BAD_CONFIGURATION
) return state
;
3158 return INSTALLSTATE_UNKNOWN
;
3161 /******************************************************************
3162 * MsiGetFileVersionA [MSI.@]
3164 UINT WINAPI
MsiGetFileVersionA(LPCSTR szFilePath
, LPSTR lpVersionBuf
,
3165 LPDWORD pcchVersionBuf
, LPSTR lpLangBuf
, LPDWORD pcchLangBuf
)
3167 LPWSTR szwFilePath
= NULL
, lpwVersionBuff
= NULL
, lpwLangBuff
= NULL
;
3168 UINT ret
= ERROR_OUTOFMEMORY
;
3170 if ((lpVersionBuf
&& !pcchVersionBuf
) ||
3171 (lpLangBuf
&& !pcchLangBuf
))
3172 return ERROR_INVALID_PARAMETER
;
3176 szwFilePath
= strdupAtoW( szFilePath
);
3181 if( lpVersionBuf
&& pcchVersionBuf
&& *pcchVersionBuf
)
3183 lpwVersionBuff
= msi_alloc(*pcchVersionBuf
*sizeof(WCHAR
));
3184 if( !lpwVersionBuff
)
3188 if( lpLangBuf
&& pcchLangBuf
&& *pcchLangBuf
)
3190 lpwLangBuff
= msi_alloc(*pcchLangBuf
*sizeof(WCHAR
));
3195 ret
= MsiGetFileVersionW(szwFilePath
, lpwVersionBuff
, pcchVersionBuf
,
3196 lpwLangBuff
, pcchLangBuf
);
3198 if( (ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) && lpwVersionBuff
)
3199 WideCharToMultiByte(CP_ACP
, 0, lpwVersionBuff
, -1,
3200 lpVersionBuf
, *pcchVersionBuf
+ 1, NULL
, NULL
);
3201 if( (ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) && lpwLangBuff
)
3202 WideCharToMultiByte(CP_ACP
, 0, lpwLangBuff
, -1,
3203 lpLangBuf
, *pcchLangBuf
+ 1, NULL
, NULL
);
3206 msi_free(szwFilePath
);
3207 msi_free(lpwVersionBuff
);
3208 msi_free(lpwLangBuff
);
3213 static UINT
get_file_version( const WCHAR
*path
, WCHAR
*verbuf
, DWORD
*verlen
,
3214 WCHAR
*langbuf
, DWORD
*langlen
)
3216 static const WCHAR szVersionResource
[] = {'\\',0};
3217 static const WCHAR szVersionFormat
[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
3218 static const WCHAR szLangFormat
[] = {'%','d',0};
3219 UINT ret
= ERROR_MORE_DATA
;
3222 VS_FIXEDFILEINFO
*ffi
;
3226 if (!(len
= GetFileVersionInfoSizeW( path
, NULL
)))
3228 error
= GetLastError();
3229 if (error
== ERROR_BAD_PATHNAME
) return ERROR_FILE_NOT_FOUND
;
3230 if (error
== ERROR_RESOURCE_DATA_NOT_FOUND
) return ERROR_FILE_INVALID
;
3233 if (!(version
= msi_alloc( len
))) return ERROR_OUTOFMEMORY
;
3234 if (!GetFileVersionInfoW( path
, 0, len
, version
))
3236 msi_free( version
);
3237 return GetLastError();
3239 if (!verbuf
&& !verlen
&& !langbuf
&& !langlen
)
3241 msi_free( version
);
3242 return ERROR_SUCCESS
;
3246 if (VerQueryValueW( version
, szVersionResource
, (LPVOID
*)&ffi
, &len
) && len
> 0)
3248 sprintfW( tmp
, szVersionFormat
,
3249 HIWORD(ffi
->dwFileVersionMS
), LOWORD(ffi
->dwFileVersionMS
),
3250 HIWORD(ffi
->dwFileVersionLS
), LOWORD(ffi
->dwFileVersionLS
) );
3251 if (verbuf
) lstrcpynW( verbuf
, tmp
, *verlen
);
3252 len
= strlenW( tmp
);
3253 if (*verlen
> len
) ret
= ERROR_SUCCESS
;
3258 if (verbuf
) *verbuf
= 0;
3264 if (VerQueryValueW( version
, szLangResource
, (LPVOID
*)&lang
, &len
) && len
> 0)
3266 sprintfW( tmp
, szLangFormat
, *lang
);
3267 if (langbuf
) lstrcpynW( langbuf
, tmp
, *langlen
);
3268 len
= strlenW( tmp
);
3269 if (*langlen
> len
) ret
= ERROR_SUCCESS
;
3274 if (langbuf
) *langbuf
= 0;
3278 msi_free( version
);
3283 /******************************************************************
3284 * MsiGetFileVersionW [MSI.@]
3286 UINT WINAPI
MsiGetFileVersionW( LPCWSTR path
, LPWSTR verbuf
, LPDWORD verlen
,
3287 LPWSTR langbuf
, LPDWORD langlen
)
3291 TRACE("%s %p %u %p %u\n", debugstr_w(path
), verbuf
, verlen
? *verlen
: 0,
3292 langbuf
, langlen
? *langlen
: 0);
3294 if ((verbuf
&& !verlen
) || (langbuf
&& !langlen
))
3295 return ERROR_INVALID_PARAMETER
;
3297 ret
= get_file_version( path
, verbuf
, verlen
, langbuf
, langlen
);
3298 if (ret
== ERROR_RESOURCE_DATA_NOT_FOUND
&& verlen
)
3301 WCHAR
*version
= msi_font_version_from_file( path
);
3302 if (!version
) return ERROR_FILE_INVALID
;
3303 len
= strlenW( version
);
3304 if (len
>= *verlen
) ret
= ERROR_MORE_DATA
;
3307 strcpyW( verbuf
, version
);
3308 ret
= ERROR_SUCCESS
;
3311 msi_free( version
);
3316 /***********************************************************************
3317 * MsiGetFeatureUsageW [MSI.@]
3319 UINT WINAPI
MsiGetFeatureUsageW( LPCWSTR szProduct
, LPCWSTR szFeature
,
3320 LPDWORD pdwUseCount
, LPWORD pwDateUsed
)
3322 FIXME("%s %s %p %p\n",debugstr_w(szProduct
), debugstr_w(szFeature
),
3323 pdwUseCount
, pwDateUsed
);
3324 return ERROR_CALL_NOT_IMPLEMENTED
;
3327 /***********************************************************************
3328 * MsiGetFeatureUsageA [MSI.@]
3330 UINT WINAPI
MsiGetFeatureUsageA( LPCSTR szProduct
, LPCSTR szFeature
,
3331 LPDWORD pdwUseCount
, LPWORD pwDateUsed
)
3333 LPWSTR prod
= NULL
, feat
= NULL
;
3334 UINT ret
= ERROR_OUTOFMEMORY
;
3336 TRACE("%s %s %p %p\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
3337 pdwUseCount
, pwDateUsed
);
3339 prod
= strdupAtoW( szProduct
);
3340 if (szProduct
&& !prod
)
3343 feat
= strdupAtoW( szFeature
);
3344 if (szFeature
&& !feat
)
3347 ret
= MsiGetFeatureUsageW( prod
, feat
, pdwUseCount
, pwDateUsed
);
3356 /***********************************************************************
3357 * MsiUseFeatureExW [MSI.@]
3359 INSTALLSTATE WINAPI
MsiUseFeatureExW( LPCWSTR szProduct
, LPCWSTR szFeature
,
3360 DWORD dwInstallMode
, DWORD dwReserved
)
3364 TRACE("%s %s %i %i\n", debugstr_w(szProduct
), debugstr_w(szFeature
),
3365 dwInstallMode
, dwReserved
);
3367 state
= MsiQueryFeatureStateW( szProduct
, szFeature
);
3370 return INSTALLSTATE_INVALIDARG
;
3372 if (state
== INSTALLSTATE_LOCAL
&& dwInstallMode
!= INSTALLMODE_NODETECTION
)
3374 FIXME("mark product %s feature %s as used\n",
3375 debugstr_w(szProduct
), debugstr_w(szFeature
) );
3381 /***********************************************************************
3382 * MsiUseFeatureExA [MSI.@]
3384 INSTALLSTATE WINAPI
MsiUseFeatureExA( LPCSTR szProduct
, LPCSTR szFeature
,
3385 DWORD dwInstallMode
, DWORD dwReserved
)
3387 INSTALLSTATE ret
= INSTALLSTATE_UNKNOWN
;
3388 LPWSTR prod
= NULL
, feat
= NULL
;
3390 TRACE("%s %s %i %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
3391 dwInstallMode
, dwReserved
);
3393 prod
= strdupAtoW( szProduct
);
3394 if (szProduct
&& !prod
)
3397 feat
= strdupAtoW( szFeature
);
3398 if (szFeature
&& !feat
)
3401 ret
= MsiUseFeatureExW( prod
, feat
, dwInstallMode
, dwReserved
);
3410 /***********************************************************************
3411 * MsiUseFeatureW [MSI.@]
3413 INSTALLSTATE WINAPI
MsiUseFeatureW( LPCWSTR szProduct
, LPCWSTR szFeature
)
3415 return MsiUseFeatureExW(szProduct
, szFeature
, 0, 0);
3418 /***********************************************************************
3419 * MsiUseFeatureA [MSI.@]
3421 INSTALLSTATE WINAPI
MsiUseFeatureA( LPCSTR szProduct
, LPCSTR szFeature
)
3423 return MsiUseFeatureExA(szProduct
, szFeature
, 0, 0);
3426 static WCHAR
*reg_get_multisz( HKEY hkey
, const WCHAR
*name
)
3430 if (RegQueryValueExW( hkey
, name
, NULL
, &type
, NULL
, &len
) || type
!= REG_MULTI_SZ
) return NULL
;
3431 if ((ret
= msi_alloc( len
))) RegQueryValueExW( hkey
, name
, NULL
, NULL
, (BYTE
*)ret
, &len
);
3435 static WCHAR
*reg_get_sz( HKEY hkey
, const WCHAR
*name
)
3439 if (RegQueryValueExW( hkey
, name
, NULL
, &type
, NULL
, &len
) || type
!= REG_SZ
) return NULL
;
3440 if ((ret
= msi_alloc( len
))) RegQueryValueExW( hkey
, name
, NULL
, NULL
, (BYTE
*)ret
, &len
);
3444 #define BASE85_SIZE 20
3446 /***********************************************************************
3447 * MSI_ProvideQualifiedComponentEx [internal]
3449 static UINT
MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent
,
3450 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPCWSTR szProduct
,
3451 DWORD Unused1
, DWORD Unused2
, awstring
*lpPathBuf
,
3452 LPDWORD pcchPathBuf
)
3454 WCHAR product
[MAX_FEATURE_CHARS
+1], comp
[MAX_FEATURE_CHARS
+1], feature
[MAX_FEATURE_CHARS
+1];
3461 if (MSIREG_OpenUserComponentsKey( szComponent
, &hkey
, FALSE
)) return ERROR_UNKNOWN_COMPONENT
;
3463 desc
= reg_get_multisz( hkey
, szQualifier
);
3465 if (!desc
) return ERROR_INDEX_ABSENT
;
3467 /* FIXME: handle multiple descriptors */
3468 ret
= MsiDecomposeDescriptorW( desc
, product
, feature
, comp
, &size
);
3470 if (ret
!= ERROR_SUCCESS
) return ret
;
3472 if (!szProduct
) szProduct
= product
;
3475 MSIINSTALLCONTEXT ctx
;
3479 /* use the first component of the feature if the descriptor component is empty */
3480 if ((ret
= msi_locate_product( szProduct
, &ctx
))) return ret
;
3481 if ((ret
= MSIREG_OpenUserDataFeaturesKey( szProduct
, NULL
, ctx
, &hkey
, FALSE
)))
3483 return ERROR_FILE_NOT_FOUND
;
3485 components
= reg_get_sz( hkey
, feature
);
3486 RegCloseKey( hkey
);
3487 if (!components
) return ERROR_FILE_NOT_FOUND
;
3489 if (strlenW( components
) < BASE85_SIZE
|| !decode_base85_guid( components
, &guid
))
3491 msi_free( components
);
3492 return ERROR_FILE_NOT_FOUND
;
3494 msi_free( components
);
3495 StringFromGUID2( &guid
, comp
, ARRAY_SIZE( comp
));
3498 state
= MSI_GetComponentPath( szProduct
, comp
, szAllSid
, MSIINSTALLCONTEXT_ALL
, lpPathBuf
, pcchPathBuf
);
3500 if (state
== INSTALLSTATE_MOREDATA
) return ERROR_MORE_DATA
;
3501 if (state
!= INSTALLSTATE_LOCAL
) return ERROR_FILE_NOT_FOUND
;
3502 return ERROR_SUCCESS
;
3505 /***********************************************************************
3506 * MsiProvideQualifiedComponentExW [MSI.@]
3508 UINT WINAPI
MsiProvideQualifiedComponentExW(LPCWSTR szComponent
,
3509 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPCWSTR szProduct
,
3510 DWORD Unused1
, DWORD Unused2
, LPWSTR lpPathBuf
,
3511 LPDWORD pcchPathBuf
)
3515 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_w(szComponent
),
3516 debugstr_w(szQualifier
), dwInstallMode
, debugstr_w(szProduct
),
3517 Unused1
, Unused2
, lpPathBuf
, pcchPathBuf
);
3519 path
.unicode
= TRUE
;
3520 path
.str
.w
= lpPathBuf
;
3522 return MSI_ProvideQualifiedComponentEx(szComponent
, szQualifier
,
3523 dwInstallMode
, szProduct
, Unused1
, Unused2
, &path
, pcchPathBuf
);
3526 /***********************************************************************
3527 * MsiProvideQualifiedComponentExA [MSI.@]
3529 UINT WINAPI
MsiProvideQualifiedComponentExA(LPCSTR szComponent
,
3530 LPCSTR szQualifier
, DWORD dwInstallMode
, LPCSTR szProduct
,
3531 DWORD Unused1
, DWORD Unused2
, LPSTR lpPathBuf
,
3532 LPDWORD pcchPathBuf
)
3534 LPWSTR szwComponent
, szwQualifier
= NULL
, szwProduct
= NULL
;
3535 UINT r
= ERROR_OUTOFMEMORY
;
3538 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent
),
3539 debugstr_a(szQualifier
), dwInstallMode
, debugstr_a(szProduct
),
3540 Unused1
, Unused2
, lpPathBuf
, pcchPathBuf
);
3542 szwComponent
= strdupAtoW( szComponent
);
3543 if (szComponent
&& !szwComponent
)
3546 szwQualifier
= strdupAtoW( szQualifier
);
3547 if (szQualifier
&& !szwQualifier
)
3550 szwProduct
= strdupAtoW( szProduct
);
3551 if (szProduct
&& !szwProduct
)
3554 path
.unicode
= FALSE
;
3555 path
.str
.a
= lpPathBuf
;
3557 r
= MSI_ProvideQualifiedComponentEx(szwComponent
, szwQualifier
,
3558 dwInstallMode
, szwProduct
, Unused1
,
3559 Unused2
, &path
, pcchPathBuf
);
3561 msi_free(szwProduct
);
3562 msi_free(szwComponent
);
3563 msi_free(szwQualifier
);
3568 /***********************************************************************
3569 * MsiProvideQualifiedComponentW [MSI.@]
3571 UINT WINAPI
MsiProvideQualifiedComponentW( LPCWSTR szComponent
,
3572 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPWSTR lpPathBuf
,
3573 LPDWORD pcchPathBuf
)
3575 return MsiProvideQualifiedComponentExW(szComponent
, szQualifier
,
3576 dwInstallMode
, NULL
, 0, 0, lpPathBuf
, pcchPathBuf
);
3579 /***********************************************************************
3580 * MsiProvideQualifiedComponentA [MSI.@]
3582 UINT WINAPI
MsiProvideQualifiedComponentA( LPCSTR szComponent
,
3583 LPCSTR szQualifier
, DWORD dwInstallMode
, LPSTR lpPathBuf
,
3584 LPDWORD pcchPathBuf
)
3586 return MsiProvideQualifiedComponentExA(szComponent
, szQualifier
,
3587 dwInstallMode
, NULL
, 0, 0, lpPathBuf
, pcchPathBuf
);
3590 /***********************************************************************
3591 * MSI_GetUserInfo [internal]
3593 static USERINFOSTATE
MSI_GetUserInfo(LPCWSTR szProduct
,
3594 awstring
*lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
3595 awstring
*lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
3596 awstring
*lpSerialBuf
, LPDWORD pcchSerialBuf
)
3598 WCHAR
*user
, *org
, *serial
, squashed_pc
[SQUASHED_GUID_SIZE
];
3599 USERINFOSTATE state
;
3604 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct
), lpUserNameBuf
,
3605 pcchUserNameBuf
, lpOrgNameBuf
, pcchOrgNameBuf
, lpSerialBuf
,
3608 if (!szProduct
|| !squash_guid( szProduct
, squashed_pc
))
3609 return USERINFOSTATE_INVALIDARG
;
3611 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
3612 &hkey
, FALSE
) != ERROR_SUCCESS
&&
3613 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3614 &hkey
, FALSE
) != ERROR_SUCCESS
&&
3615 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
3616 &hkey
, FALSE
) != ERROR_SUCCESS
)
3618 return USERINFOSTATE_UNKNOWN
;
3621 if (MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3622 NULL
, &props
, FALSE
) != ERROR_SUCCESS
&&
3623 MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_MACHINE
,
3624 NULL
, &props
, FALSE
) != ERROR_SUCCESS
)
3627 return USERINFOSTATE_ABSENT
;
3630 user
= msi_reg_get_val_str(props
, INSTALLPROPERTY_REGOWNERW
);
3631 org
= msi_reg_get_val_str(props
, INSTALLPROPERTY_REGCOMPANYW
);
3632 serial
= msi_reg_get_val_str(props
, INSTALLPROPERTY_PRODUCTIDW
);
3633 state
= USERINFOSTATE_ABSENT
;
3639 state
= USERINFOSTATE_PRESENT
;
3641 if (pcchUserNameBuf
)
3643 if (lpUserNameBuf
&& !user
)
3645 (*pcchUserNameBuf
)--;
3649 r
= msi_strcpy_to_awstring(user
, -1, lpUserNameBuf
, pcchUserNameBuf
);
3650 if (r
== ERROR_MORE_DATA
)
3652 state
= USERINFOSTATE_MOREDATA
;
3660 if (!orgptr
) orgptr
= szEmpty
;
3662 r
= msi_strcpy_to_awstring(orgptr
, -1, lpOrgNameBuf
, pcchOrgNameBuf
);
3663 if (r
== ERROR_MORE_DATA
)
3665 state
= USERINFOSTATE_MOREDATA
;
3678 r
= msi_strcpy_to_awstring(serial
, -1, lpSerialBuf
, pcchSerialBuf
);
3679 if (r
== ERROR_MORE_DATA
)
3680 state
= USERINFOSTATE_MOREDATA
;
3691 /***********************************************************************
3692 * MsiGetUserInfoW [MSI.@]
3694 USERINFOSTATE WINAPI
MsiGetUserInfoW(LPCWSTR szProduct
,
3695 LPWSTR lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
3696 LPWSTR lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
3697 LPWSTR lpSerialBuf
, LPDWORD pcchSerialBuf
)
3699 awstring user
, org
, serial
;
3701 if ((lpUserNameBuf
&& !pcchUserNameBuf
) ||
3702 (lpOrgNameBuf
&& !pcchOrgNameBuf
) ||
3703 (lpSerialBuf
&& !pcchSerialBuf
))
3704 return USERINFOSTATE_INVALIDARG
;
3706 user
.unicode
= TRUE
;
3707 user
.str
.w
= lpUserNameBuf
;
3709 org
.str
.w
= lpOrgNameBuf
;
3710 serial
.unicode
= TRUE
;
3711 serial
.str
.w
= lpSerialBuf
;
3713 return MSI_GetUserInfo( szProduct
, &user
, pcchUserNameBuf
,
3714 &org
, pcchOrgNameBuf
,
3715 &serial
, pcchSerialBuf
);
3718 USERINFOSTATE WINAPI
MsiGetUserInfoA(LPCSTR szProduct
,
3719 LPSTR lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
3720 LPSTR lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
3721 LPSTR lpSerialBuf
, LPDWORD pcchSerialBuf
)
3723 awstring user
, org
, serial
;
3727 if ((lpUserNameBuf
&& !pcchUserNameBuf
) ||
3728 (lpOrgNameBuf
&& !pcchOrgNameBuf
) ||
3729 (lpSerialBuf
&& !pcchSerialBuf
))
3730 return USERINFOSTATE_INVALIDARG
;
3732 prod
= strdupAtoW( szProduct
);
3733 if (szProduct
&& !prod
)
3734 return ERROR_OUTOFMEMORY
;
3736 user
.unicode
= FALSE
;
3737 user
.str
.a
= lpUserNameBuf
;
3738 org
.unicode
= FALSE
;
3739 org
.str
.a
= lpOrgNameBuf
;
3740 serial
.unicode
= FALSE
;
3741 serial
.str
.a
= lpSerialBuf
;
3743 r
= MSI_GetUserInfo( prod
, &user
, pcchUserNameBuf
,
3744 &org
, pcchOrgNameBuf
,
3745 &serial
, pcchSerialBuf
);
3752 UINT WINAPI
MsiCollectUserInfoW(LPCWSTR szProduct
)
3756 MSIPACKAGE
*package
;
3757 static const WCHAR szFirstRun
[] = {'F','i','r','s','t','R','u','n',0};
3759 TRACE("(%s)\n",debugstr_w(szProduct
));
3761 rc
= MsiOpenProductW(szProduct
,&handle
);
3762 if (rc
!= ERROR_SUCCESS
)
3763 return ERROR_INVALID_PARAMETER
;
3765 /* MsiCollectUserInfo cannot be called from a custom action. */
3766 package
= msihandle2msiinfo(handle
, MSIHANDLETYPE_PACKAGE
);
3768 return ERROR_CALL_NOT_IMPLEMENTED
;
3770 rc
= ACTION_PerformAction(package
, szFirstRun
);
3771 msiobj_release( &package
->hdr
);
3773 MsiCloseHandle(handle
);
3778 UINT WINAPI
MsiCollectUserInfoA(LPCSTR szProduct
)
3782 MSIPACKAGE
*package
;
3783 static const WCHAR szFirstRun
[] = {'F','i','r','s','t','R','u','n',0};
3785 TRACE("(%s)\n",debugstr_a(szProduct
));
3787 rc
= MsiOpenProductA(szProduct
,&handle
);
3788 if (rc
!= ERROR_SUCCESS
)
3789 return ERROR_INVALID_PARAMETER
;
3791 /* MsiCollectUserInfo cannot be called from a custom action. */
3792 package
= msihandle2msiinfo(handle
, MSIHANDLETYPE_PACKAGE
);
3794 return ERROR_CALL_NOT_IMPLEMENTED
;
3796 rc
= ACTION_PerformAction(package
, szFirstRun
);
3797 msiobj_release( &package
->hdr
);
3799 MsiCloseHandle(handle
);
3804 /***********************************************************************
3805 * MsiConfigureFeatureA [MSI.@]
3807 UINT WINAPI
MsiConfigureFeatureA(LPCSTR szProduct
, LPCSTR szFeature
, INSTALLSTATE eInstallState
)
3809 LPWSTR prod
, feat
= NULL
;
3810 UINT r
= ERROR_OUTOFMEMORY
;
3812 TRACE("%s %s %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
), eInstallState
);
3814 prod
= strdupAtoW( szProduct
);
3815 if (szProduct
&& !prod
)
3818 feat
= strdupAtoW( szFeature
);
3819 if (szFeature
&& !feat
)
3822 r
= MsiConfigureFeatureW(prod
, feat
, eInstallState
);
3831 /***********************************************************************
3832 * MsiConfigureFeatureW [MSI.@]
3834 UINT WINAPI
MsiConfigureFeatureW(LPCWSTR szProduct
, LPCWSTR szFeature
, INSTALLSTATE eInstallState
)
3836 MSIPACKAGE
*package
= NULL
;
3838 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
3841 TRACE("%s %s %i\n", debugstr_w(szProduct
), debugstr_w(szFeature
), eInstallState
);
3843 if (!szProduct
|| !szFeature
)
3844 return ERROR_INVALID_PARAMETER
;
3846 switch (eInstallState
)
3848 case INSTALLSTATE_DEFAULT
:
3849 /* FIXME: how do we figure out the default location? */
3850 eInstallState
= INSTALLSTATE_LOCAL
;
3852 case INSTALLSTATE_LOCAL
:
3853 case INSTALLSTATE_SOURCE
:
3854 case INSTALLSTATE_ABSENT
:
3855 case INSTALLSTATE_ADVERTISED
:
3858 return ERROR_INVALID_PARAMETER
;
3861 r
= MSI_OpenProductW( szProduct
, &package
);
3862 if (r
!= ERROR_SUCCESS
)
3865 sz
= sizeof(sourcepath
);
3866 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3867 MSICODE_PRODUCT
, INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
3869 sz
= sizeof(filename
);
3870 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3871 MSICODE_PRODUCT
, INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
3873 lstrcatW( sourcepath
, filename
);
3875 MsiSetInternalUI( INSTALLUILEVEL_BASIC
, NULL
);
3877 r
= ACTION_PerformAction(package
, szCostInitialize
);
3878 if (r
!= ERROR_SUCCESS
)
3881 r
= MSI_SetFeatureStateW( package
, szFeature
, eInstallState
);
3882 if (r
!= ERROR_SUCCESS
)
3885 r
= MSI_InstallPackage( package
, sourcepath
, NULL
);
3888 msiobj_release( &package
->hdr
);
3893 /***********************************************************************
3894 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3896 * Notes: undocumented
3898 UINT WINAPI
MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved
)
3900 WCHAR path
[MAX_PATH
];
3902 TRACE("%d\n", dwReserved
);
3906 FIXME("dwReserved=%d\n", dwReserved
);
3907 return ERROR_INVALID_PARAMETER
;
3910 if (!GetWindowsDirectoryW(path
, MAX_PATH
))
3911 return ERROR_FUNCTION_FAILED
;
3913 lstrcatW(path
, installerW
);
3915 if (!CreateDirectoryW(path
, NULL
) && GetLastError() != ERROR_ALREADY_EXISTS
)
3916 return ERROR_FUNCTION_FAILED
;
3918 return ERROR_SUCCESS
;
3921 /***********************************************************************
3922 * MsiGetShortcutTargetA [MSI.@]
3924 UINT WINAPI
MsiGetShortcutTargetA( LPCSTR szShortcutTarget
,
3925 LPSTR szProductCode
, LPSTR szFeatureId
,
3926 LPSTR szComponentCode
)
3929 const int len
= MAX_FEATURE_CHARS
+1;
3930 WCHAR product
[MAX_FEATURE_CHARS
+1], feature
[MAX_FEATURE_CHARS
+1], component
[MAX_FEATURE_CHARS
+1];
3933 target
= strdupAtoW( szShortcutTarget
);
3934 if (szShortcutTarget
&& !target
)
3935 return ERROR_OUTOFMEMORY
;
3939 r
= MsiGetShortcutTargetW( target
, product
, feature
, component
);
3941 if (r
== ERROR_SUCCESS
)
3943 WideCharToMultiByte( CP_ACP
, 0, product
, -1, szProductCode
, len
, NULL
, NULL
);
3944 WideCharToMultiByte( CP_ACP
, 0, feature
, -1, szFeatureId
, len
, NULL
, NULL
);
3945 WideCharToMultiByte( CP_ACP
, 0, component
, -1, szComponentCode
, len
, NULL
, NULL
);
3950 /***********************************************************************
3951 * MsiGetShortcutTargetW [MSI.@]
3953 UINT WINAPI
MsiGetShortcutTargetW( LPCWSTR szShortcutTarget
,
3954 LPWSTR szProductCode
, LPWSTR szFeatureId
,
3955 LPWSTR szComponentCode
)
3957 IShellLinkDataList
*dl
= NULL
;
3958 IPersistFile
*pf
= NULL
;
3959 LPEXP_DARWIN_LINK darwin
= NULL
;
3962 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget
),
3963 szProductCode
, szFeatureId
, szComponentCode
);
3965 init
= CoInitialize(NULL
);
3967 r
= CoCreateInstance( &CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
3968 &IID_IPersistFile
, (LPVOID
*) &pf
);
3969 if( SUCCEEDED( r
) )
3971 r
= IPersistFile_Load( pf
, szShortcutTarget
,
3972 STGM_READ
| STGM_SHARE_DENY_WRITE
);
3973 if( SUCCEEDED( r
) )
3975 r
= IPersistFile_QueryInterface( pf
, &IID_IShellLinkDataList
,
3977 if( SUCCEEDED( r
) )
3979 IShellLinkDataList_CopyDataBlock( dl
, EXP_DARWIN_ID_SIG
,
3981 IShellLinkDataList_Release( dl
);
3984 IPersistFile_Release( pf
);
3987 if (SUCCEEDED(init
))
3990 TRACE("darwin = %p\n", darwin
);
3997 ret
= MsiDecomposeDescriptorW( darwin
->szwDarwinID
,
3998 szProductCode
, szFeatureId
, szComponentCode
, &sz
);
3999 LocalFree( darwin
);
4003 return ERROR_FUNCTION_FAILED
;
4006 UINT WINAPI
MsiReinstallFeatureW( LPCWSTR szProduct
, LPCWSTR szFeature
, DWORD dwReinstallMode
)
4008 static const WCHAR fmtW
[] = {'%','s','=','%','s',' ','%','s','=','%','s',0};
4009 MSIPACKAGE
*package
;
4010 MSIINSTALLCONTEXT context
;
4012 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
], reinstallmode
[11];
4013 WCHAR
*ptr
, *cmdline
;
4016 TRACE("%s, %s, 0x%08x\n", debugstr_w(szProduct
), debugstr_w(szFeature
), dwReinstallMode
);
4018 r
= msi_locate_product( szProduct
, &context
);
4019 if (r
!= ERROR_SUCCESS
)
4022 ptr
= reinstallmode
;
4024 if (dwReinstallMode
& REINSTALLMODE_FILEMISSING
)
4026 if (dwReinstallMode
& REINSTALLMODE_FILEOLDERVERSION
)
4028 if (dwReinstallMode
& REINSTALLMODE_FILEEQUALVERSION
)
4030 if (dwReinstallMode
& REINSTALLMODE_FILEEXACT
)
4032 if (dwReinstallMode
& REINSTALLMODE_FILEVERIFY
)
4034 if (dwReinstallMode
& REINSTALLMODE_FILEREPLACE
)
4036 if (dwReinstallMode
& REINSTALLMODE_USERDATA
)
4038 if (dwReinstallMode
& REINSTALLMODE_MACHINEDATA
)
4040 if (dwReinstallMode
& REINSTALLMODE_SHORTCUT
)
4042 if (dwReinstallMode
& REINSTALLMODE_PACKAGE
)
4046 sz
= sizeof(sourcepath
);
4047 MsiSourceListGetInfoW( szProduct
, NULL
, context
, MSICODE_PRODUCT
,
4048 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
4049 sz
= sizeof(filename
);
4050 MsiSourceListGetInfoW( szProduct
, NULL
, context
, MSICODE_PRODUCT
,
4051 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
4052 strcatW( sourcepath
, filename
);
4054 if (dwReinstallMode
& REINSTALLMODE_PACKAGE
)
4055 r
= MSI_OpenPackageW( sourcepath
, 0, &package
);
4057 r
= MSI_OpenProductW( szProduct
, &package
);
4059 if (r
!= ERROR_SUCCESS
)
4062 sz
= (strlenW( fmtW
) + strlenW( szReinstallMode
) + strlenW( reinstallmode
)) * sizeof(WCHAR
);
4063 sz
+= (strlenW( szReinstall
) + strlenW( szFeature
)) * sizeof(WCHAR
);
4064 if (!(cmdline
= msi_alloc( sz
)))
4066 msiobj_release( &package
->hdr
);
4067 return ERROR_OUTOFMEMORY
;
4069 sprintfW( cmdline
, fmtW
, szReinstallMode
, reinstallmode
, szReinstall
, szFeature
);
4071 r
= MSI_InstallPackage( package
, sourcepath
, cmdline
);
4072 msiobj_release( &package
->hdr
);
4073 msi_free( cmdline
);
4078 UINT WINAPI
MsiReinstallFeatureA( LPCSTR szProduct
, LPCSTR szFeature
,
4079 DWORD dwReinstallMode
)
4085 TRACE("%s %s %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
4088 wszProduct
= strdupAtoW(szProduct
);
4089 wszFeature
= strdupAtoW(szFeature
);
4091 rc
= MsiReinstallFeatureW(wszProduct
, wszFeature
, dwReinstallMode
);
4093 msi_free(wszProduct
);
4094 msi_free(wszFeature
);
4101 unsigned int buf
[4];
4102 unsigned char in
[64];
4103 unsigned char digest
[16];
4106 extern VOID WINAPI
MD5Init( MD5_CTX
*);
4107 extern VOID WINAPI
MD5Update( MD5_CTX
*, const unsigned char *, unsigned int );
4108 extern VOID WINAPI
MD5Final( MD5_CTX
*);
4110 UINT
msi_get_filehash( const WCHAR
*path
, MSIFILEHASHINFO
*hash
)
4112 HANDLE handle
, mapping
;
4115 UINT r
= ERROR_FUNCTION_FAILED
;
4117 handle
= CreateFileW( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, 0, NULL
);
4118 if (handle
== INVALID_HANDLE_VALUE
)
4120 WARN("can't open file %u\n", GetLastError());
4121 return ERROR_FILE_NOT_FOUND
;
4123 if ((length
= GetFileSize( handle
, NULL
)))
4125 if ((mapping
= CreateFileMappingW( handle
, NULL
, PAGE_READONLY
, 0, 0, NULL
)))
4127 if ((p
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, length
)))
4132 MD5Update( &ctx
, p
, length
);
4134 UnmapViewOfFile( p
);
4136 memcpy( hash
->dwData
, ctx
.digest
, sizeof(hash
->dwData
) );
4139 CloseHandle( mapping
);
4144 /* Empty file -> set hash to 0 */
4145 memset( hash
->dwData
, 0, sizeof(hash
->dwData
) );
4149 CloseHandle( handle
);
4153 /***********************************************************************
4154 * MsiGetFileHashW [MSI.@]
4156 UINT WINAPI
MsiGetFileHashW( LPCWSTR szFilePath
, DWORD dwOptions
,
4157 PMSIFILEHASHINFO pHash
)
4159 TRACE("%s %08x %p\n", debugstr_w(szFilePath
), dwOptions
, pHash
);
4162 return ERROR_INVALID_PARAMETER
;
4165 return ERROR_PATH_NOT_FOUND
;
4168 return ERROR_INVALID_PARAMETER
;
4170 return ERROR_INVALID_PARAMETER
;
4171 if (pHash
->dwFileHashInfoSize
< sizeof *pHash
)
4172 return ERROR_INVALID_PARAMETER
;
4174 return msi_get_filehash( szFilePath
, pHash
);
4177 /***********************************************************************
4178 * MsiGetFileHashA [MSI.@]
4180 UINT WINAPI
MsiGetFileHashA( LPCSTR szFilePath
, DWORD dwOptions
,
4181 PMSIFILEHASHINFO pHash
)
4186 TRACE("%s %08x %p\n", debugstr_a(szFilePath
), dwOptions
, pHash
);
4188 file
= strdupAtoW( szFilePath
);
4189 if (szFilePath
&& !file
)
4190 return ERROR_OUTOFMEMORY
;
4192 r
= MsiGetFileHashW( file
, dwOptions
, pHash
);
4197 /***********************************************************************
4198 * MsiAdvertiseScriptW [MSI.@]
4200 UINT WINAPI
MsiAdvertiseScriptW( LPCWSTR szScriptFile
, DWORD dwFlags
,
4201 PHKEY phRegData
, BOOL fRemoveItems
)
4203 FIXME("%s %08x %p %d\n",
4204 debugstr_w( szScriptFile
), dwFlags
, phRegData
, fRemoveItems
);
4205 return ERROR_CALL_NOT_IMPLEMENTED
;
4208 /***********************************************************************
4209 * MsiAdvertiseScriptA [MSI.@]
4211 UINT WINAPI
MsiAdvertiseScriptA( LPCSTR szScriptFile
, DWORD dwFlags
,
4212 PHKEY phRegData
, BOOL fRemoveItems
)
4214 FIXME("%s %08x %p %d\n",
4215 debugstr_a( szScriptFile
), dwFlags
, phRegData
, fRemoveItems
);
4216 return ERROR_CALL_NOT_IMPLEMENTED
;
4219 /***********************************************************************
4220 * MsiIsProductElevatedW [MSI.@]
4222 UINT WINAPI
MsiIsProductElevatedW( LPCWSTR szProduct
, BOOL
*pfElevated
)
4224 FIXME("%s %p - stub\n",
4225 debugstr_w( szProduct
), pfElevated
);
4227 return ERROR_SUCCESS
;
4230 /***********************************************************************
4231 * MsiIsProductElevatedA [MSI.@]
4233 UINT WINAPI
MsiIsProductElevatedA( LPCSTR szProduct
, BOOL
*pfElevated
)
4235 FIXME("%s %p - stub\n",
4236 debugstr_a( szProduct
), pfElevated
);
4238 return ERROR_SUCCESS
;
4241 /***********************************************************************
4242 * MsiSetExternalUIRecord [MSI.@]
4244 UINT WINAPI
MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler
,
4245 DWORD filter
, LPVOID context
,
4246 PINSTALLUI_HANDLER_RECORD prev
)
4248 TRACE("%p %08x %p %p\n", handler
, filter
, context
, prev
);
4251 *prev
= gUIHandlerRecord
;
4253 gUIHandlerRecord
= handler
;
4254 gUIFilterRecord
= filter
;
4255 gUIContextRecord
= context
;
4257 return ERROR_SUCCESS
;
4260 /***********************************************************************
4261 * MsiInstallMissingComponentA [MSI.@]
4263 UINT WINAPI
MsiInstallMissingComponentA( LPCSTR product
, LPCSTR component
, INSTALLSTATE state
)
4266 WCHAR
*productW
= NULL
, *componentW
= NULL
;
4268 TRACE("%s, %s, %d\n", debugstr_a(product
), debugstr_a(component
), state
);
4270 if (product
&& !(productW
= strdupAtoW( product
)))
4271 return ERROR_OUTOFMEMORY
;
4273 if (component
&& !(componentW
= strdupAtoW( component
)))
4275 msi_free( productW
);
4276 return ERROR_OUTOFMEMORY
;
4279 r
= MsiInstallMissingComponentW( productW
, componentW
, state
);
4280 msi_free( productW
);
4281 msi_free( componentW
);
4285 /***********************************************************************
4286 * MsiInstallMissingComponentW [MSI.@]
4288 UINT WINAPI
MsiInstallMissingComponentW(LPCWSTR szProduct
, LPCWSTR szComponent
, INSTALLSTATE eInstallState
)
4290 FIXME("(%s %s %d\n", debugstr_w(szProduct
), debugstr_w(szComponent
), eInstallState
);
4291 return ERROR_SUCCESS
;
4294 UINT WINAPI
MsiProvideComponentA( LPCSTR product
, LPCSTR feature
, LPCSTR component
, DWORD mode
, LPSTR buf
, LPDWORD buflen
)
4296 WCHAR
*productW
= NULL
, *componentW
= NULL
, *featureW
= NULL
, *bufW
= NULL
;
4297 UINT r
= ERROR_OUTOFMEMORY
;
4301 TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_a(product
), debugstr_a(component
), debugstr_a(feature
), mode
, buf
, buflen
);
4303 if (product
&& !(productW
= strdupAtoW( product
))) goto done
;
4304 if (feature
&& !(featureW
= strdupAtoW( feature
))) goto done
;
4305 if (component
&& !(componentW
= strdupAtoW( component
))) goto done
;
4307 r
= MsiProvideComponentW( productW
, featureW
, componentW
, mode
, NULL
, &lenW
);
4308 if (r
!= ERROR_SUCCESS
)
4311 if (!(bufW
= msi_alloc( ++lenW
* sizeof(WCHAR
) )))
4313 r
= ERROR_OUTOFMEMORY
;
4317 r
= MsiProvideComponentW( productW
, featureW
, componentW
, mode
, bufW
, &lenW
);
4318 if (r
!= ERROR_SUCCESS
)
4321 len
= WideCharToMultiByte( CP_ACP
, 0, bufW
, -1, NULL
, 0, NULL
, NULL
);
4325 r
= ERROR_MORE_DATA
;
4327 WideCharToMultiByte( CP_ACP
, 0, bufW
, -1, buf
, *buflen
, NULL
, NULL
);
4333 msi_free( productW
);
4334 msi_free( featureW
);
4335 msi_free( componentW
);
4340 UINT WINAPI
MsiProvideComponentW( LPCWSTR product
, LPCWSTR feature
, LPCWSTR component
, DWORD mode
, LPWSTR buf
, LPDWORD buflen
)
4344 TRACE("%s, %s, %s, %x, %p, %p\n", debugstr_w(product
), debugstr_w(component
), debugstr_w(feature
), mode
, buf
, buflen
);
4346 state
= MsiQueryFeatureStateW( product
, feature
);
4347 TRACE("feature state: %d\n", state
);
4350 case INSTALLMODE_NODETECTION
:
4354 FIXME("mode %x not implemented\n", mode
);
4355 return ERROR_INSTALL_FAILURE
;
4358 state
= MsiGetComponentPathW( product
, component
, buf
, buflen
);
4359 TRACE("component state: %d\n", state
);
4362 case INSTALLSTATE_INVALIDARG
:
4363 return ERROR_INVALID_PARAMETER
;
4365 case INSTALLSTATE_MOREDATA
:
4366 return ERROR_MORE_DATA
;
4368 case INSTALLSTATE_ADVERTISED
:
4369 case INSTALLSTATE_LOCAL
:
4370 case INSTALLSTATE_SOURCE
:
4371 MsiUseFeatureW( product
, feature
);
4372 return ERROR_SUCCESS
;
4375 TRACE("MsiGetComponentPathW returned %d\n", state
);
4376 return ERROR_INSTALL_FAILURE
;
4380 /***********************************************************************
4381 * MsiBeginTransactionA [MSI.@]
4383 UINT WINAPI
MsiBeginTransactionA( LPCSTR name
, DWORD attrs
, MSIHANDLE
*id
, HANDLE
*event
)
4388 FIXME("%s %u %p %p\n", debugstr_a(name
), attrs
, id
, event
);
4390 nameW
= strdupAtoW( name
);
4392 return ERROR_OUTOFMEMORY
;
4394 r
= MsiBeginTransactionW( nameW
, attrs
, id
, event
);
4399 /***********************************************************************
4400 * MsiBeginTransactionW [MSI.@]
4402 UINT WINAPI
MsiBeginTransactionW( LPCWSTR name
, DWORD attrs
, MSIHANDLE
*id
, HANDLE
*event
)
4404 FIXME("%s %u %p %p\n", debugstr_w(name
), attrs
, id
, event
);
4406 *id
= (MSIHANDLE
)0xdeadbeef;
4407 *event
= (HANDLE
)0xdeadbeef;
4409 return ERROR_SUCCESS
;
4412 /***********************************************************************
4413 * MsiJoinTransaction [MSI.@]
4415 UINT WINAPI
MsiJoinTransaction( MSIHANDLE handle
, DWORD attrs
, HANDLE
*event
)
4417 FIXME("%u %08x %p\n", handle
, attrs
, event
);
4419 *event
= (HANDLE
)0xdeadbeef;
4420 return ERROR_SUCCESS
;
4423 /***********************************************************************
4424 * MsiEndTransaction [MSI.@]
4426 UINT WINAPI
MsiEndTransaction( DWORD state
)
4428 FIXME("%u\n", state
);
4429 return ERROR_SUCCESS
;
4432 UINT WINAPI
Migrate10CachedPackagesW(void* a
, void* b
, void* c
, DWORD d
)
4434 FIXME("%p,%p,%p,%08x\n", a
, b
, c
, d
);
4435 return ERROR_SUCCESS
;
4438 /***********************************************************************
4439 * MsiRemovePatchesA [MSI.@]
4441 UINT WINAPI
MsiRemovePatchesA(LPCSTR patchlist
, LPCSTR product
, INSTALLTYPE type
, LPCSTR propertylist
)
4443 FIXME("(%s %s %d %s\n", debugstr_a(patchlist
), debugstr_a(product
), type
, debugstr_a(propertylist
));
4444 return ERROR_SUCCESS
;
4447 /***********************************************************************
4448 * MsiRemovePatchesW [MSI.@]
4450 UINT WINAPI
MsiRemovePatchesW(LPCWSTR patchlist
, LPCWSTR product
, INSTALLTYPE type
, LPCWSTR propertylist
)
4452 FIXME("(%s %s %d %s\n", debugstr_w(patchlist
), debugstr_w(product
), type
, debugstr_w(propertylist
));
4453 return ERROR_SUCCESS
;