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"
52 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
56 UINT
msi_locate_product(LPCWSTR szProduct
, MSIINSTALLCONTEXT
*context
)
60 *context
= MSIINSTALLCONTEXT_NONE
;
61 if (!szProduct
) return ERROR_UNKNOWN_PRODUCT
;
63 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
64 &hkey
, FALSE
) == ERROR_SUCCESS
)
65 *context
= MSIINSTALLCONTEXT_USERMANAGED
;
66 else if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
67 &hkey
, FALSE
) == ERROR_SUCCESS
)
68 *context
= MSIINSTALLCONTEXT_MACHINE
;
69 else if (MSIREG_OpenProductKey(szProduct
, NULL
,
70 MSIINSTALLCONTEXT_USERUNMANAGED
,
71 &hkey
, FALSE
) == ERROR_SUCCESS
)
72 *context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
76 if (*context
== MSIINSTALLCONTEXT_NONE
)
77 return ERROR_UNKNOWN_PRODUCT
;
82 UINT WINAPI
MsiOpenProductA(LPCSTR szProduct
, MSIHANDLE
*phProduct
)
85 LPWSTR szwProd
= NULL
;
87 TRACE("%s %p\n",debugstr_a(szProduct
), phProduct
);
91 szwProd
= strdupAtoW( szProduct
);
93 return ERROR_OUTOFMEMORY
;
96 r
= MsiOpenProductW( szwProd
, phProduct
);
103 static UINT
MSI_OpenProductW(LPCWSTR szProduct
, MSIPACKAGE
**package
)
108 MSIINSTALLCONTEXT context
;
110 TRACE("%s %p\n", debugstr_w(szProduct
), package
);
112 r
= msi_locate_product(szProduct
, &context
);
113 if (r
!= ERROR_SUCCESS
)
116 r
= MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &props
, FALSE
);
117 if (r
!= ERROR_SUCCESS
)
118 return ERROR_UNKNOWN_PRODUCT
;
120 if (context
== MSIINSTALLCONTEXT_USERMANAGED
)
121 path
= msi_reg_get_val_str(props
, L
"ManagedLocalPackage");
123 path
= msi_reg_get_val_str(props
, L
"LocalPackage");
125 r
= ERROR_UNKNOWN_PRODUCT
;
127 if (!path
|| GetFileAttributesW(path
) == INVALID_FILE_ATTRIBUTES
)
130 if (PathIsRelativeW(path
))
132 r
= ERROR_INSTALL_PACKAGE_OPEN_FAILED
;
136 r
= MSI_OpenPackageW(path
, 0, package
);
144 UINT WINAPI
MsiOpenProductW(LPCWSTR szProduct
, MSIHANDLE
*phProduct
)
146 MSIPACKAGE
*package
= NULL
;
147 WCHAR squashed_pc
[SQUASHED_GUID_SIZE
];
150 if (!szProduct
|| !squash_guid( szProduct
, squashed_pc
))
151 return ERROR_INVALID_PARAMETER
;
154 return ERROR_INVALID_PARAMETER
;
156 r
= MSI_OpenProductW(szProduct
, &package
);
157 if (r
!= ERROR_SUCCESS
)
160 *phProduct
= alloc_msihandle(&package
->hdr
);
162 r
= ERROR_NOT_ENOUGH_MEMORY
;
164 msiobj_release(&package
->hdr
);
168 UINT WINAPI
MsiAdvertiseProductA(LPCSTR szPackagePath
, LPCSTR szScriptfilePath
,
169 LPCSTR szTransforms
, LANGID lgidLanguage
)
171 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath
),
172 debugstr_a(szScriptfilePath
), debugstr_a(szTransforms
), lgidLanguage
);
173 return ERROR_CALL_NOT_IMPLEMENTED
;
176 UINT WINAPI
MsiAdvertiseProductW(LPCWSTR szPackagePath
, LPCWSTR szScriptfilePath
,
177 LPCWSTR szTransforms
, LANGID lgidLanguage
)
179 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath
),
180 debugstr_w(szScriptfilePath
), debugstr_w(szTransforms
), lgidLanguage
);
181 return ERROR_CALL_NOT_IMPLEMENTED
;
184 UINT WINAPI
MsiAdvertiseProductExA( const char *szPackagePath
, const char *szScriptfilePath
,
185 const char *szTransforms
, LANGID lgidLanguage
, DWORD dwPlatform
, DWORD dwOptions
)
187 FIXME( "%s, %s, %s, %#x, %#lx, %#lx\n", debugstr_a(szPackagePath
), debugstr_a(szScriptfilePath
),
188 debugstr_a(szTransforms
), lgidLanguage
, dwPlatform
, dwOptions
);
189 return ERROR_CALL_NOT_IMPLEMENTED
;
192 UINT WINAPI
MsiAdvertiseProductExW( const WCHAR
*szPackagePath
, const WCHAR
*szScriptfilePath
,
193 const WCHAR
*szTransforms
, LANGID lgidLanguage
, DWORD dwPlatform
, DWORD dwOptions
)
195 FIXME( "%s, %s, %s, %#x %#lx %#lx\n", debugstr_w(szPackagePath
), debugstr_w(szScriptfilePath
),
196 debugstr_w(szTransforms
), lgidLanguage
, dwPlatform
, dwOptions
);
197 return ERROR_CALL_NOT_IMPLEMENTED
;
200 UINT WINAPI
MsiInstallProductA(LPCSTR szPackagePath
, LPCSTR szCommandLine
)
202 LPWSTR szwPath
= NULL
, szwCommand
= NULL
;
203 UINT r
= ERROR_OUTOFMEMORY
;
205 TRACE("%s %s\n",debugstr_a(szPackagePath
), debugstr_a(szCommandLine
));
209 szwPath
= strdupAtoW( szPackagePath
);
216 szwCommand
= strdupAtoW( szCommandLine
);
221 r
= MsiInstallProductW( szwPath
, szwCommand
);
225 msi_free( szwCommand
);
230 UINT WINAPI
MsiInstallProductW(LPCWSTR szPackagePath
, LPCWSTR szCommandLine
)
232 MSIPACKAGE
*package
= NULL
;
233 const WCHAR
*reinstallmode
;
237 TRACE("%s %s\n",debugstr_w(szPackagePath
), debugstr_w(szCommandLine
));
240 return ERROR_INVALID_PARAMETER
;
243 return ERROR_PATH_NOT_FOUND
;
245 reinstallmode
= msi_get_command_line_option(szCommandLine
, L
"REINSTALLMODE", &len
);
250 if (reinstallmode
[--len
] == 'v' || reinstallmode
[len
] == 'V')
252 options
|= WINE_OPENPACKAGEFLAGS_RECACHE
;
258 r
= MSI_OpenPackageW( szPackagePath
, options
, &package
);
259 if (r
== ERROR_SUCCESS
)
261 r
= MSI_InstallPackage( package
, szPackagePath
, szCommandLine
);
262 msiobj_release( &package
->hdr
);
268 UINT WINAPI
MsiReinstallProductA( const char *szProduct
, DWORD dwReinstallMode
)
273 TRACE( "%s, %#lx\n", debugstr_a(szProduct
), dwReinstallMode
);
275 wszProduct
= strdupAtoW(szProduct
);
276 rc
= MsiReinstallProductW(wszProduct
, dwReinstallMode
);
277 msi_free(wszProduct
);
281 UINT WINAPI
MsiReinstallProductW( const WCHAR
*szProduct
, DWORD dwReinstallMode
)
283 TRACE( "%s, %#lx\n", debugstr_w(szProduct
), dwReinstallMode
);
285 return MsiReinstallFeatureW(szProduct
, L
"ALL", dwReinstallMode
);
288 UINT WINAPI
MsiApplyPatchA(LPCSTR szPatchPackage
, LPCSTR szInstallPackage
,
289 INSTALLTYPE eInstallType
, LPCSTR szCommandLine
)
291 LPWSTR patch_package
= NULL
;
292 LPWSTR install_package
= NULL
;
293 LPWSTR command_line
= NULL
;
294 UINT r
= ERROR_OUTOFMEMORY
;
296 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage
), debugstr_a(szInstallPackage
),
297 eInstallType
, debugstr_a(szCommandLine
));
299 if (szPatchPackage
&& !(patch_package
= strdupAtoW(szPatchPackage
)))
302 if (szInstallPackage
&& !(install_package
= strdupAtoW(szInstallPackage
)))
305 if (szCommandLine
&& !(command_line
= strdupAtoW(szCommandLine
)))
308 r
= MsiApplyPatchW(patch_package
, install_package
, eInstallType
, command_line
);
311 msi_free(patch_package
);
312 msi_free(install_package
);
313 msi_free(command_line
);
318 static UINT
get_patch_product_codes( LPCWSTR szPatchPackage
, WCHAR
***product_codes
)
320 MSIHANDLE patch
, info
= 0;
323 static WCHAR empty
[] = L
"";
326 r
= MsiOpenDatabaseW( szPatchPackage
, MSIDBOPEN_READONLY
, &patch
);
327 if (r
!= ERROR_SUCCESS
)
330 r
= MsiGetSummaryInformationW( patch
, NULL
, 0, &info
);
331 if (r
!= ERROR_SUCCESS
)
335 r
= MsiSummaryInfoGetPropertyW( info
, PID_TEMPLATE
, &type
, NULL
, NULL
, empty
, &size
);
336 if (r
!= ERROR_MORE_DATA
|| !size
|| type
!= VT_LPSTR
)
338 ERR("Failed to read product codes from patch\n");
339 r
= ERROR_FUNCTION_FAILED
;
343 codes
= msi_alloc( ++size
* sizeof(WCHAR
) );
346 r
= ERROR_OUTOFMEMORY
;
350 r
= MsiSummaryInfoGetPropertyW( info
, PID_TEMPLATE
, &type
, NULL
, NULL
, codes
, &size
);
351 if (r
== ERROR_SUCCESS
)
352 *product_codes
= msi_split_string( codes
, ';' );
355 MsiCloseHandle( info
);
356 MsiCloseHandle( patch
);
361 static UINT
MSI_ApplyPatchW(LPCWSTR szPatchPackage
, LPCWSTR szProductCode
, LPCWSTR szCommandLine
)
363 UINT i
, r
= ERROR_FUNCTION_FAILED
;
365 LPCWSTR cmd_ptr
= szCommandLine
;
366 LPWSTR cmd
, *codes
= NULL
;
367 BOOL succeeded
= FALSE
;
369 if (!szPatchPackage
|| !szPatchPackage
[0])
370 return ERROR_INVALID_PARAMETER
;
372 if (!szProductCode
&& (r
= get_patch_product_codes( szPatchPackage
, &codes
)))
378 size
= lstrlenW(cmd_ptr
) + lstrlenW(L
"%s PATCH=\"%s\"") + lstrlenW(szPatchPackage
) + 1;
379 cmd
= msi_alloc(size
* sizeof(WCHAR
));
383 return ERROR_OUTOFMEMORY
;
385 swprintf(cmd
, size
, L
"%s PATCH=\"%s\"", cmd_ptr
, szPatchPackage
);
388 r
= MsiConfigureProductExW(szProductCode
, INSTALLLEVEL_DEFAULT
, INSTALLSTATE_DEFAULT
, cmd
);
391 for (i
= 0; codes
[i
]; i
++)
393 r
= MsiConfigureProductExW(codes
[i
], INSTALLLEVEL_DEFAULT
, INSTALLSTATE_DEFAULT
, cmd
);
394 if (r
== ERROR_SUCCESS
)
396 TRACE("patch applied\n");
410 UINT WINAPI
MsiApplyPatchW(LPCWSTR szPatchPackage
, LPCWSTR szInstallPackage
,
411 INSTALLTYPE eInstallType
, LPCWSTR szCommandLine
)
413 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage
), debugstr_w(szInstallPackage
),
414 eInstallType
, debugstr_w(szCommandLine
));
416 if (szInstallPackage
|| eInstallType
== INSTALLTYPE_NETWORK_IMAGE
||
417 eInstallType
== INSTALLTYPE_SINGLE_INSTANCE
)
419 FIXME("Only reading target products from patch\n");
420 return ERROR_CALL_NOT_IMPLEMENTED
;
423 return MSI_ApplyPatchW(szPatchPackage
, NULL
, szCommandLine
);
426 UINT WINAPI
MsiApplyMultiplePatchesA(LPCSTR szPatchPackages
,
427 LPCSTR szProductCode
, LPCSTR szPropertiesList
)
429 LPWSTR patch_packages
= NULL
;
430 LPWSTR product_code
= NULL
;
431 LPWSTR properties_list
= NULL
;
432 UINT r
= ERROR_OUTOFMEMORY
;
434 TRACE("%s %s %s\n", debugstr_a(szPatchPackages
), debugstr_a(szProductCode
),
435 debugstr_a(szPropertiesList
));
437 if (!szPatchPackages
|| !szPatchPackages
[0])
438 return ERROR_INVALID_PARAMETER
;
440 if (!(patch_packages
= strdupAtoW(szPatchPackages
)))
441 return ERROR_OUTOFMEMORY
;
443 if (szProductCode
&& !(product_code
= strdupAtoW(szProductCode
)))
446 if (szPropertiesList
&& !(properties_list
= strdupAtoW(szPropertiesList
)))
449 r
= MsiApplyMultiplePatchesW(patch_packages
, product_code
, properties_list
);
452 msi_free(patch_packages
);
453 msi_free(product_code
);
454 msi_free(properties_list
);
459 UINT WINAPI
MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages
,
460 LPCWSTR szProductCode
, LPCWSTR szPropertiesList
)
462 UINT r
= ERROR_SUCCESS
;
465 TRACE("%s %s %s\n", debugstr_w(szPatchPackages
), debugstr_w(szProductCode
),
466 debugstr_w(szPropertiesList
));
468 if (!szPatchPackages
|| !szPatchPackages
[0])
469 return ERROR_INVALID_PARAMETER
;
471 beg
= end
= szPatchPackages
;
477 while (*beg
== ' ') beg
++;
478 while (*end
&& *end
!= ';') end
++;
481 while (len
&& beg
[len
- 1] == ' ') len
--;
483 if (!len
) return ERROR_INVALID_NAME
;
485 patch
= msi_alloc((len
+ 1) * sizeof(WCHAR
));
487 return ERROR_OUTOFMEMORY
;
489 memcpy(patch
, beg
, len
* sizeof(WCHAR
));
492 r
= MSI_ApplyPatchW(patch
, szProductCode
, szPropertiesList
);
495 if (r
!= ERROR_SUCCESS
|| !*end
)
503 static void free_patchinfo( DWORD count
, MSIPATCHSEQUENCEINFOW
*info
)
506 for (i
= 0; i
< count
; i
++) msi_free( (WCHAR
*)info
[i
].szPatchData
);
510 static MSIPATCHSEQUENCEINFOW
*patchinfoAtoW( DWORD count
, const MSIPATCHSEQUENCEINFOA
*info
)
513 MSIPATCHSEQUENCEINFOW
*ret
;
515 if (!(ret
= msi_alloc( count
* sizeof(MSIPATCHSEQUENCEINFOW
) ))) return NULL
;
516 for (i
= 0; i
< count
; i
++)
518 if (info
[i
].szPatchData
&& !(ret
[i
].szPatchData
= strdupAtoW( info
[i
].szPatchData
)))
520 free_patchinfo( i
, ret
);
523 ret
[i
].ePatchDataType
= info
[i
].ePatchDataType
;
524 ret
[i
].dwOrder
= info
[i
].dwOrder
;
525 ret
[i
].uStatus
= info
[i
].uStatus
;
530 UINT WINAPI
MsiDetermineApplicablePatchesA( const char *szProductPackagePath
, DWORD cPatchInfo
,
531 MSIPATCHSEQUENCEINFOA
*pPatchInfo
)
534 WCHAR
*package_path
= NULL
;
535 MSIPATCHSEQUENCEINFOW
*psi
;
537 TRACE( "%s, %lu, %p\n", debugstr_a(szProductPackagePath
), cPatchInfo
, pPatchInfo
);
539 if (szProductPackagePath
&& !(package_path
= strdupAtoW( szProductPackagePath
)))
540 return ERROR_OUTOFMEMORY
;
542 if (!(psi
= patchinfoAtoW( cPatchInfo
, pPatchInfo
)))
544 msi_free( package_path
);
545 return ERROR_OUTOFMEMORY
;
547 r
= MsiDetermineApplicablePatchesW( package_path
, cPatchInfo
, psi
);
548 if (r
== ERROR_SUCCESS
)
550 for (i
= 0; i
< cPatchInfo
; i
++)
552 pPatchInfo
[i
].dwOrder
= psi
[i
].dwOrder
;
553 pPatchInfo
[i
].uStatus
= psi
[i
].uStatus
;
556 msi_free( package_path
);
557 free_patchinfo( cPatchInfo
, psi
);
561 static UINT
MSI_ApplicablePatchW( MSIPACKAGE
*package
, LPCWSTR patch
)
564 MSIDATABASE
*patch_db
;
567 r
= MSI_OpenDatabaseW( patch
, MSIDBOPEN_READONLY
, &patch_db
);
568 if (r
!= ERROR_SUCCESS
)
570 WARN("failed to open patch file %s\n", debugstr_w(patch
));
574 r
= msi_get_suminfo( patch_db
->storage
, 0, &si
);
575 if (r
!= ERROR_SUCCESS
)
577 msiobj_release( &patch_db
->hdr
);
578 return ERROR_FUNCTION_FAILED
;
581 r
= msi_check_patch_applicable( package
, si
);
582 if (r
!= ERROR_SUCCESS
)
583 TRACE("patch not applicable\n");
585 msiobj_release( &patch_db
->hdr
);
586 msiobj_release( &si
->hdr
);
590 /* IXMLDOMDocument should be set to XPath mode already */
591 static UINT
MSI_ApplicablePatchXML( MSIPACKAGE
*package
, IXMLDOMDocument
*desc
)
593 UINT r
= ERROR_FUNCTION_FAILED
;
594 IXMLDOMNodeList
*list
;
600 product_code
= msi_dup_property( package
->db
, L
"ProductCode" );
603 /* FIXME: the property ProductCode should be written into the DB somewhere */
604 ERR("no product code to check\n");
605 return ERROR_SUCCESS
;
608 s
= SysAllocString( L
"MsiPatch/TargetProduct/TargetProductCode" );
609 hr
= IXMLDOMDocument_selectNodes( desc
, s
, &list
);
612 return ERROR_INVALID_PATCH_XML
;
614 while (IXMLDOMNodeList_nextNode( list
, &node
) == S_OK
&& r
!= ERROR_SUCCESS
)
616 hr
= IXMLDOMNode_get_text( node
, &s
);
617 IXMLDOMNode_Release( node
);
620 if (!wcscmp( s
, product_code
)) r
= ERROR_SUCCESS
;
624 IXMLDOMNodeList_Release( list
);
626 if (r
!= ERROR_SUCCESS
)
627 TRACE("patch not applicable\n");
629 msi_free( product_code
);
633 static UINT
determine_patch_sequence( MSIPACKAGE
*package
, DWORD count
, MSIPATCHSEQUENCEINFOW
*info
)
635 IXMLDOMDocument
*desc
= NULL
;
639 FIXME("patch ordering not supported\n");
641 for (i
= 0; i
< count
; i
++)
643 switch (info
[i
].ePatchDataType
)
645 case MSIPATCH_DATATYPE_PATCHFILE
:
647 if (MSI_ApplicablePatchW( package
, info
[i
].szPatchData
) != ERROR_SUCCESS
)
649 info
[i
].dwOrder
= ~0u;
650 info
[i
].uStatus
= ERROR_PATCH_TARGET_NOT_FOUND
;
655 info
[i
].uStatus
= ERROR_SUCCESS
;
659 case MSIPATCH_DATATYPE_XMLPATH
:
660 case MSIPATCH_DATATYPE_XMLBLOB
:
668 hr
= CoCreateInstance( &CLSID_DOMDocument30
, NULL
, CLSCTX_INPROC_SERVER
,
669 &IID_IXMLDOMDocument
, (void**)&desc
);
672 ERR( "failed to create DOMDocument30 instance, %#lx\n", hr
);
673 return ERROR_FUNCTION_FAILED
;
677 s
= SysAllocString( info
[i
].szPatchData
);
678 if (info
[i
].ePatchDataType
== MSIPATCH_DATATYPE_XMLPATH
)
682 V_VT(&src
) = VT_BSTR
;
684 hr
= IXMLDOMDocument_load( desc
, src
, &b
);
687 hr
= IXMLDOMDocument_loadXML( desc
, s
, &b
);
691 ERR("failed to parse patch description\n");
692 IXMLDOMDocument_Release( desc
);
696 if (MSI_ApplicablePatchXML( package
, desc
) != ERROR_SUCCESS
)
698 info
[i
].dwOrder
= ~0u;
699 info
[i
].uStatus
= ERROR_PATCH_TARGET_NOT_FOUND
;
704 info
[i
].uStatus
= ERROR_SUCCESS
;
710 FIXME("unknown patch data type %u\n", info
[i
].ePatchDataType
);
712 info
[i
].uStatus
= ERROR_SUCCESS
;
717 TRACE("szPatchData: %s\n", debugstr_w(info
[i
].szPatchData
));
718 TRACE("ePatchDataType: %u\n", info
[i
].ePatchDataType
);
719 TRACE("dwOrder: %lu\n", info
[i
].dwOrder
);
720 TRACE("uStatus: %u\n", info
[i
].uStatus
);
723 if (desc
) IXMLDOMDocument_Release( desc
);
725 return ERROR_SUCCESS
;
728 UINT WINAPI
MsiDetermineApplicablePatchesW( const WCHAR
*szProductPackagePath
, DWORD cPatchInfo
,
729 MSIPATCHSEQUENCEINFOW
*pPatchInfo
)
734 TRACE( "%s, %lu, %p\n", debugstr_w(szProductPackagePath
), cPatchInfo
, pPatchInfo
);
736 r
= MSI_OpenPackageW( szProductPackagePath
, 0, &package
);
737 if (r
!= ERROR_SUCCESS
)
739 ERR("failed to open package %u\n", r
);
742 r
= determine_patch_sequence( package
, cPatchInfo
, pPatchInfo
);
743 msiobj_release( &package
->hdr
);
747 UINT WINAPI
MsiDeterminePatchSequenceA( const char *product
, const char *usersid
, MSIINSTALLCONTEXT context
,
748 DWORD count
, MSIPATCHSEQUENCEINFOA
*patchinfo
)
751 WCHAR
*productW
, *usersidW
= NULL
;
752 MSIPATCHSEQUENCEINFOW
*patchinfoW
;
754 TRACE( "%s, %s, %d, %lu, %p\n", debugstr_a(product
), debugstr_a(usersid
), context
, count
, patchinfo
);
756 if (!product
) return ERROR_INVALID_PARAMETER
;
757 if (!(productW
= strdupAtoW( product
))) return ERROR_OUTOFMEMORY
;
758 if (usersid
&& !(usersidW
= strdupAtoW( usersid
)))
760 msi_free( productW
);
761 return ERROR_OUTOFMEMORY
;
763 if (!(patchinfoW
= patchinfoAtoW( count
, patchinfo
)))
765 msi_free( productW
);
766 msi_free( usersidW
);
767 return ERROR_OUTOFMEMORY
;
769 r
= MsiDeterminePatchSequenceW( productW
, usersidW
, context
, count
, patchinfoW
);
770 if (r
== ERROR_SUCCESS
)
772 for (i
= 0; i
< count
; i
++)
774 patchinfo
[i
].dwOrder
= patchinfoW
[i
].dwOrder
;
775 patchinfo
[i
].uStatus
= patchinfoW
[i
].uStatus
;
778 msi_free( productW
);
779 msi_free( usersidW
);
780 free_patchinfo( count
, patchinfoW
);
784 static UINT
open_package( const WCHAR
*product
, const WCHAR
*usersid
,
785 MSIINSTALLCONTEXT context
, MSIPACKAGE
**package
)
789 WCHAR
*localpath
, sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
791 r
= MSIREG_OpenInstallProps( product
, context
, usersid
, &props
, FALSE
);
792 if (r
!= ERROR_SUCCESS
) return ERROR_BAD_CONFIGURATION
;
794 if ((localpath
= msi_reg_get_val_str( props
, L
"LocalPackage" )))
796 lstrcpyW( sourcepath
, localpath
);
797 msi_free( localpath
);
799 RegCloseKey( props
);
800 if (!localpath
|| GetFileAttributesW( sourcepath
) == INVALID_FILE_ATTRIBUTES
)
802 DWORD sz
= sizeof(sourcepath
);
803 MsiSourceListGetInfoW( product
, usersid
, context
, MSICODE_PRODUCT
,
804 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
805 sz
= sizeof(filename
);
806 MsiSourceListGetInfoW( product
, usersid
, context
, MSICODE_PRODUCT
,
807 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
808 lstrcatW( sourcepath
, filename
);
810 if (GetFileAttributesW( sourcepath
) == INVALID_FILE_ATTRIBUTES
)
811 return ERROR_INSTALL_SOURCE_ABSENT
;
813 return MSI_OpenPackageW( sourcepath
, 0, package
);
816 UINT WINAPI
MsiDeterminePatchSequenceW( const WCHAR
*product
, const WCHAR
*usersid
, MSIINSTALLCONTEXT context
,
817 DWORD count
, MSIPATCHSEQUENCEINFOW
*patchinfo
)
822 TRACE( "%s, %s, %d, %lu, %p\n", debugstr_w(product
), debugstr_w(usersid
), context
, count
, patchinfo
);
824 if (!product
) return ERROR_INVALID_PARAMETER
;
825 r
= open_package( product
, usersid
, context
, &package
);
826 if (r
!= ERROR_SUCCESS
) return r
;
828 r
= determine_patch_sequence( package
, count
, patchinfo
);
829 msiobj_release( &package
->hdr
);
833 UINT WINAPI
MsiConfigureProductExW(LPCWSTR szProduct
, int iInstallLevel
,
834 INSTALLSTATE eInstallState
, LPCWSTR szCommandLine
)
836 MSIPACKAGE
* package
= NULL
;
837 MSIINSTALLCONTEXT context
;
840 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
843 TRACE("%s %d %d %s\n",debugstr_w(szProduct
), iInstallLevel
, eInstallState
,
844 debugstr_w(szCommandLine
));
846 if (!szProduct
|| lstrlenW(szProduct
) != GUID_SIZE
- 1)
847 return ERROR_INVALID_PARAMETER
;
849 if (eInstallState
== INSTALLSTATE_ADVERTISED
||
850 eInstallState
== INSTALLSTATE_SOURCE
)
852 FIXME("State %d not implemented\n", eInstallState
);
853 return ERROR_CALL_NOT_IMPLEMENTED
;
856 r
= msi_locate_product(szProduct
, &context
);
857 if (r
!= ERROR_SUCCESS
)
860 r
= open_package(szProduct
, NULL
, context
, &package
);
861 if (r
!= ERROR_SUCCESS
)
864 sz
= lstrlenW(L
" Installed=1") + 1;
867 sz
+= lstrlenW(szCommandLine
);
869 if (eInstallState
!= INSTALLSTATE_DEFAULT
)
870 sz
+= lstrlenW(L
" INSTALLLEVEL=32767");
872 if (eInstallState
== INSTALLSTATE_ABSENT
)
873 sz
+= lstrlenW(L
" REMOVE=ALL");
875 if (context
== MSIINSTALLCONTEXT_MACHINE
)
876 sz
+= lstrlenW(L
" ALLUSERS=1");
878 commandline
= msi_alloc(sz
* sizeof(WCHAR
));
881 r
= ERROR_OUTOFMEMORY
;
887 lstrcpyW(commandline
, szCommandLine
);
889 if (eInstallState
!= INSTALLSTATE_DEFAULT
)
890 lstrcatW(commandline
, L
" INSTALLLEVEL=32767");
892 if (eInstallState
== INSTALLSTATE_ABSENT
)
893 lstrcatW(commandline
, L
" REMOVE=ALL");
895 if (context
== MSIINSTALLCONTEXT_MACHINE
)
896 lstrcatW(commandline
, L
" ALLUSERS=1");
898 sz
= sizeof(sourcepath
);
899 MsiSourceListGetInfoW(szProduct
, NULL
, context
, MSICODE_PRODUCT
,
900 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
902 sz
= sizeof(filename
);
903 MsiSourceListGetInfoW(szProduct
, NULL
, context
, MSICODE_PRODUCT
,
904 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
906 lstrcatW(sourcepath
, filename
);
908 r
= MSI_InstallPackage( package
, sourcepath
, commandline
);
910 msi_free(commandline
);
913 msiobj_release( &package
->hdr
);
918 UINT WINAPI
MsiConfigureProductExA(LPCSTR szProduct
, int iInstallLevel
,
919 INSTALLSTATE eInstallState
, LPCSTR szCommandLine
)
921 LPWSTR szwProduct
= NULL
;
922 LPWSTR szwCommandLine
= NULL
;
923 UINT r
= ERROR_OUTOFMEMORY
;
927 szwProduct
= strdupAtoW( szProduct
);
934 szwCommandLine
= strdupAtoW( szCommandLine
);
939 r
= MsiConfigureProductExW( szwProduct
, iInstallLevel
, eInstallState
,
942 msi_free( szwProduct
);
943 msi_free( szwCommandLine
);
948 UINT WINAPI
MsiConfigureProductA(LPCSTR szProduct
, int iInstallLevel
,
949 INSTALLSTATE eInstallState
)
951 LPWSTR szwProduct
= NULL
;
954 TRACE("%s %d %d\n",debugstr_a(szProduct
), iInstallLevel
, eInstallState
);
958 szwProduct
= strdupAtoW( szProduct
);
960 return ERROR_OUTOFMEMORY
;
963 r
= MsiConfigureProductW( szwProduct
, iInstallLevel
, eInstallState
);
964 msi_free( szwProduct
);
969 UINT WINAPI
MsiConfigureProductW(LPCWSTR szProduct
, int iInstallLevel
,
970 INSTALLSTATE eInstallState
)
972 return MsiConfigureProductExW(szProduct
, iInstallLevel
, eInstallState
, NULL
);
975 UINT WINAPI
MsiGetProductCodeA(LPCSTR szComponent
, LPSTR szBuffer
)
977 LPWSTR szwComponent
= NULL
;
979 WCHAR szwBuffer
[GUID_SIZE
];
981 TRACE("%s %p\n", debugstr_a(szComponent
), szBuffer
);
985 szwComponent
= strdupAtoW( szComponent
);
987 return ERROR_OUTOFMEMORY
;
991 r
= MsiGetProductCodeW( szwComponent
, szwBuffer
);
994 WideCharToMultiByte(CP_ACP
, 0, szwBuffer
, -1, szBuffer
, GUID_SIZE
, NULL
, NULL
);
996 msi_free( szwComponent
);
1001 UINT WINAPI
MsiGetProductCodeW(LPCWSTR szComponent
, LPWSTR szBuffer
)
1004 HKEY compkey
, prodkey
;
1005 WCHAR squashed_comp
[SQUASHED_GUID_SIZE
], squashed_prod
[SQUASHED_GUID_SIZE
];
1006 DWORD sz
= ARRAY_SIZE(squashed_prod
);
1008 TRACE("%s %p\n", debugstr_w(szComponent
), szBuffer
);
1010 if (!szComponent
|| !*szComponent
)
1011 return ERROR_INVALID_PARAMETER
;
1013 if (!squash_guid( szComponent
, squashed_comp
))
1014 return ERROR_INVALID_PARAMETER
;
1016 if (MSIREG_OpenUserDataComponentKey(szComponent
, NULL
, &compkey
, FALSE
) != ERROR_SUCCESS
&&
1017 MSIREG_OpenUserDataComponentKey(szComponent
, L
"S-1-5-18", &compkey
, FALSE
) != ERROR_SUCCESS
)
1019 return ERROR_UNKNOWN_COMPONENT
;
1022 rc
= RegEnumValueW( compkey
, 0, squashed_prod
, &sz
, NULL
, NULL
, NULL
, NULL
);
1023 if (rc
!= ERROR_SUCCESS
)
1025 RegCloseKey(compkey
);
1026 return ERROR_UNKNOWN_COMPONENT
;
1029 /* check simple case, only one product */
1030 rc
= RegEnumValueW( compkey
, 1, squashed_prod
, &sz
, NULL
, NULL
, NULL
, NULL
);
1031 if (rc
== ERROR_NO_MORE_ITEMS
)
1038 while ((rc
= RegEnumValueW( compkey
, index
, squashed_prod
, &sz
, NULL
, NULL
, NULL
, NULL
)) !=
1039 ERROR_NO_MORE_ITEMS
)
1043 unsquash_guid( squashed_prod
, szBuffer
);
1045 if (MSIREG_OpenProductKey(szBuffer
, NULL
,
1046 MSIINSTALLCONTEXT_USERMANAGED
,
1047 &prodkey
, FALSE
) == ERROR_SUCCESS
||
1048 MSIREG_OpenProductKey(szBuffer
, NULL
,
1049 MSIINSTALLCONTEXT_USERUNMANAGED
,
1050 &prodkey
, FALSE
) == ERROR_SUCCESS
||
1051 MSIREG_OpenProductKey(szBuffer
, NULL
,
1052 MSIINSTALLCONTEXT_MACHINE
,
1053 &prodkey
, FALSE
) == ERROR_SUCCESS
)
1055 RegCloseKey(prodkey
);
1061 rc
= ERROR_INSTALL_FAILURE
;
1064 RegCloseKey(compkey
);
1065 unsquash_guid( squashed_prod
, szBuffer
);
1069 static WCHAR
*reg_get_value( HKEY hkey
, const WCHAR
*name
, DWORD
*type
)
1073 if ((res
= RegQueryValueExW( hkey
, name
, NULL
, type
, NULL
, NULL
)) != ERROR_SUCCESS
) return NULL
;
1075 if (*type
== REG_SZ
) return msi_reg_get_val_str( hkey
, name
);
1076 if (*type
== REG_DWORD
)
1081 if (!msi_reg_get_val_dword( hkey
, name
, &val
)) return NULL
;
1082 swprintf( temp
, ARRAY_SIZE(temp
), L
"%u", val
);
1083 return strdupW( temp
);
1086 ERR( "unhandled value type %lu\n", *type
);
1090 static UINT
MSI_GetProductInfo(LPCWSTR szProduct
, LPCWSTR szAttribute
,
1091 awstring
*szValue
, LPDWORD pcchValueBuf
)
1093 static WCHAR empty
[] = L
"";
1094 MSIINSTALLCONTEXT context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
1095 UINT r
= ERROR_UNKNOWN_PROPERTY
;
1096 HKEY prodkey
, userdata
, source
;
1097 WCHAR
*val
= NULL
, squashed_pc
[SQUASHED_GUID_SIZE
], packagecode
[GUID_SIZE
];
1098 BOOL badconfig
= FALSE
;
1100 DWORD type
= REG_NONE
;
1102 TRACE("%s %s %p %p\n", debugstr_w(szProduct
),
1103 debugstr_w(szAttribute
), szValue
, pcchValueBuf
);
1105 if ((szValue
->str
.w
&& !pcchValueBuf
) || !szProduct
|| !szAttribute
)
1106 return ERROR_INVALID_PARAMETER
;
1108 if (!squash_guid( szProduct
, squashed_pc
))
1109 return ERROR_INVALID_PARAMETER
;
1111 if ((r
= MSIREG_OpenProductKey(szProduct
, NULL
,
1112 MSIINSTALLCONTEXT_USERMANAGED
,
1113 &prodkey
, FALSE
)) != ERROR_SUCCESS
&&
1114 (r
= MSIREG_OpenProductKey(szProduct
, NULL
,
1115 MSIINSTALLCONTEXT_USERUNMANAGED
,
1116 &prodkey
, FALSE
)) != ERROR_SUCCESS
&&
1117 (r
= MSIREG_OpenProductKey(szProduct
, NULL
,
1118 MSIINSTALLCONTEXT_MACHINE
,
1119 &prodkey
, FALSE
)) == ERROR_SUCCESS
)
1121 context
= MSIINSTALLCONTEXT_MACHINE
;
1124 if (!wcscmp( szAttribute
, INSTALLPROPERTY_HELPLINKW
) ||
1125 !wcscmp( szAttribute
, INSTALLPROPERTY_HELPTELEPHONEW
) ||
1126 !wcscmp( szAttribute
, INSTALLPROPERTY_INSTALLDATEW
) ||
1127 !wcscmp( szAttribute
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
) ||
1128 !wcscmp( szAttribute
, INSTALLPROPERTY_INSTALLLOCATIONW
) ||
1129 !wcscmp( szAttribute
, INSTALLPROPERTY_INSTALLSOURCEW
) ||
1130 !wcscmp( szAttribute
, INSTALLPROPERTY_LOCALPACKAGEW
) ||
1131 !wcscmp( szAttribute
, INSTALLPROPERTY_PUBLISHERW
) ||
1132 !wcscmp( szAttribute
, INSTALLPROPERTY_URLINFOABOUTW
) ||
1133 !wcscmp( szAttribute
, INSTALLPROPERTY_URLUPDATEINFOW
) ||
1134 !wcscmp( szAttribute
, INSTALLPROPERTY_VERSIONMINORW
) ||
1135 !wcscmp( szAttribute
, INSTALLPROPERTY_VERSIONMAJORW
) ||
1136 !wcscmp( szAttribute
, INSTALLPROPERTY_VERSIONSTRINGW
) ||
1137 !wcscmp( szAttribute
, INSTALLPROPERTY_PRODUCTIDW
) ||
1138 !wcscmp( szAttribute
, INSTALLPROPERTY_REGCOMPANYW
) ||
1139 !wcscmp( szAttribute
, INSTALLPROPERTY_REGOWNERW
))
1143 r
= ERROR_UNKNOWN_PRODUCT
;
1146 if (MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &userdata
, FALSE
))
1148 r
= ERROR_UNKNOWN_PROPERTY
;
1152 if (!wcscmp( szAttribute
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
))
1153 szAttribute
= L
"DisplayName";
1154 else if (!wcscmp( szAttribute
, INSTALLPROPERTY_VERSIONSTRINGW
))
1155 szAttribute
= L
"DisplayVersion";
1157 val
= reg_get_value(userdata
, szAttribute
, &type
);
1160 RegCloseKey(userdata
);
1162 else if (!wcscmp( szAttribute
, INSTALLPROPERTY_INSTANCETYPEW
) ||
1163 !wcscmp( szAttribute
, INSTALLPROPERTY_TRANSFORMSW
) ||
1164 !wcscmp( szAttribute
, INSTALLPROPERTY_LANGUAGEW
) ||
1165 !wcscmp( szAttribute
, INSTALLPROPERTY_PRODUCTNAMEW
) ||
1166 !wcscmp( szAttribute
, INSTALLPROPERTY_ASSIGNMENTTYPEW
) ||
1167 !wcscmp( szAttribute
, INSTALLPROPERTY_PACKAGECODEW
) ||
1168 !wcscmp( szAttribute
, INSTALLPROPERTY_VERSIONW
) ||
1169 !wcscmp( szAttribute
, INSTALLPROPERTY_PRODUCTICONW
) ||
1170 !wcscmp( szAttribute
, INSTALLPROPERTY_PACKAGENAMEW
) ||
1171 !wcscmp( szAttribute
, INSTALLPROPERTY_AUTHORIZED_LUA_APPW
))
1175 r
= ERROR_UNKNOWN_PRODUCT
;
1179 if (!wcscmp( szAttribute
, INSTALLPROPERTY_ASSIGNMENTTYPEW
))
1180 szAttribute
= L
"Assignment";
1182 if (!wcscmp( szAttribute
, INSTALLPROPERTY_PACKAGENAMEW
))
1184 res
= RegOpenKeyW(prodkey
, L
"SourceList", &source
);
1185 if (res
!= ERROR_SUCCESS
)
1187 r
= ERROR_UNKNOWN_PRODUCT
;
1191 val
= reg_get_value(source
, szAttribute
, &type
);
1195 RegCloseKey(source
);
1199 val
= reg_get_value(prodkey
, szAttribute
, &type
);
1204 if (val
!= empty
&& type
!= REG_DWORD
&&
1205 !wcscmp( szAttribute
, INSTALLPROPERTY_PACKAGECODEW
))
1207 if (lstrlenW( val
) != SQUASHED_GUID_SIZE
- 1)
1211 unsquash_guid(val
, packagecode
);
1213 val
= strdupW(packagecode
);
1220 r
= ERROR_UNKNOWN_PROPERTY
;
1226 int len
= lstrlenW( val
);
1228 /* If szBuffer (szValue->str) is NULL, there's no need to copy the value
1229 * out. Also, *pcchValueBuf may be uninitialized in this case, so we
1230 * can't rely on its value.
1232 if (szValue
->str
.a
|| szValue
->str
.w
)
1234 DWORD size
= *pcchValueBuf
;
1236 r
= msi_strcpy_to_awstring( val
, len
, szValue
, &size
);
1238 r
= ERROR_MORE_DATA
;
1242 *pcchValueBuf
= len
;
1246 r
= ERROR_BAD_CONFIGURATION
;
1252 RegCloseKey(prodkey
);
1256 UINT WINAPI
MsiGetProductInfoA(LPCSTR szProduct
, LPCSTR szAttribute
,
1257 LPSTR szBuffer
, LPDWORD pcchValueBuf
)
1259 LPWSTR szwProduct
, szwAttribute
= NULL
;
1260 UINT r
= ERROR_OUTOFMEMORY
;
1263 TRACE("%s %s %p %p\n", debugstr_a(szProduct
), debugstr_a(szAttribute
),
1264 szBuffer
, pcchValueBuf
);
1266 szwProduct
= strdupAtoW( szProduct
);
1267 if( szProduct
&& !szwProduct
)
1270 szwAttribute
= strdupAtoW( szAttribute
);
1271 if( szAttribute
&& !szwAttribute
)
1274 buffer
.unicode
= FALSE
;
1275 buffer
.str
.a
= szBuffer
;
1277 r
= MSI_GetProductInfo( szwProduct
, szwAttribute
,
1278 &buffer
, pcchValueBuf
);
1281 msi_free( szwProduct
);
1282 msi_free( szwAttribute
);
1287 UINT WINAPI
MsiGetProductInfoW(LPCWSTR szProduct
, LPCWSTR szAttribute
,
1288 LPWSTR szBuffer
, LPDWORD pcchValueBuf
)
1292 TRACE("%s %s %p %p\n", debugstr_w(szProduct
), debugstr_w(szAttribute
),
1293 szBuffer
, pcchValueBuf
);
1295 buffer
.unicode
= TRUE
;
1296 buffer
.str
.w
= szBuffer
;
1298 return MSI_GetProductInfo( szProduct
, szAttribute
,
1299 &buffer
, pcchValueBuf
);
1302 UINT WINAPI
MsiGetProductInfoExA(LPCSTR szProductCode
, LPCSTR szUserSid
,
1303 MSIINSTALLCONTEXT dwContext
, LPCSTR szProperty
,
1304 LPSTR szValue
, LPDWORD pcchValue
)
1306 LPWSTR product
= NULL
;
1307 LPWSTR usersid
= NULL
;
1308 LPWSTR property
= NULL
;
1309 LPWSTR value
= NULL
;
1313 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode
),
1314 debugstr_a(szUserSid
), dwContext
, debugstr_a(szProperty
),
1315 szValue
, pcchValue
);
1317 if (szValue
&& !pcchValue
)
1318 return ERROR_INVALID_PARAMETER
;
1320 if (szProductCode
) product
= strdupAtoW(szProductCode
);
1321 if (szUserSid
) usersid
= strdupAtoW(szUserSid
);
1322 if (szProperty
) property
= strdupAtoW(szProperty
);
1324 r
= MsiGetProductInfoExW(product
, usersid
, dwContext
, property
,
1326 if (r
!= ERROR_SUCCESS
)
1329 value
= msi_alloc(++len
* sizeof(WCHAR
));
1332 r
= ERROR_OUTOFMEMORY
;
1336 r
= MsiGetProductInfoExW(product
, usersid
, dwContext
, property
,
1338 if (r
!= ERROR_SUCCESS
)
1344 len
= WideCharToMultiByte(CP_ACP
, 0, value
, -1, NULL
, 0, NULL
, NULL
);
1345 if (*pcchValue
>= len
)
1346 WideCharToMultiByte(CP_ACP
, 0, value
, -1, szValue
, len
, NULL
, NULL
);
1349 r
= ERROR_MORE_DATA
;
1354 if (*pcchValue
<= len
|| !szValue
)
1355 len
= len
* sizeof(WCHAR
) - 1;
1357 *pcchValue
= len
- 1;
1368 static UINT
msi_copy_outval(LPWSTR val
, LPWSTR out
, LPDWORD size
)
1370 UINT r
= ERROR_SUCCESS
;
1373 return ERROR_UNKNOWN_PROPERTY
;
1377 if (lstrlenW(val
) >= *size
)
1379 r
= ERROR_MORE_DATA
;
1388 *size
= lstrlenW(val
);
1393 UINT WINAPI
MsiGetProductInfoExW(LPCWSTR szProductCode
, LPCWSTR szUserSid
,
1394 MSIINSTALLCONTEXT dwContext
, LPCWSTR szProperty
,
1395 LPWSTR szValue
, LPDWORD pcchValue
)
1397 WCHAR
*val
= NULL
, squashed_pc
[SQUASHED_GUID_SIZE
];
1398 LPCWSTR package
= NULL
;
1399 HKEY props
= NULL
, prod
, classes
= NULL
, managed
, hkey
= NULL
;
1401 UINT r
= ERROR_UNKNOWN_PRODUCT
;
1403 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode
),
1404 debugstr_w(szUserSid
), dwContext
, debugstr_w(szProperty
),
1405 szValue
, pcchValue
);
1407 if (!szProductCode
|| !squash_guid( szProductCode
, squashed_pc
))
1408 return ERROR_INVALID_PARAMETER
;
1410 if (szValue
&& !pcchValue
)
1411 return ERROR_INVALID_PARAMETER
;
1413 if (dwContext
!= MSIINSTALLCONTEXT_USERUNMANAGED
&&
1414 dwContext
!= MSIINSTALLCONTEXT_USERMANAGED
&&
1415 dwContext
!= MSIINSTALLCONTEXT_MACHINE
)
1416 return ERROR_INVALID_PARAMETER
;
1418 if (!szProperty
|| !*szProperty
)
1419 return ERROR_INVALID_PARAMETER
;
1421 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
&& szUserSid
)
1422 return ERROR_INVALID_PARAMETER
;
1424 /* FIXME: dwContext is provided, no need to search for it */
1425 MSIREG_OpenProductKey(szProductCode
, NULL
,MSIINSTALLCONTEXT_USERMANAGED
,
1427 MSIREG_OpenProductKey(szProductCode
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
1430 MSIREG_OpenInstallProps(szProductCode
, dwContext
, NULL
, &props
, FALSE
);
1432 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
1434 package
= INSTALLPROPERTY_LOCALPACKAGEW
;
1436 if (!props
&& !prod
)
1439 else if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1441 package
= L
"ManagedLocalPackage";
1443 if (!props
&& !managed
)
1446 else if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1448 package
= INSTALLPROPERTY_LOCALPACKAGEW
;
1449 MSIREG_OpenProductKey(szProductCode
, NULL
, dwContext
, &classes
, FALSE
);
1451 if (!props
&& !classes
)
1455 if (!wcscmp( szProperty
, INSTALLPROPERTY_HELPLINKW
) ||
1456 !wcscmp( szProperty
, INSTALLPROPERTY_HELPTELEPHONEW
) ||
1457 !wcscmp( szProperty
, INSTALLPROPERTY_INSTALLDATEW
) ||
1458 !wcscmp( szProperty
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
) ||
1459 !wcscmp( szProperty
, INSTALLPROPERTY_INSTALLLOCATIONW
) ||
1460 !wcscmp( szProperty
, INSTALLPROPERTY_INSTALLSOURCEW
) ||
1461 !wcscmp( szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
) ||
1462 !wcscmp( szProperty
, INSTALLPROPERTY_PUBLISHERW
) ||
1463 !wcscmp( szProperty
, INSTALLPROPERTY_URLINFOABOUTW
) ||
1464 !wcscmp( szProperty
, INSTALLPROPERTY_URLUPDATEINFOW
) ||
1465 !wcscmp( szProperty
, INSTALLPROPERTY_VERSIONMINORW
) ||
1466 !wcscmp( szProperty
, INSTALLPROPERTY_VERSIONMAJORW
) ||
1467 !wcscmp( szProperty
, INSTALLPROPERTY_VERSIONSTRINGW
) ||
1468 !wcscmp( szProperty
, INSTALLPROPERTY_PRODUCTIDW
) ||
1469 !wcscmp( szProperty
, INSTALLPROPERTY_REGCOMPANYW
) ||
1470 !wcscmp( szProperty
, INSTALLPROPERTY_REGOWNERW
) ||
1471 !wcscmp( szProperty
, INSTALLPROPERTY_INSTANCETYPEW
))
1473 val
= reg_get_value(props
, package
, &type
);
1476 if (prod
|| classes
)
1477 r
= ERROR_UNKNOWN_PROPERTY
;
1484 if (!wcscmp( szProperty
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
))
1485 szProperty
= L
"DisplayName";
1486 else if (!wcscmp( szProperty
, INSTALLPROPERTY_VERSIONSTRINGW
))
1487 szProperty
= L
"DisplayVersion";
1489 val
= reg_get_value(props
, szProperty
, &type
);
1493 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1495 else if (!wcscmp( szProperty
, INSTALLPROPERTY_TRANSFORMSW
) ||
1496 !wcscmp( szProperty
, INSTALLPROPERTY_LANGUAGEW
) ||
1497 !wcscmp( szProperty
, INSTALLPROPERTY_PRODUCTNAMEW
) ||
1498 !wcscmp( szProperty
, INSTALLPROPERTY_PACKAGECODEW
) ||
1499 !wcscmp( szProperty
, INSTALLPROPERTY_VERSIONW
) ||
1500 !wcscmp( szProperty
, INSTALLPROPERTY_PRODUCTICONW
) ||
1501 !wcscmp( szProperty
, INSTALLPROPERTY_PACKAGENAMEW
) ||
1502 !wcscmp( szProperty
, INSTALLPROPERTY_AUTHORIZED_LUA_APPW
))
1504 if (!prod
&& !classes
)
1507 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
1509 else if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1511 else if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1514 val
= reg_get_value(hkey
, szProperty
, &type
);
1518 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1520 else if (!wcscmp( szProperty
, INSTALLPROPERTY_PRODUCTSTATEW
))
1522 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1526 val
= reg_get_value(props
, package
, &type
);
1531 val
= strdupW(L
"5");
1534 val
= strdupW(L
"1");
1536 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1539 else if (props
&& (val
= reg_get_value(props
, package
, &type
)))
1542 val
= strdupW(L
"5");
1543 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1547 if (prod
|| managed
)
1548 val
= strdupW(L
"1");
1552 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1554 else if (!wcscmp( szProperty
, INSTALLPROPERTY_ASSIGNMENTTYPEW
))
1556 if (!prod
&& !classes
)
1561 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1564 r
= ERROR_UNKNOWN_PROPERTY
;
1569 RegCloseKey(managed
);
1570 RegCloseKey(classes
);
1576 UINT WINAPI
MsiGetPatchFileListA(LPCSTR szProductCode
, LPCSTR szPatchList
,
1577 LPDWORD pcFiles
, MSIHANDLE
**pphFileRecords
)
1579 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_a(szProductCode
),
1580 debugstr_a(szPatchList
), pcFiles
, pphFileRecords
);
1581 return ERROR_FUNCTION_FAILED
;
1584 UINT WINAPI
MsiGetPatchFileListW(LPCWSTR szProductCode
, LPCWSTR szPatchList
,
1585 LPDWORD pcFiles
, MSIHANDLE
**pphFileRecords
)
1587 FIXME("(%s, %s, %p, %p) stub!\n", debugstr_w(szProductCode
),
1588 debugstr_w(szPatchList
), pcFiles
, pphFileRecords
);
1589 return ERROR_FUNCTION_FAILED
;
1592 UINT WINAPI
MsiGetPatchInfoExA(LPCSTR szPatchCode
, LPCSTR szProductCode
,
1593 LPCSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1594 LPCSTR szProperty
, LPSTR lpValue
, DWORD
*pcchValue
)
1596 LPWSTR patch
= NULL
, product
= NULL
, usersid
= NULL
;
1597 LPWSTR property
= NULL
, val
= NULL
;
1601 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode
),
1602 debugstr_a(szProductCode
), debugstr_a(szUserSid
), dwContext
,
1603 debugstr_a(szProperty
), lpValue
, pcchValue
);
1605 if (lpValue
&& !pcchValue
)
1606 return ERROR_INVALID_PARAMETER
;
1608 if (szPatchCode
) patch
= strdupAtoW(szPatchCode
);
1609 if (szProductCode
) product
= strdupAtoW(szProductCode
);
1610 if (szUserSid
) usersid
= strdupAtoW(szUserSid
);
1611 if (szProperty
) property
= strdupAtoW(szProperty
);
1614 r
= MsiGetPatchInfoExW(patch
, product
, usersid
, dwContext
, property
,
1616 if (r
!= ERROR_SUCCESS
)
1619 val
= msi_alloc(++len
* sizeof(WCHAR
));
1622 r
= ERROR_OUTOFMEMORY
;
1626 r
= MsiGetPatchInfoExW(patch
, product
, usersid
, dwContext
, property
,
1628 if (r
!= ERROR_SUCCESS
|| !pcchValue
)
1632 WideCharToMultiByte(CP_ACP
, 0, val
, -1, lpValue
,
1633 *pcchValue
- 1, NULL
, NULL
);
1635 len
= lstrlenW(val
);
1636 if ((*val
&& *pcchValue
< len
+ 1) || !lpValue
)
1640 r
= ERROR_MORE_DATA
;
1641 lpValue
[*pcchValue
- 1] = '\0';
1644 *pcchValue
= len
* sizeof(WCHAR
);
1659 UINT WINAPI
MsiGetPatchInfoExW(LPCWSTR szPatchCode
, LPCWSTR szProductCode
,
1660 LPCWSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1661 LPCWSTR szProperty
, LPWSTR lpValue
, DWORD
*pcchValue
)
1663 WCHAR
*val
= NULL
, squashed_pc
[SQUASHED_GUID_SIZE
], squashed_patch
[SQUASHED_GUID_SIZE
];
1664 HKEY udprod
= 0, prod
= 0, props
= 0;
1665 HKEY patch
= 0, patches
= 0;
1666 HKEY udpatch
= 0, datakey
= 0;
1667 HKEY prodpatches
= 0;
1668 UINT r
= ERROR_UNKNOWN_PRODUCT
;
1672 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode
),
1673 debugstr_w(szProductCode
), debugstr_w(szUserSid
), dwContext
,
1674 debugstr_w(szProperty
), lpValue
, pcchValue
);
1676 if (!szProductCode
|| !squash_guid( szProductCode
, squashed_pc
))
1677 return ERROR_INVALID_PARAMETER
;
1679 if (!szPatchCode
|| !squash_guid( szPatchCode
, squashed_patch
))
1680 return ERROR_INVALID_PARAMETER
;
1683 return ERROR_INVALID_PARAMETER
;
1685 if (lpValue
&& !pcchValue
)
1686 return ERROR_INVALID_PARAMETER
;
1688 if (dwContext
!= MSIINSTALLCONTEXT_USERMANAGED
&&
1689 dwContext
!= MSIINSTALLCONTEXT_USERUNMANAGED
&&
1690 dwContext
!= MSIINSTALLCONTEXT_MACHINE
)
1691 return ERROR_INVALID_PARAMETER
;
1693 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
&& szUserSid
)
1694 return ERROR_INVALID_PARAMETER
;
1696 if (szUserSid
&& !wcscmp( szUserSid
, L
"S-1-5-18" ))
1697 return ERROR_INVALID_PARAMETER
;
1699 if (MSIREG_OpenUserDataProductKey(szProductCode
, dwContext
, NULL
,
1700 &udprod
, FALSE
) != ERROR_SUCCESS
)
1703 if (MSIREG_OpenInstallProps(szProductCode
, dwContext
, NULL
,
1704 &props
, FALSE
) != ERROR_SUCCESS
)
1707 r
= ERROR_UNKNOWN_PATCH
;
1709 res
= RegOpenKeyExW(udprod
, L
"Patches", 0, KEY_READ
, &patches
);
1710 if (res
!= ERROR_SUCCESS
)
1713 res
= RegOpenKeyExW( patches
, squashed_patch
, 0, KEY_READ
, &patch
);
1714 if (res
!= ERROR_SUCCESS
)
1717 if (!wcscmp( szProperty
, INSTALLPROPERTY_TRANSFORMSW
))
1719 if (MSIREG_OpenProductKey(szProductCode
, NULL
, dwContext
,
1720 &prod
, FALSE
) != ERROR_SUCCESS
)
1723 res
= RegOpenKeyExW(prod
, L
"Patches", 0, KEY_ALL_ACCESS
, &prodpatches
);
1724 if (res
!= ERROR_SUCCESS
)
1727 datakey
= prodpatches
;
1728 szProperty
= squashed_patch
;
1732 if (MSIREG_OpenUserDataPatchKey(szPatchCode
, dwContext
,
1733 &udpatch
, FALSE
) != ERROR_SUCCESS
)
1736 if (!wcscmp( szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
))
1738 if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1739 szProperty
= L
"ManagedLocalPackage";
1742 else if (!wcscmp( szProperty
, INSTALLPROPERTY_INSTALLDATEW
))
1745 szProperty
= L
"Installed";
1747 else if (!wcscmp( szProperty
, INSTALLPROPERTY_UNINSTALLABLEW
) ||
1748 !wcscmp( szProperty
, INSTALLPROPERTY_PATCHSTATEW
) ||
1749 !wcscmp( szProperty
, INSTALLPROPERTY_DISPLAYNAMEW
) ||
1750 !wcscmp( szProperty
, INSTALLPROPERTY_MOREINFOURLW
))
1756 r
= ERROR_UNKNOWN_PROPERTY
;
1761 val
= reg_get_value(datakey
, szProperty
, &type
);
1771 lstrcpynW(lpValue
, val
, *pcchValue
);
1773 len
= lstrlenW(val
);
1774 if ((*val
&& *pcchValue
< len
+ 1) || !lpValue
)
1777 r
= ERROR_MORE_DATA
;
1779 *pcchValue
= len
* sizeof(WCHAR
);
1786 RegCloseKey(prodpatches
);
1789 RegCloseKey(patches
);
1790 RegCloseKey(udpatch
);
1792 RegCloseKey(udprod
);
1797 UINT WINAPI
MsiGetPatchInfoA( LPCSTR patch
, LPCSTR attr
, LPSTR buffer
, LPDWORD buflen
)
1799 UINT r
= ERROR_OUTOFMEMORY
;
1801 LPWSTR patchW
= NULL
, attrW
= NULL
, bufferW
= NULL
;
1803 TRACE("%s %s %p %p\n", debugstr_a(patch
), debugstr_a(attr
), buffer
, buflen
);
1805 if (!patch
|| !attr
)
1806 return ERROR_INVALID_PARAMETER
;
1808 if (!(patchW
= strdupAtoW( patch
)))
1811 if (!(attrW
= strdupAtoW( attr
)))
1815 r
= MsiGetPatchInfoW( patchW
, attrW
, NULL
, &size
);
1816 if (r
!= ERROR_SUCCESS
)
1820 if (!(bufferW
= msi_alloc( size
* sizeof(WCHAR
) )))
1822 r
= ERROR_OUTOFMEMORY
;
1826 r
= MsiGetPatchInfoW( patchW
, attrW
, bufferW
, &size
);
1827 if (r
== ERROR_SUCCESS
)
1829 int len
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1831 r
= ERROR_MORE_DATA
;
1833 WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, buffer
, *buflen
, NULL
, NULL
);
1841 msi_free( bufferW
);
1845 UINT WINAPI
MsiGetPatchInfoW( LPCWSTR patch
, LPCWSTR attr
, LPWSTR buffer
, LPDWORD buflen
)
1848 WCHAR product
[GUID_SIZE
];
1851 TRACE("%s %s %p %p\n", debugstr_w(patch
), debugstr_w(attr
), buffer
, buflen
);
1853 if (!patch
|| !attr
)
1854 return ERROR_INVALID_PARAMETER
;
1856 if (wcscmp( INSTALLPROPERTY_LOCALPACKAGEW
, attr
))
1857 return ERROR_UNKNOWN_PROPERTY
;
1862 r
= MsiEnumProductsW( index
, product
);
1863 if (r
!= ERROR_SUCCESS
)
1866 r
= MsiGetPatchInfoExW( patch
, product
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
, attr
, buffer
, buflen
);
1867 if (r
== ERROR_SUCCESS
|| r
== ERROR_MORE_DATA
)
1870 r
= MsiGetPatchInfoExW( patch
, product
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
, attr
, buffer
, buflen
);
1871 if (r
== ERROR_SUCCESS
|| r
== ERROR_MORE_DATA
)
1874 r
= MsiGetPatchInfoExW( patch
, product
, NULL
, MSIINSTALLCONTEXT_MACHINE
, attr
, buffer
, buflen
);
1875 if (r
== ERROR_SUCCESS
|| r
== ERROR_MORE_DATA
)
1881 return ERROR_UNKNOWN_PRODUCT
;
1884 UINT WINAPI
MsiEnableLogA( DWORD dwLogMode
, const char *szLogFile
, DWORD attributes
)
1886 LPWSTR szwLogFile
= NULL
;
1889 TRACE( "%#lx, %s, %#lx\n", dwLogMode
, debugstr_a(szLogFile
), attributes
);
1893 szwLogFile
= strdupAtoW( szLogFile
);
1895 return ERROR_OUTOFMEMORY
;
1897 r
= MsiEnableLogW( dwLogMode
, szwLogFile
, attributes
);
1898 msi_free( szwLogFile
);
1902 UINT WINAPI
MsiEnableLogW( DWORD dwLogMode
, const WCHAR
*szLogFile
, DWORD attributes
)
1904 TRACE( "%#lx, %s, %#lx\n", dwLogMode
, debugstr_w(szLogFile
), attributes
);
1906 msi_free(gszLogFile
);
1912 if (!(attributes
& INSTALLLOGATTRIBUTES_APPEND
))
1913 DeleteFileW(szLogFile
);
1914 file
= CreateFileW(szLogFile
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
, OPEN_ALWAYS
,
1915 FILE_ATTRIBUTE_NORMAL
, NULL
);
1916 if (file
!= INVALID_HANDLE_VALUE
)
1918 gszLogFile
= strdupW(szLogFile
);
1921 else ERR( "unable to enable log %s (%lu)\n", debugstr_w(szLogFile
), GetLastError() );
1924 return ERROR_SUCCESS
;
1927 UINT WINAPI
MsiEnumComponentCostsA( MSIHANDLE handle
, const char *component
, DWORD index
, INSTALLSTATE state
,
1928 char *drive
, DWORD
*buflen
, int *cost
, int *temp
)
1932 WCHAR
*driveW
, *componentW
= NULL
;
1934 TRACE( "%lu, %s, %lu, %d, %p, %p, %p, %p\n", handle
, debugstr_a(component
), index
, state
, drive
, buflen
, cost
,
1937 if (!drive
|| !buflen
) return ERROR_INVALID_PARAMETER
;
1938 if (component
&& !(componentW
= strdupAtoW( component
))) return ERROR_OUTOFMEMORY
;
1941 if (!(driveW
= msi_alloc( len
* sizeof(WCHAR
) )))
1943 msi_free( componentW
);
1944 return ERROR_OUTOFMEMORY
;
1946 r
= MsiEnumComponentCostsW( handle
, componentW
, index
, state
, driveW
, buflen
, cost
, temp
);
1949 WideCharToMultiByte( CP_ACP
, 0, driveW
, -1, drive
, len
, NULL
, NULL
);
1951 msi_free( componentW
);
1956 static UINT
set_drive( WCHAR
*buffer
, WCHAR letter
)
1964 UINT WINAPI
MsiEnumComponentCostsW( MSIHANDLE handle
, const WCHAR
*component
, DWORD index
, INSTALLSTATE state
,
1965 WCHAR
*drive
, DWORD
*buflen
, int *cost
, int *temp
)
1967 UINT r
= ERROR_NO_MORE_ITEMS
;
1968 MSICOMPONENT
*comp
= NULL
;
1969 MSIPACKAGE
*package
;
1972 WCHAR path
[MAX_PATH
];
1974 TRACE( "%lu, %s, %lu, %d, %p, %p, %p, %p\n", handle
, debugstr_w(component
), index
, state
, drive
, buflen
, cost
,
1977 if (!drive
|| !buflen
|| !cost
|| !temp
) return ERROR_INVALID_PARAMETER
;
1978 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
1983 if (!(remote
= msi_get_remote(handle
)))
1984 return ERROR_INVALID_HANDLE
;
1988 r
= remote_EnumComponentCosts(remote
, component
, index
, state
, buffer
, cost
, temp
);
1990 __EXCEPT(rpc_filter
)
1992 r
= GetExceptionCode();
1996 if (r
== ERROR_SUCCESS
)
1998 lstrcpynW(drive
, buffer
, *buflen
);
2000 r
= ERROR_MORE_DATA
;
2006 if (!msi_get_property_int( package
->db
, L
"CostingComplete", 0 ))
2008 msiobj_release( &package
->hdr
);
2009 return ERROR_FUNCTION_NOT_CALLED
;
2011 if (component
&& component
[0] && !(comp
= msi_get_loaded_component( package
, component
)))
2013 msiobj_release( &package
->hdr
);
2014 return ERROR_UNKNOWN_COMPONENT
;
2019 msiobj_release( &package
->hdr
);
2020 return ERROR_MORE_DATA
;
2024 msiobj_release( &package
->hdr
);
2025 return ERROR_NO_MORE_ITEMS
;
2030 GetWindowsDirectoryW( path
, MAX_PATH
);
2031 if (component
&& component
[0])
2033 if (msi_is_global_assembly( comp
)) *temp
= comp
->Cost
;
2034 if (!comp
->Enabled
|| !comp
->KeyPath
)
2037 *buflen
= set_drive( drive
, path
[0] );
2040 else if ((file
= msi_get_loaded_file( package
, comp
->KeyPath
)))
2042 *cost
= max( 8, comp
->Cost
/ 512 );
2043 *buflen
= set_drive( drive
, file
->TargetPath
[0] );
2047 else if (IStorage_Stat( package
->db
->storage
, &stat
, STATFLAG_NONAME
) == S_OK
)
2049 *temp
= max( 8, stat
.cbSize
.QuadPart
/ 512 );
2050 *buflen
= set_drive( drive
, path
[0] );
2053 msiobj_release( &package
->hdr
);
2057 UINT WINAPI
MsiQueryComponentStateA(LPCSTR szProductCode
,
2058 LPCSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
2059 LPCSTR szComponent
, INSTALLSTATE
*pdwState
)
2061 LPWSTR prodcode
= NULL
, usersid
= NULL
, comp
= NULL
;
2064 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode
),
2065 debugstr_a(szUserSid
), dwContext
, debugstr_a(szComponent
), pdwState
);
2067 if (szProductCode
&& !(prodcode
= strdupAtoW(szProductCode
)))
2068 return ERROR_OUTOFMEMORY
;
2070 if (szUserSid
&& !(usersid
= strdupAtoW(szUserSid
)))
2071 return ERROR_OUTOFMEMORY
;
2073 if (szComponent
&& !(comp
= strdupAtoW(szComponent
)))
2074 return ERROR_OUTOFMEMORY
;
2076 r
= MsiQueryComponentStateW(prodcode
, usersid
, dwContext
, comp
, pdwState
);
2085 static BOOL
msi_comp_find_prod_key(LPCWSTR prodcode
, MSIINSTALLCONTEXT context
)
2090 r
= MSIREG_OpenProductKey(prodcode
, NULL
, context
, &hkey
, FALSE
);
2092 return (r
== ERROR_SUCCESS
);
2095 static BOOL
msi_comp_find_package(LPCWSTR prodcode
, MSIINSTALLCONTEXT context
)
2103 r
= MSIREG_OpenInstallProps(prodcode
, context
, NULL
, &hkey
, FALSE
);
2104 if (r
!= ERROR_SUCCESS
)
2107 if (context
== MSIINSTALLCONTEXT_USERMANAGED
)
2108 package
= L
"ManagedLocalPackage";
2110 package
= L
"LocalPackage";
2113 res
= RegQueryValueExW(hkey
, package
, NULL
, NULL
, NULL
, &sz
);
2116 return (res
== ERROR_SUCCESS
);
2119 static UINT
msi_comp_find_prodcode(WCHAR
*squashed_pc
,
2120 MSIINSTALLCONTEXT context
,
2121 LPCWSTR comp
, LPWSTR val
, DWORD
*sz
)
2127 if (context
== MSIINSTALLCONTEXT_MACHINE
)
2128 r
= MSIREG_OpenUserDataComponentKey(comp
, L
"S-1-5-18", &hkey
, FALSE
);
2130 r
= MSIREG_OpenUserDataComponentKey(comp
, NULL
, &hkey
, FALSE
);
2132 if (r
!= ERROR_SUCCESS
)
2135 res
= RegQueryValueExW( hkey
, squashed_pc
, NULL
, NULL
, (BYTE
*)val
, sz
);
2136 if (res
!= ERROR_SUCCESS
)
2143 UINT WINAPI
MsiQueryComponentStateW(LPCWSTR szProductCode
,
2144 LPCWSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
2145 LPCWSTR szComponent
, INSTALLSTATE
*pdwState
)
2147 WCHAR squashed_pc
[SQUASHED_GUID_SIZE
];
2151 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode
),
2152 debugstr_w(szUserSid
), dwContext
, debugstr_w(szComponent
), pdwState
);
2154 if (!pdwState
|| !szComponent
)
2155 return ERROR_INVALID_PARAMETER
;
2157 if (!szProductCode
|| !*szProductCode
|| lstrlenW(szProductCode
) != GUID_SIZE
- 1)
2158 return ERROR_INVALID_PARAMETER
;
2160 if (!squash_guid( szProductCode
, squashed_pc
))
2161 return ERROR_INVALID_PARAMETER
;
2163 found
= msi_comp_find_prod_key(szProductCode
, dwContext
);
2165 if (!msi_comp_find_package(szProductCode
, dwContext
))
2169 *pdwState
= INSTALLSTATE_UNKNOWN
;
2170 return ERROR_UNKNOWN_COMPONENT
;
2173 return ERROR_UNKNOWN_PRODUCT
;
2176 *pdwState
= INSTALLSTATE_UNKNOWN
;
2179 if (msi_comp_find_prodcode( squashed_pc
, dwContext
, szComponent
, NULL
, &sz
))
2180 return ERROR_UNKNOWN_COMPONENT
;
2183 *pdwState
= INSTALLSTATE_NOTUSED
;
2189 if (!(val
= msi_alloc( sz
))) return ERROR_OUTOFMEMORY
;
2190 if ((r
= msi_comp_find_prodcode( squashed_pc
, dwContext
, szComponent
, val
, &sz
)))
2196 if (lstrlenW(val
) > 2 &&
2197 val
[0] >= '0' && val
[0] <= '9' && val
[1] >= '0' && val
[1] <= '9' && val
[2] != ':')
2199 *pdwState
= INSTALLSTATE_SOURCE
;
2202 *pdwState
= INSTALLSTATE_LOCAL
;
2206 TRACE("-> %d\n", *pdwState
);
2207 return ERROR_SUCCESS
;
2210 INSTALLSTATE WINAPI
MsiQueryProductStateA(LPCSTR szProduct
)
2212 LPWSTR szwProduct
= NULL
;
2217 szwProduct
= strdupAtoW( szProduct
);
2219 return ERROR_OUTOFMEMORY
;
2221 r
= MsiQueryProductStateW( szwProduct
);
2222 msi_free( szwProduct
);
2226 INSTALLSTATE WINAPI
MsiQueryProductStateW(LPCWSTR szProduct
)
2228 MSIINSTALLCONTEXT context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
2229 INSTALLSTATE state
= INSTALLSTATE_ADVERTISED
;
2230 HKEY prodkey
= 0, userdata
= 0;
2234 TRACE("%s\n", debugstr_w(szProduct
));
2236 if (!szProduct
|| !*szProduct
)
2237 return INSTALLSTATE_INVALIDARG
;
2239 if (lstrlenW(szProduct
) != GUID_SIZE
- 1)
2240 return INSTALLSTATE_INVALIDARG
;
2242 if (szProduct
[0] != '{' || szProduct
[37] != '}')
2243 return INSTALLSTATE_UNKNOWN
;
2245 SetLastError( ERROR_SUCCESS
);
2247 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
2248 &prodkey
, FALSE
) != ERROR_SUCCESS
&&
2249 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
2250 &prodkey
, FALSE
) != ERROR_SUCCESS
&&
2251 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
2252 &prodkey
, FALSE
) == ERROR_SUCCESS
)
2254 context
= MSIINSTALLCONTEXT_MACHINE
;
2257 r
= MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &userdata
, FALSE
);
2258 if (r
!= ERROR_SUCCESS
)
2261 if (!msi_reg_get_val_dword(userdata
, L
"WindowsInstaller", &val
))
2265 state
= INSTALLSTATE_DEFAULT
;
2267 state
= INSTALLSTATE_UNKNOWN
;
2272 state
= INSTALLSTATE_UNKNOWN
;
2275 state
= INSTALLSTATE_ABSENT
;
2278 RegCloseKey(prodkey
);
2279 RegCloseKey(userdata
);
2280 TRACE("-> %d\n", state
);
2284 INSTALLUILEVEL WINAPI
MsiSetInternalUI(INSTALLUILEVEL dwUILevel
, HWND
*phWnd
)
2286 INSTALLUILEVEL old
= gUILevel
;
2287 HWND oldwnd
= gUIhwnd
;
2289 TRACE("%08x %p\n", dwUILevel
, phWnd
);
2291 if (dwUILevel
& ~(INSTALLUILEVEL_MASK
|INSTALLUILEVEL_HIDECANCEL
|INSTALLUILEVEL_PROGRESSONLY
|
2292 INSTALLUILEVEL_ENDDIALOG
|INSTALLUILEVEL_SOURCERESONLY
))
2294 FIXME("Unrecognized flags %08x\n", dwUILevel
);
2295 return INSTALLUILEVEL_NOCHANGE
;
2298 if (dwUILevel
!= INSTALLUILEVEL_NOCHANGE
)
2299 gUILevel
= dwUILevel
;
2309 INSTALLUI_HANDLERA WINAPI
MsiSetExternalUIA( INSTALLUI_HANDLERA puiHandler
, DWORD dwMessageFilter
, void *pvContext
)
2311 INSTALLUI_HANDLERA prev
= gUIHandlerA
;
2313 TRACE( "%p, %#lx, %p\n", puiHandler
, dwMessageFilter
, pvContext
);
2315 gUIHandlerA
= puiHandler
;
2317 gUIFilter
= dwMessageFilter
;
2318 gUIContext
= pvContext
;
2323 INSTALLUI_HANDLERW WINAPI
MsiSetExternalUIW( INSTALLUI_HANDLERW puiHandler
, DWORD dwMessageFilter
, void *pvContext
)
2325 INSTALLUI_HANDLERW prev
= gUIHandlerW
;
2327 TRACE( "%p, %#lx, %p\n", puiHandler
, dwMessageFilter
, pvContext
);
2330 gUIHandlerW
= puiHandler
;
2331 gUIFilter
= dwMessageFilter
;
2332 gUIContext
= pvContext
;
2337 /******************************************************************
2338 * MsiLoadStringW [MSI.@]
2340 * Loads a string from MSI's string resources.
2344 * handle [I] only -1 is handled currently
2345 * id [I] id of the string to be loaded
2346 * lpBuffer [O] buffer for the string to be written to
2347 * nBufferMax [I] maximum size of the buffer in characters
2348 * lang [I] the preferred language for the string
2352 * If successful, this function returns the language id of the string loaded
2353 * If the function fails, the function returns zero.
2357 * The type of the first parameter is unknown. LoadString's prototype
2358 * suggests that it might be a module handle. I have made it an MSI handle
2359 * for starters, as -1 is an invalid MSI handle, but not an invalid module
2360 * handle. Maybe strings can be stored in an MSI database somehow.
2362 LANGID WINAPI
MsiLoadStringW( MSIHANDLE handle
, UINT id
, WCHAR
*lpBuffer
, int nBufferMax
, LANGID lang
)
2369 TRACE( "%lu, %u, %p, %d, %#x\n", handle
, id
, lpBuffer
, nBufferMax
, lang
);
2372 FIXME( "don't know how to deal with handle = %lu\n", handle
);
2375 lang
= GetUserDefaultLangID();
2377 hres
= FindResourceExW( msi_hInstance
, (const WCHAR
*)RT_STRING
, (WCHAR
*)1, lang
);
2380 hResData
= LoadResource( msi_hInstance
, hres
);
2383 p
= LockResource( hResData
);
2387 for (i
= 0; i
< (id
& 0xf); i
++) p
+= *p
+ 1;
2390 if( nBufferMax
<= len
)
2393 memcpy( lpBuffer
, p
+1, len
* sizeof(WCHAR
));
2394 lpBuffer
[ len
] = 0;
2396 TRACE("found -> %s\n", debugstr_w(lpBuffer
));
2400 LANGID WINAPI
MsiLoadStringA( MSIHANDLE handle
, UINT id
, LPSTR lpBuffer
,
2401 int nBufferMax
, LANGID lang
)
2407 bufW
= msi_alloc(nBufferMax
*sizeof(WCHAR
));
2408 r
= MsiLoadStringW(handle
, id
, bufW
, nBufferMax
, lang
);
2411 len
= WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, NULL
, 0, NULL
, NULL
);
2412 if( len
<= nBufferMax
)
2413 WideCharToMultiByte( CP_ACP
, 0, bufW
, -1,
2414 lpBuffer
, nBufferMax
, NULL
, NULL
);
2422 INSTALLSTATE WINAPI
MsiLocateComponentA(LPCSTR szComponent
, LPSTR lpPathBuf
,
2425 char szProduct
[GUID_SIZE
];
2427 TRACE("%s %p %p\n", debugstr_a(szComponent
), lpPathBuf
, pcchBuf
);
2429 if (!szComponent
|| !pcchBuf
)
2430 return INSTALLSTATE_INVALIDARG
;
2432 if (MsiGetProductCodeA( szComponent
, szProduct
) != ERROR_SUCCESS
)
2433 return INSTALLSTATE_UNKNOWN
;
2435 return MsiGetComponentPathA( szProduct
, szComponent
, lpPathBuf
, pcchBuf
);
2438 INSTALLSTATE WINAPI
MsiLocateComponentW(LPCWSTR szComponent
, LPWSTR lpPathBuf
,
2441 WCHAR szProduct
[GUID_SIZE
];
2443 TRACE("%s %p %p\n", debugstr_w(szComponent
), lpPathBuf
, pcchBuf
);
2445 if (!szComponent
|| !pcchBuf
)
2446 return INSTALLSTATE_INVALIDARG
;
2448 if (MsiGetProductCodeW( szComponent
, szProduct
) != ERROR_SUCCESS
)
2449 return INSTALLSTATE_UNKNOWN
;
2451 return MsiGetComponentPathW( szProduct
, szComponent
, lpPathBuf
, pcchBuf
);
2454 UINT WINAPI
MsiMessageBoxA( HWND hWnd
, const char *lpText
, const char *lpCaption
, UINT uType
, WORD wLanguageId
,
2457 FIXME( "%p, %s, %s, %u, %#x, %#lx\n", hWnd
, debugstr_a(lpText
), debugstr_a(lpCaption
), uType
, wLanguageId
, f
);
2458 return MessageBoxExA( hWnd
, lpText
, lpCaption
, uType
, wLanguageId
);
2461 UINT WINAPI
MsiMessageBoxW( HWND hWnd
, const WCHAR
*lpText
, const WCHAR
*lpCaption
, UINT uType
, WORD wLanguageId
,
2464 FIXME( "%p, %s, %s, %u, %#x %#lx\n", hWnd
, debugstr_w(lpText
), debugstr_w(lpCaption
), uType
, wLanguageId
, f
);
2465 return MessageBoxExW( hWnd
, lpText
, lpCaption
, uType
, wLanguageId
);
2468 UINT WINAPI
MsiMessageBoxExA( HWND hWnd
, const char *lpText
, const char *lpCaption
, UINT uType
, DWORD unknown
,
2469 WORD wLanguageId
, DWORD f
)
2471 FIXME( "%p, %s, %s, %u, %#lx, %#x, %#lx): semi-stub\n", hWnd
, debugstr_a(lpText
), debugstr_a(lpCaption
), uType
,
2472 unknown
, wLanguageId
, f
);
2473 return MessageBoxExA( hWnd
, lpText
, lpCaption
, uType
, wLanguageId
);
2476 UINT WINAPI
MsiMessageBoxExW( HWND hWnd
, const WCHAR
*lpText
, const WCHAR
*lpCaption
, UINT uType
, DWORD unknown
,
2477 WORD wLanguageId
, DWORD f
)
2479 FIXME( "%p, %s, %s, %u, %#lx, %#x, %#lx): semi-stub\n", hWnd
, debugstr_w(lpText
), debugstr_w(lpCaption
), uType
,
2480 unknown
, wLanguageId
, f
);
2481 return MessageBoxExW( hWnd
, lpText
, lpCaption
, uType
, wLanguageId
);
2484 UINT WINAPI
MsiProvideAssemblyA( const char *szAssemblyName
, const char *szAppContext
, DWORD dwInstallMode
,
2485 DWORD dwAssemblyInfo
, char *lpPathBuf
, DWORD
*pcchPathBuf
)
2487 FIXME( "%s, %s, %#lx, %#lx, %p, %p\n", debugstr_a(szAssemblyName
), debugstr_a(szAppContext
), dwInstallMode
,
2488 dwAssemblyInfo
, lpPathBuf
, pcchPathBuf
);
2489 return ERROR_CALL_NOT_IMPLEMENTED
;
2492 UINT WINAPI
MsiProvideAssemblyW( const WCHAR
*szAssemblyName
, const WCHAR
*szAppContext
, DWORD dwInstallMode
,
2493 DWORD dwAssemblyInfo
, WCHAR
*lpPathBuf
, DWORD
*pcchPathBuf
)
2495 FIXME( "%s, %s, %#lx, %#lx, %p, %p\n", debugstr_w(szAssemblyName
), debugstr_w(szAppContext
), dwInstallMode
,
2496 dwAssemblyInfo
, lpPathBuf
, pcchPathBuf
);
2497 return ERROR_CALL_NOT_IMPLEMENTED
;
2500 UINT WINAPI
MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor
,
2501 LPSTR szPath
, LPDWORD pcchPath
, LPDWORD pcchArgs
)
2503 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor
), szPath
, pcchPath
, pcchArgs
);
2504 return ERROR_CALL_NOT_IMPLEMENTED
;
2507 UINT WINAPI
MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor
,
2508 LPWSTR szPath
, LPDWORD pcchPath
, LPDWORD pcchArgs
)
2510 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor
), szPath
, pcchPath
, pcchArgs
);
2511 return ERROR_CALL_NOT_IMPLEMENTED
;
2514 HRESULT WINAPI
MsiGetFileSignatureInformationA( const char *path
, DWORD flags
, PCCERT_CONTEXT
*cert
, BYTE
*hash
,
2518 WCHAR
*pathW
= NULL
;
2520 TRACE( "%s, %#lx, %p, %p, %p\n", debugstr_a(path
), flags
, cert
, hash
, hashlen
);
2522 if (path
&& !(pathW
= strdupAtoW( path
))) return E_OUTOFMEMORY
;
2523 r
= MsiGetFileSignatureInformationW( pathW
, flags
, cert
, hash
, hashlen
);
2528 HRESULT WINAPI
MsiGetFileSignatureInformationW( const WCHAR
*path
, DWORD flags
, PCCERT_CONTEXT
*cert
, BYTE
*hash
,
2531 static GUID generic_verify_v2
= WINTRUST_ACTION_GENERIC_VERIFY_V2
;
2534 WINTRUST_FILE_INFO info
;
2535 CRYPT_PROVIDER_SGNR
*signer
;
2536 CRYPT_PROVIDER_CERT
*provider
;
2538 TRACE( "%s, %#lx, %p, %p, %p\n", debugstr_w(path
), flags
, cert
, hash
, hashlen
);
2540 if (!path
|| !cert
) return E_INVALIDARG
;
2542 info
.cbStruct
= sizeof(info
);
2543 info
.pcwszFilePath
= path
;
2545 info
.pgKnownSubject
= NULL
;
2547 data
.cbStruct
= sizeof(data
);
2548 data
.pPolicyCallbackData
= NULL
;
2549 data
.pSIPClientData
= NULL
;
2550 data
.dwUIChoice
= WTD_UI_NONE
;
2551 data
.fdwRevocationChecks
= WTD_REVOKE_WHOLECHAIN
;
2552 data
.dwUnionChoice
= WTD_CHOICE_FILE
;
2553 data
.u
.pFile
= &info
;
2554 data
.dwStateAction
= WTD_STATEACTION_VERIFY
;
2555 data
.hWVTStateData
= NULL
;
2556 data
.pwszURLReference
= NULL
;
2557 data
.dwProvFlags
= 0;
2558 data
.dwUIContext
= WTD_UICONTEXT_INSTALL
;
2559 hr
= WinVerifyTrustEx( INVALID_HANDLE_VALUE
, &generic_verify_v2
, &data
);
2561 if (FAILED(hr
)) goto done
;
2563 if (!(signer
= WTHelperGetProvSignerFromChain( data
.hWVTStateData
, 0, FALSE
, 0 )))
2565 hr
= TRUST_E_NOSIGNATURE
;
2570 DWORD len
= signer
->psSigner
->EncryptedHash
.cbData
;
2574 hr
= HRESULT_FROM_WIN32(ERROR_MORE_DATA
);
2577 memcpy( hash
, signer
->psSigner
->EncryptedHash
.pbData
, len
);
2580 if (!(provider
= WTHelperGetProvCertFromChain( signer
, 0 )))
2582 hr
= TRUST_E_PROVIDER_UNKNOWN
;
2585 *cert
= CertDuplicateCertificateContext( provider
->pCert
);
2588 data
.dwStateAction
= WTD_STATEACTION_CLOSE
;
2589 WinVerifyTrustEx( INVALID_HANDLE_VALUE
, &generic_verify_v2
, &data
);
2593 /******************************************************************
2594 * MsiGetProductPropertyA [MSI.@]
2596 UINT WINAPI
MsiGetProductPropertyA( MSIHANDLE hProduct
, const char *szProperty
, char *szValue
, DWORD
*pccbValue
)
2598 LPWSTR prop
= NULL
, val
= NULL
;
2602 TRACE( "%lu, %s, %p, %p\n", hProduct
, debugstr_a(szProperty
), szValue
, pccbValue
);
2604 if (szValue
&& !pccbValue
)
2605 return ERROR_INVALID_PARAMETER
;
2607 if (szProperty
) prop
= strdupAtoW(szProperty
);
2610 r
= MsiGetProductPropertyW(hProduct
, prop
, NULL
, &len
);
2611 if (r
!= ERROR_SUCCESS
&& r
!= ERROR_MORE_DATA
)
2614 if (r
== ERROR_SUCCESS
)
2616 if (szValue
) *szValue
= '\0';
2617 if (pccbValue
) *pccbValue
= 0;
2621 val
= msi_alloc(++len
* sizeof(WCHAR
));
2624 r
= ERROR_OUTOFMEMORY
;
2628 r
= MsiGetProductPropertyW(hProduct
, prop
, val
, &len
);
2629 if (r
!= ERROR_SUCCESS
)
2632 len
= WideCharToMultiByte(CP_ACP
, 0, val
, -1, NULL
, 0, NULL
, NULL
);
2635 WideCharToMultiByte(CP_ACP
, 0, val
, -1, szValue
,
2636 *pccbValue
, NULL
, NULL
);
2640 if (len
> *pccbValue
)
2641 r
= ERROR_MORE_DATA
;
2643 *pccbValue
= len
- 1;
2653 /******************************************************************
2654 * MsiGetProductPropertyW [MSI.@]
2656 UINT WINAPI
MsiGetProductPropertyW( MSIHANDLE hProduct
, const WCHAR
*szProperty
, WCHAR
*szValue
, DWORD
*pccbValue
)
2658 MSIPACKAGE
*package
;
2659 MSIQUERY
*view
= NULL
;
2660 MSIRECORD
*rec
= NULL
;
2664 TRACE( "%lu, %s, %p, %p)\n", hProduct
, debugstr_w(szProperty
), szValue
, pccbValue
);
2667 return ERROR_INVALID_PARAMETER
;
2669 if (szValue
&& !pccbValue
)
2670 return ERROR_INVALID_PARAMETER
;
2672 package
= msihandle2msiinfo(hProduct
, MSIHANDLETYPE_PACKAGE
);
2674 return ERROR_INVALID_HANDLE
;
2676 r
= MSI_OpenQuery(package
->db
, &view
, L
"SELECT * FROM `Property` WHERE `Property` = '%s'", szProperty
);
2677 if (r
!= ERROR_SUCCESS
)
2680 r
= MSI_ViewExecute(view
, 0);
2681 if (r
!= ERROR_SUCCESS
)
2684 r
= MSI_ViewFetch(view
, &rec
);
2685 if (r
!= ERROR_SUCCESS
)
2688 val
= MSI_RecordGetString(rec
, 2);
2692 if (lstrlenW(val
) >= *pccbValue
)
2694 if (szValue
) lstrcpynW(szValue
, val
, *pccbValue
);
2695 r
= ERROR_MORE_DATA
;
2699 if (szValue
) lstrcpyW(szValue
, val
);
2703 *pccbValue
= lstrlenW(val
);
2708 MSI_ViewClose(view
);
2709 msiobj_release(&view
->hdr
);
2710 if (rec
) msiobj_release(&rec
->hdr
);
2715 if (szValue
) *szValue
= '\0';
2716 if (pccbValue
) *pccbValue
= 0;
2720 msiobj_release(&package
->hdr
);
2724 UINT WINAPI
MsiVerifyPackageA( LPCSTR szPackage
)
2727 LPWSTR szPack
= NULL
;
2729 TRACE("%s\n", debugstr_a(szPackage
) );
2733 szPack
= strdupAtoW( szPackage
);
2735 return ERROR_OUTOFMEMORY
;
2738 r
= MsiVerifyPackageW( szPack
);
2745 UINT WINAPI
MsiVerifyPackageW( LPCWSTR szPackage
)
2750 TRACE("%s\n", debugstr_w(szPackage
) );
2752 r
= MsiOpenDatabaseW( szPackage
, MSIDBOPEN_READONLY
, &handle
);
2753 MsiCloseHandle( handle
);
2758 static BOOL
open_userdata_comp_key( const WCHAR
*comp
, const WCHAR
*usersid
, MSIINSTALLCONTEXT ctx
,
2761 if (ctx
& MSIINSTALLCONTEXT_MACHINE
)
2763 if (!MSIREG_OpenUserDataComponentKey( comp
, L
"S-1-5-18", hkey
, FALSE
)) return TRUE
;
2765 if (ctx
& (MSIINSTALLCONTEXT_USERMANAGED
|MSIINSTALLCONTEXT_USERUNMANAGED
))
2767 if (usersid
&& !wcsicmp( usersid
, L
"S-1-1-0" ))
2769 FIXME( "only looking at the current user\n" );
2772 if (!MSIREG_OpenUserDataComponentKey( comp
, usersid
, hkey
, FALSE
)) return TRUE
;
2777 static INSTALLSTATE
MSI_GetComponentPath( const WCHAR
*szProduct
, const WCHAR
*szComponent
,
2778 const WCHAR
*szUserSid
, MSIINSTALLCONTEXT ctx
,
2779 awstring
*lpPathBuf
, DWORD
*pcchBuf
)
2781 WCHAR
*path
= NULL
, squashed_pc
[SQUASHED_GUID_SIZE
], squashed_comp
[SQUASHED_GUID_SIZE
];
2786 if (!szProduct
|| !szComponent
)
2787 return INSTALLSTATE_INVALIDARG
;
2789 if (lpPathBuf
->str
.w
&& !pcchBuf
)
2790 return INSTALLSTATE_INVALIDARG
;
2792 if (!squash_guid( szProduct
, squashed_pc
) || !squash_guid( szComponent
, squashed_comp
))
2793 return INSTALLSTATE_INVALIDARG
;
2795 if (szUserSid
&& ctx
== MSIINSTALLCONTEXT_MACHINE
)
2796 return INSTALLSTATE_INVALIDARG
;
2798 state
= INSTALLSTATE_UNKNOWN
;
2800 if (open_userdata_comp_key( szComponent
, szUserSid
, ctx
, &hkey
))
2802 path
= msi_reg_get_val_str( hkey
, squashed_pc
);
2805 state
= INSTALLSTATE_ABSENT
;
2807 if ((!MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_MACHINE
, NULL
, &hkey
, FALSE
) ||
2808 !MSIREG_OpenUserDataProductKey(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
, NULL
, &hkey
, FALSE
)) &&
2809 msi_reg_get_val_dword(hkey
, L
"WindowsInstaller", &version
) &&
2810 GetFileAttributesW(path
) != INVALID_FILE_ATTRIBUTES
)
2813 state
= INSTALLSTATE_LOCAL
;
2817 if (state
!= INSTALLSTATE_LOCAL
&&
2818 (!MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
, &hkey
, FALSE
) ||
2819 !MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
, &hkey
, FALSE
)))
2823 if (open_userdata_comp_key( szComponent
, szUserSid
, ctx
, &hkey
))
2826 path
= msi_reg_get_val_str( hkey
, squashed_pc
);
2829 state
= INSTALLSTATE_ABSENT
;
2831 if (GetFileAttributesW(path
) != INVALID_FILE_ATTRIBUTES
)
2832 state
= INSTALLSTATE_LOCAL
;
2837 return INSTALLSTATE_UNKNOWN
;
2839 if (state
== INSTALLSTATE_LOCAL
&& !*path
)
2840 state
= INSTALLSTATE_NOTUSED
;
2842 if (msi_strcpy_to_awstring(path
, -1, lpPathBuf
, pcchBuf
) == ERROR_MORE_DATA
)
2843 state
= INSTALLSTATE_MOREDATA
;
2849 /******************************************************************
2850 * MsiGetComponentPathExW [MSI.@]
2852 INSTALLSTATE WINAPI
MsiGetComponentPathExW( LPCWSTR product
, LPCWSTR comp
, LPCWSTR usersid
,
2853 MSIINSTALLCONTEXT ctx
, LPWSTR buf
, LPDWORD buflen
)
2857 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_w(product
), debugstr_w(comp
), debugstr_w(usersid
),
2860 path
.unicode
= TRUE
;
2863 return MSI_GetComponentPath( product
, comp
, usersid
, ctx
, &path
, buflen
);
2866 INSTALLSTATE WINAPI
MsiGetComponentPathExA( LPCSTR product
, LPCSTR comp
, LPCSTR usersid
,
2867 MSIINSTALLCONTEXT ctx
, LPSTR buf
, LPDWORD buflen
)
2869 WCHAR
*productW
= NULL
, *compW
= NULL
, *usersidW
= NULL
;
2870 INSTALLSTATE r
= INSTALLSTATE_UNKNOWN
;
2873 TRACE( "%s %s %s 0x%x %p %p\n", debugstr_a(product
), debugstr_a(comp
), debugstr_a(usersid
),
2876 if (product
&& !(productW
= strdupAtoW( product
))) return INSTALLSTATE_UNKNOWN
;
2877 if (comp
&& !(compW
= strdupAtoW( comp
))) goto end
;
2878 if (usersid
&& !(usersidW
= strdupAtoW( usersid
))) goto end
;
2880 path
.unicode
= FALSE
;
2883 r
= MSI_GetComponentPath( productW
, compW
, usersidW
, ctx
, &path
, buflen
);
2886 msi_free( productW
);
2888 msi_free( usersidW
);
2893 /******************************************************************
2894 * MsiGetComponentPathW [MSI.@]
2896 INSTALLSTATE WINAPI
MsiGetComponentPathW( LPCWSTR product
, LPCWSTR comp
, LPWSTR buf
, LPDWORD buflen
)
2898 return MsiGetComponentPathExW( product
, comp
, L
"S-1-1-0", MSIINSTALLCONTEXT_ALL
, buf
, buflen
);
2901 /******************************************************************
2902 * MsiGetComponentPathA [MSI.@]
2904 INSTALLSTATE WINAPI
MsiGetComponentPathA( LPCSTR product
, LPCSTR comp
, LPSTR buf
, LPDWORD buflen
)
2906 return MsiGetComponentPathExA( product
, comp
, "s-1-1-0", MSIINSTALLCONTEXT_ALL
, buf
, buflen
);
2909 static UINT
query_feature_state( const WCHAR
*product
, const WCHAR
*squashed
, const WCHAR
*usersid
,
2910 MSIINSTALLCONTEXT ctx
, const WCHAR
*feature
, INSTALLSTATE
*state
)
2914 WCHAR
*parent
, *components
, *path
;
2916 BOOL missing
= FALSE
, source
= FALSE
;
2917 WCHAR comp
[GUID_SIZE
];
2920 if (ctx
!= MSIINSTALLCONTEXT_MACHINE
) SetLastError( ERROR_SUCCESS
);
2922 if (MSIREG_OpenFeaturesKey( product
, usersid
, ctx
, &hkey
, FALSE
)) return ERROR_UNKNOWN_PRODUCT
;
2924 parent
= msi_reg_get_val_str( hkey
, feature
);
2925 RegCloseKey( hkey
);
2926 if (!parent
) return ERROR_UNKNOWN_FEATURE
;
2928 *state
= (parent
[0] == 6) ? INSTALLSTATE_ABSENT
: INSTALLSTATE_LOCAL
;
2930 if (*state
== INSTALLSTATE_ABSENT
)
2931 return ERROR_SUCCESS
;
2933 r
= MSIREG_OpenUserDataFeaturesKey( product
, usersid
, ctx
, &hkey
, FALSE
);
2934 if (r
!= ERROR_SUCCESS
)
2936 *state
= INSTALLSTATE_ADVERTISED
;
2937 return ERROR_SUCCESS
;
2939 components
= msi_reg_get_val_str( hkey
, feature
);
2940 RegCloseKey( hkey
);
2942 TRACE("buffer = %s\n", debugstr_w(components
));
2946 *state
= INSTALLSTATE_ADVERTISED
;
2947 return ERROR_SUCCESS
;
2949 for (p
= components
; *p
&& *p
!= 2 ; p
+= 20)
2951 if (!decode_base85_guid( p
, &guid
))
2953 if (p
!= components
) break;
2954 msi_free( components
);
2955 *state
= INSTALLSTATE_BADCONFIG
;
2956 return ERROR_BAD_CONFIGURATION
;
2958 StringFromGUID2( &guid
, comp
, GUID_SIZE
);
2959 if (ctx
== MSIINSTALLCONTEXT_MACHINE
)
2960 r
= MSIREG_OpenUserDataComponentKey( comp
, L
"S-1-5-18", &hkey
, FALSE
);
2962 r
= MSIREG_OpenUserDataComponentKey( comp
, usersid
, &hkey
, FALSE
);
2964 if (r
!= ERROR_SUCCESS
)
2966 msi_free( components
);
2967 *state
= INSTALLSTATE_ADVERTISED
;
2968 return ERROR_SUCCESS
;
2970 path
= msi_reg_get_val_str( hkey
, squashed
);
2971 if (!path
) missing
= TRUE
;
2972 else if (lstrlenW( path
) > 2 &&
2973 path
[0] >= '0' && path
[0] <= '9' &&
2974 path
[1] >= '0' && path
[1] <= '9')
2980 msi_free( components
);
2983 *state
= INSTALLSTATE_ADVERTISED
;
2985 *state
= INSTALLSTATE_SOURCE
;
2987 *state
= INSTALLSTATE_LOCAL
;
2989 TRACE("returning state %d\n", *state
);
2990 return ERROR_SUCCESS
;
2993 UINT WINAPI
MsiQueryFeatureStateExA( LPCSTR product
, LPCSTR usersid
, MSIINSTALLCONTEXT ctx
,
2994 LPCSTR feature
, INSTALLSTATE
*state
)
2997 WCHAR
*productW
= NULL
, *usersidW
= NULL
, *featureW
= NULL
;
2999 if (product
&& !(productW
= strdupAtoW( product
))) return ERROR_OUTOFMEMORY
;
3000 if (usersid
&& !(usersidW
= strdupAtoW( usersid
)))
3002 msi_free( productW
);
3003 return ERROR_OUTOFMEMORY
;
3005 if (feature
&& !(featureW
= strdupAtoW( feature
)))
3007 msi_free( productW
);
3008 msi_free( usersidW
);
3009 return ERROR_OUTOFMEMORY
;
3011 r
= MsiQueryFeatureStateExW( productW
, usersidW
, ctx
, featureW
, state
);
3012 msi_free( productW
);
3013 msi_free( usersidW
);
3014 msi_free( featureW
);
3018 UINT WINAPI
MsiQueryFeatureStateExW( LPCWSTR product
, LPCWSTR usersid
, MSIINSTALLCONTEXT ctx
,
3019 LPCWSTR feature
, INSTALLSTATE
*state
)
3022 if (!squash_guid( product
, squashed
)) return ERROR_INVALID_PARAMETER
;
3023 return query_feature_state( product
, squashed
, usersid
, ctx
, feature
, state
);
3026 /******************************************************************
3027 * MsiQueryFeatureStateA [MSI.@]
3029 INSTALLSTATE WINAPI
MsiQueryFeatureStateA(LPCSTR szProduct
, LPCSTR szFeature
)
3031 LPWSTR szwProduct
= NULL
, szwFeature
= NULL
;
3032 INSTALLSTATE rc
= INSTALLSTATE_UNKNOWN
;
3034 szwProduct
= strdupAtoW( szProduct
);
3035 if ( szProduct
&& !szwProduct
)
3038 szwFeature
= strdupAtoW( szFeature
);
3039 if ( szFeature
&& !szwFeature
)
3042 rc
= MsiQueryFeatureStateW(szwProduct
, szwFeature
);
3045 msi_free( szwProduct
);
3046 msi_free( szwFeature
);
3051 /******************************************************************
3052 * MsiQueryFeatureStateW [MSI.@]
3054 * Checks the state of a feature
3057 * szProduct [I] Product's GUID string
3058 * szFeature [I] Feature's GUID string
3061 * INSTALLSTATE_LOCAL Feature is installed and usable
3062 * INSTALLSTATE_ABSENT Feature is absent
3063 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
3064 * INSTALLSTATE_UNKNOWN An error occurred
3065 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
3068 INSTALLSTATE WINAPI
MsiQueryFeatureStateW(LPCWSTR szProduct
, LPCWSTR szFeature
)
3074 TRACE("%s %s\n", debugstr_w(szProduct
), debugstr_w(szFeature
));
3076 if (!szProduct
|| !szFeature
|| !squash_guid( szProduct
, squashed
))
3077 return INSTALLSTATE_INVALIDARG
;
3079 r
= query_feature_state( szProduct
, squashed
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
, szFeature
, &state
);
3080 if (r
== ERROR_SUCCESS
|| r
== ERROR_BAD_CONFIGURATION
) return state
;
3082 r
= query_feature_state( szProduct
, squashed
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
, szFeature
, &state
);
3083 if (r
== ERROR_SUCCESS
|| r
== ERROR_BAD_CONFIGURATION
) return state
;
3085 r
= query_feature_state( szProduct
, squashed
, NULL
, MSIINSTALLCONTEXT_MACHINE
, szFeature
, &state
);
3086 if (r
== ERROR_SUCCESS
|| r
== ERROR_BAD_CONFIGURATION
) return state
;
3088 return INSTALLSTATE_UNKNOWN
;
3091 /******************************************************************
3092 * MsiGetFileVersionA [MSI.@]
3094 UINT WINAPI
MsiGetFileVersionA(LPCSTR szFilePath
, LPSTR lpVersionBuf
,
3095 LPDWORD pcchVersionBuf
, LPSTR lpLangBuf
, LPDWORD pcchLangBuf
)
3097 LPWSTR szwFilePath
= NULL
, lpwVersionBuff
= NULL
, lpwLangBuff
= NULL
;
3098 UINT ret
= ERROR_OUTOFMEMORY
;
3100 if ((lpVersionBuf
&& !pcchVersionBuf
) ||
3101 (lpLangBuf
&& !pcchLangBuf
))
3102 return ERROR_INVALID_PARAMETER
;
3106 szwFilePath
= strdupAtoW( szFilePath
);
3111 if( lpVersionBuf
&& pcchVersionBuf
&& *pcchVersionBuf
)
3113 lpwVersionBuff
= msi_alloc(*pcchVersionBuf
*sizeof(WCHAR
));
3114 if( !lpwVersionBuff
)
3118 if( lpLangBuf
&& pcchLangBuf
&& *pcchLangBuf
)
3120 lpwLangBuff
= msi_alloc(*pcchLangBuf
*sizeof(WCHAR
));
3125 ret
= MsiGetFileVersionW(szwFilePath
, lpwVersionBuff
, pcchVersionBuf
,
3126 lpwLangBuff
, pcchLangBuf
);
3128 if( (ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) && lpwVersionBuff
)
3129 WideCharToMultiByte(CP_ACP
, 0, lpwVersionBuff
, -1,
3130 lpVersionBuf
, *pcchVersionBuf
+ 1, NULL
, NULL
);
3131 if( (ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) && lpwLangBuff
)
3132 WideCharToMultiByte(CP_ACP
, 0, lpwLangBuff
, -1,
3133 lpLangBuf
, *pcchLangBuf
+ 1, NULL
, NULL
);
3136 msi_free(szwFilePath
);
3137 msi_free(lpwVersionBuff
);
3138 msi_free(lpwLangBuff
);
3143 static UINT
get_file_version( const WCHAR
*path
, WCHAR
*verbuf
, DWORD
*verlen
,
3144 WCHAR
*langbuf
, DWORD
*langlen
)
3146 UINT ret
= ERROR_MORE_DATA
;
3150 VS_FIXEDFILEINFO
*ffi
;
3154 if (!(len
= GetFileVersionInfoSizeW( path
, NULL
)))
3156 error
= GetLastError();
3157 if (error
== ERROR_BAD_PATHNAME
) return ERROR_FILE_NOT_FOUND
;
3158 if (error
== ERROR_RESOURCE_DATA_NOT_FOUND
) return ERROR_FILE_INVALID
;
3161 if (!(version
= msi_alloc( len
))) return ERROR_OUTOFMEMORY
;
3162 if (!GetFileVersionInfoW( path
, 0, len
, version
))
3164 msi_free( version
);
3165 return GetLastError();
3167 if (!verbuf
&& !verlen
&& !langbuf
&& !langlen
)
3169 msi_free( version
);
3170 return ERROR_SUCCESS
;
3174 if (VerQueryValueW( version
, L
"\\", (LPVOID
*)&ffi
, &len
) && len
> 0)
3176 swprintf( tmp
, ARRAY_SIZE(tmp
), L
"%d.%d.%d.%d",
3177 HIWORD(ffi
->dwFileVersionMS
), LOWORD(ffi
->dwFileVersionMS
),
3178 HIWORD(ffi
->dwFileVersionLS
), LOWORD(ffi
->dwFileVersionLS
) );
3179 if (verbuf
) lstrcpynW( verbuf
, tmp
, *verlen
);
3180 len
= lstrlenW( tmp
);
3181 if (*verlen
> len
) ret
= ERROR_SUCCESS
;
3186 if (verbuf
) *verbuf
= 0;
3192 if (VerQueryValueW( version
, L
"\\VarFileInfo\\Translation", (LPVOID
*)&lang
, &len
) && len
> 0)
3194 swprintf( tmp
, ARRAY_SIZE(tmp
), L
"%d", *lang
);
3195 if (langbuf
) lstrcpynW( langbuf
, tmp
, *langlen
);
3196 len
= lstrlenW( tmp
);
3197 if (*langlen
> len
) ret
= ERROR_SUCCESS
;
3202 if (langbuf
) *langbuf
= 0;
3206 msi_free( version
);
3211 /******************************************************************
3212 * MsiGetFileVersionW [MSI.@]
3214 UINT WINAPI
MsiGetFileVersionW( const WCHAR
*path
, WCHAR
*verbuf
, DWORD
*verlen
, WCHAR
*langbuf
, DWORD
*langlen
)
3218 TRACE( "%s, %p(%lu), %p(%lu)\n", debugstr_w(path
), verbuf
, verlen
? *verlen
: 0, langbuf
, langlen
? *langlen
: 0 );
3220 if ((verbuf
&& !verlen
) || (langbuf
&& !langlen
))
3221 return ERROR_INVALID_PARAMETER
;
3223 ret
= get_file_version( path
, verbuf
, verlen
, langbuf
, langlen
);
3224 if (ret
== ERROR_RESOURCE_DATA_NOT_FOUND
&& verlen
)
3227 WCHAR
*version
= msi_get_font_file_version( NULL
, path
);
3228 if (!version
) return ERROR_FILE_INVALID
;
3229 len
= lstrlenW( version
);
3230 if (len
>= *verlen
) ret
= ERROR_MORE_DATA
;
3233 lstrcpyW( verbuf
, version
);
3234 ret
= ERROR_SUCCESS
;
3237 msi_free( version
);
3242 /***********************************************************************
3243 * MsiGetFeatureUsageW [MSI.@]
3245 UINT WINAPI
MsiGetFeatureUsageW( LPCWSTR szProduct
, LPCWSTR szFeature
,
3246 LPDWORD pdwUseCount
, LPWORD pwDateUsed
)
3248 FIXME("%s %s %p %p\n",debugstr_w(szProduct
), debugstr_w(szFeature
),
3249 pdwUseCount
, pwDateUsed
);
3250 return ERROR_CALL_NOT_IMPLEMENTED
;
3253 /***********************************************************************
3254 * MsiGetFeatureUsageA [MSI.@]
3256 UINT WINAPI
MsiGetFeatureUsageA( LPCSTR szProduct
, LPCSTR szFeature
,
3257 LPDWORD pdwUseCount
, LPWORD pwDateUsed
)
3259 LPWSTR prod
= NULL
, feat
= NULL
;
3260 UINT ret
= ERROR_OUTOFMEMORY
;
3262 TRACE("%s %s %p %p\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
3263 pdwUseCount
, pwDateUsed
);
3265 prod
= strdupAtoW( szProduct
);
3266 if (szProduct
&& !prod
)
3269 feat
= strdupAtoW( szFeature
);
3270 if (szFeature
&& !feat
)
3273 ret
= MsiGetFeatureUsageW( prod
, feat
, pdwUseCount
, pwDateUsed
);
3282 /***********************************************************************
3283 * MsiUseFeatureExW [MSI.@]
3285 INSTALLSTATE WINAPI
MsiUseFeatureExW( const WCHAR
*szProduct
, const WCHAR
*szFeature
, DWORD dwInstallMode
,
3290 TRACE( "%s, %s, %lu %#lx\n", debugstr_w(szProduct
), debugstr_w(szFeature
), dwInstallMode
, dwReserved
);
3292 state
= MsiQueryFeatureStateW( szProduct
, szFeature
);
3295 return INSTALLSTATE_INVALIDARG
;
3297 if (state
== INSTALLSTATE_LOCAL
&& dwInstallMode
!= INSTALLMODE_NODETECTION
)
3299 FIXME("mark product %s feature %s as used\n",
3300 debugstr_w(szProduct
), debugstr_w(szFeature
) );
3306 /***********************************************************************
3307 * MsiUseFeatureExA [MSI.@]
3309 INSTALLSTATE WINAPI
MsiUseFeatureExA( const char *szProduct
, const char *szFeature
, DWORD dwInstallMode
,
3312 INSTALLSTATE ret
= INSTALLSTATE_UNKNOWN
;
3313 WCHAR
*prod
= NULL
, *feat
= NULL
;
3315 TRACE( "%s, %s, %lu, %#lx\n", debugstr_a(szProduct
), debugstr_a(szFeature
), dwInstallMode
, dwReserved
);
3317 prod
= strdupAtoW( szProduct
);
3318 if (szProduct
&& !prod
)
3321 feat
= strdupAtoW( szFeature
);
3322 if (szFeature
&& !feat
)
3325 ret
= MsiUseFeatureExW( prod
, feat
, dwInstallMode
, dwReserved
);
3334 /***********************************************************************
3335 * MsiUseFeatureW [MSI.@]
3337 INSTALLSTATE WINAPI
MsiUseFeatureW( LPCWSTR szProduct
, LPCWSTR szFeature
)
3339 return MsiUseFeatureExW(szProduct
, szFeature
, 0, 0);
3342 /***********************************************************************
3343 * MsiUseFeatureA [MSI.@]
3345 INSTALLSTATE WINAPI
MsiUseFeatureA( LPCSTR szProduct
, LPCSTR szFeature
)
3347 return MsiUseFeatureExA(szProduct
, szFeature
, 0, 0);
3350 static WCHAR
*reg_get_multisz( HKEY hkey
, const WCHAR
*name
)
3354 if (RegQueryValueExW( hkey
, name
, NULL
, &type
, NULL
, &len
) || type
!= REG_MULTI_SZ
) return NULL
;
3355 if ((ret
= msi_alloc( len
))) RegQueryValueExW( hkey
, name
, NULL
, NULL
, (BYTE
*)ret
, &len
);
3359 static WCHAR
*reg_get_sz( HKEY hkey
, const WCHAR
*name
)
3363 if (RegQueryValueExW( hkey
, name
, NULL
, &type
, NULL
, &len
) || type
!= REG_SZ
) return NULL
;
3364 if ((ret
= msi_alloc( len
))) RegQueryValueExW( hkey
, name
, NULL
, NULL
, (BYTE
*)ret
, &len
);
3368 #define BASE85_SIZE 20
3370 /***********************************************************************
3371 * MSI_ProvideQualifiedComponentEx [internal]
3373 static UINT
MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent
,
3374 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPCWSTR szProduct
,
3375 DWORD Unused1
, DWORD Unused2
, awstring
*lpPathBuf
,
3376 LPDWORD pcchPathBuf
)
3378 WCHAR product
[MAX_FEATURE_CHARS
+1], comp
[MAX_FEATURE_CHARS
+1], feature
[MAX_FEATURE_CHARS
+1];
3385 if (MSIREG_OpenUserComponentsKey( szComponent
, &hkey
, FALSE
)) return ERROR_UNKNOWN_COMPONENT
;
3387 desc
= reg_get_multisz( hkey
, szQualifier
);
3389 if (!desc
) return ERROR_INDEX_ABSENT
;
3391 /* FIXME: handle multiple descriptors */
3392 ret
= MsiDecomposeDescriptorW( desc
, product
, feature
, comp
, &size
);
3394 if (ret
!= ERROR_SUCCESS
) return ret
;
3396 if (!szProduct
) szProduct
= product
;
3399 MSIINSTALLCONTEXT ctx
;
3403 /* use the first component of the feature if the descriptor component is empty */
3404 if ((ret
= msi_locate_product( szProduct
, &ctx
))) return ret
;
3405 if ((ret
= MSIREG_OpenUserDataFeaturesKey( szProduct
, NULL
, ctx
, &hkey
, FALSE
)))
3407 return ERROR_FILE_NOT_FOUND
;
3409 components
= reg_get_sz( hkey
, feature
);
3410 RegCloseKey( hkey
);
3411 if (!components
) return ERROR_FILE_NOT_FOUND
;
3413 if (lstrlenW( components
) < BASE85_SIZE
|| !decode_base85_guid( components
, &guid
))
3415 msi_free( components
);
3416 return ERROR_FILE_NOT_FOUND
;
3418 msi_free( components
);
3419 StringFromGUID2( &guid
, comp
, ARRAY_SIZE( comp
));
3422 state
= MSI_GetComponentPath( szProduct
, comp
, L
"S-1-1-0", MSIINSTALLCONTEXT_ALL
, lpPathBuf
, pcchPathBuf
);
3424 if (state
== INSTALLSTATE_MOREDATA
) return ERROR_MORE_DATA
;
3425 if (state
!= INSTALLSTATE_LOCAL
) return ERROR_FILE_NOT_FOUND
;
3426 return ERROR_SUCCESS
;
3429 /***********************************************************************
3430 * MsiProvideQualifiedComponentExW [MSI.@]
3432 UINT WINAPI
MsiProvideQualifiedComponentExW( const WCHAR
*szComponent
, const WCHAR
*szQualifier
, DWORD dwInstallMode
,
3433 const WCHAR
*szProduct
, DWORD Unused1
, DWORD Unused2
, WCHAR
*lpPathBuf
,
3434 DWORD
*pcchPathBuf
)
3438 TRACE( "%s, %s, %lu, %s, %#lx, %#lx, %p, %p\n", debugstr_w(szComponent
), debugstr_w(szQualifier
), dwInstallMode
,
3439 debugstr_w(szProduct
), Unused1
, Unused2
, lpPathBuf
, pcchPathBuf
);
3441 path
.unicode
= TRUE
;
3442 path
.str
.w
= lpPathBuf
;
3444 return MSI_ProvideQualifiedComponentEx( szComponent
, szQualifier
, dwInstallMode
, szProduct
, Unused1
, Unused2
,
3445 &path
, pcchPathBuf
);
3448 /***********************************************************************
3449 * MsiProvideQualifiedComponentExA [MSI.@]
3451 UINT WINAPI
MsiProvideQualifiedComponentExA( const char *szComponent
, const char *szQualifier
, DWORD dwInstallMode
,
3452 const char *szProduct
, DWORD Unused1
, DWORD Unused2
, char *lpPathBuf
,
3453 DWORD
*pcchPathBuf
)
3455 WCHAR
*szwComponent
, *szwQualifier
= NULL
, *szwProduct
= NULL
;
3456 UINT r
= ERROR_OUTOFMEMORY
;
3459 TRACE( "%s, %s, %lu, %s, %#lx, %#lx, %p, %p\n", debugstr_a(szComponent
), debugstr_a(szQualifier
), dwInstallMode
,
3460 debugstr_a(szProduct
), Unused1
, Unused2
, lpPathBuf
, pcchPathBuf
);
3462 szwComponent
= strdupAtoW( szComponent
);
3463 if (szComponent
&& !szwComponent
)
3466 szwQualifier
= strdupAtoW( szQualifier
);
3467 if (szQualifier
&& !szwQualifier
)
3470 szwProduct
= strdupAtoW( szProduct
);
3471 if (szProduct
&& !szwProduct
)
3474 path
.unicode
= FALSE
;
3475 path
.str
.a
= lpPathBuf
;
3477 r
= MSI_ProvideQualifiedComponentEx(szwComponent
, szwQualifier
,
3478 dwInstallMode
, szwProduct
, Unused1
,
3479 Unused2
, &path
, pcchPathBuf
);
3481 msi_free(szwProduct
);
3482 msi_free(szwComponent
);
3483 msi_free(szwQualifier
);
3488 /***********************************************************************
3489 * MsiProvideQualifiedComponentW [MSI.@]
3491 UINT WINAPI
MsiProvideQualifiedComponentW( LPCWSTR szComponent
,
3492 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPWSTR lpPathBuf
,
3493 LPDWORD pcchPathBuf
)
3495 return MsiProvideQualifiedComponentExW(szComponent
, szQualifier
,
3496 dwInstallMode
, NULL
, 0, 0, lpPathBuf
, pcchPathBuf
);
3499 /***********************************************************************
3500 * MsiProvideQualifiedComponentA [MSI.@]
3502 UINT WINAPI
MsiProvideQualifiedComponentA( LPCSTR szComponent
,
3503 LPCSTR szQualifier
, DWORD dwInstallMode
, LPSTR lpPathBuf
,
3504 LPDWORD pcchPathBuf
)
3506 return MsiProvideQualifiedComponentExA(szComponent
, szQualifier
,
3507 dwInstallMode
, NULL
, 0, 0, lpPathBuf
, pcchPathBuf
);
3510 /***********************************************************************
3511 * MSI_GetUserInfo [internal]
3513 static USERINFOSTATE
MSI_GetUserInfo(LPCWSTR szProduct
,
3514 awstring
*lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
3515 awstring
*lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
3516 awstring
*lpSerialBuf
, LPDWORD pcchSerialBuf
)
3518 WCHAR
*user
, *org
, *serial
, squashed_pc
[SQUASHED_GUID_SIZE
];
3519 USERINFOSTATE state
;
3524 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct
), lpUserNameBuf
,
3525 pcchUserNameBuf
, lpOrgNameBuf
, pcchOrgNameBuf
, lpSerialBuf
,
3528 if (!szProduct
|| !squash_guid( szProduct
, squashed_pc
))
3529 return USERINFOSTATE_INVALIDARG
;
3531 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
3532 &hkey
, FALSE
) != ERROR_SUCCESS
&&
3533 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3534 &hkey
, FALSE
) != ERROR_SUCCESS
&&
3535 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
3536 &hkey
, FALSE
) != ERROR_SUCCESS
)
3538 return USERINFOSTATE_UNKNOWN
;
3541 if (MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3542 NULL
, &props
, FALSE
) != ERROR_SUCCESS
&&
3543 MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_MACHINE
,
3544 NULL
, &props
, FALSE
) != ERROR_SUCCESS
)
3547 return USERINFOSTATE_ABSENT
;
3550 user
= msi_reg_get_val_str(props
, INSTALLPROPERTY_REGOWNERW
);
3551 org
= msi_reg_get_val_str(props
, INSTALLPROPERTY_REGCOMPANYW
);
3552 serial
= msi_reg_get_val_str(props
, INSTALLPROPERTY_PRODUCTIDW
);
3553 state
= USERINFOSTATE_ABSENT
;
3559 state
= USERINFOSTATE_PRESENT
;
3561 if (pcchUserNameBuf
)
3563 if (lpUserNameBuf
&& !user
)
3565 (*pcchUserNameBuf
)--;
3569 r
= msi_strcpy_to_awstring(user
, -1, lpUserNameBuf
, pcchUserNameBuf
);
3570 if (r
== ERROR_MORE_DATA
)
3572 state
= USERINFOSTATE_MOREDATA
;
3580 if (!orgptr
) orgptr
= L
"";
3582 r
= msi_strcpy_to_awstring(orgptr
, -1, lpOrgNameBuf
, pcchOrgNameBuf
);
3583 if (r
== ERROR_MORE_DATA
)
3585 state
= USERINFOSTATE_MOREDATA
;
3598 r
= msi_strcpy_to_awstring(serial
, -1, lpSerialBuf
, pcchSerialBuf
);
3599 if (r
== ERROR_MORE_DATA
)
3600 state
= USERINFOSTATE_MOREDATA
;
3611 /***********************************************************************
3612 * MsiGetUserInfoW [MSI.@]
3614 USERINFOSTATE WINAPI
MsiGetUserInfoW(LPCWSTR szProduct
,
3615 LPWSTR lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
3616 LPWSTR lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
3617 LPWSTR lpSerialBuf
, LPDWORD pcchSerialBuf
)
3619 awstring user
, org
, serial
;
3621 if ((lpUserNameBuf
&& !pcchUserNameBuf
) ||
3622 (lpOrgNameBuf
&& !pcchOrgNameBuf
) ||
3623 (lpSerialBuf
&& !pcchSerialBuf
))
3624 return USERINFOSTATE_INVALIDARG
;
3626 user
.unicode
= TRUE
;
3627 user
.str
.w
= lpUserNameBuf
;
3629 org
.str
.w
= lpOrgNameBuf
;
3630 serial
.unicode
= TRUE
;
3631 serial
.str
.w
= lpSerialBuf
;
3633 return MSI_GetUserInfo( szProduct
, &user
, pcchUserNameBuf
,
3634 &org
, pcchOrgNameBuf
,
3635 &serial
, pcchSerialBuf
);
3638 USERINFOSTATE WINAPI
MsiGetUserInfoA(LPCSTR szProduct
,
3639 LPSTR lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
3640 LPSTR lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
3641 LPSTR lpSerialBuf
, LPDWORD pcchSerialBuf
)
3643 awstring user
, org
, serial
;
3647 if ((lpUserNameBuf
&& !pcchUserNameBuf
) ||
3648 (lpOrgNameBuf
&& !pcchOrgNameBuf
) ||
3649 (lpSerialBuf
&& !pcchSerialBuf
))
3650 return USERINFOSTATE_INVALIDARG
;
3652 prod
= strdupAtoW( szProduct
);
3653 if (szProduct
&& !prod
)
3654 return ERROR_OUTOFMEMORY
;
3656 user
.unicode
= FALSE
;
3657 user
.str
.a
= lpUserNameBuf
;
3658 org
.unicode
= FALSE
;
3659 org
.str
.a
= lpOrgNameBuf
;
3660 serial
.unicode
= FALSE
;
3661 serial
.str
.a
= lpSerialBuf
;
3663 r
= MSI_GetUserInfo( prod
, &user
, pcchUserNameBuf
,
3664 &org
, pcchOrgNameBuf
,
3665 &serial
, pcchSerialBuf
);
3672 UINT WINAPI
MsiCollectUserInfoW(LPCWSTR szProduct
)
3676 MSIPACKAGE
*package
;
3678 TRACE("(%s)\n",debugstr_w(szProduct
));
3680 rc
= MsiOpenProductW(szProduct
,&handle
);
3681 if (rc
!= ERROR_SUCCESS
)
3682 return ERROR_INVALID_PARAMETER
;
3684 /* MsiCollectUserInfo cannot be called from a custom action. */
3685 package
= msihandle2msiinfo(handle
, MSIHANDLETYPE_PACKAGE
);
3687 return ERROR_CALL_NOT_IMPLEMENTED
;
3689 rc
= ACTION_PerformAction(package
, L
"FirstRun");
3690 msiobj_release( &package
->hdr
);
3692 MsiCloseHandle(handle
);
3697 UINT WINAPI
MsiCollectUserInfoA(LPCSTR szProduct
)
3701 MSIPACKAGE
*package
;
3703 TRACE("(%s)\n",debugstr_a(szProduct
));
3705 rc
= MsiOpenProductA(szProduct
,&handle
);
3706 if (rc
!= ERROR_SUCCESS
)
3707 return ERROR_INVALID_PARAMETER
;
3709 /* MsiCollectUserInfo cannot be called from a custom action. */
3710 package
= msihandle2msiinfo(handle
, MSIHANDLETYPE_PACKAGE
);
3712 return ERROR_CALL_NOT_IMPLEMENTED
;
3714 rc
= ACTION_PerformAction(package
, L
"FirstRun");
3715 msiobj_release( &package
->hdr
);
3717 MsiCloseHandle(handle
);
3722 /***********************************************************************
3723 * MsiConfigureFeatureA [MSI.@]
3725 UINT WINAPI
MsiConfigureFeatureA(LPCSTR szProduct
, LPCSTR szFeature
, INSTALLSTATE eInstallState
)
3727 LPWSTR prod
, feat
= NULL
;
3728 UINT r
= ERROR_OUTOFMEMORY
;
3730 TRACE("%s %s %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
), eInstallState
);
3732 prod
= strdupAtoW( szProduct
);
3733 if (szProduct
&& !prod
)
3736 feat
= strdupAtoW( szFeature
);
3737 if (szFeature
&& !feat
)
3740 r
= MsiConfigureFeatureW(prod
, feat
, eInstallState
);
3749 /***********************************************************************
3750 * MsiConfigureFeatureW [MSI.@]
3752 UINT WINAPI
MsiConfigureFeatureW(LPCWSTR szProduct
, LPCWSTR szFeature
, INSTALLSTATE eInstallState
)
3754 MSIPACKAGE
*package
= NULL
;
3756 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
3759 TRACE("%s %s %i\n", debugstr_w(szProduct
), debugstr_w(szFeature
), eInstallState
);
3761 if (!szProduct
|| !szFeature
)
3762 return ERROR_INVALID_PARAMETER
;
3764 switch (eInstallState
)
3766 case INSTALLSTATE_DEFAULT
:
3767 /* FIXME: how do we figure out the default location? */
3768 eInstallState
= INSTALLSTATE_LOCAL
;
3770 case INSTALLSTATE_LOCAL
:
3771 case INSTALLSTATE_SOURCE
:
3772 case INSTALLSTATE_ABSENT
:
3773 case INSTALLSTATE_ADVERTISED
:
3776 return ERROR_INVALID_PARAMETER
;
3779 r
= MSI_OpenProductW( szProduct
, &package
);
3780 if (r
!= ERROR_SUCCESS
)
3783 sz
= sizeof(sourcepath
);
3784 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3785 MSICODE_PRODUCT
, INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
3787 sz
= sizeof(filename
);
3788 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3789 MSICODE_PRODUCT
, INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
3791 lstrcatW( sourcepath
, filename
);
3793 MsiSetInternalUI( INSTALLUILEVEL_BASIC
, NULL
);
3795 r
= ACTION_PerformAction(package
, L
"CostInitialize");
3796 if (r
!= ERROR_SUCCESS
)
3799 r
= MSI_SetFeatureStateW( package
, szFeature
, eInstallState
);
3800 if (r
!= ERROR_SUCCESS
)
3803 r
= MSI_InstallPackage( package
, sourcepath
, NULL
);
3806 msiobj_release( &package
->hdr
);
3811 /***********************************************************************
3812 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3814 * Notes: undocumented
3816 UINT WINAPI
MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved
)
3818 WCHAR path
[MAX_PATH
];
3820 TRACE( "%#lx\n", dwReserved
);
3824 FIXME( "dwReserved = %#lx\n", dwReserved
);
3825 return ERROR_INVALID_PARAMETER
;
3828 if (!GetWindowsDirectoryW(path
, MAX_PATH
))
3829 return ERROR_FUNCTION_FAILED
;
3831 lstrcatW(path
, L
"\\Installer");
3833 if (!CreateDirectoryW(path
, NULL
) && GetLastError() != ERROR_ALREADY_EXISTS
)
3834 return ERROR_FUNCTION_FAILED
;
3836 return ERROR_SUCCESS
;
3839 /***********************************************************************
3840 * MsiGetShortcutTargetA [MSI.@]
3842 UINT WINAPI
MsiGetShortcutTargetA( LPCSTR szShortcutTarget
,
3843 LPSTR szProductCode
, LPSTR szFeatureId
,
3844 LPSTR szComponentCode
)
3847 const int len
= MAX_FEATURE_CHARS
+1;
3848 WCHAR product
[MAX_FEATURE_CHARS
+1], feature
[MAX_FEATURE_CHARS
+1], component
[MAX_FEATURE_CHARS
+1];
3851 target
= strdupAtoW( szShortcutTarget
);
3852 if (szShortcutTarget
&& !target
)
3853 return ERROR_OUTOFMEMORY
;
3857 r
= MsiGetShortcutTargetW( target
, product
, feature
, component
);
3859 if (r
== ERROR_SUCCESS
)
3861 WideCharToMultiByte( CP_ACP
, 0, product
, -1, szProductCode
, len
, NULL
, NULL
);
3862 WideCharToMultiByte( CP_ACP
, 0, feature
, -1, szFeatureId
, len
, NULL
, NULL
);
3863 WideCharToMultiByte( CP_ACP
, 0, component
, -1, szComponentCode
, len
, NULL
, NULL
);
3868 /***********************************************************************
3869 * MsiGetShortcutTargetW [MSI.@]
3871 UINT WINAPI
MsiGetShortcutTargetW( LPCWSTR szShortcutTarget
,
3872 LPWSTR szProductCode
, LPWSTR szFeatureId
,
3873 LPWSTR szComponentCode
)
3875 IShellLinkDataList
*dl
= NULL
;
3876 IPersistFile
*pf
= NULL
;
3877 LPEXP_DARWIN_LINK darwin
= NULL
;
3880 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget
),
3881 szProductCode
, szFeatureId
, szComponentCode
);
3883 init
= CoInitialize(NULL
);
3885 r
= CoCreateInstance( &CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
3886 &IID_IPersistFile
, (LPVOID
*) &pf
);
3887 if( SUCCEEDED( r
) )
3889 r
= IPersistFile_Load( pf
, szShortcutTarget
,
3890 STGM_READ
| STGM_SHARE_DENY_WRITE
);
3891 if( SUCCEEDED( r
) )
3893 r
= IPersistFile_QueryInterface( pf
, &IID_IShellLinkDataList
,
3895 if( SUCCEEDED( r
) )
3897 IShellLinkDataList_CopyDataBlock( dl
, EXP_DARWIN_ID_SIG
,
3899 IShellLinkDataList_Release( dl
);
3902 IPersistFile_Release( pf
);
3905 if (SUCCEEDED(init
))
3908 TRACE("darwin = %p\n", darwin
);
3915 ret
= MsiDecomposeDescriptorW( darwin
->szwDarwinID
,
3916 szProductCode
, szFeatureId
, szComponentCode
, &sz
);
3917 LocalFree( darwin
);
3921 return ERROR_FUNCTION_FAILED
;
3924 UINT WINAPI
MsiReinstallFeatureW( const WCHAR
*szProduct
, const WCHAR
*szFeature
, DWORD dwReinstallMode
)
3926 MSIPACKAGE
*package
;
3927 MSIINSTALLCONTEXT context
;
3929 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
], reinstallmode
[11];
3930 WCHAR
*ptr
, *cmdline
;
3933 TRACE( "%s, %s, %#lx\n", debugstr_w(szProduct
), debugstr_w(szFeature
), dwReinstallMode
);
3935 r
= msi_locate_product( szProduct
, &context
);
3936 if (r
!= ERROR_SUCCESS
)
3939 ptr
= reinstallmode
;
3941 if (dwReinstallMode
& REINSTALLMODE_FILEMISSING
)
3943 if (dwReinstallMode
& REINSTALLMODE_FILEOLDERVERSION
)
3945 if (dwReinstallMode
& REINSTALLMODE_FILEEQUALVERSION
)
3947 if (dwReinstallMode
& REINSTALLMODE_FILEEXACT
)
3949 if (dwReinstallMode
& REINSTALLMODE_FILEVERIFY
)
3951 if (dwReinstallMode
& REINSTALLMODE_FILEREPLACE
)
3953 if (dwReinstallMode
& REINSTALLMODE_USERDATA
)
3955 if (dwReinstallMode
& REINSTALLMODE_MACHINEDATA
)
3957 if (dwReinstallMode
& REINSTALLMODE_SHORTCUT
)
3959 if (dwReinstallMode
& REINSTALLMODE_PACKAGE
)
3963 sz
= sizeof(sourcepath
);
3964 MsiSourceListGetInfoW( szProduct
, NULL
, context
, MSICODE_PRODUCT
,
3965 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
3966 sz
= sizeof(filename
);
3967 MsiSourceListGetInfoW( szProduct
, NULL
, context
, MSICODE_PRODUCT
,
3968 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
3969 lstrcatW( sourcepath
, filename
);
3971 if (dwReinstallMode
& REINSTALLMODE_PACKAGE
)
3972 r
= MSI_OpenPackageW( sourcepath
, 0, &package
);
3974 r
= MSI_OpenProductW( szProduct
, &package
);
3976 if (r
!= ERROR_SUCCESS
)
3979 sz
= (lstrlenW( L
"%s=%s %s=%s" ) + lstrlenW( L
"REINSTALLMODE" ) + lstrlenW( reinstallmode
)) * sizeof(WCHAR
);
3980 sz
+= (lstrlenW( L
"REINSTALL" ) + lstrlenW( szFeature
)) * sizeof(WCHAR
);
3981 if (!(cmdline
= msi_alloc( sz
)))
3983 msiobj_release( &package
->hdr
);
3984 return ERROR_OUTOFMEMORY
;
3986 swprintf( cmdline
, sz
/ sizeof(WCHAR
), L
"%s=%s %s=%s", L
"REINSTALLMODE", reinstallmode
, L
"REINSTALL", szFeature
);
3988 r
= MSI_InstallPackage( package
, sourcepath
, cmdline
);
3989 msiobj_release( &package
->hdr
);
3990 msi_free( cmdline
);
3995 UINT WINAPI
MsiReinstallFeatureA( const char *szProduct
, const char *szFeature
, DWORD dwReinstallMode
)
3997 WCHAR
*wszProduct
, *wszFeature
;
4000 TRACE( "%s, %s, %lu\n", debugstr_a(szProduct
), debugstr_a(szFeature
), dwReinstallMode
);
4002 wszProduct
= strdupAtoW(szProduct
);
4003 wszFeature
= strdupAtoW(szFeature
);
4005 rc
= MsiReinstallFeatureW(wszProduct
, wszFeature
, dwReinstallMode
);
4007 msi_free(wszProduct
);
4008 msi_free(wszFeature
);
4015 unsigned int buf
[4];
4016 unsigned char in
[64];
4017 unsigned char digest
[16];
4020 extern VOID WINAPI
MD5Init( MD5_CTX
*);
4021 extern VOID WINAPI
MD5Update( MD5_CTX
*, const unsigned char *, unsigned int );
4022 extern VOID WINAPI
MD5Final( MD5_CTX
*);
4024 UINT
msi_get_filehash( MSIPACKAGE
*package
, const WCHAR
*path
, MSIFILEHASHINFO
*hash
)
4026 HANDLE handle
, mapping
;
4029 UINT r
= ERROR_FUNCTION_FAILED
;
4032 handle
= msi_create_file( package
, path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_DELETE
, OPEN_EXISTING
, 0 );
4034 handle
= CreateFileW( path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, 0, NULL
);
4035 if (handle
== INVALID_HANDLE_VALUE
)
4037 WARN( "can't open file %lu\n", GetLastError() );
4038 return ERROR_FILE_NOT_FOUND
;
4040 if ((length
= GetFileSize( handle
, NULL
)))
4042 if ((mapping
= CreateFileMappingW( handle
, NULL
, PAGE_READONLY
, 0, 0, NULL
)))
4044 if ((p
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, length
)))
4049 MD5Update( &ctx
, p
, length
);
4051 UnmapViewOfFile( p
);
4053 memcpy( hash
->dwData
, ctx
.digest
, sizeof(hash
->dwData
) );
4056 CloseHandle( mapping
);
4061 /* Empty file -> set hash to 0 */
4062 memset( hash
->dwData
, 0, sizeof(hash
->dwData
) );
4066 CloseHandle( handle
);
4070 /***********************************************************************
4071 * MsiGetFileHashW [MSI.@]
4073 UINT WINAPI
MsiGetFileHashW( const WCHAR
*szFilePath
, DWORD dwOptions
, MSIFILEHASHINFO
*pHash
)
4075 TRACE( "%s, %#lx, %p\n", debugstr_w(szFilePath
), dwOptions
, pHash
);
4078 return ERROR_INVALID_PARAMETER
;
4081 return ERROR_PATH_NOT_FOUND
;
4084 return ERROR_INVALID_PARAMETER
;
4086 return ERROR_INVALID_PARAMETER
;
4087 if (pHash
->dwFileHashInfoSize
< sizeof *pHash
)
4088 return ERROR_INVALID_PARAMETER
;
4090 return msi_get_filehash( NULL
, szFilePath
, pHash
);
4093 /***********************************************************************
4094 * MsiGetFileHashA [MSI.@]
4096 UINT WINAPI
MsiGetFileHashA( const char *szFilePath
, DWORD dwOptions
, MSIFILEHASHINFO
*pHash
)
4101 TRACE( "%s, %#lx, %p\n", debugstr_a(szFilePath
), dwOptions
, pHash
);
4103 file
= strdupAtoW( szFilePath
);
4104 if (szFilePath
&& !file
)
4105 return ERROR_OUTOFMEMORY
;
4107 r
= MsiGetFileHashW( file
, dwOptions
, pHash
);
4112 /***********************************************************************
4113 * MsiAdvertiseScriptW [MSI.@]
4115 UINT WINAPI
MsiAdvertiseScriptW( const WCHAR
*szScriptFile
, DWORD dwFlags
, HKEY
*phRegData
, BOOL fRemoveItems
)
4117 FIXME( "%s, %#lx, %p, %d\n", debugstr_w(szScriptFile
), dwFlags
, phRegData
, fRemoveItems
);
4118 return ERROR_CALL_NOT_IMPLEMENTED
;
4121 /***********************************************************************
4122 * MsiAdvertiseScriptA [MSI.@]
4124 UINT WINAPI
MsiAdvertiseScriptA( const char *szScriptFile
, DWORD dwFlags
, HKEY
*phRegData
, BOOL fRemoveItems
)
4126 FIXME( "%s, %#lx, %p, %d\n", debugstr_a(szScriptFile
), dwFlags
, phRegData
, fRemoveItems
);
4127 return ERROR_CALL_NOT_IMPLEMENTED
;
4130 /***********************************************************************
4131 * MsiIsProductElevatedW [MSI.@]
4133 UINT WINAPI
MsiIsProductElevatedW( LPCWSTR szProduct
, BOOL
*pfElevated
)
4135 FIXME("%s %p - stub\n",
4136 debugstr_w( szProduct
), pfElevated
);
4138 return ERROR_SUCCESS
;
4141 /***********************************************************************
4142 * MsiIsProductElevatedA [MSI.@]
4144 UINT WINAPI
MsiIsProductElevatedA( LPCSTR szProduct
, BOOL
*pfElevated
)
4146 FIXME("%s %p - stub\n",
4147 debugstr_a( szProduct
), pfElevated
);
4149 return ERROR_SUCCESS
;
4152 /***********************************************************************
4153 * MsiSetExternalUIRecord [MSI.@]
4155 UINT WINAPI
MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler
, DWORD filter
, void *context
,
4156 INSTALLUI_HANDLER_RECORD
*prev
)
4158 TRACE( "%p, %#lx, %p, %p\n", handler
, filter
, context
, prev
);
4161 *prev
= gUIHandlerRecord
;
4163 gUIHandlerRecord
= handler
;
4164 gUIFilterRecord
= filter
;
4165 gUIContextRecord
= context
;
4167 return ERROR_SUCCESS
;
4170 /***********************************************************************
4171 * MsiInstallMissingComponentA [MSI.@]
4173 UINT WINAPI
MsiInstallMissingComponentA( LPCSTR product
, LPCSTR component
, INSTALLSTATE state
)
4176 WCHAR
*productW
= NULL
, *componentW
= NULL
;
4178 TRACE("%s, %s, %d\n", debugstr_a(product
), debugstr_a(component
), state
);
4180 if (product
&& !(productW
= strdupAtoW( product
)))
4181 return ERROR_OUTOFMEMORY
;
4183 if (component
&& !(componentW
= strdupAtoW( component
)))
4185 msi_free( productW
);
4186 return ERROR_OUTOFMEMORY
;
4189 r
= MsiInstallMissingComponentW( productW
, componentW
, state
);
4190 msi_free( productW
);
4191 msi_free( componentW
);
4195 /***********************************************************************
4196 * MsiInstallMissingComponentW [MSI.@]
4198 UINT WINAPI
MsiInstallMissingComponentW(LPCWSTR szProduct
, LPCWSTR szComponent
, INSTALLSTATE eInstallState
)
4200 FIXME("(%s %s %d\n", debugstr_w(szProduct
), debugstr_w(szComponent
), eInstallState
);
4201 return ERROR_SUCCESS
;
4204 UINT WINAPI
MsiProvideComponentA( const char *product
, const char *feature
, const char *component
, DWORD mode
,
4205 char *buf
, DWORD
*buflen
)
4207 WCHAR
*productW
= NULL
, *componentW
= NULL
, *featureW
= NULL
, *bufW
= NULL
;
4208 UINT r
= ERROR_OUTOFMEMORY
;
4212 TRACE( "%s, %s, %s, %#lx, %p, %p\n", debugstr_a(product
), debugstr_a(component
), debugstr_a(feature
), mode
,
4215 if (product
&& !(productW
= strdupAtoW( product
))) goto done
;
4216 if (feature
&& !(featureW
= strdupAtoW( feature
))) goto done
;
4217 if (component
&& !(componentW
= strdupAtoW( component
))) goto done
;
4219 r
= MsiProvideComponentW( productW
, featureW
, componentW
, mode
, NULL
, &lenW
);
4220 if (r
!= ERROR_SUCCESS
)
4223 if (!(bufW
= msi_alloc( ++lenW
* sizeof(WCHAR
) )))
4225 r
= ERROR_OUTOFMEMORY
;
4229 r
= MsiProvideComponentW( productW
, featureW
, componentW
, mode
, bufW
, &lenW
);
4230 if (r
!= ERROR_SUCCESS
)
4233 len
= WideCharToMultiByte( CP_ACP
, 0, bufW
, -1, NULL
, 0, NULL
, NULL
);
4237 r
= ERROR_MORE_DATA
;
4239 WideCharToMultiByte( CP_ACP
, 0, bufW
, -1, buf
, *buflen
, NULL
, NULL
);
4245 msi_free( productW
);
4246 msi_free( featureW
);
4247 msi_free( componentW
);
4252 UINT WINAPI
MsiProvideComponentW( const WCHAR
*product
, const WCHAR
*feature
, const WCHAR
*component
, DWORD mode
,
4253 WCHAR
*buf
, DWORD
*buflen
)
4257 TRACE( "%s, %s, %s, %#lx, %p, %p\n", debugstr_w(product
), debugstr_w(component
), debugstr_w(feature
), mode
,
4260 state
= MsiQueryFeatureStateW( product
, feature
);
4261 TRACE("feature state: %d\n", state
);
4264 case INSTALLMODE_NODETECTION
:
4268 FIXME( "mode %#lx not implemented\n", mode
);
4269 return ERROR_INSTALL_FAILURE
;
4272 state
= MsiGetComponentPathW( product
, component
, buf
, buflen
);
4273 TRACE("component state: %d\n", state
);
4276 case INSTALLSTATE_INVALIDARG
:
4277 return ERROR_INVALID_PARAMETER
;
4279 case INSTALLSTATE_MOREDATA
:
4280 return ERROR_MORE_DATA
;
4282 case INSTALLSTATE_ADVERTISED
:
4283 case INSTALLSTATE_LOCAL
:
4284 case INSTALLSTATE_SOURCE
:
4285 MsiUseFeatureW( product
, feature
);
4286 return ERROR_SUCCESS
;
4289 TRACE("MsiGetComponentPathW returned %d\n", state
);
4290 return ERROR_INSTALL_FAILURE
;
4294 /***********************************************************************
4295 * MsiBeginTransactionA [MSI.@]
4297 UINT WINAPI
MsiBeginTransactionA( const char *name
, DWORD attrs
, MSIHANDLE
*id
, HANDLE
*event
)
4302 FIXME( "%s, %#lx, %p, %p\n", debugstr_a(name
), attrs
, id
, event
);
4304 nameW
= strdupAtoW( name
);
4306 return ERROR_OUTOFMEMORY
;
4308 r
= MsiBeginTransactionW( nameW
, attrs
, id
, event
);
4313 /***********************************************************************
4314 * MsiBeginTransactionW [MSI.@]
4316 UINT WINAPI
MsiBeginTransactionW( const WCHAR
*name
, DWORD attrs
, MSIHANDLE
*id
, HANDLE
*event
)
4318 FIXME( "%s, %#lx, %p, %p\n", debugstr_w(name
), attrs
, id
, event
);
4320 *id
= (MSIHANDLE
)0xdeadbeef;
4321 *event
= (HANDLE
)0xdeadbeef;
4323 return ERROR_SUCCESS
;
4326 /***********************************************************************
4327 * MsiJoinTransaction [MSI.@]
4329 UINT WINAPI
MsiJoinTransaction( MSIHANDLE handle
, DWORD attrs
, HANDLE
*event
)
4331 FIXME( "%lu, %#lx, %p\n", handle
, attrs
, event
);
4333 *event
= (HANDLE
)0xdeadbeef;
4334 return ERROR_SUCCESS
;
4337 /***********************************************************************
4338 * MsiEndTransaction [MSI.@]
4340 UINT WINAPI
MsiEndTransaction( DWORD state
)
4342 FIXME( "%#lx\n", state
);
4343 return ERROR_SUCCESS
;
4346 UINT WINAPI
Migrate10CachedPackagesW( void *a
, void *b
, void *c
, DWORD d
)
4348 FIXME( "%p, %p, %p, %#lx\n", a
, b
, c
, d
);
4349 return ERROR_SUCCESS
;
4352 /***********************************************************************
4353 * MsiRemovePatchesA [MSI.@]
4355 UINT WINAPI
MsiRemovePatchesA(LPCSTR patchlist
, LPCSTR product
, INSTALLTYPE type
, LPCSTR propertylist
)
4357 FIXME("(%s %s %d %s\n", debugstr_a(patchlist
), debugstr_a(product
), type
, debugstr_a(propertylist
));
4358 return ERROR_SUCCESS
;
4361 /***********************************************************************
4362 * MsiRemovePatchesW [MSI.@]
4364 UINT WINAPI
MsiRemovePatchesW(LPCWSTR patchlist
, LPCWSTR product
, INSTALLTYPE type
, LPCWSTR propertylist
)
4366 FIXME("(%s %s %d %s\n", debugstr_w(patchlist
), debugstr_w(product
), type
, debugstr_w(propertylist
));
4367 return ERROR_SUCCESS
;