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
35 #include "msiserver.h"
48 #include "wine/debug.h"
49 #include "wine/unicode.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
53 static const WCHAR installerW
[] = {'\\','I','n','s','t','a','l','l','e','r',0};
55 UINT
msi_locate_product(LPCWSTR szProduct
, MSIINSTALLCONTEXT
*context
)
59 *context
= MSIINSTALLCONTEXT_NONE
;
60 if (!szProduct
) return ERROR_UNKNOWN_PRODUCT
;
62 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
63 &hkey
, FALSE
) == ERROR_SUCCESS
)
64 *context
= MSIINSTALLCONTEXT_USERMANAGED
;
65 else if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
66 &hkey
, FALSE
) == ERROR_SUCCESS
)
67 *context
= MSIINSTALLCONTEXT_MACHINE
;
68 else if (MSIREG_OpenProductKey(szProduct
, NULL
,
69 MSIINSTALLCONTEXT_USERUNMANAGED
,
70 &hkey
, FALSE
) == ERROR_SUCCESS
)
71 *context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
75 if (*context
== MSIINSTALLCONTEXT_NONE
)
76 return ERROR_UNKNOWN_PRODUCT
;
81 UINT WINAPI
MsiOpenProductA(LPCSTR szProduct
, MSIHANDLE
*phProduct
)
84 LPWSTR szwProd
= NULL
;
86 TRACE("%s %p\n",debugstr_a(szProduct
), phProduct
);
90 szwProd
= strdupAtoW( szProduct
);
92 return ERROR_OUTOFMEMORY
;
95 r
= MsiOpenProductW( szwProd
, phProduct
);
102 static UINT
MSI_OpenProductW(LPCWSTR szProduct
, MSIPACKAGE
**package
)
107 MSIINSTALLCONTEXT context
;
109 static const WCHAR managed
[] = {
110 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0};
111 static const WCHAR local
[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
113 TRACE("%s %p\n", debugstr_w(szProduct
), package
);
115 r
= msi_locate_product(szProduct
, &context
);
116 if (r
!= ERROR_SUCCESS
)
119 r
= MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &props
, FALSE
);
120 if (r
!= ERROR_SUCCESS
)
121 return ERROR_UNKNOWN_PRODUCT
;
123 if (context
== MSIINSTALLCONTEXT_USERMANAGED
)
124 path
= msi_reg_get_val_str(props
, managed
);
126 path
= msi_reg_get_val_str(props
, local
);
128 r
= ERROR_UNKNOWN_PRODUCT
;
130 if (!path
|| GetFileAttributesW(path
) == INVALID_FILE_ATTRIBUTES
)
133 if (PathIsRelativeW(path
))
135 r
= ERROR_INSTALL_PACKAGE_OPEN_FAILED
;
139 r
= MSI_OpenPackageW(path
, package
);
147 UINT WINAPI
MsiOpenProductW(LPCWSTR szProduct
, MSIHANDLE
*phProduct
)
149 MSIPACKAGE
*package
= NULL
;
150 WCHAR squished_pc
[GUID_SIZE
];
153 if (!szProduct
|| !squash_guid(szProduct
, squished_pc
))
154 return ERROR_INVALID_PARAMETER
;
157 return ERROR_INVALID_PARAMETER
;
159 r
= MSI_OpenProductW(szProduct
, &package
);
160 if (r
!= ERROR_SUCCESS
)
163 *phProduct
= alloc_msihandle(&package
->hdr
);
165 r
= ERROR_NOT_ENOUGH_MEMORY
;
167 msiobj_release(&package
->hdr
);
171 UINT WINAPI
MsiAdvertiseProductA(LPCSTR szPackagePath
, LPCSTR szScriptfilePath
,
172 LPCSTR szTransforms
, LANGID lgidLanguage
)
174 FIXME("%s %s %s %08x\n",debugstr_a(szPackagePath
),
175 debugstr_a(szScriptfilePath
), debugstr_a(szTransforms
), lgidLanguage
);
176 return ERROR_CALL_NOT_IMPLEMENTED
;
179 UINT WINAPI
MsiAdvertiseProductW(LPCWSTR szPackagePath
, LPCWSTR szScriptfilePath
,
180 LPCWSTR szTransforms
, LANGID lgidLanguage
)
182 FIXME("%s %s %s %08x\n",debugstr_w(szPackagePath
),
183 debugstr_w(szScriptfilePath
), debugstr_w(szTransforms
), lgidLanguage
);
184 return ERROR_CALL_NOT_IMPLEMENTED
;
187 UINT WINAPI
MsiAdvertiseProductExA(LPCSTR szPackagePath
, LPCSTR szScriptfilePath
,
188 LPCSTR szTransforms
, LANGID lgidLanguage
, DWORD dwPlatform
, DWORD dwOptions
)
190 FIXME("%s %s %s %08x %08x %08x\n", debugstr_a(szPackagePath
),
191 debugstr_a(szScriptfilePath
), debugstr_a(szTransforms
),
192 lgidLanguage
, dwPlatform
, dwOptions
);
193 return ERROR_CALL_NOT_IMPLEMENTED
;
196 UINT WINAPI
MsiAdvertiseProductExW( LPCWSTR szPackagePath
, LPCWSTR szScriptfilePath
,
197 LPCWSTR szTransforms
, LANGID lgidLanguage
, DWORD dwPlatform
, DWORD dwOptions
)
199 FIXME("%s %s %s %08x %08x %08x\n", debugstr_w(szPackagePath
),
200 debugstr_w(szScriptfilePath
), debugstr_w(szTransforms
),
201 lgidLanguage
, dwPlatform
, dwOptions
);
202 return ERROR_CALL_NOT_IMPLEMENTED
;
205 UINT WINAPI
MsiInstallProductA(LPCSTR szPackagePath
, LPCSTR szCommandLine
)
207 LPWSTR szwPath
= NULL
, szwCommand
= NULL
;
208 UINT r
= ERROR_OUTOFMEMORY
;
210 TRACE("%s %s\n",debugstr_a(szPackagePath
), debugstr_a(szCommandLine
));
214 szwPath
= strdupAtoW( szPackagePath
);
221 szwCommand
= strdupAtoW( szCommandLine
);
226 r
= MsiInstallProductW( szwPath
, szwCommand
);
230 msi_free( szwCommand
);
235 UINT WINAPI
MsiInstallProductW(LPCWSTR szPackagePath
, LPCWSTR szCommandLine
)
237 MSIPACKAGE
*package
= NULL
;
240 TRACE("%s %s\n",debugstr_w(szPackagePath
), debugstr_w(szCommandLine
));
243 return ERROR_INVALID_PARAMETER
;
246 return ERROR_PATH_NOT_FOUND
;
248 r
= MSI_OpenPackageW( szPackagePath
, &package
);
249 if (r
== ERROR_SUCCESS
)
251 r
= MSI_InstallPackage( package
, szPackagePath
, szCommandLine
);
252 msiobj_release( &package
->hdr
);
258 UINT WINAPI
MsiReinstallProductA(LPCSTR szProduct
, DWORD dwReinstallMode
)
263 TRACE("%s %08x\n", debugstr_a(szProduct
), dwReinstallMode
);
265 wszProduct
= strdupAtoW(szProduct
);
267 rc
= MsiReinstallProductW(wszProduct
, dwReinstallMode
);
269 msi_free(wszProduct
);
273 UINT WINAPI
MsiReinstallProductW(LPCWSTR szProduct
, DWORD dwReinstallMode
)
275 TRACE("%s %08x\n", debugstr_w(szProduct
), dwReinstallMode
);
277 return MsiReinstallFeatureW(szProduct
, szAll
, dwReinstallMode
);
280 UINT WINAPI
MsiApplyPatchA(LPCSTR szPatchPackage
, LPCSTR szInstallPackage
,
281 INSTALLTYPE eInstallType
, LPCSTR szCommandLine
)
283 LPWSTR patch_package
= NULL
;
284 LPWSTR install_package
= NULL
;
285 LPWSTR command_line
= NULL
;
286 UINT r
= ERROR_OUTOFMEMORY
;
288 TRACE("%s %s %d %s\n", debugstr_a(szPatchPackage
), debugstr_a(szInstallPackage
),
289 eInstallType
, debugstr_a(szCommandLine
));
291 if (szPatchPackage
&& !(patch_package
= strdupAtoW(szPatchPackage
)))
294 if (szInstallPackage
&& !(install_package
= strdupAtoW(szInstallPackage
)))
297 if (szCommandLine
&& !(command_line
= strdupAtoW(szCommandLine
)))
300 r
= MsiApplyPatchW(patch_package
, install_package
, eInstallType
, command_line
);
303 msi_free(patch_package
);
304 msi_free(install_package
);
305 msi_free(command_line
);
310 static UINT
get_patch_product_codes( LPCWSTR szPatchPackage
, WCHAR
***product_codes
)
312 MSIHANDLE patch
, info
= 0;
315 static WCHAR empty
[] = {0};
318 r
= MsiOpenDatabaseW( szPatchPackage
, MSIDBOPEN_READONLY
, &patch
);
319 if (r
!= ERROR_SUCCESS
)
322 r
= MsiGetSummaryInformationW( patch
, NULL
, 0, &info
);
323 if (r
!= ERROR_SUCCESS
)
327 r
= MsiSummaryInfoGetPropertyW( info
, PID_TEMPLATE
, &type
, NULL
, NULL
, empty
, &size
);
328 if (r
!= ERROR_MORE_DATA
|| !size
|| type
!= VT_LPSTR
)
330 ERR("Failed to read product codes from patch\n");
331 r
= ERROR_FUNCTION_FAILED
;
335 codes
= msi_alloc( ++size
* sizeof(WCHAR
) );
338 r
= ERROR_OUTOFMEMORY
;
342 r
= MsiSummaryInfoGetPropertyW( info
, PID_TEMPLATE
, &type
, NULL
, NULL
, codes
, &size
);
343 if (r
== ERROR_SUCCESS
)
344 *product_codes
= msi_split_string( codes
, ';' );
347 MsiCloseHandle( info
);
348 MsiCloseHandle( patch
);
353 static UINT
MSI_ApplyPatchW(LPCWSTR szPatchPackage
, LPCWSTR szProductCode
, LPCWSTR szCommandLine
)
355 UINT i
, r
= ERROR_FUNCTION_FAILED
;
357 LPCWSTR cmd_ptr
= szCommandLine
;
358 LPWSTR cmd
, *codes
= NULL
;
359 BOOL succeeded
= FALSE
;
361 static const WCHAR fmt
[] = {'%','s',' ','P','A','T','C','H','=','"','%','s','"',0};
362 static WCHAR empty
[] = {0};
364 if (!szPatchPackage
|| !szPatchPackage
[0])
365 return ERROR_INVALID_PARAMETER
;
367 if (!szProductCode
&& (r
= get_patch_product_codes( szPatchPackage
, &codes
)))
373 size
= strlenW(cmd_ptr
) + strlenW(fmt
) + strlenW(szPatchPackage
) + 1;
374 cmd
= msi_alloc(size
* sizeof(WCHAR
));
378 return ERROR_OUTOFMEMORY
;
380 sprintfW(cmd
, fmt
, cmd_ptr
, szPatchPackage
);
383 r
= MsiConfigureProductExW(szProductCode
, INSTALLLEVEL_DEFAULT
, INSTALLSTATE_DEFAULT
, cmd
);
386 for (i
= 0; codes
[i
]; i
++)
388 r
= MsiConfigureProductExW(codes
[i
], INSTALLLEVEL_DEFAULT
, INSTALLSTATE_DEFAULT
, cmd
);
389 if (r
== ERROR_SUCCESS
)
391 TRACE("patch applied\n");
405 UINT WINAPI
MsiApplyPatchW(LPCWSTR szPatchPackage
, LPCWSTR szInstallPackage
,
406 INSTALLTYPE eInstallType
, LPCWSTR szCommandLine
)
408 TRACE("%s %s %d %s\n", debugstr_w(szPatchPackage
), debugstr_w(szInstallPackage
),
409 eInstallType
, debugstr_w(szCommandLine
));
411 if (szInstallPackage
|| eInstallType
== INSTALLTYPE_NETWORK_IMAGE
||
412 eInstallType
== INSTALLTYPE_SINGLE_INSTANCE
)
414 FIXME("Only reading target products from patch\n");
415 return ERROR_CALL_NOT_IMPLEMENTED
;
418 return MSI_ApplyPatchW(szPatchPackage
, NULL
, szCommandLine
);
421 UINT WINAPI
MsiApplyMultiplePatchesA(LPCSTR szPatchPackages
,
422 LPCSTR szProductCode
, LPCSTR szPropertiesList
)
424 LPWSTR patch_packages
= NULL
;
425 LPWSTR product_code
= NULL
;
426 LPWSTR properties_list
= NULL
;
427 UINT r
= ERROR_OUTOFMEMORY
;
429 TRACE("%s %s %s\n", debugstr_a(szPatchPackages
), debugstr_a(szProductCode
),
430 debugstr_a(szPropertiesList
));
432 if (!szPatchPackages
|| !szPatchPackages
[0])
433 return ERROR_INVALID_PARAMETER
;
435 if (!(patch_packages
= strdupAtoW(szPatchPackages
)))
436 return ERROR_OUTOFMEMORY
;
438 if (szProductCode
&& !(product_code
= strdupAtoW(szProductCode
)))
441 if (szPropertiesList
&& !(properties_list
= strdupAtoW(szPropertiesList
)))
444 r
= MsiApplyMultiplePatchesW(patch_packages
, product_code
, properties_list
);
447 msi_free(patch_packages
);
448 msi_free(product_code
);
449 msi_free(properties_list
);
454 UINT WINAPI
MsiApplyMultiplePatchesW(LPCWSTR szPatchPackages
,
455 LPCWSTR szProductCode
, LPCWSTR szPropertiesList
)
457 UINT r
= ERROR_SUCCESS
;
460 TRACE("%s %s %s\n", debugstr_w(szPatchPackages
), debugstr_w(szProductCode
),
461 debugstr_w(szPropertiesList
));
463 if (!szPatchPackages
|| !szPatchPackages
[0])
464 return ERROR_INVALID_PARAMETER
;
466 beg
= end
= szPatchPackages
;
472 while (*beg
== ' ') beg
++;
473 while (*end
&& *end
!= ';') end
++;
476 while (len
&& beg
[len
- 1] == ' ') len
--;
478 if (!len
) return ERROR_INVALID_NAME
;
480 patch
= msi_alloc((len
+ 1) * sizeof(WCHAR
));
482 return ERROR_OUTOFMEMORY
;
484 memcpy(patch
, beg
, len
* sizeof(WCHAR
));
487 r
= MSI_ApplyPatchW(patch
, szProductCode
, szPropertiesList
);
490 if (r
!= ERROR_SUCCESS
)
498 static void free_patchinfo( DWORD count
, MSIPATCHSEQUENCEINFOW
*info
)
501 for (i
= 0; i
< count
; i
++) msi_free( (WCHAR
*)info
[i
].szPatchData
);
505 static MSIPATCHSEQUENCEINFOW
*patchinfoAtoW( DWORD count
, const MSIPATCHSEQUENCEINFOA
*info
)
508 MSIPATCHSEQUENCEINFOW
*ret
;
510 if (!(ret
= msi_alloc( count
* sizeof(MSIPATCHSEQUENCEINFOW
) ))) return NULL
;
511 for (i
= 0; i
< count
; i
++)
513 if (info
[i
].szPatchData
&& !(ret
[i
].szPatchData
= strdupAtoW( info
[i
].szPatchData
)))
515 free_patchinfo( i
, ret
);
518 ret
[i
].ePatchDataType
= info
[i
].ePatchDataType
;
519 ret
[i
].dwOrder
= info
[i
].dwOrder
;
520 ret
[i
].uStatus
= info
[i
].uStatus
;
525 UINT WINAPI
MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath
,
526 DWORD cPatchInfo
, PMSIPATCHSEQUENCEINFOA pPatchInfo
)
529 WCHAR
*package_path
= NULL
;
530 MSIPATCHSEQUENCEINFOW
*psi
;
532 TRACE("%s, %u, %p\n", debugstr_a(szProductPackagePath
), cPatchInfo
, pPatchInfo
);
534 if (szProductPackagePath
&& !(package_path
= strdupAtoW( szProductPackagePath
)))
535 return ERROR_OUTOFMEMORY
;
537 if (!(psi
= patchinfoAtoW( cPatchInfo
, pPatchInfo
)))
539 msi_free( package_path
);
540 return ERROR_OUTOFMEMORY
;
542 r
= MsiDetermineApplicablePatchesW( package_path
, cPatchInfo
, psi
);
543 if (r
== ERROR_SUCCESS
)
545 for (i
= 0; i
< cPatchInfo
; i
++)
547 pPatchInfo
[i
].dwOrder
= psi
[i
].dwOrder
;
548 pPatchInfo
[i
].uStatus
= psi
[i
].uStatus
;
551 msi_free( package_path
);
552 free_patchinfo( cPatchInfo
, psi
);
556 static UINT
MSI_ApplicablePatchW( MSIPACKAGE
*package
, LPCWSTR patch
)
559 MSIDATABASE
*patch_db
;
560 UINT r
= ERROR_SUCCESS
;
562 r
= MSI_OpenDatabaseW( patch
, MSIDBOPEN_READONLY
, &patch_db
);
563 if (r
!= ERROR_SUCCESS
)
565 WARN("failed to open patch file %s\n", debugstr_w(patch
));
569 si
= MSI_GetSummaryInformationW( patch_db
->storage
, 0 );
572 msiobj_release( &patch_db
->hdr
);
573 return ERROR_FUNCTION_FAILED
;
576 r
= msi_check_patch_applicable( package
, si
);
577 if (r
!= ERROR_SUCCESS
)
578 TRACE("patch not applicable\n");
580 msiobj_release( &patch_db
->hdr
);
581 msiobj_release( &si
->hdr
);
585 /* IXMLDOMDocument should be set to XPath mode already */
586 static UINT
MSI_ApplicablePatchXML( MSIPACKAGE
*package
, IXMLDOMDocument
*desc
)
588 static const WCHAR queryW
[] = {'M','s','i','P','a','t','c','h','/',
589 'T','a','r','g','e','t','P','r','o','d','u','c','t','/',
590 'T','a','r','g','e','t','P','r','o','d','u','c','t','C','o','d','e',0};
591 UINT r
= ERROR_FUNCTION_FAILED
;
592 IXMLDOMNodeList
*list
;
598 product_code
= msi_dup_property( package
->db
, szProductCode
);
601 /* FIXME: the property ProductCode should be written into the DB somewhere */
602 ERR("no product code to check\n");
603 return ERROR_SUCCESS
;
606 s
= SysAllocString(queryW
);
607 hr
= IXMLDOMDocument_selectNodes( desc
, s
, &list
);
610 return ERROR_INVALID_PATCH_XML
;
612 while (IXMLDOMNodeList_nextNode( list
, &node
) == S_OK
&& r
!= ERROR_SUCCESS
)
614 hr
= IXMLDOMNode_get_text( node
, &s
);
615 IXMLDOMNode_Release( node
);
616 if (!strcmpW( s
, product_code
)) r
= ERROR_SUCCESS
;
619 IXMLDOMNodeList_Release( list
);
621 if (r
!= ERROR_SUCCESS
)
622 TRACE("patch not applicable\n");
624 msi_free( product_code
);
628 static UINT
determine_patch_sequence( MSIPACKAGE
*package
, DWORD count
, MSIPATCHSEQUENCEINFOW
*info
)
630 IXMLDOMDocument
*desc
= NULL
;
634 FIXME("patch ordering not supported\n");
636 for (i
= 0; i
< count
; i
++)
638 switch (info
[i
].ePatchDataType
)
640 case MSIPATCH_DATATYPE_PATCHFILE
:
642 if (MSI_ApplicablePatchW( package
, info
[i
].szPatchData
) != ERROR_SUCCESS
)
644 info
[i
].dwOrder
= ~0u;
645 info
[i
].uStatus
= ERROR_PATCH_TARGET_NOT_FOUND
;
650 info
[i
].uStatus
= ERROR_SUCCESS
;
654 case MSIPATCH_DATATYPE_XMLPATH
:
655 case MSIPATCH_DATATYPE_XMLBLOB
:
663 hr
= CoCreateInstance( &CLSID_DOMDocument30
, NULL
, CLSCTX_INPROC_SERVER
,
664 &IID_IXMLDOMDocument
, (void**)&desc
);
667 ERR("failed to create DOMDocument30 instance, 0x%08x\n", hr
);
668 return ERROR_FUNCTION_FAILED
;
672 s
= SysAllocString( info
[i
].szPatchData
);
673 if (info
[i
].ePatchDataType
== MSIPATCH_DATATYPE_XMLPATH
)
677 V_VT(&src
) = VT_BSTR
;
679 hr
= IXMLDOMDocument_load( desc
, src
, &b
);
682 hr
= IXMLDOMDocument_loadXML( desc
, s
, &b
);
686 ERR("failed to parse patch description\n");
687 IXMLDOMDocument_Release( desc
);
691 if (MSI_ApplicablePatchXML( package
, desc
) != ERROR_SUCCESS
)
693 info
[i
].dwOrder
= ~0u;
694 info
[i
].uStatus
= ERROR_PATCH_TARGET_NOT_FOUND
;
699 info
[i
].uStatus
= ERROR_SUCCESS
;
705 FIXME("unknown patch data type %u\n", info
[i
].ePatchDataType
);
707 info
[i
].uStatus
= ERROR_SUCCESS
;
712 TRACE("szPatchData: %s\n", debugstr_w(info
[i
].szPatchData
));
713 TRACE("ePatchDataType: %u\n", info
[i
].ePatchDataType
);
714 TRACE("dwOrder: %u\n", info
[i
].dwOrder
);
715 TRACE("uStatus: %u\n", info
[i
].uStatus
);
718 if (desc
) IXMLDOMDocument_Release( desc
);
720 return ERROR_SUCCESS
;
723 UINT WINAPI
MsiDetermineApplicablePatchesW(LPCWSTR szProductPackagePath
,
724 DWORD cPatchInfo
, PMSIPATCHSEQUENCEINFOW pPatchInfo
)
729 TRACE("%s, %u, %p\n", debugstr_w(szProductPackagePath
), cPatchInfo
, pPatchInfo
);
731 r
= MSI_OpenPackageW( szProductPackagePath
, &package
);
732 if (r
!= ERROR_SUCCESS
)
734 ERR("failed to open package %u\n", r
);
737 r
= determine_patch_sequence( package
, cPatchInfo
, pPatchInfo
);
738 msiobj_release( &package
->hdr
);
742 UINT WINAPI
MsiDeterminePatchSequenceA( LPCSTR product
, LPCSTR usersid
,
743 MSIINSTALLCONTEXT context
, DWORD count
, PMSIPATCHSEQUENCEINFOA patchinfo
)
746 WCHAR
*productW
, *usersidW
= NULL
;
747 MSIPATCHSEQUENCEINFOW
*patchinfoW
;
749 TRACE("%s, %s, %d, %d, %p\n", debugstr_a(product
), debugstr_a(usersid
),
750 context
, count
, patchinfo
);
752 if (!product
) return ERROR_INVALID_PARAMETER
;
753 if (!(productW
= strdupAtoW( product
))) return ERROR_OUTOFMEMORY
;
754 if (usersid
&& !(usersidW
= strdupAtoW( usersid
)))
756 msi_free( productW
);
757 return ERROR_OUTOFMEMORY
;
759 if (!(patchinfoW
= patchinfoAtoW( count
, patchinfo
)))
761 msi_free( productW
);
762 msi_free( usersidW
);
763 return ERROR_OUTOFMEMORY
;
765 r
= MsiDeterminePatchSequenceW( productW
, usersidW
, context
, count
, patchinfoW
);
766 if (r
== ERROR_SUCCESS
)
768 for (i
= 0; i
< count
; i
++)
770 patchinfo
[i
].dwOrder
= patchinfoW
[i
].dwOrder
;
771 patchinfo
[i
].uStatus
= patchinfoW
[i
].uStatus
;
774 msi_free( productW
);
775 msi_free( usersidW
);
776 free_patchinfo( count
, patchinfoW
);
780 static UINT
open_package( const WCHAR
*product
, const WCHAR
*usersid
,
781 MSIINSTALLCONTEXT context
, MSIPACKAGE
**package
)
785 WCHAR
*localpath
, sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
787 r
= MSIREG_OpenInstallProps( product
, context
, usersid
, &props
, FALSE
);
788 if (r
!= ERROR_SUCCESS
) return ERROR_BAD_CONFIGURATION
;
790 if ((localpath
= msi_reg_get_val_str( props
, szLocalPackage
)))
792 strcpyW( sourcepath
, localpath
);
793 msi_free( localpath
);
795 RegCloseKey( props
);
796 if (!localpath
|| GetFileAttributesW( sourcepath
) == INVALID_FILE_ATTRIBUTES
)
798 DWORD sz
= sizeof(sourcepath
);
799 MsiSourceListGetInfoW( product
, usersid
, context
, MSICODE_PRODUCT
,
800 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
801 sz
= sizeof(filename
);
802 MsiSourceListGetInfoW( product
, usersid
, context
, MSICODE_PRODUCT
,
803 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
804 strcatW( sourcepath
, filename
);
806 if (GetFileAttributesW( sourcepath
) == INVALID_FILE_ATTRIBUTES
)
807 return ERROR_INSTALL_SOURCE_ABSENT
;
809 return MSI_OpenPackageW( sourcepath
, package
);
812 UINT WINAPI
MsiDeterminePatchSequenceW( LPCWSTR product
, LPCWSTR usersid
,
813 MSIINSTALLCONTEXT context
, DWORD count
, PMSIPATCHSEQUENCEINFOW patchinfo
)
818 TRACE("%s, %s, %d, %d, %p\n", debugstr_w(product
), debugstr_w(usersid
),
819 context
, count
, patchinfo
);
821 if (!product
) return ERROR_INVALID_PARAMETER
;
822 r
= open_package( product
, usersid
, context
, &package
);
823 if (r
!= ERROR_SUCCESS
) return r
;
825 r
= determine_patch_sequence( package
, count
, patchinfo
);
826 msiobj_release( &package
->hdr
);
830 UINT WINAPI
MsiConfigureProductExW(LPCWSTR szProduct
, int iInstallLevel
,
831 INSTALLSTATE eInstallState
, LPCWSTR szCommandLine
)
833 MSIPACKAGE
* package
= NULL
;
834 MSIINSTALLCONTEXT context
;
837 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
840 static const WCHAR szInstalled
[] = {
841 ' ','I','n','s','t','a','l','l','e','d','=','1',0};
842 static const WCHAR szMaxInstallLevel
[] = {
843 ' ','I','N','S','T','A','L','L','L','E','V','E','L','=','3','2','7','6','7',0};
844 static const WCHAR szRemoveAll
[] = {
845 ' ','R','E','M','O','V','E','=','A','L','L',0};
846 static const WCHAR szMachine
[] = {
847 ' ','A','L','L','U','S','E','R','S','=','1',0};
849 TRACE("%s %d %d %s\n",debugstr_w(szProduct
), iInstallLevel
, eInstallState
,
850 debugstr_w(szCommandLine
));
852 if (!szProduct
|| lstrlenW(szProduct
) != GUID_SIZE
- 1)
853 return ERROR_INVALID_PARAMETER
;
855 if (eInstallState
== INSTALLSTATE_ADVERTISED
||
856 eInstallState
== INSTALLSTATE_SOURCE
)
858 FIXME("State %d not implemented\n", eInstallState
);
859 return ERROR_CALL_NOT_IMPLEMENTED
;
862 r
= msi_locate_product(szProduct
, &context
);
863 if (r
!= ERROR_SUCCESS
)
866 r
= open_package(szProduct
, NULL
, context
, &package
);
867 if (r
!= ERROR_SUCCESS
)
870 sz
= lstrlenW(szInstalled
) + 1;
873 sz
+= lstrlenW(szCommandLine
);
875 if (eInstallState
!= INSTALLSTATE_DEFAULT
)
876 sz
+= lstrlenW(szMaxInstallLevel
);
878 if (eInstallState
== INSTALLSTATE_ABSENT
)
879 sz
+= lstrlenW(szRemoveAll
);
881 if (context
== MSIINSTALLCONTEXT_MACHINE
)
882 sz
+= lstrlenW(szMachine
);
884 commandline
= msi_alloc(sz
* sizeof(WCHAR
));
887 r
= ERROR_OUTOFMEMORY
;
893 lstrcpyW(commandline
,szCommandLine
);
895 if (eInstallState
!= INSTALLSTATE_DEFAULT
)
896 lstrcatW(commandline
, szMaxInstallLevel
);
898 if (eInstallState
== INSTALLSTATE_ABSENT
)
899 lstrcatW(commandline
, szRemoveAll
);
901 if (context
== MSIINSTALLCONTEXT_MACHINE
)
902 lstrcatW(commandline
, szMachine
);
904 sz
= sizeof(sourcepath
);
905 MsiSourceListGetInfoW(szProduct
, NULL
, context
, MSICODE_PRODUCT
,
906 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
908 sz
= sizeof(filename
);
909 MsiSourceListGetInfoW(szProduct
, NULL
, context
, MSICODE_PRODUCT
,
910 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
912 strcatW(sourcepath
, filename
);
914 r
= MSI_InstallPackage( package
, sourcepath
, commandline
);
916 msi_free(commandline
);
919 msiobj_release( &package
->hdr
);
924 UINT WINAPI
MsiConfigureProductExA(LPCSTR szProduct
, int iInstallLevel
,
925 INSTALLSTATE eInstallState
, LPCSTR szCommandLine
)
927 LPWSTR szwProduct
= NULL
;
928 LPWSTR szwCommandLine
= NULL
;
929 UINT r
= ERROR_OUTOFMEMORY
;
933 szwProduct
= strdupAtoW( szProduct
);
940 szwCommandLine
= strdupAtoW( szCommandLine
);
945 r
= MsiConfigureProductExW( szwProduct
, iInstallLevel
, eInstallState
,
948 msi_free( szwProduct
);
949 msi_free( szwCommandLine
);
954 UINT WINAPI
MsiConfigureProductA(LPCSTR szProduct
, int iInstallLevel
,
955 INSTALLSTATE eInstallState
)
957 LPWSTR szwProduct
= NULL
;
960 TRACE("%s %d %d\n",debugstr_a(szProduct
), iInstallLevel
, eInstallState
);
964 szwProduct
= strdupAtoW( szProduct
);
966 return ERROR_OUTOFMEMORY
;
969 r
= MsiConfigureProductW( szwProduct
, iInstallLevel
, eInstallState
);
970 msi_free( szwProduct
);
975 UINT WINAPI
MsiConfigureProductW(LPCWSTR szProduct
, int iInstallLevel
,
976 INSTALLSTATE eInstallState
)
978 return MsiConfigureProductExW(szProduct
, iInstallLevel
, eInstallState
, NULL
);
981 UINT WINAPI
MsiGetProductCodeA(LPCSTR szComponent
, LPSTR szBuffer
)
983 LPWSTR szwComponent
= NULL
;
985 WCHAR szwBuffer
[GUID_SIZE
];
987 TRACE("%s %p\n", debugstr_a(szComponent
), szBuffer
);
991 szwComponent
= strdupAtoW( szComponent
);
993 return ERROR_OUTOFMEMORY
;
997 r
= MsiGetProductCodeW( szwComponent
, szwBuffer
);
1000 WideCharToMultiByte(CP_ACP
, 0, szwBuffer
, -1, szBuffer
, GUID_SIZE
, NULL
, NULL
);
1002 msi_free( szwComponent
);
1007 UINT WINAPI
MsiGetProductCodeW(LPCWSTR szComponent
, LPWSTR szBuffer
)
1010 HKEY compkey
, prodkey
;
1011 WCHAR squished_comp
[GUID_SIZE
];
1012 WCHAR squished_prod
[GUID_SIZE
];
1013 DWORD sz
= GUID_SIZE
;
1015 TRACE("%s %p\n", debugstr_w(szComponent
), szBuffer
);
1017 if (!szComponent
|| !*szComponent
)
1018 return ERROR_INVALID_PARAMETER
;
1020 if (!squash_guid(szComponent
, squished_comp
))
1021 return ERROR_INVALID_PARAMETER
;
1023 if (MSIREG_OpenUserDataComponentKey(szComponent
, NULL
, &compkey
, FALSE
) != ERROR_SUCCESS
&&
1024 MSIREG_OpenUserDataComponentKey(szComponent
, szLocalSid
, &compkey
, FALSE
) != ERROR_SUCCESS
)
1026 return ERROR_UNKNOWN_COMPONENT
;
1029 rc
= RegEnumValueW(compkey
, 0, squished_prod
, &sz
, NULL
, NULL
, NULL
, NULL
);
1030 if (rc
!= ERROR_SUCCESS
)
1032 RegCloseKey(compkey
);
1033 return ERROR_UNKNOWN_COMPONENT
;
1036 /* check simple case, only one product */
1037 rc
= RegEnumValueW(compkey
, 1, squished_prod
, &sz
, NULL
, NULL
, NULL
, NULL
);
1038 if (rc
== ERROR_NO_MORE_ITEMS
)
1045 while ((rc
= RegEnumValueW(compkey
, index
, squished_prod
, &sz
,
1046 NULL
, NULL
, NULL
, NULL
)) != ERROR_NO_MORE_ITEMS
)
1050 unsquash_guid(squished_prod
, szBuffer
);
1052 if (MSIREG_OpenProductKey(szBuffer
, NULL
,
1053 MSIINSTALLCONTEXT_USERMANAGED
,
1054 &prodkey
, FALSE
) == ERROR_SUCCESS
||
1055 MSIREG_OpenProductKey(szBuffer
, NULL
,
1056 MSIINSTALLCONTEXT_USERUNMANAGED
,
1057 &prodkey
, FALSE
) == ERROR_SUCCESS
||
1058 MSIREG_OpenProductKey(szBuffer
, NULL
,
1059 MSIINSTALLCONTEXT_MACHINE
,
1060 &prodkey
, FALSE
) == ERROR_SUCCESS
)
1062 RegCloseKey(prodkey
);
1068 rc
= ERROR_INSTALL_FAILURE
;
1071 RegCloseKey(compkey
);
1072 unsquash_guid(squished_prod
, szBuffer
);
1076 static LPWSTR
msi_reg_get_value(HKEY hkey
, LPCWSTR name
, DWORD
*type
)
1082 static const WCHAR format
[] = {'%','d',0};
1084 res
= RegQueryValueExW(hkey
, name
, NULL
, type
, NULL
, NULL
);
1085 if (res
!= ERROR_SUCCESS
)
1088 if (*type
== REG_SZ
)
1089 return msi_reg_get_val_str(hkey
, name
);
1091 if (!msi_reg_get_val_dword(hkey
, name
, &dval
))
1094 sprintfW(temp
, format
, dval
);
1095 return strdupW(temp
);
1098 static UINT
MSI_GetProductInfo(LPCWSTR szProduct
, LPCWSTR szAttribute
,
1099 awstring
*szValue
, LPDWORD pcchValueBuf
)
1101 MSIINSTALLCONTEXT context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
1102 UINT r
= ERROR_UNKNOWN_PROPERTY
;
1103 HKEY prodkey
, userdata
, source
;
1105 WCHAR squished_pc
[GUID_SIZE
];
1106 WCHAR packagecode
[GUID_SIZE
];
1107 BOOL badconfig
= FALSE
;
1109 DWORD type
= REG_NONE
;
1111 static WCHAR empty
[] = {0};
1112 static const WCHAR sourcelist
[] = {
1113 'S','o','u','r','c','e','L','i','s','t',0};
1114 static const WCHAR display_name
[] = {
1115 'D','i','s','p','l','a','y','N','a','m','e',0};
1116 static const WCHAR display_version
[] = {
1117 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1118 static const WCHAR assignment
[] = {
1119 'A','s','s','i','g','n','m','e','n','t',0};
1121 TRACE("%s %s %p %p\n", debugstr_w(szProduct
),
1122 debugstr_w(szAttribute
), szValue
, pcchValueBuf
);
1124 if ((szValue
->str
.w
&& !pcchValueBuf
) || !szProduct
|| !szAttribute
)
1125 return ERROR_INVALID_PARAMETER
;
1127 if (!squash_guid(szProduct
, squished_pc
))
1128 return ERROR_INVALID_PARAMETER
;
1130 if ((r
= MSIREG_OpenProductKey(szProduct
, NULL
,
1131 MSIINSTALLCONTEXT_USERMANAGED
,
1132 &prodkey
, FALSE
)) != ERROR_SUCCESS
&&
1133 (r
= MSIREG_OpenProductKey(szProduct
, NULL
,
1134 MSIINSTALLCONTEXT_USERUNMANAGED
,
1135 &prodkey
, FALSE
)) != ERROR_SUCCESS
&&
1136 (r
= MSIREG_OpenProductKey(szProduct
, NULL
,
1137 MSIINSTALLCONTEXT_MACHINE
,
1138 &prodkey
, FALSE
)) == ERROR_SUCCESS
)
1140 context
= MSIINSTALLCONTEXT_MACHINE
;
1143 MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &userdata
, FALSE
);
1145 if (!strcmpW( szAttribute
, INSTALLPROPERTY_HELPLINKW
) ||
1146 !strcmpW( szAttribute
, INSTALLPROPERTY_HELPTELEPHONEW
) ||
1147 !strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLDATEW
) ||
1148 !strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
) ||
1149 !strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLLOCATIONW
) ||
1150 !strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLSOURCEW
) ||
1151 !strcmpW( szAttribute
, INSTALLPROPERTY_LOCALPACKAGEW
) ||
1152 !strcmpW( szAttribute
, INSTALLPROPERTY_PUBLISHERW
) ||
1153 !strcmpW( szAttribute
, INSTALLPROPERTY_URLINFOABOUTW
) ||
1154 !strcmpW( szAttribute
, INSTALLPROPERTY_URLUPDATEINFOW
) ||
1155 !strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONMINORW
) ||
1156 !strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONMAJORW
) ||
1157 !strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONSTRINGW
) ||
1158 !strcmpW( szAttribute
, INSTALLPROPERTY_PRODUCTIDW
) ||
1159 !strcmpW( szAttribute
, INSTALLPROPERTY_REGCOMPANYW
) ||
1160 !strcmpW( szAttribute
, INSTALLPROPERTY_REGOWNERW
))
1164 r
= ERROR_UNKNOWN_PRODUCT
;
1169 return ERROR_UNKNOWN_PROPERTY
;
1171 if (!strcmpW( szAttribute
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
))
1172 szAttribute
= display_name
;
1173 else if (!strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONSTRINGW
))
1174 szAttribute
= display_version
;
1176 val
= msi_reg_get_value(userdata
, szAttribute
, &type
);
1180 else if (!strcmpW( szAttribute
, INSTALLPROPERTY_INSTANCETYPEW
) ||
1181 !strcmpW( szAttribute
, INSTALLPROPERTY_TRANSFORMSW
) ||
1182 !strcmpW( szAttribute
, INSTALLPROPERTY_LANGUAGEW
) ||
1183 !strcmpW( szAttribute
, INSTALLPROPERTY_PRODUCTNAMEW
) ||
1184 !strcmpW( szAttribute
, INSTALLPROPERTY_ASSIGNMENTTYPEW
) ||
1185 !strcmpW( szAttribute
, INSTALLPROPERTY_PACKAGECODEW
) ||
1186 !strcmpW( szAttribute
, INSTALLPROPERTY_VERSIONW
) ||
1187 !strcmpW( szAttribute
, INSTALLPROPERTY_PRODUCTICONW
) ||
1188 !strcmpW( szAttribute
, INSTALLPROPERTY_PACKAGENAMEW
) ||
1189 !strcmpW( szAttribute
, INSTALLPROPERTY_AUTHORIZED_LUA_APPW
))
1193 r
= ERROR_UNKNOWN_PRODUCT
;
1197 if (!strcmpW( szAttribute
, INSTALLPROPERTY_ASSIGNMENTTYPEW
))
1198 szAttribute
= assignment
;
1200 if (!strcmpW( szAttribute
, INSTALLPROPERTY_PACKAGENAMEW
))
1202 res
= RegOpenKeyW(prodkey
, sourcelist
, &source
);
1203 if (res
!= ERROR_SUCCESS
)
1205 r
= ERROR_UNKNOWN_PRODUCT
;
1209 val
= msi_reg_get_value(source
, szAttribute
, &type
);
1213 RegCloseKey(source
);
1217 val
= msi_reg_get_value(prodkey
, szAttribute
, &type
);
1222 if (val
!= empty
&& type
!= REG_DWORD
&&
1223 !strcmpW( szAttribute
, INSTALLPROPERTY_PACKAGECODEW
))
1225 if (lstrlenW(val
) != SQUISH_GUID_SIZE
- 1)
1229 unsquash_guid(val
, packagecode
);
1231 val
= strdupW(packagecode
);
1238 r
= ERROR_UNKNOWN_PROPERTY
;
1244 /* If szBuffer (szValue->str) is NULL, there's no need to copy the value
1245 * out. Also, *pcchValueBuf may be uninitialized in this case, so we
1246 * can't rely on its value.
1248 if (szValue
->str
.a
|| szValue
->str
.w
)
1250 DWORD size
= *pcchValueBuf
;
1251 if (strlenW(val
) < size
)
1252 r
= msi_strcpy_to_awstring(val
, szValue
, &size
);
1255 r
= ERROR_MORE_DATA
;
1260 *pcchValueBuf
= lstrlenW(val
);
1264 r
= ERROR_BAD_CONFIGURATION
;
1270 RegCloseKey(prodkey
);
1271 RegCloseKey(userdata
);
1275 UINT WINAPI
MsiGetProductInfoA(LPCSTR szProduct
, LPCSTR szAttribute
,
1276 LPSTR szBuffer
, LPDWORD pcchValueBuf
)
1278 LPWSTR szwProduct
, szwAttribute
= NULL
;
1279 UINT r
= ERROR_OUTOFMEMORY
;
1282 TRACE("%s %s %p %p\n", debugstr_a(szProduct
), debugstr_a(szAttribute
),
1283 szBuffer
, pcchValueBuf
);
1285 szwProduct
= strdupAtoW( szProduct
);
1286 if( szProduct
&& !szwProduct
)
1289 szwAttribute
= strdupAtoW( szAttribute
);
1290 if( szAttribute
&& !szwAttribute
)
1293 buffer
.unicode
= FALSE
;
1294 buffer
.str
.a
= szBuffer
;
1296 r
= MSI_GetProductInfo( szwProduct
, szwAttribute
,
1297 &buffer
, pcchValueBuf
);
1300 msi_free( szwProduct
);
1301 msi_free( szwAttribute
);
1306 UINT WINAPI
MsiGetProductInfoW(LPCWSTR szProduct
, LPCWSTR szAttribute
,
1307 LPWSTR szBuffer
, LPDWORD pcchValueBuf
)
1311 TRACE("%s %s %p %p\n", debugstr_w(szProduct
), debugstr_w(szAttribute
),
1312 szBuffer
, pcchValueBuf
);
1314 buffer
.unicode
= TRUE
;
1315 buffer
.str
.w
= szBuffer
;
1317 return MSI_GetProductInfo( szProduct
, szAttribute
,
1318 &buffer
, pcchValueBuf
);
1321 UINT WINAPI
MsiGetProductInfoExA(LPCSTR szProductCode
, LPCSTR szUserSid
,
1322 MSIINSTALLCONTEXT dwContext
, LPCSTR szProperty
,
1323 LPSTR szValue
, LPDWORD pcchValue
)
1325 LPWSTR product
= NULL
;
1326 LPWSTR usersid
= NULL
;
1327 LPWSTR property
= NULL
;
1328 LPWSTR value
= NULL
;
1332 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_a(szProductCode
),
1333 debugstr_a(szUserSid
), dwContext
, debugstr_a(szProperty
),
1334 szValue
, pcchValue
);
1336 if (szValue
&& !pcchValue
)
1337 return ERROR_INVALID_PARAMETER
;
1339 if (szProductCode
) product
= strdupAtoW(szProductCode
);
1340 if (szUserSid
) usersid
= strdupAtoW(szUserSid
);
1341 if (szProperty
) property
= strdupAtoW(szProperty
);
1343 r
= MsiGetProductInfoExW(product
, usersid
, dwContext
, property
,
1345 if (r
!= ERROR_SUCCESS
)
1348 value
= msi_alloc(++len
* sizeof(WCHAR
));
1351 r
= ERROR_OUTOFMEMORY
;
1355 r
= MsiGetProductInfoExW(product
, usersid
, dwContext
, property
,
1357 if (r
!= ERROR_SUCCESS
)
1363 len
= WideCharToMultiByte(CP_ACP
, 0, value
, -1, NULL
, 0, NULL
, NULL
);
1364 if (*pcchValue
>= len
)
1365 WideCharToMultiByte(CP_ACP
, 0, value
, -1, szValue
, len
, NULL
, NULL
);
1368 r
= ERROR_MORE_DATA
;
1373 if (*pcchValue
<= len
|| !szValue
)
1374 len
= len
* sizeof(WCHAR
) - 1;
1376 *pcchValue
= len
- 1;
1387 static UINT
msi_copy_outval(LPWSTR val
, LPWSTR out
, LPDWORD size
)
1389 UINT r
= ERROR_SUCCESS
;
1392 return ERROR_UNKNOWN_PROPERTY
;
1396 if (strlenW(val
) >= *size
)
1398 r
= ERROR_MORE_DATA
;
1407 *size
= lstrlenW(val
);
1412 UINT WINAPI
MsiGetProductInfoExW(LPCWSTR szProductCode
, LPCWSTR szUserSid
,
1413 MSIINSTALLCONTEXT dwContext
, LPCWSTR szProperty
,
1414 LPWSTR szValue
, LPDWORD pcchValue
)
1416 WCHAR squished_pc
[GUID_SIZE
];
1418 LPCWSTR package
= NULL
;
1419 HKEY props
= NULL
, prod
;
1420 HKEY classes
= NULL
, managed
;
1423 UINT r
= ERROR_UNKNOWN_PRODUCT
;
1425 static const WCHAR five
[] = {'5',0};
1426 static const WCHAR displayname
[] = {
1427 'D','i','s','p','l','a','y','N','a','m','e',0};
1428 static const WCHAR displayversion
[] = {
1429 'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
1430 static const WCHAR managed_local_package
[] = {
1431 'M','a','n','a','g','e','d','L','o','c','a','l',
1432 'P','a','c','k','a','g','e',0};
1434 TRACE("(%s, %s, %d, %s, %p, %p)\n", debugstr_w(szProductCode
),
1435 debugstr_w(szUserSid
), dwContext
, debugstr_w(szProperty
),
1436 szValue
, pcchValue
);
1438 if (!szProductCode
|| !squash_guid(szProductCode
, squished_pc
))
1439 return ERROR_INVALID_PARAMETER
;
1441 if (szValue
&& !pcchValue
)
1442 return ERROR_INVALID_PARAMETER
;
1444 if (dwContext
!= MSIINSTALLCONTEXT_USERUNMANAGED
&&
1445 dwContext
!= MSIINSTALLCONTEXT_USERMANAGED
&&
1446 dwContext
!= MSIINSTALLCONTEXT_MACHINE
)
1447 return ERROR_INVALID_PARAMETER
;
1449 if (!szProperty
|| !*szProperty
)
1450 return ERROR_INVALID_PARAMETER
;
1452 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
&& szUserSid
)
1453 return ERROR_INVALID_PARAMETER
;
1455 /* FIXME: dwContext is provided, no need to search for it */
1456 MSIREG_OpenProductKey(szProductCode
, NULL
,MSIINSTALLCONTEXT_USERMANAGED
,
1458 MSIREG_OpenProductKey(szProductCode
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
1461 MSIREG_OpenInstallProps(szProductCode
, dwContext
, NULL
, &props
, FALSE
);
1463 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
1465 package
= INSTALLPROPERTY_LOCALPACKAGEW
;
1467 if (!props
&& !prod
)
1470 else if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1472 package
= managed_local_package
;
1474 if (!props
&& !managed
)
1477 else if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1479 package
= INSTALLPROPERTY_LOCALPACKAGEW
;
1480 MSIREG_OpenProductKey(szProductCode
, NULL
, dwContext
, &classes
, FALSE
);
1482 if (!props
&& !classes
)
1486 if (!strcmpW( szProperty
, INSTALLPROPERTY_HELPLINKW
) ||
1487 !strcmpW( szProperty
, INSTALLPROPERTY_HELPTELEPHONEW
) ||
1488 !strcmpW( szProperty
, INSTALLPROPERTY_INSTALLDATEW
) ||
1489 !strcmpW( szProperty
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
) ||
1490 !strcmpW( szProperty
, INSTALLPROPERTY_INSTALLLOCATIONW
) ||
1491 !strcmpW( szProperty
, INSTALLPROPERTY_INSTALLSOURCEW
) ||
1492 !strcmpW( szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
) ||
1493 !strcmpW( szProperty
, INSTALLPROPERTY_PUBLISHERW
) ||
1494 !strcmpW( szProperty
, INSTALLPROPERTY_URLINFOABOUTW
) ||
1495 !strcmpW( szProperty
, INSTALLPROPERTY_URLUPDATEINFOW
) ||
1496 !strcmpW( szProperty
, INSTALLPROPERTY_VERSIONMINORW
) ||
1497 !strcmpW( szProperty
, INSTALLPROPERTY_VERSIONMAJORW
) ||
1498 !strcmpW( szProperty
, INSTALLPROPERTY_VERSIONSTRINGW
) ||
1499 !strcmpW( szProperty
, INSTALLPROPERTY_PRODUCTIDW
) ||
1500 !strcmpW( szProperty
, INSTALLPROPERTY_REGCOMPANYW
) ||
1501 !strcmpW( szProperty
, INSTALLPROPERTY_REGOWNERW
) ||
1502 !strcmpW( szProperty
, INSTALLPROPERTY_INSTANCETYPEW
))
1504 val
= msi_reg_get_value(props
, package
, &type
);
1507 if (prod
|| classes
)
1508 r
= ERROR_UNKNOWN_PROPERTY
;
1515 if (!strcmpW( szProperty
, INSTALLPROPERTY_INSTALLEDPRODUCTNAMEW
))
1516 szProperty
= displayname
;
1517 else if (!strcmpW( szProperty
, INSTALLPROPERTY_VERSIONSTRINGW
))
1518 szProperty
= displayversion
;
1520 val
= msi_reg_get_value(props
, szProperty
, &type
);
1522 val
= strdupW(szEmpty
);
1524 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1526 else if (!strcmpW( szProperty
, INSTALLPROPERTY_TRANSFORMSW
) ||
1527 !strcmpW( szProperty
, INSTALLPROPERTY_LANGUAGEW
) ||
1528 !strcmpW( szProperty
, INSTALLPROPERTY_PRODUCTNAMEW
) ||
1529 !strcmpW( szProperty
, INSTALLPROPERTY_PACKAGECODEW
) ||
1530 !strcmpW( szProperty
, INSTALLPROPERTY_VERSIONW
) ||
1531 !strcmpW( szProperty
, INSTALLPROPERTY_PRODUCTICONW
) ||
1532 !strcmpW( szProperty
, INSTALLPROPERTY_PACKAGENAMEW
) ||
1533 !strcmpW( szProperty
, INSTALLPROPERTY_AUTHORIZED_LUA_APPW
))
1535 if (!prod
&& !classes
)
1538 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
1540 else if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1542 else if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1545 val
= msi_reg_get_value(hkey
, szProperty
, &type
);
1547 val
= strdupW(szEmpty
);
1549 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1551 else if (!strcmpW( szProperty
, INSTALLPROPERTY_PRODUCTSTATEW
))
1553 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
1557 val
= msi_reg_get_value(props
, package
, &type
);
1562 val
= strdupW(five
);
1565 val
= strdupW(szOne
);
1567 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1570 else if (props
&& (val
= msi_reg_get_value(props
, package
, &type
)))
1573 val
= strdupW(five
);
1574 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1578 if (prod
|| managed
)
1579 val
= strdupW(szOne
);
1583 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1585 else if (!strcmpW( szProperty
, INSTALLPROPERTY_ASSIGNMENTTYPEW
))
1587 if (!prod
&& !classes
)
1591 val
= strdupW(szEmpty
);
1592 r
= msi_copy_outval(val
, szValue
, pcchValue
);
1595 r
= ERROR_UNKNOWN_PROPERTY
;
1600 RegCloseKey(managed
);
1601 RegCloseKey(classes
);
1607 UINT WINAPI
MsiGetPatchInfoExA(LPCSTR szPatchCode
, LPCSTR szProductCode
,
1608 LPCSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1609 LPCSTR szProperty
, LPSTR lpValue
, DWORD
*pcchValue
)
1611 LPWSTR patch
= NULL
, product
= NULL
, usersid
= NULL
;
1612 LPWSTR property
= NULL
, val
= NULL
;
1616 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_a(szPatchCode
),
1617 debugstr_a(szProductCode
), debugstr_a(szUserSid
), dwContext
,
1618 debugstr_a(szProperty
), lpValue
, pcchValue
);
1620 if (lpValue
&& !pcchValue
)
1621 return ERROR_INVALID_PARAMETER
;
1623 if (szPatchCode
) patch
= strdupAtoW(szPatchCode
);
1624 if (szProductCode
) product
= strdupAtoW(szProductCode
);
1625 if (szUserSid
) usersid
= strdupAtoW(szUserSid
);
1626 if (szProperty
) property
= strdupAtoW(szProperty
);
1629 r
= MsiGetPatchInfoExW(patch
, product
, usersid
, dwContext
, property
,
1631 if (r
!= ERROR_SUCCESS
)
1634 val
= msi_alloc(++len
* sizeof(WCHAR
));
1637 r
= ERROR_OUTOFMEMORY
;
1641 r
= MsiGetPatchInfoExW(patch
, product
, usersid
, dwContext
, property
,
1643 if (r
!= ERROR_SUCCESS
|| !pcchValue
)
1647 WideCharToMultiByte(CP_ACP
, 0, val
, -1, lpValue
,
1648 *pcchValue
- 1, NULL
, NULL
);
1650 len
= lstrlenW(val
);
1651 if ((*val
&& *pcchValue
< len
+ 1) || !lpValue
)
1655 r
= ERROR_MORE_DATA
;
1656 lpValue
[*pcchValue
- 1] = '\0';
1659 *pcchValue
= len
* sizeof(WCHAR
);
1674 UINT WINAPI
MsiGetPatchInfoExW(LPCWSTR szPatchCode
, LPCWSTR szProductCode
,
1675 LPCWSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
1676 LPCWSTR szProperty
, LPWSTR lpValue
, DWORD
*pcchValue
)
1678 WCHAR squished_pc
[GUID_SIZE
];
1679 WCHAR squished_patch
[GUID_SIZE
];
1680 HKEY udprod
= 0, prod
= 0, props
= 0;
1681 HKEY patch
= 0, patches
= 0;
1682 HKEY udpatch
= 0, datakey
= 0;
1683 HKEY prodpatches
= 0;
1685 UINT r
= ERROR_UNKNOWN_PRODUCT
;
1689 static const WCHAR szManagedPackage
[] = {'M','a','n','a','g','e','d',
1690 'L','o','c','a','l','P','a','c','k','a','g','e',0};
1692 TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode
),
1693 debugstr_w(szProductCode
), debugstr_w(szUserSid
), dwContext
,
1694 debugstr_w(szProperty
), lpValue
, pcchValue
);
1696 if (!szProductCode
|| !squash_guid(szProductCode
, squished_pc
))
1697 return ERROR_INVALID_PARAMETER
;
1699 if (!szPatchCode
|| !squash_guid(szPatchCode
, squished_patch
))
1700 return ERROR_INVALID_PARAMETER
;
1703 return ERROR_INVALID_PARAMETER
;
1705 if (lpValue
&& !pcchValue
)
1706 return ERROR_INVALID_PARAMETER
;
1708 if (dwContext
!= MSIINSTALLCONTEXT_USERMANAGED
&&
1709 dwContext
!= MSIINSTALLCONTEXT_USERUNMANAGED
&&
1710 dwContext
!= MSIINSTALLCONTEXT_MACHINE
)
1711 return ERROR_INVALID_PARAMETER
;
1713 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
&& szUserSid
)
1714 return ERROR_INVALID_PARAMETER
;
1716 if (szUserSid
&& !strcmpW( szUserSid
, szLocalSid
))
1717 return ERROR_INVALID_PARAMETER
;
1719 if (MSIREG_OpenUserDataProductKey(szProductCode
, dwContext
, NULL
,
1720 &udprod
, FALSE
) != ERROR_SUCCESS
)
1723 if (MSIREG_OpenInstallProps(szProductCode
, dwContext
, NULL
,
1724 &props
, FALSE
) != ERROR_SUCCESS
)
1727 r
= ERROR_UNKNOWN_PATCH
;
1729 res
= RegOpenKeyExW(udprod
, szPatches
, 0, KEY_WOW64_64KEY
|KEY_READ
, &patches
);
1730 if (res
!= ERROR_SUCCESS
)
1733 res
= RegOpenKeyExW(patches
, squished_patch
, 0, KEY_WOW64_64KEY
|KEY_READ
, &patch
);
1734 if (res
!= ERROR_SUCCESS
)
1737 if (!strcmpW( szProperty
, INSTALLPROPERTY_TRANSFORMSW
))
1739 if (MSIREG_OpenProductKey(szProductCode
, NULL
, dwContext
,
1740 &prod
, FALSE
) != ERROR_SUCCESS
)
1743 res
= RegOpenKeyExW(prod
, szPatches
, 0, KEY_WOW64_64KEY
|KEY_ALL_ACCESS
, &prodpatches
);
1744 if (res
!= ERROR_SUCCESS
)
1747 datakey
= prodpatches
;
1748 szProperty
= squished_patch
;
1752 if (MSIREG_OpenUserDataPatchKey(szPatchCode
, dwContext
,
1753 &udpatch
, FALSE
) != ERROR_SUCCESS
)
1756 if (!strcmpW( szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
))
1758 if (dwContext
== MSIINSTALLCONTEXT_USERMANAGED
)
1759 szProperty
= szManagedPackage
;
1762 else if (!strcmpW( szProperty
, INSTALLPROPERTY_INSTALLDATEW
))
1765 szProperty
= szInstalled
;
1767 else if (!strcmpW( szProperty
, INSTALLPROPERTY_LOCALPACKAGEW
))
1771 else if (!strcmpW( szProperty
, INSTALLPROPERTY_UNINSTALLABLEW
) ||
1772 !strcmpW( szProperty
, INSTALLPROPERTY_PATCHSTATEW
) ||
1773 !strcmpW( szProperty
, INSTALLPROPERTY_DISPLAYNAMEW
) ||
1774 !strcmpW( szProperty
, INSTALLPROPERTY_MOREINFOURLW
))
1780 r
= ERROR_UNKNOWN_PROPERTY
;
1785 val
= msi_reg_get_val_str(datakey
, szProperty
);
1787 val
= strdupW(szEmpty
);
1795 lstrcpynW(lpValue
, val
, *pcchValue
);
1797 len
= lstrlenW(val
);
1798 if ((*val
&& *pcchValue
< len
+ 1) || !lpValue
)
1801 r
= ERROR_MORE_DATA
;
1803 *pcchValue
= len
* sizeof(WCHAR
);
1810 RegCloseKey(prodpatches
);
1813 RegCloseKey(patches
);
1814 RegCloseKey(udpatch
);
1816 RegCloseKey(udprod
);
1821 UINT WINAPI
MsiGetPatchInfoA( LPCSTR patch
, LPCSTR attr
, LPSTR buffer
, LPDWORD buflen
)
1823 UINT r
= ERROR_OUTOFMEMORY
;
1825 LPWSTR patchW
= NULL
, attrW
= NULL
, bufferW
= NULL
;
1827 TRACE("%s %s %p %p\n", debugstr_a(patch
), debugstr_a(attr
), buffer
, buflen
);
1829 if (!patch
|| !attr
)
1830 return ERROR_INVALID_PARAMETER
;
1832 if (!(patchW
= strdupAtoW( patch
)))
1835 if (!(attrW
= strdupAtoW( attr
)))
1839 r
= MsiGetPatchInfoW( patchW
, attrW
, NULL
, &size
);
1840 if (r
!= ERROR_SUCCESS
)
1844 if (!(bufferW
= msi_alloc( size
* sizeof(WCHAR
) )))
1846 r
= ERROR_OUTOFMEMORY
;
1850 r
= MsiGetPatchInfoW( patchW
, attrW
, bufferW
, &size
);
1851 if (r
== ERROR_SUCCESS
)
1853 int len
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1855 r
= ERROR_MORE_DATA
;
1857 WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, buffer
, *buflen
, NULL
, NULL
);
1865 msi_free( bufferW
);
1869 UINT WINAPI
MsiGetPatchInfoW( LPCWSTR patch
, LPCWSTR attr
, LPWSTR buffer
, LPDWORD buflen
)
1872 WCHAR product
[GUID_SIZE
];
1875 TRACE("%s %s %p %p\n", debugstr_w(patch
), debugstr_w(attr
), buffer
, buflen
);
1877 if (!patch
|| !attr
)
1878 return ERROR_INVALID_PARAMETER
;
1880 if (strcmpW( INSTALLPROPERTY_LOCALPACKAGEW
, attr
))
1881 return ERROR_UNKNOWN_PROPERTY
;
1886 r
= MsiEnumProductsW( index
, product
);
1887 if (r
!= ERROR_SUCCESS
)
1890 r
= MsiGetPatchInfoExW( patch
, product
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
, attr
, buffer
, buflen
);
1891 if (r
== ERROR_SUCCESS
|| r
== ERROR_MORE_DATA
)
1894 r
= MsiGetPatchInfoExW( patch
, product
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
, attr
, buffer
, buflen
);
1895 if (r
== ERROR_SUCCESS
|| r
== ERROR_MORE_DATA
)
1898 r
= MsiGetPatchInfoExW( patch
, product
, NULL
, MSIINSTALLCONTEXT_MACHINE
, attr
, buffer
, buflen
);
1899 if (r
== ERROR_SUCCESS
|| r
== ERROR_MORE_DATA
)
1905 return ERROR_UNKNOWN_PRODUCT
;
1908 UINT WINAPI
MsiEnableLogA(DWORD dwLogMode
, LPCSTR szLogFile
, DWORD attributes
)
1910 LPWSTR szwLogFile
= NULL
;
1913 TRACE("%08x %s %08x\n", dwLogMode
, debugstr_a(szLogFile
), attributes
);
1917 szwLogFile
= strdupAtoW( szLogFile
);
1919 return ERROR_OUTOFMEMORY
;
1921 r
= MsiEnableLogW( dwLogMode
, szwLogFile
, attributes
);
1922 msi_free( szwLogFile
);
1926 UINT WINAPI
MsiEnableLogW(DWORD dwLogMode
, LPCWSTR szLogFile
, DWORD attributes
)
1928 TRACE("%08x %s %08x\n", dwLogMode
, debugstr_w(szLogFile
), attributes
);
1930 msi_free(gszLogFile
);
1936 if (!(attributes
& INSTALLLOGATTRIBUTES_APPEND
))
1937 DeleteFileW(szLogFile
);
1938 file
= CreateFileW(szLogFile
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
, OPEN_ALWAYS
,
1939 FILE_ATTRIBUTE_NORMAL
, NULL
);
1940 if (file
!= INVALID_HANDLE_VALUE
)
1942 gszLogFile
= strdupW(szLogFile
);
1946 ERR("Unable to enable log %s (%u)\n", debugstr_w(szLogFile
), GetLastError());
1949 return ERROR_SUCCESS
;
1952 UINT WINAPI
MsiEnumComponentCostsA( MSIHANDLE handle
, LPCSTR component
, DWORD index
,
1953 INSTALLSTATE state
, LPSTR drive
, DWORD
*buflen
,
1954 int *cost
, int *temp
)
1958 WCHAR
*driveW
, *componentW
= NULL
;
1960 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle
, debugstr_a(component
), index
,
1961 state
, drive
, buflen
, cost
, temp
);
1963 if (!drive
|| !buflen
) return ERROR_INVALID_PARAMETER
;
1964 if (component
&& !(componentW
= strdupAtoW( component
))) return ERROR_OUTOFMEMORY
;
1967 if (!(driveW
= msi_alloc( len
* sizeof(WCHAR
) )))
1969 msi_free( componentW
);
1970 return ERROR_OUTOFMEMORY
;
1972 r
= MsiEnumComponentCostsW( handle
, componentW
, index
, state
, driveW
, buflen
, cost
, temp
);
1975 WideCharToMultiByte( CP_ACP
, 0, driveW
, -1, drive
, len
, NULL
, NULL
);
1977 msi_free( componentW
);
1982 static UINT
set_drive( WCHAR
*buffer
, WCHAR letter
)
1990 UINT WINAPI
MsiEnumComponentCostsW( MSIHANDLE handle
, LPCWSTR component
, DWORD index
,
1991 INSTALLSTATE state
, LPWSTR drive
, DWORD
*buflen
,
1992 int *cost
, int *temp
)
1994 UINT r
= ERROR_NO_MORE_ITEMS
;
1995 MSICOMPONENT
*comp
= NULL
;
1996 MSIPACKAGE
*package
;
1999 WCHAR path
[MAX_PATH
];
2001 TRACE("%d, %s, %u, %d, %p, %p, %p %p\n", handle
, debugstr_w(component
), index
,
2002 state
, drive
, buflen
, cost
, temp
);
2004 if (!drive
|| !buflen
|| !cost
|| !temp
) return ERROR_INVALID_PARAMETER
;
2005 if (!(package
= msihandle2msiinfo( handle
, MSIHANDLETYPE_PACKAGE
)))
2008 IWineMsiRemotePackage
*remote_package
;
2011 if (!(remote_package
= (IWineMsiRemotePackage
*)msi_get_remote( handle
)))
2012 return ERROR_INVALID_HANDLE
;
2014 if (component
&& !(bname
= SysAllocString( component
)))
2016 IWineMsiRemotePackage_Release( remote_package
);
2017 return ERROR_OUTOFMEMORY
;
2019 hr
= IWineMsiRemotePackage_EnumComponentCosts( remote_package
, bname
, index
, state
, drive
, buflen
, cost
, temp
);
2020 IWineMsiRemotePackage_Release( remote_package
);
2021 SysFreeString( bname
);
2024 if (HRESULT_FACILITY(hr
) == FACILITY_WIN32
) return HRESULT_CODE(hr
);
2025 return ERROR_FUNCTION_FAILED
;
2027 return ERROR_SUCCESS
;
2030 if (!msi_get_property_int( package
->db
, szCostingComplete
, 0 ))
2032 msiobj_release( &package
->hdr
);
2033 return ERROR_FUNCTION_NOT_CALLED
;
2035 if (component
&& component
[0] && !(comp
= msi_get_loaded_component( package
, component
)))
2037 msiobj_release( &package
->hdr
);
2038 return ERROR_UNKNOWN_COMPONENT
;
2043 msiobj_release( &package
->hdr
);
2044 return ERROR_MORE_DATA
;
2048 msiobj_release( &package
->hdr
);
2049 return ERROR_NO_MORE_ITEMS
;
2054 GetWindowsDirectoryW( path
, MAX_PATH
);
2055 if (component
&& component
[0])
2057 if (comp
->assembly
&& !comp
->assembly
->application
) *temp
= comp
->Cost
;
2058 if (!comp
->Enabled
|| !comp
->KeyPath
)
2061 *buflen
= set_drive( drive
, path
[0] );
2064 else if ((file
= msi_get_loaded_file( package
, comp
->KeyPath
)))
2066 *cost
= max( 8, comp
->Cost
/ 512 );
2067 *buflen
= set_drive( drive
, file
->TargetPath
[0] );
2071 else if (IStorage_Stat( package
->db
->storage
, &stat
, STATFLAG_NONAME
) == S_OK
)
2073 *temp
= max( 8, stat
.cbSize
.QuadPart
/ 512 );
2074 *buflen
= set_drive( drive
, path
[0] );
2077 msiobj_release( &package
->hdr
);
2081 UINT WINAPI
MsiQueryComponentStateA(LPCSTR szProductCode
,
2082 LPCSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
2083 LPCSTR szComponent
, INSTALLSTATE
*pdwState
)
2085 LPWSTR prodcode
= NULL
, usersid
= NULL
, comp
= NULL
;
2088 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_a(szProductCode
),
2089 debugstr_a(szUserSid
), dwContext
, debugstr_a(szComponent
), pdwState
);
2091 if (szProductCode
&& !(prodcode
= strdupAtoW(szProductCode
)))
2092 return ERROR_OUTOFMEMORY
;
2094 if (szUserSid
&& !(usersid
= strdupAtoW(szUserSid
)))
2095 return ERROR_OUTOFMEMORY
;
2097 if (szComponent
&& !(comp
= strdupAtoW(szComponent
)))
2098 return ERROR_OUTOFMEMORY
;
2100 r
= MsiQueryComponentStateW(prodcode
, usersid
, dwContext
, comp
, pdwState
);
2109 static BOOL
msi_comp_find_prod_key(LPCWSTR prodcode
, MSIINSTALLCONTEXT context
)
2114 r
= MSIREG_OpenProductKey(prodcode
, NULL
, context
, &hkey
, FALSE
);
2116 return (r
== ERROR_SUCCESS
);
2119 static BOOL
msi_comp_find_package(LPCWSTR prodcode
, MSIINSTALLCONTEXT context
)
2127 static const WCHAR local_package
[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
2128 static const WCHAR managed_local_package
[] = {
2129 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
2132 r
= MSIREG_OpenInstallProps(prodcode
, context
, NULL
, &hkey
, FALSE
);
2133 if (r
!= ERROR_SUCCESS
)
2136 if (context
== MSIINSTALLCONTEXT_USERMANAGED
)
2137 package
= managed_local_package
;
2139 package
= local_package
;
2142 res
= RegQueryValueExW(hkey
, package
, NULL
, NULL
, NULL
, &sz
);
2145 return (res
== ERROR_SUCCESS
);
2148 static BOOL
msi_comp_find_prodcode(LPWSTR squished_pc
,
2149 MSIINSTALLCONTEXT context
,
2150 LPCWSTR comp
, LPWSTR val
, DWORD
*sz
)
2156 if (context
== MSIINSTALLCONTEXT_MACHINE
)
2157 r
= MSIREG_OpenUserDataComponentKey(comp
, szLocalSid
, &hkey
, FALSE
);
2159 r
= MSIREG_OpenUserDataComponentKey(comp
, NULL
, &hkey
, FALSE
);
2161 if (r
!= ERROR_SUCCESS
)
2164 res
= RegQueryValueExW(hkey
, squished_pc
, NULL
, NULL
, (BYTE
*)val
, sz
);
2165 if (res
!= ERROR_SUCCESS
)
2172 UINT WINAPI
MsiQueryComponentStateW(LPCWSTR szProductCode
,
2173 LPCWSTR szUserSid
, MSIINSTALLCONTEXT dwContext
,
2174 LPCWSTR szComponent
, INSTALLSTATE
*pdwState
)
2176 WCHAR squished_pc
[GUID_SIZE
];
2177 WCHAR val
[MAX_PATH
];
2181 TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode
),
2182 debugstr_w(szUserSid
), dwContext
, debugstr_w(szComponent
), pdwState
);
2184 if (!pdwState
|| !szComponent
)
2185 return ERROR_INVALID_PARAMETER
;
2187 if (!szProductCode
|| !*szProductCode
|| lstrlenW(szProductCode
) != GUID_SIZE
- 1)
2188 return ERROR_INVALID_PARAMETER
;
2190 if (!squash_guid(szProductCode
, squished_pc
))
2191 return ERROR_INVALID_PARAMETER
;
2193 found
= msi_comp_find_prod_key(szProductCode
, dwContext
);
2195 if (!msi_comp_find_package(szProductCode
, dwContext
))
2199 *pdwState
= INSTALLSTATE_UNKNOWN
;
2200 return ERROR_UNKNOWN_COMPONENT
;
2203 return ERROR_UNKNOWN_PRODUCT
;
2206 *pdwState
= INSTALLSTATE_UNKNOWN
;
2209 if (!msi_comp_find_prodcode(squished_pc
, dwContext
, szComponent
, val
, &sz
))
2210 return ERROR_UNKNOWN_COMPONENT
;
2213 *pdwState
= INSTALLSTATE_NOTUSED
;
2216 if (lstrlenW(val
) > 2 &&
2217 val
[0] >= '0' && val
[0] <= '9' && val
[1] >= '0' && val
[1] <= '9')
2219 *pdwState
= INSTALLSTATE_SOURCE
;
2222 *pdwState
= INSTALLSTATE_LOCAL
;
2225 TRACE("-> %d\n", *pdwState
);
2226 return ERROR_SUCCESS
;
2229 INSTALLSTATE WINAPI
MsiQueryProductStateA(LPCSTR szProduct
)
2231 LPWSTR szwProduct
= NULL
;
2236 szwProduct
= strdupAtoW( szProduct
);
2238 return ERROR_OUTOFMEMORY
;
2240 r
= MsiQueryProductStateW( szwProduct
);
2241 msi_free( szwProduct
);
2245 INSTALLSTATE WINAPI
MsiQueryProductStateW(LPCWSTR szProduct
)
2247 MSIINSTALLCONTEXT context
= MSIINSTALLCONTEXT_USERUNMANAGED
;
2248 INSTALLSTATE state
= INSTALLSTATE_ADVERTISED
;
2249 HKEY prodkey
= 0, userdata
= 0;
2253 TRACE("%s\n", debugstr_w(szProduct
));
2255 if (!szProduct
|| !*szProduct
)
2256 return INSTALLSTATE_INVALIDARG
;
2258 if (lstrlenW(szProduct
) != GUID_SIZE
- 1)
2259 return INSTALLSTATE_INVALIDARG
;
2261 if (szProduct
[0] != '{' || szProduct
[37] != '}')
2262 return INSTALLSTATE_UNKNOWN
;
2264 SetLastError( ERROR_SUCCESS
);
2266 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
2267 &prodkey
, FALSE
) != ERROR_SUCCESS
&&
2268 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
2269 &prodkey
, FALSE
) != ERROR_SUCCESS
&&
2270 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
2271 &prodkey
, FALSE
) == ERROR_SUCCESS
)
2273 context
= MSIINSTALLCONTEXT_MACHINE
;
2276 r
= MSIREG_OpenInstallProps(szProduct
, context
, NULL
, &userdata
, FALSE
);
2277 if (r
!= ERROR_SUCCESS
)
2280 if (!msi_reg_get_val_dword(userdata
, szWindowsInstaller
, &val
))
2284 state
= INSTALLSTATE_DEFAULT
;
2286 state
= INSTALLSTATE_UNKNOWN
;
2291 state
= INSTALLSTATE_UNKNOWN
;
2294 state
= INSTALLSTATE_ABSENT
;
2297 RegCloseKey(prodkey
);
2298 RegCloseKey(userdata
);
2299 TRACE("-> %d\n", state
);
2303 INSTALLUILEVEL WINAPI
MsiSetInternalUI(INSTALLUILEVEL dwUILevel
, HWND
*phWnd
)
2305 INSTALLUILEVEL old
= gUILevel
;
2306 HWND oldwnd
= gUIhwnd
;
2308 TRACE("%08x %p\n", dwUILevel
, phWnd
);
2310 gUILevel
= dwUILevel
;
2319 INSTALLUI_HANDLERA WINAPI
MsiSetExternalUIA(INSTALLUI_HANDLERA puiHandler
,
2320 DWORD dwMessageFilter
, LPVOID pvContext
)
2322 INSTALLUI_HANDLERA prev
= gUIHandlerA
;
2324 TRACE("%p %08x %p\n", puiHandler
, dwMessageFilter
, pvContext
);
2326 gUIHandlerA
= puiHandler
;
2328 gUIFilter
= dwMessageFilter
;
2329 gUIContext
= pvContext
;
2334 INSTALLUI_HANDLERW WINAPI
MsiSetExternalUIW(INSTALLUI_HANDLERW puiHandler
,
2335 DWORD dwMessageFilter
, LPVOID pvContext
)
2337 INSTALLUI_HANDLERW prev
= gUIHandlerW
;
2339 TRACE("%p %08x %p\n", puiHandler
, dwMessageFilter
, pvContext
);
2342 gUIHandlerW
= puiHandler
;
2343 gUIFilter
= dwMessageFilter
;
2344 gUIContext
= pvContext
;
2349 /******************************************************************
2350 * MsiLoadStringW [MSI.@]
2352 * Loads a string from MSI's string resources.
2356 * handle [I] only -1 is handled currently
2357 * id [I] id of the string to be loaded
2358 * lpBuffer [O] buffer for the string to be written to
2359 * nBufferMax [I] maximum size of the buffer in characters
2360 * lang [I] the preferred language for the string
2364 * If successful, this function returns the language id of the string loaded
2365 * If the function fails, the function returns zero.
2369 * The type of the first parameter is unknown. LoadString's prototype
2370 * suggests that it might be a module handle. I have made it an MSI handle
2371 * for starters, as -1 is an invalid MSI handle, but not an invalid module
2372 * handle. Maybe strings can be stored in an MSI database somehow.
2374 LANGID WINAPI
MsiLoadStringW( MSIHANDLE handle
, UINT id
, LPWSTR lpBuffer
,
2375 int nBufferMax
, LANGID lang
)
2382 TRACE("%d %u %p %d %d\n", handle
, id
, lpBuffer
, nBufferMax
, lang
);
2385 FIXME("don't know how to deal with handle = %08x\n", handle
);
2388 lang
= GetUserDefaultLangID();
2390 hres
= FindResourceExW( msi_hInstance
, (LPCWSTR
) RT_STRING
,
2394 hResData
= LoadResource( msi_hInstance
, hres
);
2397 p
= LockResource( hResData
);
2401 for (i
= 0; i
< (id
& 0xf); i
++) p
+= *p
+ 1;
2404 if( nBufferMax
<= len
)
2407 memcpy( lpBuffer
, p
+1, len
* sizeof(WCHAR
));
2408 lpBuffer
[ len
] = 0;
2410 TRACE("found -> %s\n", debugstr_w(lpBuffer
));
2414 LANGID WINAPI
MsiLoadStringA( MSIHANDLE handle
, UINT id
, LPSTR lpBuffer
,
2415 int nBufferMax
, LANGID lang
)
2421 bufW
= msi_alloc(nBufferMax
*sizeof(WCHAR
));
2422 r
= MsiLoadStringW(handle
, id
, bufW
, nBufferMax
, lang
);
2425 len
= WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, NULL
, 0, NULL
, NULL
);
2426 if( len
<= nBufferMax
)
2427 WideCharToMultiByte( CP_ACP
, 0, bufW
, -1,
2428 lpBuffer
, nBufferMax
, NULL
, NULL
);
2436 INSTALLSTATE WINAPI
MsiLocateComponentA(LPCSTR szComponent
, LPSTR lpPathBuf
,
2439 char szProduct
[GUID_SIZE
];
2441 TRACE("%s %p %p\n", debugstr_a(szComponent
), lpPathBuf
, pcchBuf
);
2443 if (!szComponent
|| !pcchBuf
)
2444 return INSTALLSTATE_INVALIDARG
;
2446 if (MsiGetProductCodeA( szComponent
, szProduct
) != ERROR_SUCCESS
)
2447 return INSTALLSTATE_UNKNOWN
;
2449 return MsiGetComponentPathA( szProduct
, szComponent
, lpPathBuf
, pcchBuf
);
2452 INSTALLSTATE WINAPI
MsiLocateComponentW(LPCWSTR szComponent
, LPWSTR lpPathBuf
,
2455 WCHAR szProduct
[GUID_SIZE
];
2457 TRACE("%s %p %p\n", debugstr_w(szComponent
), lpPathBuf
, pcchBuf
);
2459 if (!szComponent
|| !pcchBuf
)
2460 return INSTALLSTATE_INVALIDARG
;
2462 if (MsiGetProductCodeW( szComponent
, szProduct
) != ERROR_SUCCESS
)
2463 return INSTALLSTATE_UNKNOWN
;
2465 return MsiGetComponentPathW( szProduct
, szComponent
, lpPathBuf
, pcchBuf
);
2468 UINT WINAPI
MsiMessageBoxA(HWND hWnd
, LPCSTR lpText
, LPCSTR lpCaption
, UINT uType
,
2469 WORD wLanguageId
, DWORD f
)
2471 FIXME("%p %s %s %u %08x %08x\n", hWnd
, debugstr_a(lpText
), debugstr_a(lpCaption
),
2472 uType
, wLanguageId
, f
);
2473 return MessageBoxExA(hWnd
,lpText
,lpCaption
,uType
,wLanguageId
);
2476 UINT WINAPI
MsiMessageBoxW(HWND hWnd
, LPCWSTR lpText
, LPCWSTR lpCaption
, UINT uType
,
2477 WORD wLanguageId
, DWORD f
)
2479 FIXME("%p %s %s %u %08x %08x\n", hWnd
, debugstr_w(lpText
), debugstr_w(lpCaption
),
2480 uType
, wLanguageId
, f
);
2481 return MessageBoxExW(hWnd
,lpText
,lpCaption
,uType
,wLanguageId
);
2484 UINT WINAPI
MsiMessageBoxExA(HWND hWnd
, LPCSTR lpText
, LPCSTR lpCaption
, UINT uType
,
2485 DWORD unknown
, WORD wLanguageId
, DWORD f
)
2487 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd
, debugstr_a(lpText
),
2488 debugstr_a(lpCaption
), uType
, unknown
, wLanguageId
, f
);
2489 return MessageBoxExA(hWnd
, lpText
, lpCaption
, uType
, wLanguageId
);
2492 UINT WINAPI
MsiMessageBoxExW(HWND hWnd
, LPCWSTR lpText
, LPCWSTR lpCaption
, UINT uType
,
2493 DWORD unknown
, WORD wLanguageId
, DWORD f
)
2495 FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd
, debugstr_w(lpText
),
2496 debugstr_w(lpCaption
), uType
, unknown
, wLanguageId
, f
);
2497 return MessageBoxExW(hWnd
, lpText
, lpCaption
, uType
, wLanguageId
);
2500 UINT WINAPI
MsiProvideAssemblyA( LPCSTR szAssemblyName
, LPCSTR szAppContext
,
2501 DWORD dwInstallMode
, DWORD dwAssemblyInfo
, LPSTR lpPathBuf
,
2502 LPDWORD pcchPathBuf
)
2504 FIXME("%s %s %08x %08x %p %p\n", debugstr_a(szAssemblyName
),
2505 debugstr_a(szAppContext
), dwInstallMode
, dwAssemblyInfo
, lpPathBuf
,
2507 return ERROR_CALL_NOT_IMPLEMENTED
;
2510 UINT WINAPI
MsiProvideAssemblyW( LPCWSTR szAssemblyName
, LPCWSTR szAppContext
,
2511 DWORD dwInstallMode
, DWORD dwAssemblyInfo
, LPWSTR lpPathBuf
,
2512 LPDWORD pcchPathBuf
)
2514 FIXME("%s %s %08x %08x %p %p\n", debugstr_w(szAssemblyName
),
2515 debugstr_w(szAppContext
), dwInstallMode
, dwAssemblyInfo
, lpPathBuf
,
2517 return ERROR_CALL_NOT_IMPLEMENTED
;
2520 UINT WINAPI
MsiProvideComponentFromDescriptorA( LPCSTR szDescriptor
,
2521 LPSTR szPath
, LPDWORD pcchPath
, LPDWORD pcchArgs
)
2523 FIXME("%s %p %p %p\n", debugstr_a(szDescriptor
), szPath
, pcchPath
, pcchArgs
);
2524 return ERROR_CALL_NOT_IMPLEMENTED
;
2527 UINT WINAPI
MsiProvideComponentFromDescriptorW( LPCWSTR szDescriptor
,
2528 LPWSTR szPath
, LPDWORD pcchPath
, LPDWORD pcchArgs
)
2530 FIXME("%s %p %p %p\n", debugstr_w(szDescriptor
), szPath
, pcchPath
, pcchArgs
);
2531 return ERROR_CALL_NOT_IMPLEMENTED
;
2534 HRESULT WINAPI
MsiGetFileSignatureInformationA( LPCSTR path
, DWORD flags
, PCCERT_CONTEXT
*cert
,
2535 LPBYTE hash
, LPDWORD hashlen
)
2538 WCHAR
*pathW
= NULL
;
2540 TRACE("%s %08x %p %p %p\n", debugstr_a(path
), flags
, cert
, hash
, hashlen
);
2542 if (path
&& !(pathW
= strdupAtoW( path
))) return ERROR_OUTOFMEMORY
;
2543 r
= MsiGetFileSignatureInformationW( pathW
, flags
, cert
, hash
, hashlen
);
2548 HRESULT WINAPI
MsiGetFileSignatureInformationW( LPCWSTR path
, DWORD flags
, PCCERT_CONTEXT
*cert
,
2549 LPBYTE hash
, LPDWORD hashlen
)
2551 static GUID generic_verify_v2
= WINTRUST_ACTION_GENERIC_VERIFY_V2
;
2554 WINTRUST_FILE_INFO info
;
2555 CRYPT_PROVIDER_SGNR
*signer
;
2556 CRYPT_PROVIDER_CERT
*provider
;
2558 TRACE("%s %08x %p %p %p\n", debugstr_w(path
), flags
, cert
, hash
, hashlen
);
2560 if (!path
|| !cert
) return E_INVALIDARG
;
2562 info
.cbStruct
= sizeof(info
);
2563 info
.pcwszFilePath
= path
;
2565 info
.pgKnownSubject
= NULL
;
2567 data
.cbStruct
= sizeof(data
);
2568 data
.pPolicyCallbackData
= NULL
;
2569 data
.pSIPClientData
= NULL
;
2570 data
.dwUIChoice
= WTD_UI_NONE
;
2571 data
.fdwRevocationChecks
= WTD_REVOKE_WHOLECHAIN
;
2572 data
.dwUnionChoice
= WTD_CHOICE_FILE
;
2573 data
.u
.pFile
= &info
;
2574 data
.dwStateAction
= WTD_STATEACTION_VERIFY
;
2575 data
.hWVTStateData
= NULL
;
2576 data
.pwszURLReference
= NULL
;
2577 data
.dwProvFlags
= 0;
2578 data
.dwUIContext
= WTD_UICONTEXT_INSTALL
;
2579 hr
= WinVerifyTrustEx( INVALID_HANDLE_VALUE
, &generic_verify_v2
, &data
);
2580 if (FAILED(hr
)) goto done
;
2582 if (!(signer
= WTHelperGetProvSignerFromChain( data
.hWVTStateData
, 0, FALSE
, 0 )))
2584 hr
= TRUST_E_NOSIGNATURE
;
2589 DWORD len
= signer
->psSigner
->EncryptedHash
.cbData
;
2593 hr
= HRESULT_FROM_WIN32(ERROR_MORE_DATA
);
2596 memcpy( hash
, signer
->psSigner
->EncryptedHash
.pbData
, len
);
2599 if (!(provider
= WTHelperGetProvCertFromChain( signer
, 0 )))
2601 hr
= TRUST_E_PROVIDER_UNKNOWN
;
2604 *cert
= CertDuplicateCertificateContext( provider
->pCert
);
2607 data
.dwStateAction
= WTD_STATEACTION_CLOSE
;
2608 WinVerifyTrustEx( INVALID_HANDLE_VALUE
, &generic_verify_v2
, &data
);
2612 /******************************************************************
2613 * MsiGetProductPropertyA [MSI.@]
2615 UINT WINAPI
MsiGetProductPropertyA(MSIHANDLE hProduct
, LPCSTR szProperty
,
2616 LPSTR szValue
, LPDWORD pccbValue
)
2618 LPWSTR prop
= NULL
, val
= NULL
;
2622 TRACE("(%d, %s, %p, %p)\n", hProduct
, debugstr_a(szProperty
),
2623 szValue
, pccbValue
);
2625 if (szValue
&& !pccbValue
)
2626 return ERROR_INVALID_PARAMETER
;
2628 if (szProperty
) prop
= strdupAtoW(szProperty
);
2631 r
= MsiGetProductPropertyW(hProduct
, prop
, NULL
, &len
);
2632 if (r
!= ERROR_SUCCESS
&& r
!= ERROR_MORE_DATA
)
2635 if (r
== ERROR_SUCCESS
)
2637 if (szValue
) *szValue
= '\0';
2638 if (pccbValue
) *pccbValue
= 0;
2642 val
= msi_alloc(++len
* sizeof(WCHAR
));
2645 r
= ERROR_OUTOFMEMORY
;
2649 r
= MsiGetProductPropertyW(hProduct
, prop
, val
, &len
);
2650 if (r
!= ERROR_SUCCESS
)
2653 len
= WideCharToMultiByte(CP_ACP
, 0, val
, -1, NULL
, 0, NULL
, NULL
);
2656 WideCharToMultiByte(CP_ACP
, 0, val
, -1, szValue
,
2657 *pccbValue
, NULL
, NULL
);
2661 if (len
> *pccbValue
)
2662 r
= ERROR_MORE_DATA
;
2664 *pccbValue
= len
- 1;
2674 /******************************************************************
2675 * MsiGetProductPropertyW [MSI.@]
2677 UINT WINAPI
MsiGetProductPropertyW(MSIHANDLE hProduct
, LPCWSTR szProperty
,
2678 LPWSTR szValue
, LPDWORD pccbValue
)
2680 MSIPACKAGE
*package
;
2681 MSIQUERY
*view
= NULL
;
2682 MSIRECORD
*rec
= NULL
;
2686 static const WCHAR query
[] = {
2687 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
2688 '`','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
2689 '`','P','r','o','p','e','r','t','y','`','=','\'','%','s','\'',0};
2691 TRACE("(%d, %s, %p, %p)\n", hProduct
, debugstr_w(szProperty
),
2692 szValue
, pccbValue
);
2695 return ERROR_INVALID_PARAMETER
;
2697 if (szValue
&& !pccbValue
)
2698 return ERROR_INVALID_PARAMETER
;
2700 package
= msihandle2msiinfo(hProduct
, MSIHANDLETYPE_PACKAGE
);
2702 return ERROR_INVALID_HANDLE
;
2704 r
= MSI_OpenQuery(package
->db
, &view
, query
, szProperty
);
2705 if (r
!= ERROR_SUCCESS
)
2708 r
= MSI_ViewExecute(view
, 0);
2709 if (r
!= ERROR_SUCCESS
)
2712 r
= MSI_ViewFetch(view
, &rec
);
2713 if (r
!= ERROR_SUCCESS
)
2716 val
= MSI_RecordGetString(rec
, 2);
2720 if (lstrlenW(val
) >= *pccbValue
)
2722 lstrcpynW(szValue
, val
, *pccbValue
);
2723 *pccbValue
= lstrlenW(val
);
2724 r
= ERROR_MORE_DATA
;
2728 lstrcpyW(szValue
, val
);
2729 *pccbValue
= lstrlenW(val
);
2736 MSI_ViewClose(view
);
2737 msiobj_release(&view
->hdr
);
2738 if (rec
) msiobj_release(&rec
->hdr
);
2743 if (szValue
) *szValue
= '\0';
2744 if (pccbValue
) *pccbValue
= 0;
2748 msiobj_release(&package
->hdr
);
2752 UINT WINAPI
MsiVerifyPackageA( LPCSTR szPackage
)
2755 LPWSTR szPack
= NULL
;
2757 TRACE("%s\n", debugstr_a(szPackage
) );
2761 szPack
= strdupAtoW( szPackage
);
2763 return ERROR_OUTOFMEMORY
;
2766 r
= MsiVerifyPackageW( szPack
);
2773 UINT WINAPI
MsiVerifyPackageW( LPCWSTR szPackage
)
2778 TRACE("%s\n", debugstr_w(szPackage
) );
2780 r
= MsiOpenDatabaseW( szPackage
, MSIDBOPEN_READONLY
, &handle
);
2781 MsiCloseHandle( handle
);
2786 static INSTALLSTATE
MSI_GetComponentPath(LPCWSTR szProduct
, LPCWSTR szComponent
,
2787 awstring
* lpPathBuf
, LPDWORD pcchBuf
)
2789 static const WCHAR wininstaller
[] =
2790 {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
2791 WCHAR squished_pc
[GUID_SIZE
];
2792 WCHAR squished_comp
[GUID_SIZE
];
2798 if (!szProduct
|| !szComponent
)
2799 return INSTALLSTATE_INVALIDARG
;
2801 if (lpPathBuf
->str
.w
&& !pcchBuf
)
2802 return INSTALLSTATE_INVALIDARG
;
2804 if (!squash_guid(szProduct
, squished_pc
) ||
2805 !squash_guid(szComponent
, squished_comp
))
2806 return INSTALLSTATE_INVALIDARG
;
2808 state
= INSTALLSTATE_UNKNOWN
;
2810 if (MSIREG_OpenUserDataComponentKey(szComponent
, szLocalSid
, &hkey
, FALSE
) == ERROR_SUCCESS
||
2811 MSIREG_OpenUserDataComponentKey(szComponent
, NULL
, &hkey
, FALSE
) == ERROR_SUCCESS
)
2813 path
= msi_reg_get_val_str(hkey
, squished_pc
);
2816 state
= INSTALLSTATE_ABSENT
;
2818 if ((MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_MACHINE
, NULL
,
2819 &hkey
, FALSE
) == ERROR_SUCCESS
||
2820 MSIREG_OpenUserDataProductKey(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
,
2821 NULL
, &hkey
, FALSE
) == ERROR_SUCCESS
) &&
2822 msi_reg_get_val_dword(hkey
, wininstaller
, &version
) &&
2823 GetFileAttributesW(path
) != INVALID_FILE_ATTRIBUTES
)
2826 state
= INSTALLSTATE_LOCAL
;
2830 if (state
!= INSTALLSTATE_LOCAL
&&
2831 (MSIREG_OpenProductKey(szProduct
, NULL
,
2832 MSIINSTALLCONTEXT_USERUNMANAGED
,
2833 &hkey
, FALSE
) == ERROR_SUCCESS
||
2834 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
2835 &hkey
, FALSE
) == ERROR_SUCCESS
))
2839 if (MSIREG_OpenUserDataComponentKey(szComponent
, szLocalSid
, &hkey
, FALSE
) == ERROR_SUCCESS
||
2840 MSIREG_OpenUserDataComponentKey(szComponent
, NULL
, &hkey
, FALSE
) == ERROR_SUCCESS
)
2843 path
= msi_reg_get_val_str(hkey
, squished_pc
);
2846 state
= INSTALLSTATE_ABSENT
;
2848 if (GetFileAttributesW(path
) != INVALID_FILE_ATTRIBUTES
)
2849 state
= INSTALLSTATE_LOCAL
;
2854 return INSTALLSTATE_UNKNOWN
;
2856 if (state
== INSTALLSTATE_LOCAL
&& !*path
)
2857 state
= INSTALLSTATE_NOTUSED
;
2859 msi_strcpy_to_awstring(path
, lpPathBuf
, pcchBuf
);
2864 /******************************************************************
2865 * MsiGetComponentPathW [MSI.@]
2867 INSTALLSTATE WINAPI
MsiGetComponentPathW(LPCWSTR szProduct
, LPCWSTR szComponent
,
2868 LPWSTR lpPathBuf
, LPDWORD pcchBuf
)
2872 TRACE("%s %s %p %p\n", debugstr_w(szProduct
), debugstr_w(szComponent
), lpPathBuf
, pcchBuf
);
2874 path
.unicode
= TRUE
;
2875 path
.str
.w
= lpPathBuf
;
2877 return MSI_GetComponentPath( szProduct
, szComponent
, &path
, pcchBuf
);
2880 /******************************************************************
2881 * MsiGetComponentPathA [MSI.@]
2883 INSTALLSTATE WINAPI
MsiGetComponentPathA(LPCSTR szProduct
, LPCSTR szComponent
,
2884 LPSTR lpPathBuf
, LPDWORD pcchBuf
)
2886 LPWSTR szwProduct
, szwComponent
= NULL
;
2887 INSTALLSTATE r
= INSTALLSTATE_UNKNOWN
;
2890 TRACE("%s %s %p %p\n", debugstr_a(szProduct
), debugstr_a(szComponent
), lpPathBuf
, pcchBuf
);
2892 szwProduct
= strdupAtoW( szProduct
);
2893 if( szProduct
&& !szwProduct
)
2896 szwComponent
= strdupAtoW( szComponent
);
2897 if( szComponent
&& !szwComponent
)
2900 path
.unicode
= FALSE
;
2901 path
.str
.a
= lpPathBuf
;
2903 r
= MSI_GetComponentPath( szwProduct
, szwComponent
, &path
, pcchBuf
);
2906 msi_free( szwProduct
);
2907 msi_free( szwComponent
);
2912 /******************************************************************
2913 * MsiQueryFeatureStateA [MSI.@]
2915 INSTALLSTATE WINAPI
MsiQueryFeatureStateA(LPCSTR szProduct
, LPCSTR szFeature
)
2917 LPWSTR szwProduct
= NULL
, szwFeature
= NULL
;
2918 INSTALLSTATE rc
= INSTALLSTATE_UNKNOWN
;
2920 szwProduct
= strdupAtoW( szProduct
);
2921 if ( szProduct
&& !szwProduct
)
2924 szwFeature
= strdupAtoW( szFeature
);
2925 if ( szFeature
&& !szwFeature
)
2928 rc
= MsiQueryFeatureStateW(szwProduct
, szwFeature
);
2931 msi_free( szwProduct
);
2932 msi_free( szwFeature
);
2937 /******************************************************************
2938 * MsiQueryFeatureStateW [MSI.@]
2940 * Checks the state of a feature
2943 * szProduct [I] Product's GUID string
2944 * szFeature [I] Feature's GUID string
2947 * INSTALLSTATE_LOCAL Feature is installed and usable
2948 * INSTALLSTATE_ABSENT Feature is absent
2949 * INSTALLSTATE_ADVERTISED Feature should be installed on demand
2950 * INSTALLSTATE_UNKNOWN An error occurred
2951 * INSTALLSTATE_INVALIDARG One of the GUIDs was invalid
2954 INSTALLSTATE WINAPI
MsiQueryFeatureStateW(LPCWSTR szProduct
, LPCWSTR szFeature
)
2956 WCHAR squishProduct
[33], comp
[GUID_SIZE
];
2958 LPWSTR components
, p
, parent_feature
, path
;
2962 BOOL missing
= FALSE
;
2963 BOOL machine
= FALSE
;
2964 BOOL source
= FALSE
;
2966 TRACE("%s %s\n", debugstr_w(szProduct
), debugstr_w(szFeature
));
2968 if (!szProduct
|| !szFeature
)
2969 return INSTALLSTATE_INVALIDARG
;
2971 if (!squash_guid( szProduct
, squishProduct
))
2972 return INSTALLSTATE_INVALIDARG
;
2974 SetLastError( ERROR_SUCCESS
);
2976 if (MSIREG_OpenFeaturesKey(szProduct
, MSIINSTALLCONTEXT_USERMANAGED
,
2977 &hkey
, FALSE
) != ERROR_SUCCESS
&&
2978 MSIREG_OpenFeaturesKey(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
,
2979 &hkey
, FALSE
) != ERROR_SUCCESS
)
2981 rc
= MSIREG_OpenFeaturesKey(szProduct
, MSIINSTALLCONTEXT_MACHINE
,
2983 if (rc
!= ERROR_SUCCESS
)
2984 return INSTALLSTATE_UNKNOWN
;
2989 parent_feature
= msi_reg_get_val_str( hkey
, szFeature
);
2992 if (!parent_feature
)
2993 return INSTALLSTATE_UNKNOWN
;
2995 r
= (parent_feature
[0] == 6) ? INSTALLSTATE_ABSENT
: INSTALLSTATE_LOCAL
;
2996 msi_free(parent_feature
);
2997 if (r
== INSTALLSTATE_ABSENT
)
3001 rc
= MSIREG_OpenUserDataFeaturesKey(szProduct
,
3002 MSIINSTALLCONTEXT_MACHINE
,
3005 rc
= MSIREG_OpenUserDataFeaturesKey(szProduct
,
3006 MSIINSTALLCONTEXT_USERUNMANAGED
,
3009 if (rc
!= ERROR_SUCCESS
)
3010 return INSTALLSTATE_ADVERTISED
;
3012 components
= msi_reg_get_val_str( hkey
, szFeature
);
3015 TRACE("rc = %d buffer = %s\n", rc
, debugstr_w(components
));
3018 return INSTALLSTATE_ADVERTISED
;
3020 for( p
= components
; *p
&& *p
!= 2 ; p
+= 20)
3022 if (!decode_base85_guid( p
, &guid
))
3024 if (p
!= components
)
3027 msi_free(components
);
3028 return INSTALLSTATE_BADCONFIG
;
3031 StringFromGUID2(&guid
, comp
, GUID_SIZE
);
3034 rc
= MSIREG_OpenUserDataComponentKey(comp
, szLocalSid
, &hkey
, FALSE
);
3036 rc
= MSIREG_OpenUserDataComponentKey(comp
, NULL
, &hkey
, FALSE
);
3038 if (rc
!= ERROR_SUCCESS
)
3040 msi_free(components
);
3041 return INSTALLSTATE_ADVERTISED
;
3044 path
= msi_reg_get_val_str(hkey
, squishProduct
);
3047 else if (lstrlenW(path
) > 2 &&
3048 path
[0] >= '0' && path
[0] <= '9' &&
3049 path
[1] >= '0' && path
[1] <= '9')
3056 msi_free(components
);
3059 r
= INSTALLSTATE_ADVERTISED
;
3061 r
= INSTALLSTATE_SOURCE
;
3063 r
= INSTALLSTATE_LOCAL
;
3065 TRACE("-> %d\n", r
);
3069 /******************************************************************
3070 * MsiGetFileVersionA [MSI.@]
3072 UINT WINAPI
MsiGetFileVersionA(LPCSTR szFilePath
, LPSTR lpVersionBuf
,
3073 LPDWORD pcchVersionBuf
, LPSTR lpLangBuf
, LPDWORD pcchLangBuf
)
3075 LPWSTR szwFilePath
= NULL
, lpwVersionBuff
= NULL
, lpwLangBuff
= NULL
;
3076 UINT ret
= ERROR_OUTOFMEMORY
;
3078 if ((lpVersionBuf
&& !pcchVersionBuf
) ||
3079 (lpLangBuf
&& !pcchLangBuf
))
3080 return ERROR_INVALID_PARAMETER
;
3084 szwFilePath
= strdupAtoW( szFilePath
);
3089 if( lpVersionBuf
&& pcchVersionBuf
&& *pcchVersionBuf
)
3091 lpwVersionBuff
= msi_alloc(*pcchVersionBuf
*sizeof(WCHAR
));
3092 if( !lpwVersionBuff
)
3096 if( lpLangBuf
&& pcchLangBuf
&& *pcchLangBuf
)
3098 lpwLangBuff
= msi_alloc(*pcchLangBuf
*sizeof(WCHAR
));
3103 ret
= MsiGetFileVersionW(szwFilePath
, lpwVersionBuff
, pcchVersionBuf
,
3104 lpwLangBuff
, pcchLangBuf
);
3106 if( (ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) && lpwVersionBuff
)
3107 WideCharToMultiByte(CP_ACP
, 0, lpwVersionBuff
, -1,
3108 lpVersionBuf
, *pcchVersionBuf
+ 1, NULL
, NULL
);
3109 if( (ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) && lpwLangBuff
)
3110 WideCharToMultiByte(CP_ACP
, 0, lpwLangBuff
, -1,
3111 lpLangBuf
, *pcchLangBuf
+ 1, NULL
, NULL
);
3114 msi_free(szwFilePath
);
3115 msi_free(lpwVersionBuff
);
3116 msi_free(lpwLangBuff
);
3121 static UINT
get_file_version( const WCHAR
*path
, WCHAR
*verbuf
, DWORD
*verlen
,
3122 WCHAR
*langbuf
, DWORD
*langlen
)
3124 static const WCHAR szVersionResource
[] = {'\\',0};
3125 static const WCHAR szVersionFormat
[] = {
3126 '%','d','.','%','d','.','%','d','.','%','d',0};
3127 static const WCHAR szLangResource
[] = {
3128 '\\','V','a','r','F','i','l','e','I','n','f','o','\\',
3129 'T','r','a','n','s','l','a','t','i','o','n',0};
3130 static const WCHAR szLangFormat
[] = {'%','d',0};
3131 UINT ret
= ERROR_SUCCESS
;
3134 VS_FIXEDFILEINFO
*ffi
;
3138 if (!(len
= GetFileVersionInfoSizeW( path
, NULL
)))
3140 error
= GetLastError();
3141 if (error
== ERROR_BAD_PATHNAME
) return ERROR_FILE_NOT_FOUND
;
3144 if (!(version
= msi_alloc( len
))) return ERROR_OUTOFMEMORY
;
3145 if (!GetFileVersionInfoW( path
, 0, len
, version
))
3147 msi_free( version
);
3148 return GetLastError();
3152 if (VerQueryValueW( version
, szVersionResource
, (LPVOID
*)&ffi
, &len
) && len
> 0)
3154 sprintfW( tmp
, szVersionFormat
,
3155 HIWORD(ffi
->dwFileVersionMS
), LOWORD(ffi
->dwFileVersionMS
),
3156 HIWORD(ffi
->dwFileVersionLS
), LOWORD(ffi
->dwFileVersionLS
) );
3157 if (verbuf
) lstrcpynW( verbuf
, tmp
, *verlen
);
3158 len
= strlenW( tmp
);
3159 if (len
>= *verlen
) ret
= ERROR_MORE_DATA
;
3164 if (verbuf
) *verbuf
= 0;
3170 if (VerQueryValueW( version
, szLangResource
, (LPVOID
*)&lang
, &len
) && len
> 0)
3172 sprintfW( tmp
, szLangFormat
, *lang
);
3173 if (langbuf
) lstrcpynW( langbuf
, tmp
, *langlen
);
3174 len
= strlenW( tmp
);
3175 if (len
>= *langlen
) ret
= ERROR_MORE_DATA
;
3180 if (langbuf
) *langbuf
= 0;
3184 msi_free( version
);
3189 /******************************************************************
3190 * MsiGetFileVersionW [MSI.@]
3192 UINT WINAPI
MsiGetFileVersionW( LPCWSTR path
, LPWSTR verbuf
, LPDWORD verlen
,
3193 LPWSTR langbuf
, LPDWORD langlen
)
3197 TRACE("%s %p %u %p %u\n", debugstr_w(path
), verbuf
, verlen
? *verlen
: 0,
3198 langbuf
, langlen
? *langlen
: 0);
3200 if ((verbuf
&& !verlen
) || (langbuf
&& !langlen
))
3201 return ERROR_INVALID_PARAMETER
;
3203 ret
= get_file_version( path
, verbuf
, verlen
, langbuf
, langlen
);
3204 if (ret
== ERROR_RESOURCE_DATA_NOT_FOUND
)
3207 WCHAR
*version
= msi_font_version_from_file( path
);
3208 if (!version
) return ERROR_FILE_INVALID
;
3209 len
= strlenW( version
);
3212 strcpyW( verbuf
, version
);
3213 ret
= ERROR_SUCCESS
;
3215 else ret
= ERROR_MORE_DATA
;
3217 msi_free( version
);
3222 /***********************************************************************
3223 * MsiGetFeatureUsageW [MSI.@]
3225 UINT WINAPI
MsiGetFeatureUsageW( LPCWSTR szProduct
, LPCWSTR szFeature
,
3226 LPDWORD pdwUseCount
, LPWORD pwDateUsed
)
3228 FIXME("%s %s %p %p\n",debugstr_w(szProduct
), debugstr_w(szFeature
),
3229 pdwUseCount
, pwDateUsed
);
3230 return ERROR_CALL_NOT_IMPLEMENTED
;
3233 /***********************************************************************
3234 * MsiGetFeatureUsageA [MSI.@]
3236 UINT WINAPI
MsiGetFeatureUsageA( LPCSTR szProduct
, LPCSTR szFeature
,
3237 LPDWORD pdwUseCount
, LPWORD pwDateUsed
)
3239 LPWSTR prod
= NULL
, feat
= NULL
;
3240 UINT ret
= ERROR_OUTOFMEMORY
;
3242 TRACE("%s %s %p %p\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
3243 pdwUseCount
, pwDateUsed
);
3245 prod
= strdupAtoW( szProduct
);
3246 if (szProduct
&& !prod
)
3249 feat
= strdupAtoW( szFeature
);
3250 if (szFeature
&& !feat
)
3253 ret
= MsiGetFeatureUsageW( prod
, feat
, pdwUseCount
, pwDateUsed
);
3262 /***********************************************************************
3263 * MsiUseFeatureExW [MSI.@]
3265 INSTALLSTATE WINAPI
MsiUseFeatureExW( LPCWSTR szProduct
, LPCWSTR szFeature
,
3266 DWORD dwInstallMode
, DWORD dwReserved
)
3270 TRACE("%s %s %i %i\n", debugstr_w(szProduct
), debugstr_w(szFeature
),
3271 dwInstallMode
, dwReserved
);
3273 state
= MsiQueryFeatureStateW( szProduct
, szFeature
);
3276 return INSTALLSTATE_INVALIDARG
;
3278 if (state
== INSTALLSTATE_LOCAL
&& dwInstallMode
!= INSTALLMODE_NODETECTION
)
3280 FIXME("mark product %s feature %s as used\n",
3281 debugstr_w(szProduct
), debugstr_w(szFeature
) );
3287 /***********************************************************************
3288 * MsiUseFeatureExA [MSI.@]
3290 INSTALLSTATE WINAPI
MsiUseFeatureExA( LPCSTR szProduct
, LPCSTR szFeature
,
3291 DWORD dwInstallMode
, DWORD dwReserved
)
3293 INSTALLSTATE ret
= INSTALLSTATE_UNKNOWN
;
3294 LPWSTR prod
= NULL
, feat
= NULL
;
3296 TRACE("%s %s %i %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
3297 dwInstallMode
, dwReserved
);
3299 prod
= strdupAtoW( szProduct
);
3300 if (szProduct
&& !prod
)
3303 feat
= strdupAtoW( szFeature
);
3304 if (szFeature
&& !feat
)
3307 ret
= MsiUseFeatureExW( prod
, feat
, dwInstallMode
, dwReserved
);
3316 /***********************************************************************
3317 * MsiUseFeatureW [MSI.@]
3319 INSTALLSTATE WINAPI
MsiUseFeatureW( LPCWSTR szProduct
, LPCWSTR szFeature
)
3321 return MsiUseFeatureExW(szProduct
, szFeature
, 0, 0);
3324 /***********************************************************************
3325 * MsiUseFeatureA [MSI.@]
3327 INSTALLSTATE WINAPI
MsiUseFeatureA( LPCSTR szProduct
, LPCSTR szFeature
)
3329 return MsiUseFeatureExA(szProduct
, szFeature
, 0, 0);
3332 /***********************************************************************
3333 * MSI_ProvideQualifiedComponentEx [internal]
3335 static UINT
MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent
,
3336 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPCWSTR szProduct
,
3337 DWORD Unused1
, DWORD Unused2
, awstring
*lpPathBuf
,
3338 LPDWORD pcchPathBuf
)
3340 WCHAR product
[MAX_FEATURE_CHARS
+1], component
[MAX_FEATURE_CHARS
+1],
3341 feature
[MAX_FEATURE_CHARS
+1];
3347 rc
= MSIREG_OpenUserComponentsKey(szComponent
, &hkey
, FALSE
);
3348 if (rc
!= ERROR_SUCCESS
)
3349 return ERROR_INDEX_ABSENT
;
3351 info
= msi_reg_get_val_str( hkey
, szQualifier
);
3355 return ERROR_INDEX_ABSENT
;
3357 MsiDecomposeDescriptorW(info
, product
, feature
, component
, &sz
);
3360 rc
= MSI_GetComponentPath(product
, component
, lpPathBuf
, pcchPathBuf
);
3362 rc
= MSI_GetComponentPath(szProduct
, component
, lpPathBuf
, pcchPathBuf
);
3366 if (rc
!= INSTALLSTATE_LOCAL
)
3367 return ERROR_FILE_NOT_FOUND
;
3369 return ERROR_SUCCESS
;
3372 /***********************************************************************
3373 * MsiProvideQualifiedComponentExW [MSI.@]
3375 UINT WINAPI
MsiProvideQualifiedComponentExW(LPCWSTR szComponent
,
3376 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPCWSTR szProduct
,
3377 DWORD Unused1
, DWORD Unused2
, LPWSTR lpPathBuf
,
3378 LPDWORD pcchPathBuf
)
3382 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_w(szComponent
),
3383 debugstr_w(szQualifier
), dwInstallMode
, debugstr_w(szProduct
),
3384 Unused1
, Unused2
, lpPathBuf
, pcchPathBuf
);
3386 path
.unicode
= TRUE
;
3387 path
.str
.w
= lpPathBuf
;
3389 return MSI_ProvideQualifiedComponentEx(szComponent
, szQualifier
,
3390 dwInstallMode
, szProduct
, Unused1
, Unused2
, &path
, pcchPathBuf
);
3393 /***********************************************************************
3394 * MsiProvideQualifiedComponentExA [MSI.@]
3396 UINT WINAPI
MsiProvideQualifiedComponentExA(LPCSTR szComponent
,
3397 LPCSTR szQualifier
, DWORD dwInstallMode
, LPCSTR szProduct
,
3398 DWORD Unused1
, DWORD Unused2
, LPSTR lpPathBuf
,
3399 LPDWORD pcchPathBuf
)
3401 LPWSTR szwComponent
, szwQualifier
= NULL
, szwProduct
= NULL
;
3402 UINT r
= ERROR_OUTOFMEMORY
;
3405 TRACE("%s %s %u %s %u %u %p %p\n", debugstr_a(szComponent
),
3406 debugstr_a(szQualifier
), dwInstallMode
, debugstr_a(szProduct
),
3407 Unused1
, Unused2
, lpPathBuf
, pcchPathBuf
);
3409 szwComponent
= strdupAtoW( szComponent
);
3410 if (szComponent
&& !szwComponent
)
3413 szwQualifier
= strdupAtoW( szQualifier
);
3414 if (szQualifier
&& !szwQualifier
)
3417 szwProduct
= strdupAtoW( szProduct
);
3418 if (szProduct
&& !szwProduct
)
3421 path
.unicode
= FALSE
;
3422 path
.str
.a
= lpPathBuf
;
3424 r
= MSI_ProvideQualifiedComponentEx(szwComponent
, szwQualifier
,
3425 dwInstallMode
, szwProduct
, Unused1
,
3426 Unused2
, &path
, pcchPathBuf
);
3428 msi_free(szwProduct
);
3429 msi_free(szwComponent
);
3430 msi_free(szwQualifier
);
3435 /***********************************************************************
3436 * MsiProvideQualifiedComponentW [MSI.@]
3438 UINT WINAPI
MsiProvideQualifiedComponentW( LPCWSTR szComponent
,
3439 LPCWSTR szQualifier
, DWORD dwInstallMode
, LPWSTR lpPathBuf
,
3440 LPDWORD pcchPathBuf
)
3442 return MsiProvideQualifiedComponentExW(szComponent
, szQualifier
,
3443 dwInstallMode
, NULL
, 0, 0, lpPathBuf
, pcchPathBuf
);
3446 /***********************************************************************
3447 * MsiProvideQualifiedComponentA [MSI.@]
3449 UINT WINAPI
MsiProvideQualifiedComponentA( LPCSTR szComponent
,
3450 LPCSTR szQualifier
, DWORD dwInstallMode
, LPSTR lpPathBuf
,
3451 LPDWORD pcchPathBuf
)
3453 return MsiProvideQualifiedComponentExA(szComponent
, szQualifier
,
3454 dwInstallMode
, NULL
, 0, 0, lpPathBuf
, pcchPathBuf
);
3457 /***********************************************************************
3458 * MSI_GetUserInfo [internal]
3460 static USERINFOSTATE
MSI_GetUserInfo(LPCWSTR szProduct
,
3461 awstring
*lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
3462 awstring
*lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
3463 awstring
*lpSerialBuf
, LPDWORD pcchSerialBuf
)
3465 WCHAR squished_pc
[SQUISH_GUID_SIZE
];
3466 LPWSTR user
, org
, serial
;
3467 USERINFOSTATE state
;
3472 TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct
), lpUserNameBuf
,
3473 pcchUserNameBuf
, lpOrgNameBuf
, pcchOrgNameBuf
, lpSerialBuf
,
3476 if (!szProduct
|| !squash_guid(szProduct
, squished_pc
))
3477 return USERINFOSTATE_INVALIDARG
;
3479 if (MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERMANAGED
,
3480 &hkey
, FALSE
) != ERROR_SUCCESS
&&
3481 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3482 &hkey
, FALSE
) != ERROR_SUCCESS
&&
3483 MSIREG_OpenProductKey(szProduct
, NULL
, MSIINSTALLCONTEXT_MACHINE
,
3484 &hkey
, FALSE
) != ERROR_SUCCESS
)
3486 return USERINFOSTATE_UNKNOWN
;
3489 if (MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3490 NULL
, &props
, FALSE
) != ERROR_SUCCESS
&&
3491 MSIREG_OpenInstallProps(szProduct
, MSIINSTALLCONTEXT_MACHINE
,
3492 NULL
, &props
, FALSE
) != ERROR_SUCCESS
)
3495 return USERINFOSTATE_ABSENT
;
3498 user
= msi_reg_get_val_str(props
, INSTALLPROPERTY_REGOWNERW
);
3499 org
= msi_reg_get_val_str(props
, INSTALLPROPERTY_REGCOMPANYW
);
3500 serial
= msi_reg_get_val_str(props
, INSTALLPROPERTY_PRODUCTIDW
);
3501 state
= USERINFOSTATE_ABSENT
;
3507 state
= USERINFOSTATE_PRESENT
;
3509 if (pcchUserNameBuf
)
3511 if (lpUserNameBuf
&& !user
)
3513 (*pcchUserNameBuf
)--;
3517 r
= msi_strcpy_to_awstring(user
, lpUserNameBuf
, pcchUserNameBuf
);
3518 if (r
== ERROR_MORE_DATA
)
3520 state
= USERINFOSTATE_MOREDATA
;
3528 if (!orgptr
) orgptr
= szEmpty
;
3530 r
= msi_strcpy_to_awstring(orgptr
, lpOrgNameBuf
, pcchOrgNameBuf
);
3531 if (r
== ERROR_MORE_DATA
)
3533 state
= USERINFOSTATE_MOREDATA
;
3546 r
= msi_strcpy_to_awstring(serial
, lpSerialBuf
, pcchSerialBuf
);
3547 if (r
== ERROR_MORE_DATA
)
3548 state
= USERINFOSTATE_MOREDATA
;
3559 /***********************************************************************
3560 * MsiGetUserInfoW [MSI.@]
3562 USERINFOSTATE WINAPI
MsiGetUserInfoW(LPCWSTR szProduct
,
3563 LPWSTR lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
3564 LPWSTR lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
3565 LPWSTR lpSerialBuf
, LPDWORD pcchSerialBuf
)
3567 awstring user
, org
, serial
;
3569 if ((lpUserNameBuf
&& !pcchUserNameBuf
) ||
3570 (lpOrgNameBuf
&& !pcchOrgNameBuf
) ||
3571 (lpSerialBuf
&& !pcchSerialBuf
))
3572 return USERINFOSTATE_INVALIDARG
;
3574 user
.unicode
= TRUE
;
3575 user
.str
.w
= lpUserNameBuf
;
3577 org
.str
.w
= lpOrgNameBuf
;
3578 serial
.unicode
= TRUE
;
3579 serial
.str
.w
= lpSerialBuf
;
3581 return MSI_GetUserInfo( szProduct
, &user
, pcchUserNameBuf
,
3582 &org
, pcchOrgNameBuf
,
3583 &serial
, pcchSerialBuf
);
3586 USERINFOSTATE WINAPI
MsiGetUserInfoA(LPCSTR szProduct
,
3587 LPSTR lpUserNameBuf
, LPDWORD pcchUserNameBuf
,
3588 LPSTR lpOrgNameBuf
, LPDWORD pcchOrgNameBuf
,
3589 LPSTR lpSerialBuf
, LPDWORD pcchSerialBuf
)
3591 awstring user
, org
, serial
;
3595 if ((lpUserNameBuf
&& !pcchUserNameBuf
) ||
3596 (lpOrgNameBuf
&& !pcchOrgNameBuf
) ||
3597 (lpSerialBuf
&& !pcchSerialBuf
))
3598 return USERINFOSTATE_INVALIDARG
;
3600 prod
= strdupAtoW( szProduct
);
3601 if (szProduct
&& !prod
)
3602 return ERROR_OUTOFMEMORY
;
3604 user
.unicode
= FALSE
;
3605 user
.str
.a
= lpUserNameBuf
;
3606 org
.unicode
= FALSE
;
3607 org
.str
.a
= lpOrgNameBuf
;
3608 serial
.unicode
= FALSE
;
3609 serial
.str
.a
= lpSerialBuf
;
3611 r
= MSI_GetUserInfo( prod
, &user
, pcchUserNameBuf
,
3612 &org
, pcchOrgNameBuf
,
3613 &serial
, pcchSerialBuf
);
3620 UINT WINAPI
MsiCollectUserInfoW(LPCWSTR szProduct
)
3624 MSIPACKAGE
*package
;
3625 static const WCHAR szFirstRun
[] = {'F','i','r','s','t','R','u','n',0};
3627 TRACE("(%s)\n",debugstr_w(szProduct
));
3629 rc
= MsiOpenProductW(szProduct
,&handle
);
3630 if (rc
!= ERROR_SUCCESS
)
3631 return ERROR_INVALID_PARAMETER
;
3633 /* MsiCollectUserInfo cannot be called from a custom action. */
3634 package
= msihandle2msiinfo(handle
, MSIHANDLETYPE_PACKAGE
);
3636 return ERROR_CALL_NOT_IMPLEMENTED
;
3638 rc
= ACTION_PerformUIAction(package
, szFirstRun
, SCRIPT_NONE
);
3639 msiobj_release( &package
->hdr
);
3641 MsiCloseHandle(handle
);
3646 UINT WINAPI
MsiCollectUserInfoA(LPCSTR szProduct
)
3650 MSIPACKAGE
*package
;
3651 static const WCHAR szFirstRun
[] = {'F','i','r','s','t','R','u','n',0};
3653 TRACE("(%s)\n",debugstr_a(szProduct
));
3655 rc
= MsiOpenProductA(szProduct
,&handle
);
3656 if (rc
!= ERROR_SUCCESS
)
3657 return ERROR_INVALID_PARAMETER
;
3659 /* MsiCollectUserInfo cannot be called from a custom action. */
3660 package
= msihandle2msiinfo(handle
, MSIHANDLETYPE_PACKAGE
);
3662 return ERROR_CALL_NOT_IMPLEMENTED
;
3664 rc
= ACTION_PerformUIAction(package
, szFirstRun
, SCRIPT_NONE
);
3665 msiobj_release( &package
->hdr
);
3667 MsiCloseHandle(handle
);
3672 /***********************************************************************
3673 * MsiConfigureFeatureA [MSI.@]
3675 UINT WINAPI
MsiConfigureFeatureA(LPCSTR szProduct
, LPCSTR szFeature
, INSTALLSTATE eInstallState
)
3677 LPWSTR prod
, feat
= NULL
;
3678 UINT r
= ERROR_OUTOFMEMORY
;
3680 TRACE("%s %s %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
), eInstallState
);
3682 prod
= strdupAtoW( szProduct
);
3683 if (szProduct
&& !prod
)
3686 feat
= strdupAtoW( szFeature
);
3687 if (szFeature
&& !feat
)
3690 r
= MsiConfigureFeatureW(prod
, feat
, eInstallState
);
3699 /***********************************************************************
3700 * MsiConfigureFeatureW [MSI.@]
3702 UINT WINAPI
MsiConfigureFeatureW(LPCWSTR szProduct
, LPCWSTR szFeature
, INSTALLSTATE eInstallState
)
3704 MSIPACKAGE
*package
= NULL
;
3706 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
];
3709 TRACE("%s %s %i\n", debugstr_w(szProduct
), debugstr_w(szFeature
), eInstallState
);
3711 if (!szProduct
|| !szFeature
)
3712 return ERROR_INVALID_PARAMETER
;
3714 switch (eInstallState
)
3716 case INSTALLSTATE_DEFAULT
:
3717 /* FIXME: how do we figure out the default location? */
3718 eInstallState
= INSTALLSTATE_LOCAL
;
3720 case INSTALLSTATE_LOCAL
:
3721 case INSTALLSTATE_SOURCE
:
3722 case INSTALLSTATE_ABSENT
:
3723 case INSTALLSTATE_ADVERTISED
:
3726 return ERROR_INVALID_PARAMETER
;
3729 r
= MSI_OpenProductW( szProduct
, &package
);
3730 if (r
!= ERROR_SUCCESS
)
3733 sz
= sizeof(sourcepath
);
3734 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3735 MSICODE_PRODUCT
, INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
3737 sz
= sizeof(filename
);
3738 MsiSourceListGetInfoW(szProduct
, NULL
, MSIINSTALLCONTEXT_USERUNMANAGED
,
3739 MSICODE_PRODUCT
, INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
3741 lstrcatW( sourcepath
, filename
);
3743 MsiSetInternalUI( INSTALLUILEVEL_BASIC
, NULL
);
3745 r
= ACTION_PerformUIAction( package
, szCostInitialize
, SCRIPT_NONE
);
3746 if (r
!= ERROR_SUCCESS
)
3749 r
= MSI_SetFeatureStateW( package
, szFeature
, eInstallState
);
3750 if (r
!= ERROR_SUCCESS
)
3753 r
= MSI_InstallPackage( package
, sourcepath
, NULL
);
3756 msiobj_release( &package
->hdr
);
3761 /***********************************************************************
3762 * MsiCreateAndVerifyInstallerDirectory [MSI.@]
3764 * Notes: undocumented
3766 UINT WINAPI
MsiCreateAndVerifyInstallerDirectory(DWORD dwReserved
)
3768 WCHAR path
[MAX_PATH
];
3770 TRACE("%d\n", dwReserved
);
3774 FIXME("dwReserved=%d\n", dwReserved
);
3775 return ERROR_INVALID_PARAMETER
;
3778 if (!GetWindowsDirectoryW(path
, MAX_PATH
))
3779 return ERROR_FUNCTION_FAILED
;
3781 lstrcatW(path
, installerW
);
3783 if (!CreateDirectoryW(path
, NULL
))
3784 return ERROR_FUNCTION_FAILED
;
3786 return ERROR_SUCCESS
;
3789 /***********************************************************************
3790 * MsiGetShortcutTargetA [MSI.@]
3792 UINT WINAPI
MsiGetShortcutTargetA( LPCSTR szShortcutTarget
,
3793 LPSTR szProductCode
, LPSTR szFeatureId
,
3794 LPSTR szComponentCode
)
3797 const int len
= MAX_FEATURE_CHARS
+1;
3798 WCHAR product
[MAX_FEATURE_CHARS
+1], feature
[MAX_FEATURE_CHARS
+1], component
[MAX_FEATURE_CHARS
+1];
3801 target
= strdupAtoW( szShortcutTarget
);
3802 if (szShortcutTarget
&& !target
)
3803 return ERROR_OUTOFMEMORY
;
3807 r
= MsiGetShortcutTargetW( target
, product
, feature
, component
);
3809 if (r
== ERROR_SUCCESS
)
3811 WideCharToMultiByte( CP_ACP
, 0, product
, -1, szProductCode
, len
, NULL
, NULL
);
3812 WideCharToMultiByte( CP_ACP
, 0, feature
, -1, szFeatureId
, len
, NULL
, NULL
);
3813 WideCharToMultiByte( CP_ACP
, 0, component
, -1, szComponentCode
, len
, NULL
, NULL
);
3818 /***********************************************************************
3819 * MsiGetShortcutTargetW [MSI.@]
3821 UINT WINAPI
MsiGetShortcutTargetW( LPCWSTR szShortcutTarget
,
3822 LPWSTR szProductCode
, LPWSTR szFeatureId
,
3823 LPWSTR szComponentCode
)
3825 IShellLinkDataList
*dl
= NULL
;
3826 IPersistFile
*pf
= NULL
;
3827 LPEXP_DARWIN_LINK darwin
= NULL
;
3830 TRACE("%s %p %p %p\n", debugstr_w(szShortcutTarget
),
3831 szProductCode
, szFeatureId
, szComponentCode
);
3833 init
= CoInitialize(NULL
);
3835 r
= CoCreateInstance( &CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
3836 &IID_IPersistFile
, (LPVOID
*) &pf
);
3837 if( SUCCEEDED( r
) )
3839 r
= IPersistFile_Load( pf
, szShortcutTarget
,
3840 STGM_READ
| STGM_SHARE_DENY_WRITE
);
3841 if( SUCCEEDED( r
) )
3843 r
= IPersistFile_QueryInterface( pf
, &IID_IShellLinkDataList
,
3845 if( SUCCEEDED( r
) )
3847 IShellLinkDataList_CopyDataBlock( dl
, EXP_DARWIN_ID_SIG
,
3849 IShellLinkDataList_Release( dl
);
3852 IPersistFile_Release( pf
);
3855 if (SUCCEEDED(init
))
3858 TRACE("darwin = %p\n", darwin
);
3865 ret
= MsiDecomposeDescriptorW( darwin
->szwDarwinID
,
3866 szProductCode
, szFeatureId
, szComponentCode
, &sz
);
3867 LocalFree( darwin
);
3871 return ERROR_FUNCTION_FAILED
;
3874 UINT WINAPI
MsiReinstallFeatureW( LPCWSTR szProduct
, LPCWSTR szFeature
, DWORD dwReinstallMode
)
3876 static const WCHAR fmtW
[] = {'%','s','=','%','s',' ','%','s','=','%','s',0};
3877 MSIPACKAGE
*package
;
3878 MSIINSTALLCONTEXT context
;
3880 WCHAR sourcepath
[MAX_PATH
], filename
[MAX_PATH
], reinstallmode
[11];
3881 WCHAR
*ptr
, *cmdline
;
3884 TRACE("%s, %s, 0x%08x\n", debugstr_w(szProduct
), debugstr_w(szFeature
), dwReinstallMode
);
3886 r
= msi_locate_product( szProduct
, &context
);
3887 if (r
!= ERROR_SUCCESS
)
3890 ptr
= reinstallmode
;
3892 if (dwReinstallMode
& REINSTALLMODE_FILEMISSING
)
3894 if (dwReinstallMode
& REINSTALLMODE_FILEOLDERVERSION
)
3896 if (dwReinstallMode
& REINSTALLMODE_FILEEQUALVERSION
)
3898 if (dwReinstallMode
& REINSTALLMODE_FILEEXACT
)
3900 if (dwReinstallMode
& REINSTALLMODE_FILEVERIFY
)
3902 if (dwReinstallMode
& REINSTALLMODE_FILEREPLACE
)
3904 if (dwReinstallMode
& REINSTALLMODE_USERDATA
)
3906 if (dwReinstallMode
& REINSTALLMODE_MACHINEDATA
)
3908 if (dwReinstallMode
& REINSTALLMODE_SHORTCUT
)
3910 if (dwReinstallMode
& REINSTALLMODE_PACKAGE
)
3914 sz
= sizeof(sourcepath
);
3915 MsiSourceListGetInfoW( szProduct
, NULL
, context
, MSICODE_PRODUCT
,
3916 INSTALLPROPERTY_LASTUSEDSOURCEW
, sourcepath
, &sz
);
3917 sz
= sizeof(filename
);
3918 MsiSourceListGetInfoW( szProduct
, NULL
, context
, MSICODE_PRODUCT
,
3919 INSTALLPROPERTY_PACKAGENAMEW
, filename
, &sz
);
3920 strcatW( sourcepath
, filename
);
3922 if (dwReinstallMode
& REINSTALLMODE_PACKAGE
)
3923 r
= MSI_OpenPackageW( sourcepath
, &package
);
3925 r
= MSI_OpenProductW( szProduct
, &package
);
3927 if (r
!= ERROR_SUCCESS
)
3930 sz
= (strlenW( fmtW
) + strlenW( szReinstallMode
) + strlenW( reinstallmode
)) * sizeof(WCHAR
);
3931 sz
+= (strlenW( szReinstall
) + strlenW( szFeature
)) * sizeof(WCHAR
);
3932 if (!(cmdline
= msi_alloc( sz
)))
3934 msiobj_release( &package
->hdr
);
3935 return ERROR_OUTOFMEMORY
;
3937 sprintfW( cmdline
, fmtW
, szReinstallMode
, reinstallmode
, szReinstall
, szFeature
);
3939 r
= MSI_InstallPackage( package
, sourcepath
, cmdline
);
3940 msiobj_release( &package
->hdr
);
3941 msi_free( cmdline
);
3946 UINT WINAPI
MsiReinstallFeatureA( LPCSTR szProduct
, LPCSTR szFeature
,
3947 DWORD dwReinstallMode
)
3953 TRACE("%s %s %i\n", debugstr_a(szProduct
), debugstr_a(szFeature
),
3956 wszProduct
= strdupAtoW(szProduct
);
3957 wszFeature
= strdupAtoW(szFeature
);
3959 rc
= MsiReinstallFeatureW(wszProduct
, wszFeature
, dwReinstallMode
);
3961 msi_free(wszProduct
);
3962 msi_free(wszFeature
);
3969 unsigned int buf
[4];
3970 unsigned char in
[64];
3971 unsigned char digest
[16];
3974 extern VOID WINAPI
MD5Init( MD5_CTX
*);
3975 extern VOID WINAPI
MD5Update( MD5_CTX
*, const unsigned char *, unsigned int );
3976 extern VOID WINAPI
MD5Final( MD5_CTX
*);
3978 /***********************************************************************
3979 * MsiGetFileHashW [MSI.@]
3981 UINT WINAPI
MsiGetFileHashW( LPCWSTR szFilePath
, DWORD dwOptions
,
3982 PMSIFILEHASHINFO pHash
)
3984 HANDLE handle
, mapping
;
3987 UINT r
= ERROR_FUNCTION_FAILED
;
3989 TRACE("%s %08x %p\n", debugstr_w(szFilePath
), dwOptions
, pHash
);
3992 return ERROR_INVALID_PARAMETER
;
3995 return ERROR_PATH_NOT_FOUND
;
3998 return ERROR_INVALID_PARAMETER
;
4000 return ERROR_INVALID_PARAMETER
;
4001 if (pHash
->dwFileHashInfoSize
< sizeof *pHash
)
4002 return ERROR_INVALID_PARAMETER
;
4004 handle
= CreateFileW( szFilePath
, GENERIC_READ
,
4005 FILE_SHARE_READ
| FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, 0, NULL
);
4006 if (handle
== INVALID_HANDLE_VALUE
)
4008 WARN("can't open file %u\n", GetLastError());
4009 return ERROR_FILE_NOT_FOUND
;
4011 length
= GetFileSize( handle
, NULL
);
4013 mapping
= CreateFileMappingW( handle
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4016 p
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, length
);
4022 MD5Update( &ctx
, p
, length
);
4024 UnmapViewOfFile( p
);
4026 memcpy( pHash
->dwData
, ctx
.digest
, sizeof pHash
->dwData
);
4029 CloseHandle( mapping
);
4031 CloseHandle( handle
);
4036 /***********************************************************************
4037 * MsiGetFileHashA [MSI.@]
4039 UINT WINAPI
MsiGetFileHashA( LPCSTR szFilePath
, DWORD dwOptions
,
4040 PMSIFILEHASHINFO pHash
)
4045 TRACE("%s %08x %p\n", debugstr_a(szFilePath
), dwOptions
, pHash
);
4047 file
= strdupAtoW( szFilePath
);
4048 if (szFilePath
&& !file
)
4049 return ERROR_OUTOFMEMORY
;
4051 r
= MsiGetFileHashW( file
, dwOptions
, pHash
);
4056 /***********************************************************************
4057 * MsiAdvertiseScriptW [MSI.@]
4059 UINT WINAPI
MsiAdvertiseScriptW( LPCWSTR szScriptFile
, DWORD dwFlags
,
4060 PHKEY phRegData
, BOOL fRemoveItems
)
4062 FIXME("%s %08x %p %d\n",
4063 debugstr_w( szScriptFile
), dwFlags
, phRegData
, fRemoveItems
);
4064 return ERROR_CALL_NOT_IMPLEMENTED
;
4067 /***********************************************************************
4068 * MsiAdvertiseScriptA [MSI.@]
4070 UINT WINAPI
MsiAdvertiseScriptA( LPCSTR szScriptFile
, DWORD dwFlags
,
4071 PHKEY phRegData
, BOOL fRemoveItems
)
4073 FIXME("%s %08x %p %d\n",
4074 debugstr_a( szScriptFile
), dwFlags
, phRegData
, fRemoveItems
);
4075 return ERROR_CALL_NOT_IMPLEMENTED
;
4078 /***********************************************************************
4079 * MsiIsProductElevatedW [MSI.@]
4081 UINT WINAPI
MsiIsProductElevatedW( LPCWSTR szProduct
, BOOL
*pfElevated
)
4083 FIXME("%s %p - stub\n",
4084 debugstr_w( szProduct
), pfElevated
);
4086 return ERROR_SUCCESS
;
4089 /***********************************************************************
4090 * MsiIsProductElevatedA [MSI.@]
4092 UINT WINAPI
MsiIsProductElevatedA( LPCSTR szProduct
, BOOL
*pfElevated
)
4094 FIXME("%s %p - stub\n",
4095 debugstr_a( szProduct
), pfElevated
);
4097 return ERROR_SUCCESS
;
4100 /***********************************************************************
4101 * MsiSetExternalUIRecord [MSI.@]
4103 UINT WINAPI
MsiSetExternalUIRecord( INSTALLUI_HANDLER_RECORD handler
,
4104 DWORD filter
, LPVOID context
,
4105 PINSTALLUI_HANDLER_RECORD prev
)
4107 TRACE("%p %08x %p %p\n", handler
, filter
, context
, prev
);
4110 *prev
= gUIHandlerRecord
;
4112 gUIHandlerRecord
= handler
;
4114 gUIContext
= context
;
4116 return ERROR_SUCCESS
;
4119 /***********************************************************************
4120 * MsiInstallMissingComponentA [MSI.@]
4122 UINT WINAPI
MsiInstallMissingComponentA( LPCSTR product
, LPCSTR component
, INSTALLSTATE state
)
4125 WCHAR
*productW
= NULL
, *componentW
= NULL
;
4127 TRACE("%s, %s, %d\n", debugstr_a(product
), debugstr_a(component
), state
);
4129 if (product
&& !(productW
= strdupAtoW( product
)))
4130 return ERROR_OUTOFMEMORY
;
4132 if (component
&& !(componentW
= strdupAtoW( component
)))
4134 msi_free( productW
);
4135 return ERROR_OUTOFMEMORY
;
4138 r
= MsiInstallMissingComponentW( productW
, componentW
, state
);
4139 msi_free( productW
);
4140 msi_free( componentW
);
4144 /***********************************************************************
4145 * MsiInstallMissingComponentW [MSI.@]
4147 UINT WINAPI
MsiInstallMissingComponentW(LPCWSTR szProduct
, LPCWSTR szComponent
, INSTALLSTATE eInstallState
)
4149 FIXME("(%s %s %d\n", debugstr_w(szProduct
), debugstr_w(szComponent
), eInstallState
);
4150 return ERROR_SUCCESS
;
4153 /***********************************************************************
4154 * MsiBeginTransactionA [MSI.@]
4156 UINT WINAPI
MsiBeginTransactionA( LPCSTR name
, DWORD attrs
, MSIHANDLE
*id
, HANDLE
*event
)
4161 FIXME("%s %u %p %p\n", debugstr_a(name
), attrs
, id
, event
);
4163 nameW
= strdupAtoW( name
);
4165 return ERROR_OUTOFMEMORY
;
4167 r
= MsiBeginTransactionW( nameW
, attrs
, id
, event
);
4172 /***********************************************************************
4173 * MsiBeginTransactionW [MSI.@]
4175 UINT WINAPI
MsiBeginTransactionW( LPCWSTR name
, DWORD attrs
, MSIHANDLE
*id
, HANDLE
*event
)
4177 FIXME("%s %u %p %p\n", debugstr_w(name
), attrs
, id
, event
);
4179 *id
= (MSIHANDLE
)0xdeadbeef;
4180 *event
= (HANDLE
)0xdeadbeef;
4182 return ERROR_SUCCESS
;
4185 /***********************************************************************
4186 * MsiEndTransaction [MSI.@]
4188 UINT WINAPI
MsiEndTransaction( DWORD state
)
4190 FIXME("%u\n", state
);
4191 return ERROR_SUCCESS
;