Vanara/PInvoke/Msi/Msi.Installer2.cs

7277 lines
337 KiB
C#
Raw Blame History

using System;
using System.Runtime.InteropServices;
using System.Text;
using static Vanara.PInvoke.Crypt32;
namespace Vanara.PInvoke
{
/// <summary>Items from the Msi.dll</summary>
public static partial class Msi
{
/// <summary>
/// The <c>MsiExtractPatchXMLData</c> function extracts information from a patch that can be used to determine if the patch applies
/// to a target system. The function returns an XML string that can be provided to MsiDeterminePatchSequence and
/// MsiDetermineApplicablePatches instead of the full patch file. The returned information can be used to determine whether the
/// patch is applicable.
/// </summary>
/// <param name="szPatchPath">
/// The full path to the patch that is being queried. Pass in as a null-terminated string. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="dwReserved">A reserved argument that must be 0 (zero).</param>
/// <param name="szXMLData">
/// <para>
/// A pointer to a buffer to hold the XML string that contains the extracted patch information. This buffer should be large enough
/// to contain the received information. If the buffer is too small, the function returns ERROR_MORE_DATA and sets *pcchXMLData to
/// the number of <c>TCHAR</c> in the value, not including the terminating NULL character.
/// </para>
/// <para>
/// If szXMLData is set to <c>NULL</c> and pcchXMLData is set to a valid pointer, the function returns ERROR_SUCCESS and sets
/// *pcchXMLData to the number of <c>TCHAR</c> in the value, not including the terminating NULL character. The function can then be
/// called again to retrieve the value, with szXMLData buffer large enough to contain *pcchXMLData + 1 characters.
/// </para>
/// </param>
/// <param name="pcchXMLData">
/// <para>
/// A pointer to a variable that specifies the number of <c>TCHAR</c> in the szXMLData buffer. When the function returns, this
/// parameter is set to the size of the requested value whether or not the function copies the value into the specified buffer. The
/// size is returned as the number of <c>TCHAR</c> in the requested value, not including the terminating null character.
/// </para>
/// <para>If this parameter is set to <c>NULL</c>, the function returns ERROR_INVALID_PARAMETER.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiExtractPatchXMLData</c> function can return the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>The function failed in a way that is not identified by any of the return values in this table.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The value does not fit in the provided buffer.</term>
/// </item>
/// <item>
/// <term>ERROR_PATCH_OPEN_FAILED</term>
/// <term>The patch file could not be opened.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function was successful.</term>
/// </item>
/// <item>
/// <term>ERROR_PATCH_PACKAGE_INVALID</term>
/// <term>The patch file could not be opened.</term>
/// </item>
/// <item>
/// <term>ERROR_CALL_NOT_IMPLEMENTED</term>
/// <term>This error can be returned if MSXML 3.0 is not installed.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>The ExtractPatchXMLData method of the Installer object uses the <c>MsiExtractPatchXMLData</c> function.</remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiextractpatchxmldataa UINT MsiExtractPatchXMLDataA( LPCSTR
// szPatchPath, DWORD dwReserved, LPSTR szXMLData, LPDWORD pcchXMLData );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiExtractPatchXMLDataA")]
public static extern Win32Error MsiExtractPatchXMLData([MarshalAs(UnmanagedType.LPTStr)] string szPatchPath, [Optional] uint dwReserved,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szXMLData, ref uint pcchXMLData);
/// <summary>
/// The <c>MsiGetComponentPath</c> function returns the full path to an installed component. If the key path for the component is a
/// registry key then the registry key is returned.
/// </summary>
/// <param name="szProduct">Specifies the product code for the client product.</param>
/// <param name="szComponent">Specifies the component ID of the component to be located.</param>
/// <param name="lpPathBuf">
/// <para>
/// Pointer to a variable that receives the path to the component. This parameter can be null. If the component is a registry key,
/// the registry roots are represented numerically. If this is a registry subkey path, there is a backslash at the end of the Key
/// Path. If this is a registry value key path, there is no backslash at the end. For example, a registry path on a 32-bit operating
/// system of <c>HKEY_CURRENT_USER</c>\ <c>SOFTWARE</c>\ <c>Microsoft</c> is returned as "01:\SOFTWARE\Microsoft". The registry
/// roots returned on 32-bit operating systems are defined as shown in the following table.
/// </para>
/// <para>
/// <c>Note</c> On 64-bit operating systems, a value of 20 is added to the numerical registry roots in this table to distinguish
/// them from registry key paths on 32-bit operating systems. For example, a registry key path of <c>HKEY_CURRENT_USER</c>\
/// <c>SOFTWARE</c>\ <c>Microsoft</c> is returned as "21:\SOFTWARE\Microsoft\", if the component path is a registry key on a 64-bit
/// operating system.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Root</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>HKEY_CLASSES_ROOT</term>
/// <term>00</term>
/// </item>
/// <item>
/// <term>HKEY_CURRENT_USER</term>
/// <term>01</term>
/// </item>
/// <item>
/// <term>HKEY_LOCAL_MACHINE</term>
/// <term>02</term>
/// </item>
/// <item>
/// <term>HKEY_USERS</term>
/// <term>03</term>
/// </item>
/// </list>
/// </param>
/// <param name="pcchBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpPathBuf is null, pcchBuf can be null.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiGetComponentPath</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_NOTUSED</term>
/// <term>The component being requested is disabled on the computer.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// <term>The component is not installed.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_INVALIDARG</term>
/// <term>One of the function parameters is invalid.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_LOCAL</term>
/// <term>The component is installed locally.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCE</term>
/// <term>The component is installed to run from source.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCEABSENT</term>
/// <term>The component source is inaccessible.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>The product code or component ID is unknown.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>Upon success of the <c>MsiGetComponentPath</c> function, the pcchBuf parameter contains the length of the string in lpPathBuf.</para>
/// <para>The <c>MsiGetComponentPath</c> function might return INSTALLSTATE_ABSENT or INSTALL_STATE_UNKNOWN, for the following reasons:</para>
/// <list type="bullet">
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// <description>
/// The application did not properly ensure that the feature was installed by calling MsiUseFeature and, if necessary, MsiConfigureFeature.
/// </description>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <description>
/// The feature is not published. The application should have determined this earlier by calling MsiQueryFeatureState or
/// MsiEnumFeatures. The application makes these calls while it initializes. An application should only use features that are known
/// to be published. Since INSTALLSTATE_UNKNOWN should have been returned by MsiUseFeature as well, either MsiUseFeature was not
/// called, or its return value was not properly checked.
/// </description>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetcomponentpatha INSTALLSTATE MsiGetComponentPathA( LPCSTR
// szProduct, LPCSTR szComponent, LPSTR lpPathBuf, LPDWORD pcchBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetComponentPathA")]
public static extern INSTALLSTATE MsiGetComponentPath([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szComponent, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf,
ref uint pcchBuf);
/// <summary>
/// <para>
/// The <c>MsiGetComponentPathEx</c> function returns the full path to an installed component. If the key path for the component is
/// a registry key then the function returns the registry key.
/// </para>
/// <para>
/// This function extends the existing MsiGetComponentPath function to enable searches for components across user accounts and
/// installation contexts.
/// </para>
/// </summary>
/// <param name="szProductCode">
/// A null-terminated string value that specifies an application's product code GUID. The function gets the path of installed
/// components used by this application.
/// </param>
/// <param name="szComponentCode">
/// A null-terminated string value that specifies a component code GUID. The function gets the path of an installed component having
/// this component code.
/// </param>
/// <param name="szUserSid">
/// <para>
/// A null-terminated string value that specifies the security identifier (SID) for a user in the system. The function gets the
/// paths of installed components of applications installed under the user accounts identified by this SID. The special SID string
/// s-1-1-0 (Everyone) specifies all users in the system. If this parameter is <c>NULL</c>, the function gets the path of an
/// installed component for the currently logged-on user only.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>SID type</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>Specifies the currently logged-on user.</term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>Specifies a particular user in the system. An example of an user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// <item>
/// <term>s-1-1-0</term>
/// <term>Specifies all users in the system.</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string s-1-5-18 (System) cannot be used to search applications installed in the per-machine
/// installation context. Setting the SID value to s-1-5-18 returns <c>ERROR_INVALID_PARAMETER</c>. When dwContext is set to
/// MSIINSTALLCONTEXT_MACHINE only, szUserSid must be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// A flag that specifies the installation context. The function gets the paths of installed components of applications installed in
/// the specified installation context. This parameter can be a combination of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED 1</term>
/// <term>Include applications installed in the per<65>user<65>managed installation context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED 2</term>
/// <term>Include applications installed in the per<65>user<65>unmanaged installation context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE 4</term>
/// <term>
/// Include applications installed in the per-machine installation context. When dwInstallContext is set to
/// MSIINSTALLCONTEXT_MACHINE only, the szUserSID parameter must be NULL.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="lpOutPathBuffer">
/// <para>
/// A string value that receives the path to the component. This parameter can be <c>NULL</c>. If the component is a registry key,
/// the registry roots are represented numerically. If this is a registry subkey path, there is a backslash at the end of the Key
/// Path. If this is a registry value key path, there is no backslash at the end. For example, a registry path on a 32-bit operating
/// system of <c>HKEY_CURRENT_USER</c>\ <c>SOFTWARE</c>\ <c>Microsoft</c> is returned as "01:\SOFTWARE\Microsoft". The registry
/// roots returned on 32-bit operating systems are defined as shown in the following table.
/// </para>
/// <para>
/// <c>Note</c> On 64-bit operating systems, a value of 20 is added to the numerical registry roots in this table to distinguish
/// them from registry key paths on 32-bit operating systems. For example, a registry key path of <c>HKEY_CURRENT_USER</c>\
/// <c>SOFTWARE</c>\ <c>Microsoft</c> is returned as "21:\SOFTWARE\Microsoft\", if the component path is a registry key on a 64-bit
/// operating system.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Root</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>HKEY_CLASSES_ROOT</term>
/// <term>00</term>
/// </item>
/// <item>
/// <term>HKEY_CURRENT_USER</term>
/// <term>01</term>
/// </item>
/// <item>
/// <term>HKEY_LOCAL_MACHINE</term>
/// <term>02</term>
/// </item>
/// <item>
/// <term>HKEY_USERS</term>
/// <term>03</term>
/// </item>
/// </list>
/// </param>
/// <param name="pcchOutPathBuffer">
/// Pointer to a location that receives the size of the buffer, in <c>TCHAR</c>, pointed to by the szPathBuf parameter. The value in
/// this location should be set to the count of <c>TCHAR</c> in the string including the terminating null character. If the size of
/// the buffer is too small, this parameter receives the length of the string value without including the terminating null character
/// in the count.
/// </param>
/// <returns>
/// <para>The <c>MsiGetComponentPathEx</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_NOTUSED</term>
/// <term>The component being requested is disabled on the computer.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_BADCONFIG</term>
/// <term>Configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// <term>The component is not installed.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_INVALIDARG</term>
/// <term>One of the function parameters is invalid.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_LOCAL</term>
/// <term>The component is installed locally.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCE</term>
/// <term>The component is installed to run from source.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCEABSENT</term>
/// <term>The component source is inaccessible.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>The product code or component ID is unknown.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_BROKEN</term>
/// <term>The component is corrupt or partially missing in some way and requires repair.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>MsiGetComponentPathEx</c> function might return <c>INSTALLSTATE_ABSENT</c> or <c>INSTALL_STATE_UNKNOWN</c>, for the
/// following reasons:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetcomponentpathexa INSTALLSTATE MsiGetComponentPathExA( LPCSTR
// szProductCode, LPCSTR szComponentCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPSTR lpOutPathBuffer, LPDWORD
// pcchOutPathBuffer );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetComponentPathExA")]
public static extern INSTALLSTATE MsiGetComponentPathEx([MarshalAs(UnmanagedType.LPTStr)] string szProductCode,
[MarshalAs(UnmanagedType.LPTStr)] string szComponentCode, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid,
[Optional] MSIINSTALLCONTEXT dwContext, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpOutPathBuffer,
ref uint pcchOutPathBuffer);
/// <summary>The <c>MsiGetFeatureInfo</c> function returns descriptive information for a feature.</summary>
/// <param name="hProduct">Handle to the product that owns the feature. This handle is obtained from MsiOpenProduct.</param>
/// <param name="szFeature">Feature code for the feature about which information should be returned.</param>
/// <param name="lpAttributes">
/// <para>Pointer to a location containing one or more of the following Attribute flags.</para>
/// <para>INSTALLFEATUREATTRIBUTE_FAVORLOCAL (1)</para>
/// <para>INSTALLFEATUREATTRIBUTE_FAVORSOURCE (2)</para>
/// <para>INSTALLFEATUREATTRIBUTE_FOLLOWPARENT (4)</para>
/// <para>INSTALLFEATUREATTRIBUTE_FAVORADVERTISE (8)</para>
/// <para>INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE (16)</para>
/// <para>INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE (32)</para>
/// <para>
/// For more information, see Feature Table. The values that <c>MsiGetFeatureInfo</c> returns are double the values in the
/// Attributes column of the Feature Table.
/// </para>
/// </param>
/// <param name="lpTitleBuf">
/// <para>
/// Pointer to a buffer to receive the localized name of the feature, which corresponds to the Title field in the Feature Table.
/// </para>
/// <para>This parameter is optional and can be null.</para>
/// </param>
/// <param name="pcchTitleBuf">
/// As input, the size of lpTitleBuf. As output, the number of characters returned in lpTitleBuf. On input, this is the full size of
/// the buffer, and includes a space for a terminating null character. If the buffer that is passed in is too small, the count
/// returned does not include the terminating null character.
/// </param>
/// <param name="lpHelpBuf">
/// Pointer to a buffer to receive the localized description of the feature, which corresponds to the Description field for the
/// feature in the Feature table. This parameter is optional and can be null.
/// </param>
/// <param name="pcchHelpBuf">
/// As input, the size of lpHelpBuf. As output, the number of characters returned in lpHelpBuf. On input, this is the full size of
/// the buffer, and includes a space for a terminating null character. If the buffer passed in is too small, the count returned does
/// not include the terminating null character.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_HANDLE</term>
/// <term>The product handle is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>One of the parameters is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>A buffer is too small to hold the requested data.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function returns successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_FEATURE</term>
/// <term>The feature is not known.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// The buffer sizes for the <c>MsiGetFeatureInfo</c> function should include an extra character for the terminating null character.
/// If a buffer is too small, the returned string is truncated with null, and the buffer size contains the number of characters in
/// the whole string, not including the terminating null character. For more information, see Calling Database Functions From Programs.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetfeatureinfow UINT MsiGetFeatureInfoW( MSIHANDLE hProduct,
// LPCWSTR szFeature, LPDWORD lpAttributes, LPWSTR lpTitleBuf, LPDWORD pcchTitleBuf, LPWSTR lpHelpBuf, LPDWORD pcchHelpBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetFeatureInfoW")]
public static extern Win32Error MsiGetFeatureInfo(MSIHANDLE hProduct, [MarshalAs(UnmanagedType.LPTStr)] string szFeature,
out INSTALLFEATUREATTRIBUTE lpAttributes, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpTitleBuf,
ref uint pcchTitleBuf, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpHelpBuf, ref uint pcchHelpBuf);
/// <summary>The <c>MsiGetFeatureUsage</c> function returns the usage metrics for a product feature.</summary>
/// <param name="szProduct">Specifies the product code for the product that contains the feature.</param>
/// <param name="szFeature">Specifies the feature code for the feature for which metrics are to be returned.</param>
/// <param name="pdwUseCount">Indicates the number of times the feature has been used.</param>
/// <param name="pwDateUsed">
/// <para>Specifies the date that the feature was last used. The date is in the MS-DOS date format, as shown in the following table.</para>
/// <list type="table">
/// <listheader>
/// <term>Bits</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0 <20> 4</term>
/// <term>Day of the month (1-31)</term>
/// </item>
/// <item>
/// <term>5 <20> 8</term>
/// <term>Month (1 = January, 2 = February, and so on)</term>
/// </item>
/// <item>
/// <term>9 <20> 15</term>
/// <term>Year offset from 1980 (add 1980 to get actual year)</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>The <c>MsiGetFeatureUsage</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>No usage information is available or the product or feature is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetfeatureusagew UINT MsiGetFeatureUsageW( LPCWSTR szProduct,
// LPCWSTR szFeature, LPDWORD pdwUseCount, LPWORD pwDateUsed );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetFeatureUsageW")]
public static extern Win32Error MsiGetFeatureUsage([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szFeature, out uint pdwUseCount, out ushort pwDateUsed);
/// <summary>
/// <para>
/// The <c>MsiGetFileHash</c> function takes the path to a file and returns a 128-bit hash of that file. Authoring tools may use
/// <c>MsiGetFileHash</c> to obtain the file hash needed to populate the MsiFileHash table.
/// </para>
/// <para>
/// Windows Installer uses file hashing as a means to detect and eliminate unnecessary file copying. A file hash stored in the
/// MsiFileHash table may be compared to a hash of an existing file on the user's computer.
/// </para>
/// </summary>
/// <param name="szFilePath">Path to file that is to be hashed.</param>
/// <param name="dwOptions">The value in this column must be 0. This parameter is reserved for future use.</param>
/// <param name="pHash">Pointer to the returned file hash information.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The file does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The file could not be opened to get version information.</term>
/// </item>
/// <item>
/// <term>E_FAIL</term>
/// <term>Unexpected error has occurred.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The entire 128-bit file hash is returned as four 32-bit fields. The numbering of the four fields is zero-based. The values
/// returned by <c>MsiGetFileHash</c> correspond to the four fields of the MSIFILEHASHINFO structure. The first field corresponds to
/// the HashPart1 column of the MsiFileHash table, the second field corresponds to the HashPart2 column, the third field corresponds
/// to the HashPart3 column, and the fourth field corresponds to the HashPart4 column.
/// </para>
/// <para>
/// The hash information entered into the MsiFileHash table must be obtained by calling <c>MsiGetFileHash</c> or the FileHash
/// method. Do not attempt to use other methods to generate the file hash.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetfilehasha UINT MsiGetFileHashA( LPCSTR szFilePath, DWORD
// dwOptions, PMSIFILEHASHINFO pHash );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetFileHashA")]
public static extern Win32Error MsiGetFileHash([MarshalAs(UnmanagedType.LPTStr)] string szFilePath, [Optional] uint dwOptions, ref MSIFILEHASHINFO pHash);
/// <summary>
/// <para>
/// The <c>MsiGetFileSignatureInformation</c> function takes the path to a file that has been digitally signed and returns the
/// file's signer certificate and hash. <c>MsiGetFileSignatureInformation</c> may be called to obtain the signer certificate and
/// hash needed to populate the MsiDigitalCertificate, MsiPatchCertificate, and MsiDigitalSignature tables.
/// </para>
/// <para>
/// <c>Windows Installer 3.0 and later:</c> Beginning with Windows Installer 3.0, the Windows Installer can verify the digital
/// signatures of patches (.msp files) by using the MsiPatchCertificate and MsiDigitalCertificate tables. For more information see
/// Guidelines for Authoring Secure Installations and User Account Control (UAC) Patching.
/// </para>
/// <para>
/// <c>Windows Installer 2.0:</c> Digital signatures of patches is not supported. Windows Installer 2.0 uses digital signatures as a
/// means to detect corrupted resources, and can only verify the digital signatures of external cabinets, and only by the use of the
/// MsiDigitalSignature and MsiDigitalCertificate tables.
/// </para>
/// </summary>
/// <param name="szSignedObjectPath">
/// Pointer to a null-terminated string specifying the full path to the file that contains the digital signature.
/// </param>
/// <param name="dwFlags">
/// <para>Special error case flags.</para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSI_INVALID_HASH_IS_FATAL 0x1</term>
/// <term>
/// Without this flag set, and when requesting only the certificate context, an invalid hash in the digital signature does not cause
/// MsiGetFileSignatureInformation to return a fatal error. To return a fatal error for an invalid hash, set the
/// MSI_INVALID_HASH_IS_FATAL flag.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="ppcCertContext">Returned signer certificate context</param>
/// <param name="pbHashData">Returned hash buffer. This parameter can be <c>NULL</c> if the hash data is not being requested.</param>
/// <param name="pcbHashData">
/// Pointer to a variable that specifies the size, in bytes, of the buffer pointed to by the pbHashData parameter. This parameter
/// cannot be <c>NULL</c> if pbHashData is non- <c>NULL</c>. If ERROR_MORE_DATA is returned, pbHashData gives the size of the buffer
/// required to hold the hash data. If ERROR_SUCCESS is returned, it gives the number of bytes written to the hash buffer. The
/// pcbHashData parameter is ignored if pbHashData is <c>NULL</c>.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS/S_OK</term>
/// <term>Successful completion.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>Invalid parameter was specified.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>
/// WinVerifyTrust is not available on the system. MsiGetFileSignatureInformation requires the presence of the Wintrust.dll file on
/// the system.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>
/// A buffer is too small to hold the requested data. If ERROR_MORE_DATA is returned, pcbHashData gives the size of the buffer
/// required to hold the hash data.
/// </term>
/// </item>
/// <item>
/// <term>TRUST_E_NOSIGNATURE</term>
/// <term>File is not signed</term>
/// </item>
/// <item>
/// <term>TRUST_E_BAD_DIGEST</term>
/// <term>The file's current hash is invalid according to the hash stored in the file's digital signature.</term>
/// </item>
/// <item>
/// <term>CERT_E_REVOKED</term>
/// <term>The file's signer certificate has been revoked. The file's digital signature is compromised.</term>
/// </item>
/// <item>
/// <term>TRUST_E_SUBJECT_NOT_TRUSTED</term>
/// <term>
/// The subject failed the specified verification action. Most trust providers return a more detailed error code that describes the
/// reason for the failure.
/// </term>
/// </item>
/// <item>
/// <term>TRUST_E_PROVIDER_UNKNOWN</term>
/// <term>The trust provider is not recognized on this system.</term>
/// </item>
/// <item>
/// <term>TRUST_E_ACTION_UNKNOWN</term>
/// <term>The trust provider does not support the specified action.</term>
/// </item>
/// <item>
/// <term>TRUST_E_SUBJECT_FORM_UNKNOWN</term>
/// <term>The trust provider does not support the form specified for the subject.</term>
/// </item>
/// </list>
/// <para>
/// <c>MsiGetFileSignatureInformation</c> also returns all the Win32 error values mapped to their equivalent <c>HRESULT</c> data
/// type by <c>HRESULT_FROM_WIN32</c>.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// When requesting only the certificate context, an invalid hash in the digital signature does not cause
/// <c>MsiGetFileSignatureInformation</c> to return a fatal error. To return a fatal error for an invalid hash, set the
/// MSI_INVALID_HASH_IS_FATAL flag in the dwFlags parameter.
/// </para>
/// <para>
/// The certificate context and hash information is extracted from the file by a call to WinVerifyTrust. The ppcCertContext
/// parameter is a duplicate of the signer certificate context from the signature. It is the responsibility of the caller to call
/// CertFreeCertificateContext to free the certificate context when finished.
/// </para>
/// <para>Note that <c>MsiGetFileSignatureInformation</c> requires the presence of the Wintrust.dll file on the system.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetfilesignatureinformationw HRESULT
// MsiGetFileSignatureInformationW( LPCWSTR szSignedObjectPath, DWORD dwFlags, PCCERT_CONTEXT *ppcCertContext, LPBYTE pbHashData,
// LPDWORD pcbHashData );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetFileSignatureInformationW")]
public static extern HRESULT MsiGetFileSignatureInformation([MarshalAs(UnmanagedType.LPTStr)] string szSignedObjectPath,
MSISIGINFO dwFlags, out SafePCCERT_CONTEXT ppcCertContext, [Out, Optional] IntPtr pbHashData, ref uint pcbHashData);
/// <summary>
/// The <c>MsiGetFileVersion</c> returns the version string and language string in the format that the installer expects to find
/// them in the database. If you want only version information, set lpLangBuf and pcchLangBuf to 0 (zero). If you just want language
/// information, set lpVersionBuf and pcchVersionBuf to 0 (zero).
/// </summary>
/// <param name="szFilePath">Specifies the path to the file.</param>
/// <param name="lpVersionBuf">
/// <para>Returns the file version.</para>
/// <para>Set to 0 for language information only.</para>
/// </param>
/// <param name="pcchVersionBuf">
/// <para>In and out buffer count as the number of <c>TCHAR</c>.</para>
/// <para>
/// Set to 0 (zero) for language information only. On input, this is the full size of the buffer, including a space for a
/// terminating null character. If the buffer passed in is too small, the count returned does not include the terminating null character.
/// </para>
/// </param>
/// <param name="lpLangBuf">
/// <para>Returns the file language.</para>
/// <para>Set to 0 (zero) for version information only.</para>
/// </param>
/// <param name="pcchLangBuf">
/// <para>In and out buffer count as the number of <c>TCHAR</c>.</para>
/// <para>
/// Set to 0 (zero) for version information only. On input, this is the full size of the buffer, including a space for a terminating
/// null character. If the buffer passed in is too small, the count returned does not include the terminating null character.
/// </para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>Successful completion.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>File does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>File cannot be opened to get version information.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_INVALID</term>
/// <term>File does not contain version information.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>The version information is invalid.</term>
/// </item>
/// <item>
/// <term>E_FAIL</term>
/// <term>Unexpected error.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetfileversiona UINT MsiGetFileVersionA( LPCSTR szFilePath,
// LPSTR lpVersionBuf, LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetFileVersionA")]
public static extern Win32Error MsiGetFileVersion([MarshalAs(UnmanagedType.LPTStr)] string szFilePath,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpVersionBuf, ref uint pcchVersionBuf,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpLangBuf, ref uint pcchLangBuf);
/// <summary>
/// The <c>MsiGetFileVersion</c> returns the version string and language string in the format that the installer expects to find
/// them in the database. If you want only version information, set lpLangBuf and pcchLangBuf to 0 (zero). If you just want language
/// information, set lpVersionBuf and pcchVersionBuf to 0 (zero).
/// </summary>
/// <param name="szFilePath">Specifies the path to the file.</param>
/// <param name="lpVersionBuf">
/// <para>Returns the file version.</para>
/// <para>Set to 0 for language information only.</para>
/// </param>
/// <param name="pcchVersionBuf">
/// <para>In and out buffer count as the number of <c>TCHAR</c>.</para>
/// <para>
/// Set to 0 (zero) for language information only. On input, this is the full size of the buffer, including a space for a
/// terminating null character. If the buffer passed in is too small, the count returned does not include the terminating null character.
/// </para>
/// </param>
/// <param name="lpLangBuf">
/// <para>Returns the file language.</para>
/// <para>Set to 0 (zero) for version information only.</para>
/// </param>
/// <param name="pcchLangBuf">
/// <para>In and out buffer count as the number of <c>TCHAR</c>.</para>
/// <para>
/// Set to 0 (zero) for version information only. On input, this is the full size of the buffer, including a space for a terminating
/// null character. If the buffer passed in is too small, the count returned does not include the terminating null character.
/// </para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>Successful completion.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>File does not exist.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>File cannot be opened to get version information.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_INVALID</term>
/// <term>File does not contain version information.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_DATA</term>
/// <term>The version information is invalid.</term>
/// </item>
/// <item>
/// <term>E_FAIL</term>
/// <term>Unexpected error.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetfileversiona UINT MsiGetFileVersionA( LPCSTR szFilePath,
// LPSTR lpVersionBuf, LPDWORD pcchVersionBuf, LPSTR lpLangBuf, LPDWORD pcchLangBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetFileVersionA")]
public static extern Win32Error MsiGetFileVersion([MarshalAs(UnmanagedType.LPTStr)] string szFilePath,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpVersionBuf, [In, Optional] IntPtr pcchVersionBuf,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpLangBuf, [In, Optional] IntPtr pcchLangBuf);
/// <summary>
/// The <c>MsiGetPatchFileList</c> function is provided a list of .msp files, delimited by semicolons, and retrieves the list of
/// files that can be updated by the patches.
/// </summary>
/// <param name="szProductCode">
/// A null-terminated string value containing the ProductCode (GUID) of the product which is the target of the patches. This
/// parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szPatchPackages">
/// A null-terminated string value that contains the list of Windows Installer patches (.msp files). Each patch can be specified by
/// the full path to the patch package. The patches in the list are delimited by semicolons. At least one patch must be specified.
/// </param>
/// <param name="pcFiles">
/// A pointer to a location that receives the number of files that will be updated on this system by this list of patches specified
/// by szPatchList. This parameter is required.
/// </param>
/// <param name="pphFileRecords">
/// A pointer to a location that receives a pointer to an array of records. The first field (0-index) of each record contains the
/// full file path of a file that can be updated when the list of patches in szPatchList are applied on this computer. This
/// parameter is required.
/// </param>
/// <returns>
/// <para>The <c>MsiGetPatchFileList</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>The function failed.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// For example, szPatchList could have the value: "c:\sus\download\cache\Office\sp1.msp; c:\sus\download\cache\Office\QFE1.msp; c:\sus\download\cache\Office\QFEn.msp".
/// </para>
/// <para>
/// This function runs in the context of the caller. The product code is searched in the order of user-unmanaged context,
/// user-managed context, and machine context.
/// </para>
/// <para>You must close all MSIHANDLE objects that are returned by this function by calling the MsiCloseHandle function.</para>
/// <para>If the function fails, you can obtain extended error information by using the MsiGetLastErrorRecord function.</para>
/// <para>For more information about using the <c>MsiGetPatchFileList</c> function see Listing the Files that can be Updated.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetpatchfilelista UINT MsiGetPatchFileListA( LPCSTR
// szProductCode, LPCSTR szPatchPackages, LPDWORD pcFiles, MSIHANDLE **pphFileRecords );
[DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetPatchFileListA")]
public static extern Win32Error MsiGetPatchFileList([MarshalAs(UnmanagedType.LPTStr)] string szProductCode,
[MarshalAs(UnmanagedType.LPTStr)] string szPatchPackages, out uint pcFiles,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] out MSIHANDLE[] pphFileRecords);
/// <summary>The <c>MsiGetPatchInfo</c> function returns information about a patch.</summary>
/// <param name="szPatch">Specifies the patch code for the patch package.</param>
/// <param name="szAttribute">
/// <para>Specifies the attribute to be retrieved.</para>
/// <list type="table">
/// <listheader>
/// <term>Attribute</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLPROPERTY_LOCALPACKAGE</term>
/// <term>Local cached package.</term>
/// </item>
/// </list>
/// </param>
/// <param name="lpValueBuf">Pointer to a buffer that receives the property value. This parameter can be null.</param>
/// <param name="pcchValueBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpValueBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpValueBuf is null, pcchValueBuf can be null.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiGetPatchInfo</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>A buffer is too small to hold the requested data.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The patch package is not installed.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PROPERTY</term>
/// <term>The property is unrecognized.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// When the <c>MsiGetPatchInfo</c> function returns, the pcchValueBuf parameter contains the length of the class string stored in
/// the buffer. The count returned does not include the terminating null character.
/// </para>
/// <para>
/// If the buffer is too small to hold the requested data, <c>MsiGetPatchInfo</c> returns ERROR_MORE_DATA, and pcchValueBuf contains
/// the number of characters copied to lpValueBuf, without counting the null character.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetpatchinfoa UINT MsiGetPatchInfoA( LPCSTR szPatch, LPCSTR
// szAttribute, LPSTR lpValueBuf, LPDWORD pcchValueBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetPatchInfoA")]
public static extern Win32Error MsiGetPatchInfo([MarshalAs(UnmanagedType.LPTStr)] string szPatch,
[MarshalAs(UnmanagedType.LPTStr)] string szAttribute, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpValueBuf,
ref uint pcchValueBuf);
/// <summary>
/// The <c>MsiGetPatchInfoEx</c> function queries for information about the application of a patch to a specified instance of a product.
/// </summary>
/// <param name="szPatchCode">A null-terminated string that contains the GUID of the patch. This parameter cannot be <c>NULL</c>.</param>
/// <param name="szProductCode">
/// A null-terminated string that contains the ProductCode GUID of the product instance. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// A null-terminated string that specifies the security identifier (SID) under which the instance of the patch being queried
/// exists. Using a <c>NULL</c> value specifies the current user.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>Specifies the user that is logged on.</term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>
/// Specifies the enumeration for a specific user ID in the system. The following example identifies a possible user SID: "S-1-3-64-2415071341-1358098788-3127455600-2561".
/// </term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string "S-1-5-18" (system) cannot be used to enumerate products installed as per-machine. If
/// dwContext is <c>MSIINSTALLCONTEXT_MACHINE</c>, szUserSid must be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// Restricts the enumeration to a per-user-unmanaged, per-user-managed, or per-machine context. This parameter can be any one of
/// the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED 1</term>
/// <term>Query that is extended to all per<65>user-managed installations for the users that szUserSid specifies.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED 2</term>
/// <term>Query that is extended to all per<65>user-unmanaged installations for the users that szUserSid specifies.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE 4</term>
/// <term>Query that is extended to all per-machine installations.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szProperty">
/// <para>A null-terminated string that specifies the property value to retrieve. The szProperty parameter can be one of the following:</para>
/// <list type="table">
/// <listheader>
/// <term>Name</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLPROPERTY_LOCALPACKAGE "LocalPackage"</term>
/// <term>Gets the cached patch file that the product uses.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_TRANSFORMS "Transforms"</term>
/// <term>
/// Gets the set of patch transforms that the last patch installation applied to the product. This value may not be available for
/// per-user, non-managed applications if the user is not logged on.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLDATE "InstallDate"</term>
/// <term>
/// Gets the last time this product received service. The value of this property is replaced each time a patch is applied or removed
/// from the product or the /v Command-Line Option is used to repair the product. If the product has received no repairs or patches
/// this property contains the time this product was installed on this computer.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_UNINSTALLABLE "Uninstallable"</term>
/// <term>
/// Returns "1" if the patch is marked as possible to uninstall from the product. In this case, the installer can still block the
/// uninstallation if this patch is required by another patch that cannot be uninstalled.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PATCHSTATE "State"</term>
/// <term>
/// Returns "1" if this patch is currently applied to the product. Returns "2" if this patch is superseded by another patch. Returns
/// "4" if this patch is obsolete. These values correspond to the constants the dwFilter parameter of MsiEnumPatchesEx uses.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_DISPLAYNAME "DisplayName"</term>
/// <term>
/// Get the registered display name for the patch. For patches that do not include the DisplayName property in the MsiPatchMetadata
/// table, the returned display name is an empty string ("").
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_MOREINFOURL "MoreInfoURL"</term>
/// <term>
/// Get the registered support information URL for the patch. For patches that do not include the MoreInfoURL property in the
/// MsiPatchMetadata table, the returned support information URL is an empty string ("").
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="lpValue">
/// <para>
/// This parameter is a pointer to a buffer that receives the property value. This buffer should be large enough to contain the
/// information. If the buffer is too small, the function returns <c>ERROR_MORE_DATA</c> and sets *pcchValue to the number of
/// <c>TCHAR</c> in the property value, not including the terminating <c>NULL</c> character.
/// </para>
/// <para>
/// If lpValue is set to <c>NULL</c> and pcchValue is set to a valid pointer, the function returns <c>ERROR_SUCCESS</c> and sets
/// *pcchValue to the number of <c>TCHAR</c> in the value, not including the terminating <c>NULL</c> character. The function can
/// then be called again to retrieve the value, with lpValue buffer large enough to contain *pcchValue + 1 characters.
/// </para>
/// <para>
/// If lpValue and pcchValue are both set to <c>NULL</c>, the function returns <c>ERROR_SUCCESS</c> if the value exists, without
/// retrieving the value.
/// </para>
/// </param>
/// <param name="pcchValue">
/// <para>
/// When calling the function, this parameter should be a pointer to a variable that specifies the number of <c>TCHAR</c> in the
/// lpValue buffer. When the function returns, this parameter is set to the size of the requested value whether or not the function
/// copies the value into the specified buffer. The size is returned as the number of <c>TCHAR</c> in the requested value, not
/// including the terminating null character.
/// </para>
/// <para>This parameter can be set to <c>NULL</c> only if lpValue is also <c>NULL</c>. Otherwise, the function returns <c>ERROR_INVALID_PARAMETER</c>.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiGetPatchInfoEx</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The function fails trying to access a resource with insufficient privileges.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>The function fails and the error is not identified in other error codes.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The value does not fit in the provided buffer.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The patch is enumerated successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product that szProduct specifies is not installed on the computer.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PROPERTY</term>
/// <term>The property is unrecognized.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch is unrecognized.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para><c>Windows Installer 2.0:</c> Not supported. This function is available beginning with Windows Installer version 3.0.</para>
/// <para>
/// A user may query patch data for any product instance that is visible. The administrator group can query patch data for any
/// product instance and any user on the computer. Not all values are guaranteed to be available for per-user, non-managed
/// applications if the user is not logged on.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetpatchinfoexa UINT MsiGetPatchInfoExA( LPCSTR szPatchCode,
// LPCSTR szProductCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCSTR szProperty, LPSTR lpValue, LPDWORD pcchValue );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetPatchInfoExA")]
public static extern Win32Error MsiGetPatchInfoEx([MarshalAs(UnmanagedType.LPTStr)] string szPatchCode,
[MarshalAs(UnmanagedType.LPTStr)] string szProductCode, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid,
MSIINSTALLCONTEXT dwContext, [MarshalAs(UnmanagedType.LPTStr)] string szProperty,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpValue, ref uint pcchValue);
/// <summary>
/// The <c>MsiGetProductCode</c> function returns the product code of an application by using the component code of an installed or
/// advertised component of the application. During initialization, an application must determine under which product code it has
/// been installed or advertised.
/// </summary>
/// <param name="szComponent">
/// This parameter specifies the component code of a component that has been installed by the application. This will be typically
/// the component code of the component containing the executable file of the application.
/// </param>
/// <param name="lpBuf39">
/// Pointer to a buffer that receives the product code. This buffer must be 39 characters long. The first 38 characters are for the
/// GUID, and the last character is for the terminating null character.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The product code could not be determined.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_COMPONENT</term>
/// <term>The specified component is unknown.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// During initialization, an application must determine the product code under which it was installed. An application can be part
/// of different products in different installations. For example, an application can be part of a suite of applications, or it can
/// be installed by itself.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetproductcodea UINT MsiGetProductCodeA( LPCSTR szComponent,
// LPSTR lpBuf39 );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetProductCodeA")]
public static extern Win32Error MsiGetProductCode([MarshalAs(UnmanagedType.LPTStr)] string szComponent,
[Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpBuf39);
/// <summary>The <c>MsiGetProductInfo</c> function returns product information for published and installed products.</summary>
/// <param name="szProduct">Specifies the product code for the product.</param>
/// <param name="szAttribute">
/// <para>Specifies the property to be retrieved.</para>
/// <para>
/// The Required Properties are guaranteed to be available, but other properties are available only if that property is set. For
/// more information, see Properties. The properties in the following list can be retrieved only from applications that are installed.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Property</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLPROPERTY_HELPLINK</term>
/// <term>Support link. For more information, see the ARPHELPLINK property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_HELPTELEPHONE</term>
/// <term>Support telephone. For more information, see the ARPHELPTELEPHONE property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLDATE</term>
/// <term>
/// The last time this product received service. The value of this property is replaced each time a patch is applied or removed from
/// the product or the /v Command-Line Option is used to repair the product. If the product has received no repairs or patches this
/// property contains the time this product was installed on this computer.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLEDLANGUAGE</term>
/// <term>Installed language. Windows Installer 4.5 and earlier: Not supported.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLEDPRODUCTNAME</term>
/// <term>Installed product name. For more information, see the ProductName property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLLOCATION</term>
/// <term>Installation location. For more information, see the ARPINSTALLLOCATION property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLSOURCE</term>
/// <term>Installation source. For more information, see the SourceDir property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_LOCALPACKAGE</term>
/// <term>Local cached package.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PUBLISHER</term>
/// <term>Publisher. For more information, see the Manufacturer property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_URLINFOABOUT</term>
/// <term>URL information. For more information, see the ARPURLINFOABOUT property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_URLUPDATEINFO</term>
/// <term>URL update information. For more information, see the ARPURLUPDATEINFO property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_VERSIONMINOR</term>
/// <term>Minor product version derived from the ProductVersion property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_VERSIONMAJOR</term>
/// <term>Major product version derived from the ProductVersion property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_VERSIONSTRING</term>
/// <term>Product version. For more information, see the ProductVersion property.</term>
/// </item>
/// </list>
/// <para>
/// To retrieve the product ID, registered owner, or registered company from applications that are installed, set szProperty to one
/// of the following text string values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ProductID</term>
/// <term>The product identifier for the product. For more information, see the ProductID property.</term>
/// </item>
/// <item>
/// <term>RegCompany</term>
/// <term>The company registered to use this product.</term>
/// </item>
/// <item>
/// <term>RegOwner</term>
/// <term>The owner registered to use this product.</term>
/// </item>
/// </list>
/// <para>
/// To retrieve the instance type of the product, set szProperty to the following value. This property is available for advertised
/// or installed products.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>InstanceType</term>
/// <term>
/// A missing value or a value of 0 (zero) indicates a normal product installation. A value of 1 (one) indicates a product installed
/// using a multiple instance transform and the MSINEWINSTANCE property. Available with the installer running Windows Server 2003 or
/// Windows XP with SP1. For more information see, Installing Multiple Instances of Products and Patches.
/// </term>
/// </item>
/// </list>
/// <para>The advertised properties in the following list can be retrieved from applications that are advertised or installed.</para>
/// <list type="table">
/// <listheader>
/// <term>Property</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>INSTALLPROPERTY_TRANSFORMS</term>
/// <term>Transforms.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_LANGUAGE</term>
/// <term>Product language.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PRODUCTNAME</term>
/// <term>Human readable product name. For more information, see the ProductName property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_ASSIGNMENTTYPE</term>
/// <term>
/// Equals 0 (zero) if the product is advertised or installed per-user. Equals 1 (one) if the product is advertised or installed
/// per-machine for all users.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PACKAGECODE</term>
/// <term>Identifier of the package this product was installed from. For more information, see Package Codes.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_VERSION</term>
/// <term>Product version derived from the ProductVersion property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PRODUCTICON</term>
/// <term>Primary icon for the package. For more information, see the ARPPRODUCTICON property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PACKAGENAME</term>
/// <term>Name of the original installation package.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_AUTHORIZED_LUA_APP</term>
/// <term>
/// A value of one (1) indicates a product that can be serviced by non-administrators using User Account Control (UAC) Patching. A
/// missing value or a value of 0 (zero) indicates that least-privilege patching is not enabled. Available in Windows Installer 3.0
/// or later.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="lpValueBuf">Pointer to a buffer that receives the property value. This parameter can be null.</param>
/// <param name="pcchValueBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpValueBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>
/// If lpValueBuf is null, pcchValueBuf can be null. In this case, the function checks that the property is registered correctly
/// with the product.
/// </para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>A buffer is too small to hold the requested data.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product is unadvertised or uninstalled.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PROPERTY</term>
/// <term>The property is unrecognized.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// When the <c>MsiGetProductInfo</c> function returns, the pcchValueBuf parameter contains the length of the string stored in the
/// buffer. The count returned does not include the terminating null character. If the buffer is not large enough,
/// <c>MsiGetProductInfo</c> returns ERROR_MORE_DATA and pcchValueBuf contains the size of the string, in characters, without
/// counting the null character.
/// </para>
/// <para>
/// <c>MsiGetProductInfo</c>(INSTALLPROPERTY_LOCALPACKAGE) does not necessarily return a path to the cached package. The cached
/// package is for internal use only. Maintenance mode installations should be invoked through the MsiConfigureFeature,
/// MsiConfigureProduct, or MsiConfigureProductEx functions.
/// </para>
/// <para>
/// If you attempt to use <c>MsiGetProductInfo</c> to query an advertised product for a property that is only available to installed
/// products, the function returns ERROR_UNKNOWN_PROPERTY. For example, if the application is advertised and not installed, a query
/// for the INSTALLPROPERTY_INSTALLLOCATION property returns an error of ERROR_UNKNOWN_PROPERTY.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetproductinfoa UINT MsiGetProductInfoA( LPCSTR szProduct,
// LPCSTR szAttribute, LPSTR lpValueBuf, LPDWORD pcchValueBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetProductInfoA")]
public static extern Win32Error MsiGetProductInfo([MarshalAs(UnmanagedType.LPTStr)] string szProduct, [MarshalAs(UnmanagedType.LPTStr)] string szAttribute,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpValueBuf, ref uint pcchValueBuf);
/// <summary>
/// <para>
/// The <c>MsiGetProductInfoEx</c> function returns product information for advertised and installed products. This function can
/// retrieve information
/// </para>
/// <para>about an instance of a product that is installed under a user account other than the current user.</para>
/// <para>
/// The calling process must have administrative privileges for a user who is different from the current user. The
/// <c>MsiGetProductInfoEx</c> function cannot query an instance of a product that is advertised under a per-user-unmanaged context
/// for a user account other than the current user.
/// </para>
/// <para>This function is an extension of the MsiGetProductInfo function.</para>
/// </summary>
/// <param name="szProductCode">The ProductCode GUID of the product instance that is being queried.</param>
/// <param name="szUserSid">
/// <para>
/// The security identifier (SID) of the account under which the instance of the product that is being queried exists. A <c>NULL</c>
/// specifies the current user SID.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>The currently logged-on user.</term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>The enumeration for a specific user in the system. An example of user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string "S-1-5-18" (system) cannot be used to enumerate products installed as per-machine. If
/// dwContext is "MSIINSTALLCONTEXT_MACHINE", szUserSid must be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>The installation context of the product instance that is being queried.</para>
/// <list type="table">
/// <listheader>
/// <term>Name</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>Retrieves the product property for the per<65>user<65>managed instance of the product.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>Retrieves the product property for the per<65>user<65>unmanaged instance of the product.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>Retrieves the product property for the per-machine instance of the product.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szProperty">
/// <para>Property being queried.</para>
/// <para>
/// The property to be retrieved. The properties in the following table can only be retrieved from applications that are already
/// installed. All required properties are guaranteed to be available, but other properties are available only if the property is
/// set. For more information, see Required Properties and Properties.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Property</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLPROPERTY_PRODUCTSTATE</term>
/// <term>The state of the product returned in string form as "1" for advertised and "5" for installed.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_HELPLINK</term>
/// <term>The support link. For more information, see the ARPHELPLINK property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_HELPTELEPHONE</term>
/// <term>The support telephone. For more information, see the ARPHELPTELEPHONE property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLDATE</term>
/// <term>
/// The last time this product received service. The value of this property is replaced each time a patch is applied or removed from
/// the product or the /v Command-Line Option is used to repair the product. If the product has received no repairs or patches this
/// property contains the time this product was installed on this computer.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLEDLANGUAGE</term>
/// <term>Installed language. Windows Installer 4.5 and earlier: Not supported.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLEDPRODUCTNAME</term>
/// <term>The installed product name. For more information, see the ProductName property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLLOCATION</term>
/// <term>The installation location. For more information, see the ARPINSTALLLOCATION property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_INSTALLSOURCE</term>
/// <term>The installation source. For more information, see the SourceDir property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_LOCALPACKAGE</term>
/// <term>The local cached package.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PUBLISHER</term>
/// <term>The publisher. For more information, see the Manufacturer property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_URLINFOABOUT</term>
/// <term>URL information. For more information, see the ARPURLINFOABOUT property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_URLUPDATEINFO</term>
/// <term>The URL update information. For more information, see the ARPURLUPDATEINFO property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_VERSIONMINOR</term>
/// <term>The minor product version that is derived from the ProductVersion property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_VERSIONMAJOR</term>
/// <term>The major product version that is derived from the ProductVersion property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_VERSIONSTRING</term>
/// <term>The product version. For more information, see the ProductVersion property.</term>
/// </item>
/// </list>
/// <para>
/// To retrieve the product ID, registered owner, or registered company from applications that are installed, set szProperty to one
/// of the following text string values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ProductID</term>
/// <term>The product identifier. For more information, see the ProductID property.</term>
/// </item>
/// <item>
/// <term>RegCompany</term>
/// <term>The company that is registered to use the product.</term>
/// </item>
/// <item>
/// <term>RegOwner</term>
/// <term>The owner who is registered to use the product.</term>
/// </item>
/// </list>
/// <para>
/// To retrieve the instance type of the product, set szProperty to the following value. This property is available for advertised
/// or installed products.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>InstanceType</term>
/// <term>
/// A missing value or a value of 0 (zero) indicates a normal product installation. A value of one (1) indicates a product installed
/// using a multiple instance transform and the MSINEWINSTANCE property. For more information, see Installing Multiple Instances of
/// Products and Patches.
/// </term>
/// </item>
/// </list>
/// <para>
/// The properties in the following table can be retrieved from applications that are advertised or installed. These properties
/// cannot be retrieved for product instances that are installed under a per-user-unmanaged context for user accounts other than
/// current user account.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Property</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>INSTALLPROPERTY_TRANSFORMS</term>
/// <term>Transforms.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_LANGUAGE</term>
/// <term>Product language.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PRODUCTNAME</term>
/// <term>Human readable product name. For more information, see the ProductName property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_ASSIGNMENTTYPE</term>
/// <term>
/// Equals 0 (zero) if the product is advertised or installed per-user. Equals one (1) if the product is advertised or installed
/// per-computer for all users.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PACKAGECODE</term>
/// <term>Identifier of the package that a product is installed from. For more information, see the Package Codes property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_VERSION</term>
/// <term>Product version derived from the ProductVersion property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PRODUCTICON</term>
/// <term>Primary icon for the package. For more information, see the ARPPRODUCTICON property.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PACKAGENAME</term>
/// <term>Name of the original installation package.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_AUTHORIZED_LUA_APP</term>
/// <term>
/// A value of one (1) indicates a product that can be serviced by non-administrators using User Account Control (UAC) Patching. A
/// missing value or a value of 0 (zero) indicates that least-privilege patching is not enabled. Available in Windows Installer 3.0
/// or later.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="szValue">
/// <para>
/// A pointer to a buffer that receives the property value. This buffer should be large enough to contain the information. If the
/// buffer is too small, the function returns <c>ERROR_MORE_DATA</c> and sets *pcchValue to the number of <c>TCHAR</c> in the value,
/// not including the terminating NULL character.
/// </para>
/// <para>
/// If lpValue is set to <c>NULL</c> and pcchValue is set to a valid pointer, the function returns <c>ERROR_SUCCESS</c> and sets
/// *pcchValue to the number of <c>TCHAR</c> in the value, not including the terminating NULL character. The function can then be
/// called again to retrieve the value, with lpValue buffer large enough to contain *pcchValue + 1 characters.
/// </para>
/// <para>
/// If lpValue and pcchValue are both set to <c>NULL</c>, the function returns <c>ERROR_SUCCESS</c> if the value exists, without
/// retrieving the value.
/// </para>
/// </param>
/// <param name="pcchValue">
/// <para>
/// A pointer to a variable that specifies the number of <c>TCHAR</c> in the lpValue buffer. When the function returns, this
/// parameter is set to the size of the requested value whether or not the function copies the value into the specified buffer. The
/// size is returned as the number of <c>TCHAR</c> in the requested value, not including the terminating null character.
/// </para>
/// <para>This parameter can be set to <c>NULL</c> only if lpValue is also <c>NULL</c>. Otherwise, the function returns <c>ERROR_INVALID_PARAMETER</c>.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiGetProductInfoEx</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The calling process must have administrative privileges to get information for a product installed for a user other than the
/// current user.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>A buffer is too small to hold the requested data.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product is unadvertised or uninstalled.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PROPERTY</term>
/// <term>The property is unrecognized.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>An unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// When the <c>MsiGetProductInfoEx</c> function returns, the pcchValue parameter contains the length of the string that is stored
/// in the buffer. The count returned does not include the terminating null character. If the buffer is not big enough,
/// <c>MsiGetProductInfoEx</c> returns <c>ERROR_MORE_DATA</c>, and the pcchValue parameter contains the size of the string, in
/// <c>TCHAR</c>, without counting the null character.
/// </para>
/// <para>
/// The <c>MsiGetProductInfoEx</c> function ( <c>INSTALLPROPERTY_LOCALPACKAGE</c>) returns a path to the cached package. The cached
/// package is for internal use only. Maintenance mode installations must be invoked through the MsiConfigureFeature,
/// MsiConfigureProduct, or MsiConfigureProductEx functions.
/// </para>
/// <para>
/// The MsiGetProductInfo function returns <c>ERROR_UNKNOWN_PROPERTY</c> if the application being queried is advertised and not
/// installed. For example, if the application is advertised and not installed, a query for <c>INSTALLPROPERTY_INSTALLLOCATION</c>
/// returns an error of <c>ERROR_UNKNOWN_PROPERTY</c>.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetproductinfoexa UINT MsiGetProductInfoExA( LPCSTR
// szProductCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCSTR szProperty, LPSTR szValue, LPDWORD pcchValue );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetProductInfoExA")]
public static extern Win32Error MsiGetProductInfoEx([MarshalAs(UnmanagedType.LPTStr)] string szProductCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, [MarshalAs(UnmanagedType.LPTStr)] string szProperty,
[Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szValue, ref uint pcchValue);
/// <summary>The <c>MsiGetProductInfoFromScript</c> function returns product information for a Windows Installer script file.</summary>
/// <param name="szScriptFile">
/// A null-terminated string specifying the full path to the script file. The script file is the advertise script that was created
/// by calling MsiAdvertiseProduct or MsiAdvertiseProductEx.
/// </param>
/// <param name="lpProductBuf39">
/// Points to a buffer that receives the product code. The buffer must be 39 characters long. The first 38 characters are for the
/// product code GUID, and the last character is for the terminating null character.
/// </param>
/// <param name="plgidLanguage">Points to a variable that receives the product language.</param>
/// <param name="pdwVersion">Points to a buffer that receives the product version.</param>
/// <param name="lpNameBuf">Points to a buffer that receives the product name. The buffer includes a terminating null character.</param>
/// <param name="pcchNameBuf">
/// Points to a variable that specifies the size, in characters, of the buffer pointed to by the lpNameBuf parameter. This size
/// should include the terminating null character. When the function returns, this variable contains the length of the string stored
/// in the buffer. The count returned does not include the terminating null character. If the buffer is not large enough, the
/// function returns ERROR_MORE_DATA, and the variable contains the size of the string in characters, without counting the null character.
/// </param>
/// <param name="lpPackageBuf">Points to a buffer that receives the package name. The buffer includes the terminating null character.</param>
/// <param name="pcchPackageBuf">
/// Points to a variable that specifies the size, in characters, of the buffer pointed to by the lpPackageNameBuf parameter. This
/// size should include the terminating null character. When the function returns, this variable contains the length of the string
/// stored in the buffer. The count returned does not include the terminating null character. If the buffer is not large enough, the
/// function returns ERROR_MORE_DATA, and the variable contains the size of the string in characters, without counting the null character.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid argument was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>A buffer was too small to hold the entire value.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>Could not get script information.</term>
/// </item>
/// <item>
/// <term>ERROR_CALL_NOT_IMPLEMENTED</term>
/// <term>This function is only available on Windows 2000 and Windows XP.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetproductinfofromscripta UINT MsiGetProductInfoFromScriptA(
// LPCSTR szScriptFile, LPSTR lpProductBuf39, LANGID *plgidLanguage, LPDWORD pdwVersion, LPSTR lpNameBuf, LPDWORD pcchNameBuf, LPSTR
// lpPackageBuf, LPDWORD pcchPackageBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetProductInfoFromScriptA")]
public static extern Win32Error MsiGetProductInfoFromScript([MarshalAs(UnmanagedType.LPTStr)] string szScriptFile,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpProductBuf39, out ushort plgidLanguage, out uint pdwVersion,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpNameBuf, ref uint pcchNameBuf,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPackageBuf, ref uint pcchPackageBuf);
/// <summary>The <c>MsiGetProductProperty</c> function retrieves product properties. These properties are in the product database.</summary>
/// <param name="hProduct">Handle to the product obtained from MsiOpenProduct.</param>
/// <param name="szProperty">Specifies the property to retrieve. This is case-sensitive.</param>
/// <param name="lpValueBuf">
/// Pointer to a buffer that receives the property value. The value is truncated and null-terminated if lpValueBuf is too small.
/// This parameter can be null.
/// </param>
/// <param name="pcchValueBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpValueBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpValueBuf is null, pcchValueBuf can be null.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiGetProductProperty</c> function return the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_HANDLE</term>
/// <term>An invalid handle was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>A buffer is too small to hold the entire property value.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// When the <c>MsiGetProductProperty</c> function returns, the pcchValueBuf parameter contains the length of the string stored in
/// the buffer. The count returned does not include the terminating null character. If the buffer is not big enough,
/// <c>MsiGetProductProperty</c> returns ERROR_MORE_DATA, and <c>MsiGetProductProperty</c> contains the size of the string, in
/// characters, without counting the null character.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetproductpropertya UINT MsiGetProductPropertyA( MSIHANDLE
// hProduct, LPCSTR szProperty, LPSTR lpValueBuf, LPDWORD pcchValueBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetProductPropertyA")]
public static extern Win32Error MsiGetProductProperty(MSIHANDLE hProduct, [MarshalAs(UnmanagedType.LPTStr)] string szProperty,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpValueBuf, ref uint pcchValueBuf);
/// <summary>
/// The <c>MsiGetShortcutTarget</c> function examines a shortcut and returns its product, feature name, and component if available.
/// </summary>
/// <param name="szShortcutPath">A null-terminated string specifying the full path to a shortcut.</param>
/// <param name="szProductCode">
/// A GUID for the product code of the shortcut. This string buffer must be 39 characters long. The first 38 characters are for the
/// GUID, and the last character is for the terminating null character. This parameter can be null.
/// </param>
/// <param name="szFeatureId">
/// The feature name of the shortcut. The string buffer must be MAX_FEATURE_CHARS+1 characters long. This parameter can be null.
/// </param>
/// <param name="szComponentCode">
/// A GUID of the component code. This string buffer must be 39 characters long. The first 38 characters are for the GUID, and the
/// last character is for the terminating null character. This parameter can be null.
/// </param>
/// <returns>This function returns UINT.</returns>
/// <remarks>
/// <para>
/// If the function fails, and the shortcut exists, the regular contents of the shortcut may be accessed through the IShellLink interface.
/// </para>
/// <para>Otherwise, the state of the target may be determined by using the Installer Selection Functions.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetshortcuttargeta UINT MsiGetShortcutTargetA( LPCSTR
// szShortcutPath, LPSTR szProductCode, LPSTR szFeatureId, LPSTR szComponentCode );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetShortcutTargetA")]
public static extern Win32Error MsiGetShortcutTarget([MarshalAs(UnmanagedType.LPTStr)] string szShortcutPath,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szProductCode,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szFeatureId,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szComponentCode);
/// <summary>The <c>MsiGetUserInfo</c> function returns the registered user information for an installed product.</summary>
/// <param name="szProduct">Specifies the product code for the product to be queried.</param>
/// <param name="lpUserNameBuf">Pointer to a variable that receives the name of the user.</param>
/// <param name="pcchUserNameBuf">
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpUserNameBuf parameter. This size
/// should include the terminating null character.
/// </param>
/// <param name="lpOrgNameBuf">Pointer to a buffer that receives the organization name.</param>
/// <param name="pcchOrgNameBuf">
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpOrgNameBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </param>
/// <param name="lpSerialBuf">Pointer to a buffer that receives the product ID.</param>
/// <param name="pcchSerialBuf">
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpSerialBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>USERINFOSTATE_ABSENT</term>
/// <term>Some or all of the user information is absent.</term>
/// </item>
/// <item>
/// <term>USERINFOSTATE_INVALIDARG</term>
/// <term>One of the function parameters was invalid.</term>
/// </item>
/// <item>
/// <term>USERINFOSTATE_MOREDATA</term>
/// <term>A buffer is too small to hold the requested data.</term>
/// </item>
/// <item>
/// <term>USERINFOSTATE_PRESENT</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>USERINFOSTATE_UNKNOWN</term>
/// <term>The product code does not identify a known product.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// When the <c>MsiGetUserInfo</c> function returns, the pcchNameBuf parameter contains the length of the class string stored in the
/// buffer. The count returned does not include the terminating null character. If the buffer is not big enough, the
/// <c>MsiGetUserInfo</c> function returns USERINFOSTATE_MOREDATA, and <c>MsiGetUserInfo</c> contains the size of the string, in
/// characters, without counting the null character.
/// </para>
/// <para>The user information is considered to be present even in the absence of a company name.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msigetuserinfoa USERINFOSTATE MsiGetUserInfoA( LPCSTR szProduct,
// LPSTR lpUserNameBuf, LPDWORD pcchUserNameBuf, LPSTR lpOrgNameBuf, LPDWORD pcchOrgNameBuf, LPSTR lpSerialBuf, LPDWORD
// pcchSerialBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiGetUserInfoA")]
public static extern USERINFOSTATE MsiGetUserInfo([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpUserNameBuf, ref uint pcchUserNameBuf,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpOrgNameBuf, ref uint pcchOrgNameBuf,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpSerialBuf, ref uint pcchSerialBuf);
/// <summary>The <c>MsiInstallMissingComponent</c> function installs files that are unexpectedly missing.</summary>
/// <param name="szProduct">Specifies the product code for the product that owns the component to be installed.</param>
/// <param name="szComponent">Identifies the component to be installed.</param>
/// <param name="eInstallState">
/// <para>Specifies the way the component should be installed. This parameter must be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_LOCAL</term>
/// <term>The component should be locally installed.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCE</term>
/// <term>The component should be installed to run from the source.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_DEFAULT</term>
/// <term>The component should be installed according to the installer defaults.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration information is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The installation failed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SOURCE_ABSENT</term>
/// <term>The source was unavailable.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SUSPEND</term>
/// <term>The installation was suspended.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_USEREXIT</term>
/// <term>The user exited the installation.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>One of the parameters is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code is unrecognized.</term>
/// </item>
/// </list>
/// <para>For more information about error messages, see Displayed Error Messages</para>
/// </returns>
/// <remarks>
/// The <c>MsiInstallMissingComponent</c> function resolves the feature(s) that the component belongs to. Then, the product feature
/// that requires the least additional disk space is installed.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiinstallmissingcomponenta UINT MsiInstallMissingComponentA(
// LPCSTR szProduct, LPCSTR szComponent, INSTALLSTATE eInstallState );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiInstallMissingComponentA")]
public static extern Win32Error MsiInstallMissingComponent([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szComponent, INSTALLSTATE eInstallState);
/// <summary>The <c>MsiInstallMissingFile</c> function installs files that are unexpectedly missing.</summary>
/// <param name="szProduct">Specifies the product code for the product that owns the file to be installed.</param>
/// <param name="szFile">Specifies the file to be installed.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration information is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The installation failed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SOURCE_ABSENT</term>
/// <term>The source was unavailable.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SUSPEND</term>
/// <term>The installation was suspended.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_USEREXIT</term>
/// <term>The user exited the installation.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>A parameter was invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code is unrecognized.</term>
/// </item>
/// </list>
/// <para>For more information about error messages, see Displayed Error Messages.</para>
/// </returns>
/// <remarks>
/// The <c>MsiInstallMissingFile</c> function obtains the component that the file belongs to from the file table. Then, the product
/// feature that requires the least additional disk space is installed.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiinstallmissingfilea UINT MsiInstallMissingFileA( LPCSTR
// szProduct, LPCSTR szFile );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiInstallMissingFileA")]
public static extern Win32Error MsiInstallMissingFile([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szFile);
/// <summary>The <c>MsiInstallProduct</c> function installs or uninstalls a product.</summary>
/// <param name="szPackagePath">
/// A null-terminated string that specifies the path to the location of the Windows Installer package. The string value can contain
/// a URL (e.g. <c>http://packageLocation/package/package.msi</c>), a network path (e.g. \packageLocation\package.msi), a file path
/// (e.g. file://packageLocation/package.msi), or a local path (e.g. D:\packageLocation\package.msi).
/// </param>
/// <param name="szCommandLine">
/// <para>
/// A null-terminated string that specifies the command line property settings. This should be a list of the format Property=Setting
/// Property=Setting. For more information, see About Properties.
/// </para>
/// <para>
/// To perform an administrative installation, include ACTION=ADMIN in szCommandLine. For more information, see the ACTION property.
/// </para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completes successfully.</term>
/// </item>
/// <item>
/// <term>An error relating to an action</term>
/// <term>For more information, see Error Codes.</term>
/// </item>
/// <item>
/// <term>Initialization Error</term>
/// <term>An error that relates to initialization occurred.</term>
/// </item>
/// </list>
/// <para>For more information, see Displayed Error Messages.</para>
/// </returns>
/// <remarks>
/// <para>The <c>MsiInstallProduct</c> function displays the user interface with the current settings and log mode.</para>
/// <list type="bullet">
/// <item>
/// <term>You can change user interface settings by using the MsiSetInternalUI, MsiSetExternalUI, or MsiSetExternalUIRecord functions.</term>
/// </item>
/// <item>
/// <term>You can set the log mode by using the MsiEnableLog function.</term>
/// </item>
/// <item>
/// <term>You can completely remove a product by setting REMOVE=ALL in szCommandLine.</term>
/// </item>
/// </list>
/// <para>For more information, see REMOVE Property.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiinstallproducta UINT MsiInstallProductA( LPCSTR szPackagePath,
// LPCSTR szCommandLine );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiInstallProductA")]
public static extern Win32Error MsiInstallProduct([MarshalAs(UnmanagedType.LPTStr)] string szPackagePath, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szCommandLine);
/// <summary>
/// <para>
/// The <c>MsiIsProductElevated</c> function returns whether or not the product is managed. Only applications that require elevated
/// privileges for installation and being installed through advertisement are considered managed, which means that an application
/// installed per-machine is always considered managed.
/// </para>
/// <para>
/// An application that is installed per-user is only considered managed if it is advertised by a local system process that is
/// impersonating the user. For more information, see Advertising a Per-User Application to be Installed with Elevated Privileges.
/// </para>
/// <para>
/// <c>MsiIsProductElevated</c> verifies that the local system owns the product registry data. The function does not refer to
/// account policies such as AlwaysInstallElevated.
/// </para>
/// </summary>
/// <param name="szProduct">
/// <para>The full product code GUID of the product.</para>
/// <para>This parameter is required and cannot be <c>NULL</c> or empty.</para>
/// </param>
/// <param name="pfElevated">
/// <para>A pointer to a BOOL for the result.</para>
/// <para>This parameter cannot be <c>NULL</c>.</para>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, the return value is ERROR_SUCCESS, and pfElevated is set to <c>TRUE</c> if the product is a managed application.
/// </para>
/// <para>If the function fails, the return value is one of the error codes identified in the following table.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product is not currently known.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid argument is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration information for the product is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>The function failed.</term>
/// </item>
/// <item>
/// <term>ERROR_CALL_NOT_IMPLEMENTED</term>
/// <term>The function is not available for a specific platform.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiisproductelevatedw UINT MsiIsProductElevatedW( LPCWSTR
// szProduct, BOOL *pfElevated );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiIsProductElevatedW")]
public static extern Win32Error MsiIsProductElevated([MarshalAs(UnmanagedType.LPTStr)] string szProduct, [MarshalAs(UnmanagedType.Bool)] out bool pfElevated);
/// <summary>
/// <para>
/// The <c>MsiJoinTransaction</c> function requests that the Windows Installer make the current process the owner of the transaction
/// installing the multiple-package installation.
/// </para>
/// <para><c>Windows Installer 4.0 and earlier:</c> Not supported. This function is available beginning with Windows Installer 4.5.</para>
/// </summary>
/// <param name="hTransactionHandle">
/// The transaction ID, which identifies the transaction and is the identifier returned by the MsiBeginTransaction function.
/// </param>
/// <param name="dwTransactionAttributes">
/// <para>Attributes of the multiple-package installation.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0</term>
/// <term>When 0 or no value is set, Windows Installer closes the UI from the previous installation.</term>
/// </item>
/// <item>
/// <term>MSITRANSACTION_CHAIN_EMBEDDEDUI</term>
/// <term>Set this attribute to request that the Windows Installer not shutdown the embedded UI until the transaction is complete.</term>
/// </item>
/// <item>
/// <term>MSITRANSACTION_JOIN_EXISTING_EMBEDDEDUI</term>
/// <term>
/// Set this attribute to request that the Windows Installer transfer the embedded UI from the original installation. If the
/// original installation has no embedded UI, setting this attribute does nothing.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="phChangeOfOwnerEvent">
/// This parameter returns a handle to an event that is set when the <c>MsiJoinTransaction</c> function changes the owner of the
/// transaction to a new owner. The current owner can use this to determine when ownership of the transaction has changed. Leaving a
/// transaction without an owner will roll back the transaction.
/// </param>
/// <returns>
/// <para>The <c>MsiJoinTransaction</c> function can return the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The user that owns the transaction and the user that joins the transaction are not the same.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>A parameter that is not valid is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_ALREADY_RUNNING</term>
/// <term>The owner cannot be changed while an active installation is in progress.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_HANDLE_STATE</term>
/// <term>The transaction ID provided is not valid.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Because a transaction can be owned by no more than one process at a time, the functions authored into the MsiEmbeddedChainer
/// table can use <c>MsiJoinTransaction</c> to request ownership of the transaction before using the Windows Installer API to
/// configure or install an application. The installer verifies that there is no installation in progress. The installer verifies
/// that the process requesting ownership and the process that currently owns the transaction share a parent process in the same
/// process tree. If the function succeeds, the process that calls <c>MsiJoinTransaction</c> becomes the current owner of the transaction.
/// </para>
/// <para>
/// <c>MsiJoinTransaction</c> sets the internal UI of the new installation to the UI level of thew original installation. After the
/// new installation owns the transaction, it can call MsiSetInternalUI to change the UI level. This enables the new installation to
/// run at a higher UI level than the original installation.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msijointransaction UINT MsiJoinTransaction( MSIHANDLE
// hTransactionHandle, DWORD dwTransactionAttributes, HANDLE *phChangeOfOwnerEvent );
[DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiJoinTransaction")]
public static extern Win32Error MsiJoinTransaction(MSIHANDLE hTransactionHandle, MSITRANSACTION dwTransactionAttributes,
out System.Threading.EventWaitHandle phChangeOfOwnerEvent);
/// <summary>
/// The <c>MsiLocateComponent</c> function returns the full path to an installed component without a product code. This function
/// attempts to determine the product using MsiGetProductCode, but is not guaranteed to find the correct product for the caller.
/// MsiGetComponentPath should always be called when possible.
/// </summary>
/// <param name="szComponent">Specifies the component ID of the component to be located.</param>
/// <param name="lpPathBuf">
/// Pointer to a variable that receives the path to the component. The variable includes the terminating null character.
/// </param>
/// <param name="pcchBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. Upon success of the
/// <c>MsiLocateComponent</c> function, the variable pointed to by pcchBuf contains the count of characters not including the
/// terminating null character. If the size of the buffer passed in is too small, the function returns INSTALLSTATE_MOREDATA.
/// </para>
/// <para>If lpPathBuf is null, pcchBuf can be null.</para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_NOTUSED</term>
/// <term>The component being requested is disabled on the computer.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// <term>The component is not installed. See Remarks.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_INVALIDARG</term>
/// <term>One of the function parameters is invalid.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_LOCAL</term>
/// <term>The component is installed locally.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_MOREDATA</term>
/// <term>The buffer provided was too small.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCE</term>
/// <term>The component is installed to run from source.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCEABSENT</term>
/// <term>The component source is inaccessible.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>The product code or component ID is unknown. See Remarks.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>The <c>MsiLocateComponent</c> function might return INSTALLSTATE_ABSENT or INSTALL_STATE_UNKNOWN, for the following reasons:</para>
/// <list type="bullet">
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// <description>
/// The application did not properly ensure that the feature was installed by calling MsiUseFeature and, if necessary, MsiConfigureFeature.
/// </description>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <description>
/// The feature is not published. The application should have determined this earlier by calling MsiQueryFeatureState or
/// MsiEnumFeatures. The application makes these calls while it initializes. An application should only use features that are known
/// to be published. Since INSTALLSTATE_UNKNOWN should have been returned by MsiUseFeature as well, either MsiUseFeature was not
/// called, or its return value was not properly checked.
/// </description>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msilocatecomponenta INSTALLSTATE MsiLocateComponentA( LPCSTR
// szComponent, LPSTR lpPathBuf, LPDWORD pcchBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiLocateComponentA")]
public static extern INSTALLSTATE MsiLocateComponent([MarshalAs(UnmanagedType.LPTStr)] string szComponent,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf, ref uint pcchBuf);
/// <summary>
/// The <c>MsiNotifySidChange</c> function notifies and updates the Windows Installer internal information with changes to user SIDs.
/// </summary>
/// <param name="pOldSid">Null-terminated string that specifies the string value of the previous security identifier(SID).</param>
/// <param name="pNewSid">Null-terminated string that specifies the string value of the new security identifier(SID).</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter is passed to the function. This error returned if any of the parameters is NULL.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_OUTOFMEMORY</term>
/// <term>Insufficient memory was available.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Internal failure during execution.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <c>Windows Installer 2.0 and Windows Installer 3.0:</c> Not supported. This function is available beginning with Windows
/// Installer 3.1.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msinotifysidchangea UINT MsiNotifySidChangeA( LPCSTR pOldSid,
// LPCSTR pNewSid );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiNotifySidChangeA")]
public static extern Win32Error MsiNotifySidChange([MarshalAs(UnmanagedType.LPTStr)] string pOldSid,
[MarshalAs(UnmanagedType.LPTStr)] string pNewSid);
/// <summary>
/// The <c>MsiOpenPackage</c> function opens a package to use with the functions that access the product database. The
/// MsiCloseHandle function must be called with the handle when the handle is not needed.
/// </summary>
/// <param name="szPackagePath">The path to the package.</param>
/// <param name="hProduct">A pointer to a variable that receives the product handle.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration information is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The product could not be opened.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_REMOTE_PROHIBITED</term>
/// <term>Windows Installer does not permit installation from a remote desktop connection.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completes successfully.</term>
/// </item>
/// </list>
/// <para>If this function fails, it may return a system error code. For more information, see System Error Codes.</para>
/// </returns>
/// <remarks>
/// MsiOpenPackage can accept an opened database handle in the form "#nnnn", where nnnn is the database handle in string form, i.e.
/// #123, instead of a path to the package. This is intended for development tasks such as running validation actions, or for use
/// with database management tools.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiopenpackagea UINT MsiOpenPackageA( LPCSTR szPackagePath,
// MSIHANDLE *hProduct );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiOpenPackageA")]
public static extern Win32Error MsiOpenPackage([MarshalAs(UnmanagedType.LPTStr)] string szPackagePath, out PMSIHANDLE hProduct);
/// <summary>
/// The <c>MsiOpenPackageEx</c> function opens a package to use with functions that access the product database. The MsiCloseHandle
/// function must be called with the handle when the handle is no longer needed.
/// </summary>
/// <param name="szPackagePath">The path to the package.</param>
/// <param name="dwOptions">
/// <para>The bit flags to indicate whether or not to ignore the computer state. Pass in 0 (zero) to use MsiOpenPackage behavior.</para>
/// <list type="table">
/// <listheader>
/// <term>Constant</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIOPENPACKAGEFLAGS_IGNOREMACHINESTATE 1</term>
/// <term>Ignore the computer state when creating the product handle.</term>
/// </item>
/// </list>
/// </param>
/// <param name="hProduct">A pointer to a variable that receives the product handle.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration information is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The product could not be opened.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_REMOTE_PROHIBITED</term>
/// <term>Windows Installer does not permit installation from a remote desktop connection.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completes successfully.</term>
/// </item>
/// </list>
/// <para>If this function fails, it may return a system error code. For more information, see System Error Codes.</para>
/// </returns>
/// <remarks>
/// <para>
/// To create a restricted product handle that is independent of the current machine state and incapable of changing the current
/// machine state, use <c>MsiOpenPackageEx</c> with MSIOPENPACKAGEFLAGS_IGNOREMACHINESTATE set in dwOptions.
/// </para>
/// <para>
/// Note that if dwOptions is MSIOPENPACKAGEFLAGS_IGNOREMACHINESTATE or 1, <c>MsiOpenPackageEx</c> ignores the current machine state
/// when creating the product handle. If the value of dwOptions is 0, <c>MsiOpenPackageEx</c> is the same as MsiOpenPackage and
/// creates a product handle that is dependent upon whether the package specified by szPackagePath is already installed on the computer.
/// </para>
/// <para>
/// The restricted handle created by using <c>MsiOpenPackageEx</c> with MSIOPENPACKAGEFLAGS_IGNOREMACHINESTATE only permits
/// execution of dialogs, a subset of the standard actions, and custom actions that set properties ( Custom Action Type 35, Custom
/// Action Type 51, and Custom Action Type 19). The restricted handle prevents the use of custom actions that run Dynamic-Link
/// Libraries, Executable Files or Scripts.
/// </para>
/// <para>
/// You can call MsiDoAction on the following standard actions using the restricted handle. All other actions return
/// ERROR_FUNCTION_NOT_CALLED if called with the restricted handle.
/// </para>
/// <list type="bullet">
/// <item>
/// <term>ADMIN</term>
/// </item>
/// <item>
/// <term>ADVERTISE</term>
/// </item>
/// <item>
/// <term>INSTALL</term>
/// </item>
/// <item>
/// <term>SEQUENCE</term>
/// </item>
/// <item>
/// <term>AppSearch action</term>
/// </item>
/// <item>
/// <term>CCPSearch</term>
/// </item>
/// <item>
/// <term>CostFinalize</term>
/// </item>
/// <item>
/// <term>CostInitialize</term>
/// </item>
/// <item>
/// <term>FileCost</term>
/// </item>
/// <item>
/// <term>FindRelatedProducts</term>
/// </item>
/// <item>
/// <term>IsolateComponents action</term>
/// </item>
/// <item>
/// <term>LaunchConditions</term>
/// </item>
/// <item>
/// <term>MigrateFeatureStates</term>
/// </item>
/// <item>
/// <term>ResolveSource</term>
/// </item>
/// <item>
/// <term>RMCCPSearch</term>
/// </item>
/// <item>
/// <term>ValidateProductID</term>
/// </item>
/// </list>
/// <para>The MsiCloseHandle function must be called when the handle is not needed.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiopenpackageexa UINT MsiOpenPackageExA( LPCSTR szPackagePath,
// DWORD dwOptions, MSIHANDLE *hProduct );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiOpenPackageExA")]
public static extern Win32Error MsiOpenPackageEx([MarshalAs(UnmanagedType.LPTStr)] string szPackagePath, MSIOPENPACKAGEFLAGS dwOptions,
out PMSIHANDLE hProduct);
/// <summary>
/// <para>
/// The <c>MsiOpenProduct</c> function opens a product for use with the functions that access the product database. The
/// MsiCloseHandle function must be called with the handle when the handle is no longer needed.
/// </para>
/// <para>
/// <c>Note</c> Initialize COM on the same thread before calling the MsiOpenPackage, MsiOpenPackageEx, or <c>MsiOpenProduct</c> function.
/// </para>
/// </summary>
/// <param name="szProduct">Specifies the product code of the product to be opened.</param>
/// <param name="hProduct">Pointer to a variable that receives the product handle.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration information is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The product could not be opened.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SOURCE_ABSENT</term>
/// <term>The source was unavailable.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code was unrecognized.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiopenproducta UINT MsiOpenProductA( LPCSTR szProduct, MSIHANDLE
// *hProduct );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiOpenProductA")]
public static extern Win32Error MsiOpenProduct([MarshalAs(UnmanagedType.LPTStr)] string szProduct, out PMSIHANDLE hProduct);
/// <summary>The <c>MsiProcessAdvertiseScript</c> function processes an advertise script file into the specified locations.</summary>
/// <param name="szScriptFile">The full path to a script file generated by MsiAdvertiseProduct or MsiAdvertiseProductEx.</param>
/// <param name="szIconFolder">
/// An optional path to a folder in which advertised icon files and transform files are located. If this parameter is <c>NULL</c>,
/// no icon or transform files are written.
/// </param>
/// <param name="hRegData">
/// A registry key under which registry data is to be written. If this parameter is <c>NULL</c>, the installer writes the registry
/// data under the appropriate key, based on whether the advertisement is per-user or per-machine. If this parameter is non-
/// <c>NULL</c>, the script will write the registry data under the specified registry key rather than the normal location. In this
/// case, the application will not get advertised to the user.
/// </param>
/// <param name="fShortcuts">
/// <c>TRUE</c> if shortcuts should be created. If a special folder is returned by SHGetSpecialFolderLocation it will hold the shortcuts.
/// </param>
/// <param name="fRemoveItems"><c>TRUE</c> if specified items are to be removed instead of created.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The calling process was not running under the LocalSystem account.</term>
/// </item>
/// <item>
/// <term>An error relating to an action</term>
/// <term>See Error Codes.</term>
/// </item>
/// <item>
/// <term>Initialization Error</term>
/// <term>An error relating to initialization occurred.</term>
/// </item>
/// <item>
/// <term>ERROR_CALL_NOT_IMPLEMENTED</term>
/// <term>This function is not available for this platform.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// The process calling this function must be running under the LocalSystem account. To advertise an application for per-user
/// installation to a targeted user, the thread that calls this function must impersonate the targeted user. If the thread calling
/// this function is not impersonating a targeted user, the application is advertised to all users for installation with elevated privileges.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiprocessadvertisescripta UINT MsiProcessAdvertiseScriptA( LPCSTR
// szScriptFile, LPCSTR szIconFolder, HKEY hRegData, BOOL fShortcuts, BOOL fRemoveItems );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiProcessAdvertiseScriptA")]
public static extern Win32Error MsiProcessAdvertiseScript([MarshalAs(UnmanagedType.LPTStr)] string szScriptFile,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szIconFolder, HKEY hRegData, [MarshalAs(UnmanagedType.Bool)] bool fShortcuts,
[MarshalAs(UnmanagedType.Bool)] bool fRemoveItems);
/// <summary>
/// The <c>MsiProvideAssembly</c> function returns the full path to a Windows Installer component that contains an assembly. The
/// function prompts for a source and performs any necessary installation. <c>MsiProvideAssembly</c> increments the usage count for
/// the feature.
/// </summary>
/// <param name="szAssemblyName">The assembly name as a string.</param>
/// <param name="szAppContext">
/// Set to null for global assemblies. For private assemblies, set szAppContext to the full path of the application configuration
/// file or to the full path of the executable file of the application to which the assembly has been made private.
/// </param>
/// <param name="dwInstallMode">
/// <para>Defines the installation mode. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLMODE_DEFAULT</term>
/// <term>
/// Provide the component and perform any installation necessary to provide the component. If the key file of a component in the
/// requested feature, or a feature parent, is missing, reinstall the feature using MsiReinstallFeature with the following flag bits
/// set: REINSTALLMODE_FILEMISSING, REINSTALLMODE_FILEOLDERVERSION, REINSTALLMODE_FILEVERIFY, REINSTALLMODE_MACHINEDATA,
/// REINSTALLMODE_USERDATA and REINSTALLMODE_SHORTCUT.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode verifies that the key file of
/// the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file of the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NOSOURCERESOLUTION</term>
/// <term>
/// Provide the component only if the feature's installation state is INSTALLSTATE_LOCAL. If the feature installation state is
/// INSTALLSTATE_SOURCE, return ERROR_INSTALL_SOURCE_ABSENT. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION_ANY</term>
/// <term>
/// Provide the component if a feature exists from any installed product. Otherwise return ERROR_FILE_NOT_FOUND. This mode only
/// checks that the component is registered and does not verify that the key file of the component exists. This flag is similar to
/// the INSTALLMODE_NODETECTION flag except that with this flag we check for any product that has installed the assembly as opposed
/// to the last product as is the case with the INSTALLMODE_NODETECTION flag. This flag can only be used with MsiProvideAssembly.
/// </term>
/// </item>
/// <item>
/// <term>combination of the REINSTALLMODE flags</term>
/// <term>
/// Call MsiReinstallFeature to reinstall feature using this parameter for the dwReinstallMode parameter, and then provide the component.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="dwAssemblyInfo">
/// <para>Assembly information and assembly type. Set to one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIASSEMBLYINFO_NETASSEMBLY 0</term>
/// <term>.NET Assembly</term>
/// </item>
/// <item>
/// <term>MSIASSEMBLYINFO_WIN32ASSEMBLY 1</term>
/// <term>Win32 Assembly</term>
/// </item>
/// </list>
/// </param>
/// <param name="lpPathBuf">Pointer to a variable that receives the path to the component. This parameter can be null.</param>
/// <param name="pcchPathBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpPathBuf is null, pcchPathBuf can be null.</para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The feature is absent or broken. This error is returned for dwInstallMode = INSTALLMODE_EXISTING.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The installation failed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_NOTUSED</term>
/// <term>The component being requested is disabled on the computer.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_FEATURE</term>
/// <term>The feature ID does not identify a known feature.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_COMPONENT</term>
/// <term>The component ID does not specify a known component.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code does not identify a known product.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>An unrecognized product or a feature name was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The buffer overflow is returned.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>The system does not have enough memory to complete the operation. Available with Windows Server 2003.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SOURCE_ABSENT</term>
/// <term>Unable to detect a source.</term>
/// </item>
/// </list>
/// <para>For more information, see Displayed Error Messages.</para>
/// </returns>
/// <remarks>
/// <para>When the <c>MsiProvideAssembly</c> function succeeds, the pcchPathBuf parameter contains the length of the string in lpPathBuf.</para>
/// <para>The INSTALLMODE_EXISTING option cannot be used in combination with the REINSTALLMODE flag.</para>
/// <para>
/// Features with components that contain a corrupted file or the wrong version of a file must be explicitly reinstalled by the
/// user, or by having the application call MsiReinstallFeature.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiprovideassemblya UINT MsiProvideAssemblyA( LPCSTR
// szAssemblyName, LPCSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, LPDWORD pcchPathBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiProvideAssemblyA")]
public static extern Win32Error MsiProvideAssembly([MarshalAs(UnmanagedType.LPTStr)] string szAssemblyName,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szAppContext, INSTALLMODE dwInstallMode, MSIASSEMBLYINFO dwAssemblyInfo,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf, ref uint pcchPathBuf);
/// <summary>
/// The <c>MsiProvideAssembly</c> function returns the full path to a Windows Installer component that contains an assembly. The
/// function prompts for a source and performs any necessary installation. <c>MsiProvideAssembly</c> increments the usage count for
/// the feature.
/// </summary>
/// <param name="szAssemblyName">The assembly name as a string.</param>
/// <param name="szAppContext">
/// Set to null for global assemblies. For private assemblies, set szAppContext to the full path of the application configuration
/// file or to the full path of the executable file of the application to which the assembly has been made private.
/// </param>
/// <param name="dwInstallMode">
/// <para>Defines the installation mode. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLMODE_DEFAULT</term>
/// <term>
/// Provide the component and perform any installation necessary to provide the component. If the key file of a component in the
/// requested feature, or a feature parent, is missing, reinstall the feature using MsiReinstallFeature with the following flag bits
/// set: REINSTALLMODE_FILEMISSING, REINSTALLMODE_FILEOLDERVERSION, REINSTALLMODE_FILEVERIFY, REINSTALLMODE_MACHINEDATA,
/// REINSTALLMODE_USERDATA and REINSTALLMODE_SHORTCUT.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode verifies that the key file of
/// the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file of the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NOSOURCERESOLUTION</term>
/// <term>
/// Provide the component only if the feature's installation state is INSTALLSTATE_LOCAL. If the feature installation state is
/// INSTALLSTATE_SOURCE, return ERROR_INSTALL_SOURCE_ABSENT. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION_ANY</term>
/// <term>
/// Provide the component if a feature exists from any installed product. Otherwise return ERROR_FILE_NOT_FOUND. This mode only
/// checks that the component is registered and does not verify that the key file of the component exists. This flag is similar to
/// the INSTALLMODE_NODETECTION flag except that with this flag we check for any product that has installed the assembly as opposed
/// to the last product as is the case with the INSTALLMODE_NODETECTION flag. This flag can only be used with MsiProvideAssembly.
/// </term>
/// </item>
/// <item>
/// <term>combination of the REINSTALLMODE flags</term>
/// <term>
/// Call MsiReinstallFeature to reinstall feature using this parameter for the dwReinstallMode parameter, and then provide the component.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="dwAssemblyInfo">
/// <para>Assembly information and assembly type. Set to one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIASSEMBLYINFO_NETASSEMBLY 0</term>
/// <term>.NET Assembly</term>
/// </item>
/// <item>
/// <term>MSIASSEMBLYINFO_WIN32ASSEMBLY 1</term>
/// <term>Win32 Assembly</term>
/// </item>
/// </list>
/// </param>
/// <param name="lpPathBuf">Pointer to a variable that receives the path to the component. This parameter can be null.</param>
/// <param name="pcchPathBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpPathBuf is null, pcchPathBuf can be null.</para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The feature is absent or broken. This error is returned for dwInstallMode = INSTALLMODE_EXISTING.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The installation failed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_NOTUSED</term>
/// <term>The component being requested is disabled on the computer.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_FEATURE</term>
/// <term>The feature ID does not identify a known feature.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_COMPONENT</term>
/// <term>The component ID does not specify a known component.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code does not identify a known product.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>An unrecognized product or a feature name was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The buffer overflow is returned.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_ENOUGH_MEMORY</term>
/// <term>The system does not have enough memory to complete the operation. Available with Windows Server 2003.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SOURCE_ABSENT</term>
/// <term>Unable to detect a source.</term>
/// </item>
/// </list>
/// <para>For more information, see Displayed Error Messages.</para>
/// </returns>
/// <remarks>
/// <para>When the <c>MsiProvideAssembly</c> function succeeds, the pcchPathBuf parameter contains the length of the string in lpPathBuf.</para>
/// <para>The INSTALLMODE_EXISTING option cannot be used in combination with the REINSTALLMODE flag.</para>
/// <para>
/// Features with components that contain a corrupted file or the wrong version of a file must be explicitly reinstalled by the
/// user, or by having the application call MsiReinstallFeature.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiprovideassemblya UINT MsiProvideAssemblyA( LPCSTR
// szAssemblyName, LPCSTR szAppContext, DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf, LPDWORD pcchPathBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiProvideAssemblyA")]
public static extern Win32Error MsiProvideAssembly([MarshalAs(UnmanagedType.LPTStr)] string szAssemblyName,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szAppContext, INSTALLMODE dwInstallMode, MSIASSEMBLYINFO dwAssemblyInfo,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf, [In, Optional] IntPtr pcchPathBuf);
/// <summary>
/// The <c>MsiProvideComponent</c> function returns the full component path, performing any necessary installation. This function
/// prompts for source if necessary and increments the usage count for the feature.
/// </summary>
/// <param name="szProduct">Specifies the product code for the product that contains the feature with the necessary component.</param>
/// <param name="szFeature">Specifies the feature ID of the feature with the necessary component.</param>
/// <param name="szComponent">Specifies the component code of the necessary component.</param>
/// <param name="dwInstallMode">
/// <para>Defines the installation mode. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLMODE_DEFAULT</term>
/// <term>
/// Provide the component and perform any installation necessary to provide the component. If the key file of a component in the
/// requested feature, or a feature parent, is missing, reinstall the feature using MsiReinstallFeature with the following flag bits
/// set: REINSTALLMODE_FILEMISSING, REINSTALLMODE_FILEOLDERVERSION, REINSTALLMODE_FILEVERIFY, REINSTALLMODE_MACHINEDATA,
/// REINSTALLMODE_USERDATA and REINSTALLMODE_SHORTCUT.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode verifies that the key file of
/// the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file of the component exists.
/// </term>
/// </item>
/// <item>
/// <term>combination of the REINSTALLMODE flags</term>
/// <term>
/// Call MsiReinstallFeature to reinstall feature using this parameter for the dwReinstallMode parameter, and then provide the component.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NOSOURCERESOLUTION</term>
/// <term>
/// Provide the component only if the feature's installation state is INSTALLSTATE_LOCAL. If the feature's installation state is
/// INSTALLSTATE_SOURCE, return ERROR_INSTALL_SOURCE_ABSENT. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file exists.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="lpPathBuf">Pointer to a variable that receives the path to the component. This parameter can be null.</param>
/// <param name="pcchPathBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpPathBuf is null, pcchBuf can be null.</para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The feature is absent or broken. this error is returned for dwInstallMode = INSTALLMODE_EXISTING.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The installation failed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_NOTUSED</term>
/// <term>The component being requested is disabled on the computer.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_FEATURE</term>
/// <term>The feature ID does not identify a known feature.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code does not identify a known product.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>An unrecognized product or a feature name was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The buffer overflow is returned.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SOURCE_ABSENT</term>
/// <term>Unable to detect a source.</term>
/// </item>
/// </list>
/// <para>For more information, see Displayed Error Messages.</para>
/// </returns>
/// <remarks>
/// <para>
/// Upon success of the <c>MsiProvideComponent</c> function, the pcchPathBuf parameter contains the length of the string in lpPathBuf.
/// </para>
/// <para>
/// The <c>MsiProvideComponent</c> function combines the functionality of MsiUseFeature, MsiConfigureFeature, and
/// MsiGetComponentPath. You can use the <c>MsiProvideComponent</c> function to simplify the calling sequence. However, because this
/// function increments the usage count, use it with caution to prevent inaccurate usage counts. The <c>MsiProvideComponent</c>
/// function also provides less flexibility than the series of individual calls.
/// </para>
/// <para>
/// If the application is recovering from an unexpected situation, the application has probably already called MsiUseFeature and
/// incremented the usage count. In this case, the application should call MsiConfigureFeature instead of <c>MsiProvideComponent</c>
/// to avoid incrementing the count again.
/// </para>
/// <para>The INSTALLMODE_EXISTING option cannot be used in combination with the REINSTALLMODE flag.</para>
/// <para>
/// Features with components containing a corrupted file or the wrong version of a file must be explicitly reinstalled by the user
/// or by having the application call MsiReinstallFeature.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiprovidecomponenta UINT MsiProvideComponentA( LPCSTR szProduct,
// LPCSTR szFeature, LPCSTR szComponent, DWORD dwInstallMode, LPSTR lpPathBuf, LPDWORD pcchPathBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiProvideComponentA")]
public static extern Win32Error MsiProvideComponent([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szFeature, [MarshalAs(UnmanagedType.LPTStr)] string szComponent,
INSTALLMODE dwInstallMode, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf, ref uint pcchPathBuf);
/// <summary>
/// The <c>MsiProvideComponent</c> function returns the full component path, performing any necessary installation. This function
/// prompts for source if necessary and increments the usage count for the feature.
/// </summary>
/// <param name="szProduct">Specifies the product code for the product that contains the feature with the necessary component.</param>
/// <param name="szFeature">Specifies the feature ID of the feature with the necessary component.</param>
/// <param name="szComponent">Specifies the component code of the necessary component.</param>
/// <param name="dwInstallMode">
/// <para>Defines the installation mode. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLMODE_DEFAULT</term>
/// <term>
/// Provide the component and perform any installation necessary to provide the component. If the key file of a component in the
/// requested feature, or a feature parent, is missing, reinstall the feature using MsiReinstallFeature with the following flag bits
/// set: REINSTALLMODE_FILEMISSING, REINSTALLMODE_FILEOLDERVERSION, REINSTALLMODE_FILEVERIFY, REINSTALLMODE_MACHINEDATA,
/// REINSTALLMODE_USERDATA and REINSTALLMODE_SHORTCUT.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode verifies that the key file of
/// the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file of the component exists.
/// </term>
/// </item>
/// <item>
/// <term>combination of the REINSTALLMODE flags</term>
/// <term>
/// Call MsiReinstallFeature to reinstall feature using this parameter for the dwReinstallMode parameter, and then provide the component.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NOSOURCERESOLUTION</term>
/// <term>
/// Provide the component only if the feature's installation state is INSTALLSTATE_LOCAL. If the feature's installation state is
/// INSTALLSTATE_SOURCE, return ERROR_INSTALL_SOURCE_ABSENT. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file exists.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="lpPathBuf">Pointer to a variable that receives the path to the component. This parameter can be null.</param>
/// <param name="pcchPathBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpPathBuf is null, pcchBuf can be null.</para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The feature is absent or broken. this error is returned for dwInstallMode = INSTALLMODE_EXISTING.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The installation failed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_NOTUSED</term>
/// <term>The component being requested is disabled on the computer.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_FEATURE</term>
/// <term>The feature ID does not identify a known feature.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code does not identify a known product.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>An unrecognized product or a feature name was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The buffer overflow is returned.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SOURCE_ABSENT</term>
/// <term>Unable to detect a source.</term>
/// </item>
/// </list>
/// <para>For more information, see Displayed Error Messages.</para>
/// </returns>
/// <remarks>
/// <para>
/// Upon success of the <c>MsiProvideComponent</c> function, the pcchPathBuf parameter contains the length of the string in lpPathBuf.
/// </para>
/// <para>
/// The <c>MsiProvideComponent</c> function combines the functionality of MsiUseFeature, MsiConfigureFeature, and
/// MsiGetComponentPath. You can use the <c>MsiProvideComponent</c> function to simplify the calling sequence. However, because this
/// function increments the usage count, use it with caution to prevent inaccurate usage counts. The <c>MsiProvideComponent</c>
/// function also provides less flexibility than the series of individual calls.
/// </para>
/// <para>
/// If the application is recovering from an unexpected situation, the application has probably already called MsiUseFeature and
/// incremented the usage count. In this case, the application should call MsiConfigureFeature instead of <c>MsiProvideComponent</c>
/// to avoid incrementing the count again.
/// </para>
/// <para>The INSTALLMODE_EXISTING option cannot be used in combination with the REINSTALLMODE flag.</para>
/// <para>
/// Features with components containing a corrupted file or the wrong version of a file must be explicitly reinstalled by the user
/// or by having the application call MsiReinstallFeature.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiprovidecomponenta UINT MsiProvideComponentA( LPCSTR szProduct,
// LPCSTR szFeature, LPCSTR szComponent, DWORD dwInstallMode, LPSTR lpPathBuf, LPDWORD pcchPathBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiProvideComponentA")]
public static extern Win32Error MsiProvideComponent([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szFeature, [MarshalAs(UnmanagedType.LPTStr)] string szComponent,
INSTALLMODE dwInstallMode, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf, [In, Optional] IntPtr pcchPathBuf);
/// <summary>
/// The <c>MsiProvideQualifiedComponent</c> function returns the full component path for a qualified component and performs any
/// necessary installation. This function prompts for source if necessary, and increments the usage count for the feature.
/// </summary>
/// <param name="szCategory">
/// Specifies the component ID for the requested component. This may not be the GUID for the component itself, but rather a server
/// that provides the correct functionality, as in the ComponentId column of the PublishComponent table.
/// </param>
/// <param name="szQualifier">Specifies a qualifier into a list of advertising components (from PublishComponent Table).</param>
/// <param name="dwInstallMode">
/// <para>Defines the installation mode. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLMODE_DEFAULT</term>
/// <term>
/// Provide the component and perform any installation necessary to provide the component. If the key file of a component in the
/// requested feature, or a feature parent, is missing, reinstall the feature using MsiReinstallFeature with the following flag bits
/// set: REINSTALLMODE_FILEMISSING, REINSTALLMODE_FILEOLDERVERSION, REINSTALLMODE_FILEVERIFY, REINSTALLMODE_MACHINEDATA,
/// REINSTALLMODE_USERDATA, and REINSTALLMODE_SHORTCUT.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode verifies that the key file of
/// the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file of the component exists.
/// </term>
/// </item>
/// <item>
/// <term>combination of the REINSTALLMODE flags</term>
/// <term>
/// Call MsiReinstallFeature to reinstall the feature using this parameter for the dwReinstallMode parameter, and then provide the component.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NOSOURCERESOLUTION</term>
/// <term>
/// Provide the component only if the feature's installation state is INSTALLSTATE_LOCAL. If the feature's installation state is
/// INSTALLSTATE_SOURCE, return ERROR_INSTALL_SOURCE_ABSENT. Otherwise, it returns ERROR_FILE_NOT_FOUND. This mode only checks that
/// the component is registered and does not verify that the key file exists.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="lpPathBuf">Pointer to a variable that receives the path to the component. This parameter can be null.</param>
/// <param name="pcchPathBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpPathBuf is null, pcchBuf can be null.</para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_INDEX_ABSENT</term>
/// <term>The component qualifier is invalid or absent.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The feature is absent or broken. This error is returned for dwInstallMode = INSTALLMODE_EXISTING.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_COMPONENT</term>
/// <term>The specified component is unknown.</term>
/// </item>
/// <item>
/// <term>An error relating to an action</term>
/// <term>See Error Codes.</term>
/// </item>
/// <item>
/// <term>Initialization Error</term>
/// <term>An error relating to initialization occurred.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Upon success of the <c>MsiProvideQualifiedComponent</c> function, the pcchPathBuf parameter contains the length of the string in lpPathBuf.
/// </para>
/// <para>
/// Features with components containing a corrupted file or the wrong version of a file must be explicitly reinstalled by the user
/// or by having the application call MsiReinstallFeature.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiprovidequalifiedcomponenta UINT MsiProvideQualifiedComponentA(
// LPCSTR szCategory, LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf, LPDWORD pcchPathBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiProvideQualifiedComponentA")]
public static extern Win32Error MsiProvideQualifiedComponent([MarshalAs(UnmanagedType.LPTStr)] string szCategory,
[MarshalAs(UnmanagedType.LPTStr)] string szQualifier, INSTALLMODE dwInstallMode,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf, ref uint pcchPathBuf);
/// <summary>
/// The <c>MsiProvideQualifiedComponent</c> function returns the full component path for a qualified component and performs any
/// necessary installation. This function prompts for source if necessary, and increments the usage count for the feature.
/// </summary>
/// <param name="szCategory">
/// Specifies the component ID for the requested component. This may not be the GUID for the component itself, but rather a server
/// that provides the correct functionality, as in the ComponentId column of the PublishComponent table.
/// </param>
/// <param name="szQualifier">Specifies a qualifier into a list of advertising components (from PublishComponent Table).</param>
/// <param name="dwInstallMode">
/// <para>Defines the installation mode. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLMODE_DEFAULT</term>
/// <term>
/// Provide the component and perform any installation necessary to provide the component. If the key file of a component in the
/// requested feature, or a feature parent, is missing, reinstall the feature using MsiReinstallFeature with the following flag bits
/// set: REINSTALLMODE_FILEMISSING, REINSTALLMODE_FILEOLDERVERSION, REINSTALLMODE_FILEVERIFY, REINSTALLMODE_MACHINEDATA,
/// REINSTALLMODE_USERDATA, and REINSTALLMODE_SHORTCUT.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode verifies that the key file of
/// the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file of the component exists.
/// </term>
/// </item>
/// <item>
/// <term>combination of the REINSTALLMODE flags</term>
/// <term>
/// Call MsiReinstallFeature to reinstall the feature using this parameter for the dwReinstallMode parameter, and then provide the component.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NOSOURCERESOLUTION</term>
/// <term>
/// Provide the component only if the feature's installation state is INSTALLSTATE_LOCAL. If the feature's installation state is
/// INSTALLSTATE_SOURCE, return ERROR_INSTALL_SOURCE_ABSENT. Otherwise, it returns ERROR_FILE_NOT_FOUND. This mode only checks that
/// the component is registered and does not verify that the key file exists.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="lpPathBuf">Pointer to a variable that receives the path to the component. This parameter can be null.</param>
/// <param name="pcchPathBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpPathBuf is null, pcchBuf can be null.</para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_INDEX_ABSENT</term>
/// <term>The component qualifier is invalid or absent.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The feature is absent or broken. This error is returned for dwInstallMode = INSTALLMODE_EXISTING.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_COMPONENT</term>
/// <term>The specified component is unknown.</term>
/// </item>
/// <item>
/// <term>An error relating to an action</term>
/// <term>See Error Codes.</term>
/// </item>
/// <item>
/// <term>Initialization Error</term>
/// <term>An error relating to initialization occurred.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Upon success of the <c>MsiProvideQualifiedComponent</c> function, the pcchPathBuf parameter contains the length of the string in lpPathBuf.
/// </para>
/// <para>
/// Features with components containing a corrupted file or the wrong version of a file must be explicitly reinstalled by the user
/// or by having the application call MsiReinstallFeature.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiprovidequalifiedcomponenta UINT MsiProvideQualifiedComponentA(
// LPCSTR szCategory, LPCSTR szQualifier, DWORD dwInstallMode, LPSTR lpPathBuf, LPDWORD pcchPathBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiProvideQualifiedComponentA")]
public static extern Win32Error MsiProvideQualifiedComponent([MarshalAs(UnmanagedType.LPTStr)] string szCategory,
[MarshalAs(UnmanagedType.LPTStr)] string szQualifier, INSTALLMODE dwInstallMode,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf, [In, Optional] IntPtr pcchPathBuf);
/// <summary>
/// The <c>MsiProvideQualifiedComponentEx</c> function returns the full component path for a qualified component that is published
/// by a product and performs any necessary installation. This function prompts for source if necessary and increments the usage
/// count for the feature.
/// </summary>
/// <param name="szCategory">
/// Specifies the component ID that for the requested component. This may not be the GUID for the component itself but rather a
/// server that provides the correct functionality, as in the ComponentId column of the PublishComponent table.
/// </param>
/// <param name="szQualifier">Specifies a qualifier into a list of advertising components (from PublishComponent Table).</param>
/// <param name="dwInstallMode">
/// <para>Defines the installation mode. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLMODE_DEFAULT</term>
/// <term>
/// Provide the component and perform any installation necessary to provide the component. If the key file of a component in the
/// requested feature, or a feature parent, is missing, reinstall the feature using MsiReinstallFeature with the following flag bits
/// set: REINSTALLMODE_FILEMISSING, REINSTALLMODE_FILEOLDERVERSION, REINSTALLMODE_FILEVERIFY, REINSTALLMODE_MACHINEDATA,
/// REINSTALLMODE_USERDATA and REINSTALLMODE_SHORTCUT.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode verifies that the key file of
/// the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file of the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>Provide the component only if the feature exists, else return ERROR_FILE_NOT_FOUND.</term>
/// </item>
/// <item>
/// <term>combination of the REINSTALLMODE flags</term>
/// <term>
/// Call MsiReinstallFeature to reinstall feature using this parameter for the dwReinstallMode parameter, and then provide the component.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NOSOURCERESOLUTION</term>
/// <term>
/// Provide the component only if the feature's installation state is INSTALLSTATE_LOCAL. If the feature's installation state is
/// INSTALLSTATE_SOURCE, return ERROR_INSTALL_SOURCE_ABSENT. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file exists.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="szProduct">
/// Specifies the product to match that has published the qualified component. If this is null, then this API works the same as MsiProvideQualifiedComponent.
/// </param>
/// <param name="dwUnused1">Reserved. Must be zero.</param>
/// <param name="dwUnused2">Reserved. Must be zero.</param>
/// <param name="lpPathBuf">Pointer to a variable that receives the path to the component. This parameter can be null.</param>
/// <param name="pcchPathBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpPathBuf is null, pcchBuf can be null.</para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_INDEX_ABSENT</term>
/// <term>Component qualifier invalid or not present.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The feature is absent or broken. this error is returned for dwInstallMode = INSTALLMODE_EXISTING.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_COMPONENT</term>
/// <term>The specified component is unknown.</term>
/// </item>
/// <item>
/// <term>An error relating to an action</term>
/// <term>See Error Codes.</term>
/// </item>
/// <item>
/// <term>Initialization Error</term>
/// <term>An error relating to initialization occurred.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Upon success of the <c>MsiProvideQualifiedComponentEx</c> function, the pcchPathBuf parameter contains the length of the string
/// in lpPathBuf.
/// </para>
/// <para>
/// Features with components containing a corrupted file or the wrong version of a file must be explicitly reinstalled by the user
/// or by having the application call MsiReinstallFeature.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiprovidequalifiedcomponentexa UINT
// MsiProvideQualifiedComponentExA( LPCSTR szCategory, LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct, DWORD dwUnused1,
// DWORD dwUnused2, LPSTR lpPathBuf, LPDWORD pcchPathBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiProvideQualifiedComponentExA")]
public static extern Win32Error MsiProvideQualifiedComponentEx([MarshalAs(UnmanagedType.LPTStr)] string szCategory,
[MarshalAs(UnmanagedType.LPTStr)] string szQualifier, INSTALLMODE dwInstallMode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szProduct, [Optional] uint dwUnused1, [Optional] uint dwUnused2,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf, ref uint pcchPathBuf);
/// <summary>
/// The <c>MsiProvideQualifiedComponentEx</c> function returns the full component path for a qualified component that is published
/// by a product and performs any necessary installation. This function prompts for source if necessary and increments the usage
/// count for the feature.
/// </summary>
/// <param name="szCategory">
/// Specifies the component ID that for the requested component. This may not be the GUID for the component itself but rather a
/// server that provides the correct functionality, as in the ComponentId column of the PublishComponent table.
/// </param>
/// <param name="szQualifier">Specifies a qualifier into a list of advertising components (from PublishComponent Table).</param>
/// <param name="dwInstallMode">
/// <para>Defines the installation mode. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLMODE_DEFAULT</term>
/// <term>
/// Provide the component and perform any installation necessary to provide the component. If the key file of a component in the
/// requested feature, or a feature parent, is missing, reinstall the feature using MsiReinstallFeature with the following flag bits
/// set: REINSTALLMODE_FILEMISSING, REINSTALLMODE_FILEOLDERVERSION, REINSTALLMODE_FILEVERIFY, REINSTALLMODE_MACHINEDATA,
/// REINSTALLMODE_USERDATA and REINSTALLMODE_SHORTCUT.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode verifies that the key file of
/// the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NODETECTION</term>
/// <term>
/// Provide the component only if the feature exists. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file of the component exists.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_EXISTING</term>
/// <term>Provide the component only if the feature exists, else return ERROR_FILE_NOT_FOUND.</term>
/// </item>
/// <item>
/// <term>combination of the REINSTALLMODE flags</term>
/// <term>
/// Call MsiReinstallFeature to reinstall feature using this parameter for the dwReinstallMode parameter, and then provide the component.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLMODE_NOSOURCERESOLUTION</term>
/// <term>
/// Provide the component only if the feature's installation state is INSTALLSTATE_LOCAL. If the feature's installation state is
/// INSTALLSTATE_SOURCE, return ERROR_INSTALL_SOURCE_ABSENT. Otherwise return ERROR_FILE_NOT_FOUND. This mode only checks that the
/// component is registered and does not verify that the key file exists.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="szProduct">
/// Specifies the product to match that has published the qualified component. If this is null, then this API works the same as MsiProvideQualifiedComponent.
/// </param>
/// <param name="dwUnused1">Reserved. Must be zero.</param>
/// <param name="dwUnused2">Reserved. Must be zero.</param>
/// <param name="lpPathBuf">Pointer to a variable that receives the path to the component. This parameter can be null.</param>
/// <param name="pcchPathBuf">
/// <para>
/// Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpPathBuf parameter. On input,
/// this is the full size of the buffer, including a space for a terminating null character. If the buffer passed in is too small,
/// the count returned does not include the terminating null character.
/// </para>
/// <para>If lpPathBuf is null, pcchBuf can be null.</para>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_INDEX_ABSENT</term>
/// <term>Component qualifier invalid or not present.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND</term>
/// <term>The feature is absent or broken. this error is returned for dwInstallMode = INSTALLMODE_EXISTING.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_COMPONENT</term>
/// <term>The specified component is unknown.</term>
/// </item>
/// <item>
/// <term>An error relating to an action</term>
/// <term>See Error Codes.</term>
/// </item>
/// <item>
/// <term>Initialization Error</term>
/// <term>An error relating to initialization occurred.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Upon success of the <c>MsiProvideQualifiedComponentEx</c> function, the pcchPathBuf parameter contains the length of the string
/// in lpPathBuf.
/// </para>
/// <para>
/// Features with components containing a corrupted file or the wrong version of a file must be explicitly reinstalled by the user
/// or by having the application call MsiReinstallFeature.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiprovidequalifiedcomponentexa UINT
// MsiProvideQualifiedComponentExA( LPCSTR szCategory, LPCSTR szQualifier, DWORD dwInstallMode, LPCSTR szProduct, DWORD dwUnused1,
// DWORD dwUnused2, LPSTR lpPathBuf, LPDWORD pcchPathBuf );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiProvideQualifiedComponentExA")]
public static extern Win32Error MsiProvideQualifiedComponentEx([MarshalAs(UnmanagedType.LPTStr)] string szCategory,
[MarshalAs(UnmanagedType.LPTStr)] string szQualifier, INSTALLMODE dwInstallMode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szProduct, [Optional] uint dwUnused1, [Optional] uint dwUnused2,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpPathBuf, [In, Optional] IntPtr pcchPathBuf);
/// <summary>
/// The <c>MsiQueryComponentState</c> function returns the installed state for a component. This function can query for a component
/// of an instance of a product that is installed under user accounts other than the current user provided the product is not
/// advertised under the per-user-unmanaged context for a user account other than the current user. The calling process must have
/// administrative privileges to get information for a product installed for a user other than the current user.
/// </summary>
/// <param name="szProductCode">Specifies the ProductCode GUID for the product that contains the component.</param>
/// <param name="szUserSid">
/// <para>
/// Specifies the security identifier (SID) of the account under which the instance of the product being queried exists. If
/// dwContext is not MSIINSTALLCONTEXT_MACHINE, null specifies the current user.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>NULL denotes the currently logged on user.</term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>Specifies enumeration for a particular user in the system. An example of user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string "S-1-5-18" (system) cannot be used to enumerate products installed as per-machine. If
/// dwContext is <c>MSIINSTALLCONTEXT_MACHINE</c>, szUserSid must be null.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>The installation context of the product instance being queried.</para>
/// <list type="table">
/// <listheader>
/// <term>Name</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>Retrieves the component's state for the per<65>user<65>managed instance of the product.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>Retrieves the component's state for the per<65>user<65>non-managed instance of the product.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>Retrieves the component's state for the per-machine instance of the product.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szComponentCode">
/// Specifies the component being queried. Component code GUID of the component as found in the ComponentID column of the Component table.
/// </param>
/// <param name="pdwState">
/// <para>
/// Installation state of the component for the specified product instance. This parameter can return one of the following or null values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_LOCAL</term>
/// <term>The component is installed locally.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCE</term>
/// <term>The component is installed to run from the source.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>The <c>MsiQueryComponentState</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The calling process must have administrative privileges to get information for a product installed for a user other than the
/// current user.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_COMPONENT</term>
/// <term>The component ID does not identify a known component.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code does not identify a known product.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Failures that cannot be ascribed to any Windows error code.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>Buffer too small to get the user SID.</term>
/// </item>
/// </list>
/// <para>For more information, see Displayed Error Messages.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiquerycomponentstatea UINT MsiQueryComponentStateA( LPCSTR
// szProductCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCSTR szComponentCode, INSTALLSTATE *pdwState );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiQueryComponentStateA")]
public static extern Win32Error MsiQueryComponentState([MarshalAs(UnmanagedType.LPTStr)] string szProductCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext,
[MarshalAs(UnmanagedType.LPTStr)] string szComponentCode, out INSTALLSTATE pdwState);
/// <summary>The <c>MsiQueryFeatureState</c> function returns the installed state for a product feature.</summary>
/// <param name="szProduct">Specifies the product code for the product that contains the feature of interest.</param>
/// <param name="szFeature">Identifies the feature of interest.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// <term>The feature is not installed.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_ADVERTISED</term>
/// <term>The feature is advertised</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_LOCAL</term>
/// <term>The feature is installed locally.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCE</term>
/// <term>The feature is installed to run from source.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_INVALIDARG</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>The product code or feature ID is unknown.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>The <c>MsiQueryFeatureState</c> function does not validate that the feature is actually accessible.</remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiqueryfeaturestatea INSTALLSTATE MsiQueryFeatureStateA( LPCSTR
// szProduct, LPCSTR szFeature );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiQueryFeatureStateA")]
public static extern INSTALLSTATE MsiQueryFeatureState([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szFeature);
/// <summary>
/// The <c>MsiQueryFeatureStateEx</c> function returns the installed state for a product feature. This function can be used to query
/// any feature of an instance of a product installed under the machine account or any context under the current user account or the
/// per-user-managed context under any user account other than the current user. A user must have administrative privileges to get
/// information for a product installed for a user other than the current user.
/// </summary>
/// <param name="szProductCode">ProductCode GUID of the product that contains the feature of interest.</param>
/// <param name="szUserSid">
/// <para>
/// Specifies the security identifier (SID) of the account, under which, the instance of the product being queried exists. If
/// dwContext is not <c>MSIINSTALLCONTEXT_MACHINE</c>, a null value specifies the current user.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>NULL denotes the currently logged on user.</term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>Specifies enumeration for a particular user in the system. An example of user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string s-1-5-18 (system) cannot be used to enumerate features of products installed as per-machine.
/// If dwContext is <c>MSIINSTALLCONTEXT_MACHINE</c>, szUserSid must be null.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>The installation context of the product instance being queried.</para>
/// <list type="table">
/// <listheader>
/// <term>Name</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>Retrieves the feature state for the per-user-managed instance of the product.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>Retrieves the feature state for the per-user-unmanaged instance of the product.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>Retrieves the feature state for the per-machine instance of the product.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szFeature">
/// Specifies the feature being queried. Identifier of the feature as found in the <c>Feature</c> column of the Feature table.
/// </param>
/// <param name="pdwState">
/// <para>
/// Installation state of the feature for the specified product instance. This parameter can return one of the following or null.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_ADVERTISED</term>
/// <term>This feature is advertised.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_LOCAL</term>
/// <term>The feature is installed locally.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCE</term>
/// <term>The feature is installed to run from source.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>The <c>MsiQueryFeatureStateEx</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// A user must have administrative privileges to get information for a product installed for a user other than the current user.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_FEATURE</term>
/// <term>The feature ID does not identify a known feature.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code does not identify a known product.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>An unexpected internal failure.</term>
/// </item>
/// </list>
/// <para>For more information, see Displayed Error Messages.</para>
/// </returns>
/// <remarks>
/// The <c>MsiQueryFeatureStateEx</c> function does not validate that the feature is actually accessible. The
/// <c>MsiQueryFeatureStateEx</c> function does not validate the feature ID. <c>ERROR_UNKNOWN_FEATURE</c> is returned for any
/// unknown feature ID. When the query is made on a product installed under the per-user-unmanaged context for a user account other
/// than the current user, the function fails. In this case the function returns <c>ERROR_UNKNOWN_FEATURE</c>, or if the product is
/// advertised only (not installed), <c>ERROR_UNKNOWN_PRODUCT</c> is returned.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiqueryfeaturestateexa UINT MsiQueryFeatureStateExA( LPCSTR
// szProductCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCSTR szFeature, INSTALLSTATE *pdwState );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiQueryFeatureStateExA")]
public static extern Win32Error MsiQueryFeatureStateEx([MarshalAs(UnmanagedType.LPTStr)] string szProductCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext,
[MarshalAs(UnmanagedType.LPTStr)] string szFeature, out INSTALLSTATE pdwState);
/// <summary>The <c>MsiQueryProductState</c> function returns the installed state for a product.</summary>
/// <param name="szProduct">Specifies the product code that identifies the product to be queried.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// <term>The product is installed for a different user.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_ADVERTISED</term>
/// <term>The product is advertised but not installed.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_DEFAULT</term>
/// <term>The product is installed for the current user.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_INVALIDARG</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>The product is neither advertised or installed.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiqueryproductstatea INSTALLSTATE MsiQueryProductStateA( LPCSTR
// szProduct );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiQueryProductStateA")]
public static extern INSTALLSTATE MsiQueryProductState([MarshalAs(UnmanagedType.LPTStr)] string szProduct);
/// <summary>The <c>MsiReinstallFeature</c> function reinstalls features.</summary>
/// <param name="szProduct">Specifies the product code for the product that contains the feature to be reinstalled.</param>
/// <param name="szFeature">
/// Specifies the feature to be reinstalled. The parent feature or child feature of the specified feature is not reinstalled. To
/// reinstall the parent or child feature, you must call the <c>MsiReinstallFeature</c> function for each separately or use the
/// MsiReinstallProduct function.
/// </param>
/// <param name="dwReinstallMode">
/// <para>Specifies what to install. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>REINSTALLMODE_FILEMISSING</term>
/// <term>Reinstall only if the file is missing.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEOLDERVERSION</term>
/// <term>Reinstall if the file is missing or is an older version.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEEQUALVERSION</term>
/// <term>Reinstall if the file is missing, or is an equal or older version.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEEXACT</term>
/// <term>Reinstall if the file is missing or is a different version.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEVERIFY</term>
/// <term>
/// Verify the checksum values, and reinstall the file if they are missing or corrupt. This flag only repairs files that have
/// msidbFileAttributesChecksum in the Attributes column of the File table.
/// </term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEREPLACE</term>
/// <term>Force all files to be reinstalled, regardless of checksum or version.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_USERDATA</term>
/// <term>Rewrite all required registry entries from the Registry Table that go to theHKEY_CURRENT_USER or HKEY_USERS registry hive.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_MACHINEDATA</term>
/// <term>
/// Rewrite all required registry entries from the Registry Table that go to the HKEY_LOCAL_MACHINEor HKEY_CLASSES_ROOT registry
/// hive. Rewrite all information from the Class Table, Verb Table, PublishComponent Table, ProgID Table, MIME Table, Icon Table,
/// Extension Table, and AppID Table regardless of machine or user assignment. Reinstall all qualified components. When reinstalling
/// an application, this option runs the RegisterTypeLibraries and InstallODBC actions.
/// </term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_SHORTCUT</term>
/// <term>Reinstall all shortcuts and re-cache all icons overwriting any existing shortcuts and icons.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_PACKAGE</term>
/// <term>
/// Use to run from the source package and re-cache the local package. Do not use for the first installation of an application or feature.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The installation failed.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>The installation service could not be accessed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SUSPEND</term>
/// <term>The installation was suspended and is incomplete.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_USEREXIT</term>
/// <term>The user canceled the installation.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_FEATURE</term>
/// <term>The feature ID does not identify a known feature.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code does not identify a known product.</term>
/// </item>
/// </list>
/// <para>For more information, see Displayed Error Messages.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msireinstallfeaturea UINT MsiReinstallFeatureA( LPCSTR szProduct,
// LPCSTR szFeature, DWORD dwReinstallMode );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiReinstallFeatureA")]
public static extern Win32Error MsiReinstallFeature([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szFeature, REINSTALLMODE dwReinstallMode);
/// <summary>The <c>MsiReinstallProduct</c> function reinstalls products.</summary>
/// <param name="szProduct">Specifies the product code for the product to be reinstalled.</param>
/// <param name="szReinstallMode">
/// <para>Specifies the reinstall mode. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>REINSTALLMODE_FILEMISSING</term>
/// <term>Reinstall only if the file is missing.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEOLDERVERSION</term>
/// <term>Reinstall if the file is missing or is an older version.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEEQUALVERSION</term>
/// <term>Reinstall if the file is missing, or is an equal or older version.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEEXACT</term>
/// <term>Reinstall if the file is missing or is a different version.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEVERIFY</term>
/// <term>
/// Verify the checksum values and reinstall the file if they are missing or corrupt. This flag only repairs files that have
/// msidbFileAttributesChecksum in the Attributes column of the File table.
/// </term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_FILEREPLACE</term>
/// <term>Force all files to be reinstalled, regardless of checksum or version.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_USERDATA</term>
/// <term>Rewrite all required registry entries from the Registry Table that go to theHKEY_CURRENT_USER or HKEY_USERS registry hive.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_MACHINEDATA</term>
/// <term>
/// Rewrite all required registry entries from the Registry Table that go to the HKEY_LOCAL_MACHINEor HKEY_CLASSES_ROOT registry
/// hive. Rewrite all information from the Class Table, Verb Table, PublishComponent Table, ProgID Table, MIMET Table, Icon Table,
/// Extension Table, and AppID Table regardless of machine or user assignment. Reinstall all qualified components. When reinstalling
/// an application, this option runs the RegisterTypeLibraries and InstallODBC actions.
/// </term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_SHORTCUT</term>
/// <term>Reinstall all shortcuts and re-cache all icons overwriting any existing shortcuts and icons.</term>
/// </item>
/// <item>
/// <term>REINSTALLMODE_PACKAGE</term>
/// <term>
/// Use to run from the source package and re-cache the local package. Do not use for the first installation of an application or feature.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INSTALL_FAILURE</term>
/// <term>The installation failed.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>The installation service could not be accessed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SUSPEND</term>
/// <term>The installation was suspended and is incomplete.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_USEREXIT</term>
/// <term>The user canceled the installation.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completed successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product code does not identify a known product.</term>
/// </item>
/// </list>
/// <para>For more information, see Displayed Error Messages.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msireinstallproducta UINT MsiReinstallProductA( LPCSTR szProduct,
// DWORD szReinstallMode );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiReinstallProductA")]
public static extern Win32Error MsiReinstallProduct([MarshalAs(UnmanagedType.LPTStr)] string szProduct, REINSTALLMODE szReinstallMode);
/// <summary>
/// The <c>MsiRemovePatches</c> function removes one or more patches from a single product. To remove a patch from multiple
/// products, <c>MsiRemovePatches</c> must be called for each product.
/// </summary>
/// <param name="szPatchList">
/// A null-terminated string that represents the list of patches to remove. Each patch can be specified by the GUID of the patch or
/// the full path to the patch package. The patches in the list are delimited by semicolons.
/// </param>
/// <param name="szProductCode">
/// A null-terminated string that is the ProductCode (GUID) of the product from which the patches are removed. This parameter cannot
/// be <c>NULL</c>.
/// </param>
/// <param name="eUninstallType">
/// <para>Value that indicates the type of patch removal to perform. This parameter must be <c>INSTALLTYPE_SINGLE_INSTANCE</c>.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLTYPE_SINGLE_INSTANCE</term>
/// <term>The patch is uninstalled for only the product specified by szProduct.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szPropertyList">
/// A null-terminated string that specifies command-line property settings. For more information see About Properties and Setting
/// Public Property Values on the Command Line. This parameter can be <c>NULL</c>.
/// </param>
/// <returns>
/// <para>The <c>MsiRemovePatches</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was included.</term>
/// </item>
/// <item>
/// <term>ERROR_PATCH_PACKAGE_OPEN_FAILED</term>
/// <term>The patch package could not be opened.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The patch was successfully removed.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product specified by szProductList is not installed either per-machine or per-user for the caller of MsiRemovePatches.</term>
/// </item>
/// <item>
/// <term>ERROR_PATCH_PACKAGE_OPEN_FAILED</term>
/// <term>The patch package could not be opened.</term>
/// </item>
/// <item>
/// <term>ERROR_PATCH_PACKAGE_INVALID</term>
/// <term>The patch package is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_PATCH_PACKAGE_UNSUPPORTED</term>
/// <term>The patch package cannot be processed by this version of the Windows Installer service.</term>
/// </item>
/// <item>
/// <term>ERROR_PATCH_REMOVAL_UNSUPPORTED</term>
/// <term>The patch package is not removable.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch has not been applied to this product.</term>
/// </item>
/// <item>
/// <term>ERROR_PATCH_REMOVAL_DISALLOWED</term>
/// <term>Patch removal was disallowed by policy.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// See Uninstalling Patches for an example that demonstrates how an application can remove a patch from all products that are
/// available to the user.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiremovepatchesa UINT MsiRemovePatchesA( LPCSTR szPatchList,
// LPCSTR szProductCode, INSTALLTYPE eUninstallType, LPCSTR szPropertyList );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiRemovePatchesA")]
public static extern Win32Error MsiRemovePatches([MarshalAs(UnmanagedType.LPTStr)] string szPatchList,
[MarshalAs(UnmanagedType.LPTStr)] string szProductCode, INSTALLTYPE eUninstallType,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szPropertyList);
/// <summary>
/// The <c>MsiSetExternalUI</c> function enables an external user-interface handler. This external UI handler is called before the
/// normal internal user-interface handler. The external UI handler has the option to suppress the internal UI by returning a
/// non-zero value to indicate that it has handled the messages. For more information, see About the User Interface.
/// </summary>
/// <param name="puiHandler">Specifies a callback function that conforms to the INSTALLUI_HANDLER specification.</param>
/// <param name="dwMessageFilter">
/// <para>
/// Specifies which messages to handle using the external message handler. If the external handler returns a non-zero result, then
/// that message will not be sent to the UI, instead the message will be logged if logging has been enabled. For more information,
/// see the MsiEnableLog function.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLLOGMODE_FILESINUSE</term>
/// <term>Files in use information. When this message is received, a FilesInUse Dialog should be displayed.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_FATALEXIT</term>
/// <term>Premature termination of installation.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_ERROR</term>
/// <term>The error messages are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_WARNING</term>
/// <term>The warning messages are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_USER</term>
/// <term>The user requests are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_INFO</term>
/// <term>The status messages that are not displayed are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_RESOLVESOURCE</term>
/// <term>Request to determine a valid source location.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_RMFILESINUSE</term>
/// <term>Files in use information. When this message is received, a MsiRMFilesInUse Dialog should be displayed.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_OUTOFDISKSPACE</term>
/// <term>There was insufficient disk space.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_ACTIONSTART</term>
/// <term>The start of new installation actions are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_ACTIONDATA</term>
/// <term>The data record with the installation action is logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_COMMONDATA</term>
/// <term>The parameters for user-interface initialization are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_PROGRESS</term>
/// <term>
/// Progress bar information. This message includes information on units so far and total number of units. For an explanation of the
/// message format, see the MsiProcessMessage function. This message is only sent to an external user interface and is not logged.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_INITIALIZE</term>
/// <term>
/// If this is not a quiet installation, then the basic UI has been initialized. If this is a full UI installation, the full UI is
/// not yet initialized. This message is only sent to an external user interface and is not logged.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_TERMINATE</term>
/// <term>
/// If a full UI is being used, the full UI has ended. If this is not a quiet installation, the basic UI has not yet ended. This
/// message is only sent to an external user interface and is not logged.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_SHOWDIALOG</term>
/// <term>Sent prior to display of the full UI dialog. This message is only sent to an external user interface and is not logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_INSTALLSTART</term>
/// <term>Installation of product begins. The message contains the product's ProductName and ProductCode.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_INSTALLEND</term>
/// <term>Installation of product ends. The message contains the product's ProductName, ProductCode, and return value.</term>
/// </item>
/// </list>
/// </param>
/// <param name="pvContext">
/// Pointer to an application context that is passed to the callback function. This parameter can be used for error checking.
/// </param>
/// <returns>The return value is the previously set external handler, or zero (0) if there was no previously set handler.</returns>
/// <remarks>
/// <para>
/// To restore the previous UI handler, second call is made to <c>MsiSetExternalUI</c> using the INSTALLUI_HANDLER returned by the
/// first call to <c>MsiSetExternalUI</c> and specifying zero (0) for dwMessageFilter.
/// </para>
/// <para>
/// The external user interface handler pointed to by the puiHandler parameter does not have full control over the external user
/// interface unless MsiSetInternalUI is called with the dwUILevel parameter set to INSTALLUILEVEL_NONE. If <c>MsiSetInternalUI</c>
/// is not called, the internal user interface level defaults to INSTALLUILEVEL_BASIC. As a result, any message not handled by the
/// external user interface handler is handled by Windows Installer. The initial "Preparing to install. . ." dialog always appears
/// even if the external user interface handler handles all messages.
/// </para>
/// <para>
/// <c>MsiSetExternalUI</c> should only be called from a Bootstrapping application. You cannot call <c>MsiSetExternalUI</c> from a
/// custom action.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisetexternaluia INSTALLUI_HANDLERA MsiSetExternalUIA(
// INSTALLUI_HANDLERA puiHandler, DWORD dwMessageFilter, LPVOID pvContext );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSetExternalUIA")]
public static extern INSTALLUI_HANDLER MsiSetExternalUI([Optional] INSTALLUI_HANDLER puiHandler, INSTALLLOGMODE dwMessageFilter,
[In, Optional] IntPtr pvContext);
/// <summary>The <c>MsiSetExternalUIRecord</c> function enables an external user-interface (UI) handler.</summary>
/// <param name="puiHandler">
/// <para>Specifies a callback function that conforms to the INSTALLUI_HANDLER_RECORD specification.</para>
/// <para>To disable the current external UI handler, call the function with this parameter set to a <c>NULL</c> value.</para>
/// </param>
/// <param name="dwMessageFilter">
/// <para>
/// Specifies which messages to handle using the external message handler. If the external handler returns a non-zero result, then
/// that message is not sent to the UI, instead the message is logged if logging is enabled. For more information, see MsiEnableLog.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLLOGMODE_FILESINUSE</term>
/// <term>Files in use information. When this message is received, a FilesInUse Dialog should be displayed.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_FATALEXIT</term>
/// <term>Premature termination of installation.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_ERROR</term>
/// <term>The error messages are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_WARNING</term>
/// <term>The warning messages are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_USER</term>
/// <term>The user requests are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_INFO</term>
/// <term>The status messages that are not displayed are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_RESOLVESOURCE</term>
/// <term>Request to determine a valid source location.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_RMFILESINUSE</term>
/// <term>Files in use information. When this message is received, a MsiRMFilesInUse Dialog should be displayed.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_OUTOFDISKSPACE</term>
/// <term>The is insufficient disk space.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_ACTIONSTART</term>
/// <term>The start of new installation actions are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_ACTIONDATA</term>
/// <term>The data record with the installation action is logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_COMMONDATA</term>
/// <term>The parameters for user-interface initialization are logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_PROGRESS</term>
/// <term>
/// The Progress bar information. This message includes information about units so far and total number of units. This message is
/// only sent to an external user interface and is not logged. For more information, see MsiProcessMessage.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_INITIALIZE</term>
/// <term>
/// If this is not a quiet installation, then the basic UI is initialized. If this is a full UI installation, the Full UI is not yet
/// initialized. This message is only sent to an external user interface and is not logged.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_TERMINATE</term>
/// <term>
/// If a full UI is being used, the full UI has ended. If this is not a quiet installation, the basic UI has not ended. This message
/// is only sent to an external user interface and is not logged.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_SHOWDIALOG</term>
/// <term>Sent prior to display of the Full UI dialog. This message is only sent to an external user interface and is not logged.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_INSTALLSTART</term>
/// <term>Installation of product begins. The message contains the product's ProductName and ProductCode.</term>
/// </item>
/// <item>
/// <term>INSTALLLOGMODE_INSTALLEND</term>
/// <term>Installation of product ends. The message contains the product's ProductName, ProductCode, and return value.</term>
/// </item>
/// </list>
/// </param>
/// <param name="pvContext">
/// <para>A pointer to an application context that is passed to the callback function.</para>
/// <para>This parameter can be used for error checking.</para>
/// </param>
/// <param name="ppuiPrevHandler">
/// Returns the pointer to the previously set callback function that conforms to the INSTALLUI_HANDLER_RECORD specification, or
/// <c>NULL</c> if no callback is previously set.
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function completes successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_CALL_NOT_IMPLEMENTED</term>
/// <term>
/// This value indicates that an attempt is made to call this function from a custom action. This function cannot be called from a
/// custom action.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>This function cannot be called from Custom Actions.</para>
/// <para>
/// The external UI handler enabled by calling <c>MsiSetExternalUIRecord</c> receives messages in the format of a Record Object. The
/// external UI handler enabled by calling MsiSetExternalUI receives messages in the format of a string. An external UI is always
/// called before the Windows Installer internal UI. An enabled record-based external UI is called before any string-based external
/// UI. If the record-based external UI handler returns 0 (zero), the message is sent to any enabled string-based external UI
/// handler. If the external UI handler returns a non-zero value, the internal Windows Installer UI handler is suppressed and the
/// messages are considered handled.
/// </para>
/// <para>
/// This function stores the external user interfaces it has set. To replace the current external UI handler with a previous
/// handler, call the function and specify the INSTALLUI_HANDLER_RECORD as the puiHandler parameter and 0 (zero) as the
/// dwMessageFilter parameter.
/// </para>
/// <para>
/// The external user interface handler pointed to by the puiHandler parameter does not have full control over the external user
/// interface unless MsiSetInternalUI is called with the dwUILevel parameter set to INSTALLUILEVEL_NONE. If <c>MsiSetInternalUI</c>
/// is not called, the internal user interface level defaults to INSTALLUILEVEL_BASIC. As a result, any message not handled by the
/// external user interface handler is handled by Windows Installer. The initial "Preparing to install. . ." dialog always appears
/// even if the external user interface handler handles all messages. MsiSetExternalUI should only be called from an Bootstrapping
/// application. You cannot call <c>MsiSetExternalUI</c> from a custom action.
/// </para>
/// <para>To disable this external UI handler, call <c>MsiSetExternalUIRecord</c> with a <c>NULL</c> value for the puiHandler parameter.</para>
/// <para>
/// <c>Windows Installer 2.0 and Windows Installer 3.0:</c> Not supported. The <c>MsiSetExternalUIRecord</c> function is available
/// beginning with Windows Installer 3.1.
/// </para>
/// <para>For more information about using a record-based external handler, see Monitoring an Installation Using MsiSetExternalUIRecord.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisetexternaluirecord UINT MsiSetExternalUIRecord(
// INSTALLUI_HANDLER_RECORD puiHandler, DWORD dwMessageFilter, LPVOID pvContext, PINSTALLUI_HANDLER_RECORD ppuiPrevHandler );
[DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSetExternalUIRecord")]
public static extern Win32Error MsiSetExternalUIRecord([Optional] INSTALLUI_HANDLER_RECORD puiHandler, INSTALLLOGMODE dwMessageFilter,
[In, Optional] IntPtr pvContext, out INSTALLUI_HANDLER_RECORD ppuiPrevHandler);
/// <summary>
/// The <c>MsiSetInternalUI</c> function enables the installer's internal user interface. Then this user interface is used for all
/// subsequent calls to user-interface-generating installer functions in this process. For more information, see User Interface Levels.
/// </summary>
/// <param name="dwUILevel">
/// <para>Specifies the level of complexity of the user interface. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLUILEVEL_FULL</term>
/// <term>Authored user interface with wizards, progress, and errors.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_REDUCED</term>
/// <term>Authored user interface with wizard dialog boxes suppressed.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_BASIC</term>
/// <term>Simple progress and error handling.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_DEFAULT</term>
/// <term>The installer chooses an appropriate user interface level.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_NONE</term>
/// <term>Completely silent installation.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_ENDDIALOG</term>
/// <term>
/// If combined with any above value, the installer displays a modal dialog box at the end of a successful installation or if there
/// has been an error. No dialog box is displayed if the user cancels.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_PROGRESSONLY</term>
/// <term>
/// If combined with the INSTALLUILEVEL_BASIC value, the installer shows simple progress dialog boxes but does not display any modal
/// dialog boxes or error dialog boxes.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_NOCHANGE</term>
/// <term>No change in the UI level. However, if phWnd is not Null, the parent window can change.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_HIDECANCEL</term>
/// <term>
/// If combined with the INSTALLUILEVEL_BASIC value, the installer shows simple progress dialog boxes but does not display a Cancel
/// button on the dialog. This prevents users from canceling the install.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_SOURCERESONLY</term>
/// <term>
/// If this value is combined with the INSTALLUILEVEL_NONE value, the installer displays only the dialog boxes used for source
/// resolution. No other dialog boxes are shown. This value has no effect if the UI level is not INSTALLUILEVEL_NONE. It is used
/// with an external user interface designed to handle all of the UI except for source resolution. In this case, the installer
/// handles source resolution.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="phWnd">
/// Pointer to a window. This window becomes the owner of any user interface created. A pointer to the previous owner of the user
/// interface is returned. If this parameter is null, the owner of the user interface does not change.
/// </param>
/// <returns>
/// The previous user interface level is returned. If an invalid dwUILevel is passed, then <c>INSTALLUILEVEL_NOCHANGE</c> is returned.
/// </returns>
/// <remarks>
/// <para>
/// The <c>MsiSetInternalUI</c> function is useful when the installer must display a user interface. For example, if a feature is
/// installed, but the source is a compact disc that must be inserted, the installer prompts the user for the compact disc.
/// Depending on the nature of the installation, the application might also display progress indicators or query the user for information.
/// </para>
/// <para>
/// When Msi.dll is loaded, the user interface level is set to DEFAULT and the user interface owner is set to 0 (that is, the
/// initial user interface owner is the desktop).
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisetinternalui INSTALLUILEVEL MsiSetInternalUI( INSTALLUILEVEL
// dwUILevel, HWND *phWnd );
[DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSetInternalUI")]
public static extern INSTALLUILEVEL MsiSetInternalUI(INSTALLUILEVEL dwUILevel, ref HWND phWnd);
/// <summary>
/// The <c>MsiSetInternalUI</c> function enables the installer's internal user interface. Then this user interface is used for all
/// subsequent calls to user-interface-generating installer functions in this process. For more information, see User Interface Levels.
/// </summary>
/// <param name="dwUILevel">
/// <para>Specifies the level of complexity of the user interface. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLUILEVEL_FULL</term>
/// <term>Authored user interface with wizards, progress, and errors.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_REDUCED</term>
/// <term>Authored user interface with wizard dialog boxes suppressed.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_BASIC</term>
/// <term>Simple progress and error handling.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_DEFAULT</term>
/// <term>The installer chooses an appropriate user interface level.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_NONE</term>
/// <term>Completely silent installation.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_ENDDIALOG</term>
/// <term>
/// If combined with any above value, the installer displays a modal dialog box at the end of a successful installation or if there
/// has been an error. No dialog box is displayed if the user cancels.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_PROGRESSONLY</term>
/// <term>
/// If combined with the INSTALLUILEVEL_BASIC value, the installer shows simple progress dialog boxes but does not display any modal
/// dialog boxes or error dialog boxes.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_NOCHANGE</term>
/// <term>No change in the UI level. However, if phWnd is not Null, the parent window can change.</term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_HIDECANCEL</term>
/// <term>
/// If combined with the INSTALLUILEVEL_BASIC value, the installer shows simple progress dialog boxes but does not display a Cancel
/// button on the dialog. This prevents users from canceling the install.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLUILEVEL_SOURCERESONLY</term>
/// <term>
/// If this value is combined with the INSTALLUILEVEL_NONE value, the installer displays only the dialog boxes used for source
/// resolution. No other dialog boxes are shown. This value has no effect if the UI level is not INSTALLUILEVEL_NONE. It is used
/// with an external user interface designed to handle all of the UI except for source resolution. In this case, the installer
/// handles source resolution.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="phWnd">
/// Pointer to a window. This window becomes the owner of any user interface created. A pointer to the previous owner of the user
/// interface is returned. If this parameter is null, the owner of the user interface does not change.
/// </param>
/// <returns>
/// The previous user interface level is returned. If an invalid dwUILevel is passed, then <c>INSTALLUILEVEL_NOCHANGE</c> is returned.
/// </returns>
/// <remarks>
/// <para>
/// The <c>MsiSetInternalUI</c> function is useful when the installer must display a user interface. For example, if a feature is
/// installed, but the source is a compact disc that must be inserted, the installer prompts the user for the compact disc.
/// Depending on the nature of the installation, the application might also display progress indicators or query the user for information.
/// </para>
/// <para>
/// When Msi.dll is loaded, the user interface level is set to DEFAULT and the user interface owner is set to 0 (that is, the
/// initial user interface owner is the desktop).
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisetinternalui INSTALLUILEVEL MsiSetInternalUI( INSTALLUILEVEL
// dwUILevel, HWND *phWnd );
[DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSetInternalUI")]
public static extern INSTALLUILEVEL MsiSetInternalUI(INSTALLUILEVEL dwUILevel, [In, Optional] IntPtr phWnd);
/// <summary>
/// The <c>MsiSourceListAddMediaDisk</c> function adds or updates a disk of the media source of a registered product or patch. If
/// the disk specified already exists, it is updated with the new values. If the disk specified does not exist, a new disk entry is
/// created with the new values.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns ERROR_INVALID_PARAMETER. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// This parameter can be a string SID that specifies the user account that contains the product or patch. The SID is not validated
/// or resolved. An incorrect SID can return ERROR_UNKNOWN_PRODUCT or ERROR_UNKNOWN_PATCH.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>
/// NULL denotes the currently logged on user. When referencing the current user account, szUserSID can be NULL and dwContext can be
/// MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>Specifies enumeration for a particular user in the system. An example of user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string s-1-5-18 (system) cannot be used to enumerate products or patches installed as per-machine.
/// Setting the SID value to s-1-5-18 returns ERROR_INVALID_PARAMETER. When dwContext is set to MSIINSTALLCONTEXT_MACHINE only,
/// szUserSid must be <c>NULL</c>.
/// </para>
/// <para>
/// <c>Note</c> The special SID string s-1-1-0 (everyone) should not be used. Setting the SID value to s-1-1-0 fails and returns
/// ERROR_INVALID_PARAM .
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>The dwOptions value specifies the meaning of szProductCodeOrPatchCode.</para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code GUID.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code GUID.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwDiskId">This parameter provides the ID of the disk being added or updated.</param>
/// <param name="szVolumeLabel">
/// The szVolumeLabel provides the label of the disk being added or updated. An update overwrites the existing volume label in the
/// registry. To change the disk prompt only, get the existing volume label from the registry and provide it in this call along with
/// the new disk prompt. Passing a <c>NULL</c> or empty string for szVolumeLabel registers an empty string (0 bytes in length) as
/// the volume label.
/// </param>
/// <param name="szDiskPrompt">
/// On entry to <c>MsiSourceListAddMediaDisk</c>, szDiskPrompt provides the disk prompt of the disk being added or updated. An
/// update overwrites the registered disk prompt. To change the volume label only, get the existing disk prompt that is registered
/// and provide it when calling <c>MsiSourceListAddMediaDisk</c> along with the new volume label. Passing <c>NULL</c> or an empty
/// string registers an empty string (0 bytes in length) as the disk prompt.
/// </param>
/// <returns>
/// <para>The <c>MsiSourceListAddMediaDisk</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The user does not have the ability to read the specified media source or the specified product or patch. This does not indicate
/// whether a media source, product or patch was found.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>The Windows Installer service could not be accessed.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The value was successfully reordered.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Administrators can modify the installation of a product or patch instance that exists under the machine context or under their
/// own per-user context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under
/// any user's per-user-managed context. Administrators cannot modify another user's installation of a product or patch instance
/// that exists under that other user's per-user-unmanaged context.
/// </para>
/// <para>
/// Non-administrators cannot modify the installation of a product or patch instance that exists under another user's per-user
/// context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under their own
/// per-user-unmanaged context. They can modify the installation of a product or patch instance under the machine context or their
/// own per-user-managed context only if they are enabled to browse for a product or patch source. Users can be enabled to browse
/// for sources by setting policy. For more information, see DisableBrowse, AllowLockdownBrowse, AllowLockDownMedia and
/// AlwaysInstallElevated policies.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistaddmediadiska UINT MsiSourceListAddMediaDiskA( LPCSTR
// szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwDiskId, LPCSTR szVolumeLabel,
// LPCSTR szDiskPrompt );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListAddMediaDiskA")]
public static extern Win32Error MsiSourceListAddMediaDisk([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, MSICODE dwOptions, uint dwDiskId,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szVolumeLabel, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szDiskPrompt);
/// <summary>
/// <para>
/// The <c>MsiSourceListAddSource</c> function adds to the list of valid network sources that contain the specified type of sources
/// for a product or patch in a specified user context.
/// </para>
/// <para>The number of sources in the SOURCELIST property is unlimited.</para>
/// </summary>
/// <param name="szProduct">The ProductCode of the product to modify.</param>
/// <param name="szUserName">
/// <para>
/// The user name for a per-user installation. On Windows 2000 or Windows XP, the user name should always be in the format of
/// DOMAIN\USERNAME (or MACHINENAME\USERNAME for a local user).
/// </para>
/// <para>An empty string or <c>NULL</c> for a per-machine installation.</para>
/// </param>
/// <param name="dwReserved">Reserved for future use. This value must be set to 0.</param>
/// <param name="szSource">Pointer to the string specifying the source.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The user does not have the ability to add a source.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_USERNAME</term>
/// <term>Could not resolve the user name.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>The function did not succeed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>Could not access installer service.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The source was added.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The specified product is unknown.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// An administrator can modify per-machine installations, their own per-user non-managed installations, and the per-user managed
/// installations for any user. A non-administrator can only modify per-machine installations and their own (managed or
/// non-managed)per-user installations. Users can be enabled to browse for sources by setting policy. For more information, see the
/// DisableBrowse, AllowLockdownBrowse, and AlwaysInstallElevated policies.
/// </para>
/// <para>
/// Note that this function merely adds the new source to the list of valid sources. If another source was used to install the
/// product, the new source is not used until the current source is unavailable.
/// </para>
/// <para>It is the responsibility of the caller to ensure that the provided source is a valid source image for the product.</para>
/// <para>
/// If the user name is an empty string or <c>NULL</c>, the function operates on the per-machine installation of the product. In
/// this case, if the product is installed only in the per-user state, the function returns ERROR_UNKNOWN_PRODUCT.
/// </para>
/// <para>
/// If the user name is not an empty string or <c>NULL</c>, it specifies the name of the user whose product installation is
/// modified. If the user name is the current user name, the function first attempts to modify a non-managed installation of the
/// product. If no non-managed installation of the product can be found, the function then tries to modify a managed per-user
/// installation of the product. If no managed or unmanaged per-user installations of the product can be found, the function returns
/// ERROR_UNKNOWN_PRODUCT, even if the product is installed per-machine.
/// </para>
/// <para>
/// This function can not modify a non-managed installation for any user besides the current user. If the user name is not an empty
/// string or <c>NULL</c>, but is not the current user, the function only checks for a managed per-user installation of the product
/// for the specified user. If the product is not installed as managed per-user for the specified user, the function returns
/// ERROR_UNKNOWN_PRODUCT, even if the product is installed per-machine.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistaddsourcea UINT MsiSourceListAddSourceA( LPCSTR
// szProduct, LPCSTR szUserName, DWORD dwReserved, LPCSTR szSource );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListAddSourceA")]
public static extern Win32Error MsiSourceListAddSource([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserName, [Optional] uint dwReserved, [MarshalAs(UnmanagedType.LPTStr)] string szSource);
/// <summary>
/// The <c>MsiSourceListAddSourceEx</c> function adds or reorders the set of sources of a patch or product in a specified context.
/// It can also create a source list for a patch that does not exist in the specified context.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns <c>ERROR_INVALID_PARAMETER</c>. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// This parameter can be a string SID that specifies the user account that contains the product or patch. The SID is not validated
/// or resolved. An incorrect SID can return <c>ERROR_UNKNOWN_PRODUCT</c> or <c>ERROR_UNKNOWN_PATCH</c>. When referencing a machine
/// context, szUserSID must be <c>NULL</c> and dwContext must be <c>MSIINSTALLCONTEXT_MACHINE</c>.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>
/// NULL denotes the currently logged on user. When referencing the current user account, szUserSID can be NULL and dwContext can be
/// MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>Specifies enumeration for a particular user in the system. An example of a user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string s-1-5-18 (system) cannot be used to enumerate products or patches installed as per-machine.
/// Setting the SID value to "S-1-5-18" returns <c>ERROR_INVALID_PARAMETER</c>.
/// </para>
/// <para>
/// <c>Note</c> The special SID string s-1-1-0 (everyone) should not be used. Setting the SID value to "S-1-1-0" fails and returns <c>ERROR_INVALID_PARAM</c>.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>
/// The dwOptions value determines the interpretation of the szProductCodeOrPatchCode value and the type of sources to clear. This
/// parameter must be a combination of one of the following <c>MSISOURCETYPE_</c> constants and one of the following <c>MSICODE_</c> constants.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSISOURCETYPE_NETWORK</term>
/// <term>The source is a network type.</term>
/// </item>
/// <item>
/// <term>MSISOURCETYPE_URL</term>
/// <term>The source is a URL type.</term>
/// </item>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szSource">
/// Source to add or move. This parameter is expected to contain only the path without the filename. The filename is already
/// registered as "PackageName" and can be manipulated through MsiSourceListSetInfo. This argument is required.
/// </param>
/// <param name="dwIndex">
/// <para>
/// This parameter provides the new index for the source. All sources are indexed in the source list from 1 to N, where N is the
/// count of sources in the list. Every source in the list has a unique index.
/// </para>
/// <para>
/// If <c>MsiSourceListAddSourceEx</c> is called with a new source and dwIndex set to 0 (zero), the new source is appended to the
/// existing list. If dwIndex is set to 0 and the source already exists in the list, no update is done on the list.
/// </para>
/// <para>
/// If <c>MsiSourceListAddSourceEx</c> is called with a new source and dwIndex set to a non-zero value less than count (N), the new
/// source is placed at the specified index and the other sources are re-indexed. If the source already exists, it is moved to the
/// specified index and the other sources are re-indexed.
/// </para>
/// <para>
/// If <c>MsiSourceListAddSourceEx</c> is called with a new source and dwIndex set to a non-zero value greater than the count of
/// sources (N), the new source is appended to the existing list. If the source already exists, it is moved to the end of the list
/// and the other sources are re-indexed.
/// </para>
/// </param>
/// <returns>
/// <para>The <c>MsiSourceListAddSourceEx</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The user does not have the ability to add or move a source. Does not indicate whether the product or patch was found.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>Could not access the Windows Installer service.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The source was inserted or updated.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The specified product is unknown.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The specified patch is unknown.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Administrators can modify the installation of a product or patch instance that exists under the machine context or under their
/// own per-user context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under
/// any user's per-user-managed context. Administrators cannot modify another user's installation of a product or patch instance
/// that exists under that other user's per-user-unmanaged context.
/// </para>
/// <para>
/// Non-administrators cannot modify the installation of a product or patch instance that exists under another user's per-user
/// context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under their own
/// per-user-unmanaged context. They can modify the installation of a product or patch instance under the machine context or their
/// own per-user-managed context only if they are enabled to browse for a product or patch source. Users can be enabled to browse
/// for sources by setting policy. For more information, see the DisableBrowse, AllowLockdownBrowse, and AlwaysInstallElevated policies.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistaddsourceexa UINT MsiSourceListAddSourceExA( LPCSTR
// szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCSTR szSource, DWORD dwIndex );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListAddSourceExA")]
public static extern Win32Error MsiSourceListAddSourceEx([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, uint dwOptions,
[MarshalAs(UnmanagedType.LPTStr)] string szSource, uint dwIndex);
/// <summary>
/// The <c>MsiSourceListClearAll</c> function removes all network sources from the source list of a patch or product in a specified
/// context. For more information, see Source Resiliency.
/// </summary>
/// <param name="szProduct">The ProductCode of the product to modify.</param>
/// <param name="szUserName">
/// <para>
/// The user name for a per-user installation. The user name should always be in the format of DOMAIN\USERNAME (or
/// MACHINENAME\USERNAME for a local user).
/// </para>
/// <para>An empty string or <c>NULL</c> for a per-machine installation.</para>
/// </param>
/// <param name="dwReserved">Reserved for future use. This value must be set to 0.</param>
/// <returns>
/// <para>The <c>MsiSourceListClearAll</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The user does not have the ability to clear the source list for this product.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_USERNAME</term>
/// <term>Could not resolve the user name.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>The function did not succeed.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>Could not access installer service.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The specified product is unknown.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// An administrator can modify per-machine installations, their own per-user non-managed installations, and the per-user managed
/// installations for any user. A non-administrator can only modify per-machine installations and their own (managed or
/// non-managed)per-user installations. Users can be enabled to browse for sources by setting policy. For more information, see the
/// DisableBrowse, AllowLockdownBrowse, and AlwaysInstallElevated policies.
/// </para>
/// <para>
/// If a network source is the current source for the product, this function forces the installer to search the source list for a
/// valid source the next time a source is needed. If the current source is media or a URL source, it is still valid after this call
/// and the source list is not searched unless MsiSourceListForceResolution is also called.
/// </para>
/// <para>
/// If the user name is an empty string or <c>NULL</c>, the function operates on the per-machine installation of the product. In
/// this case, if the product is installed as per-user only, the function returns ERROR_UNKNOWN_PRODUCT.
/// </para>
/// <para>
/// If the user name is not an empty string or <c>NULL</c>, it specifies the name of the user whose product installation is
/// modified. If the user name is the current user name, the function first attempts to modify a non-managed installation of the
/// product. If no non-managed installation of the product can be found, the function then tries to modify a managed per-user
/// installation of the product. If no managed or unmanaged per-user installations of the product can be found, the function returns
/// ERROR_UNKNOWN_PRODUCT, even if the product is installed per-machine.
/// </para>
/// <para>
/// This function cannot modify a non-managed installation for any user besides the current user. If the user name is not an empty
/// string or <c>NULL</c>, but is not the current user, the function only checks for a managed per-user installation of the product
/// for the specified user. If the product is not installed as managed per-user for the specified user, the function returns
/// ERROR_UNKNOWN_PRODUCT, even if the product is installed per-machine.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistclearalla UINT MsiSourceListClearAllA( LPCSTR
// szProduct, LPCSTR szUserName, DWORD dwReserved );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListClearAllA")]
public static extern Win32Error MsiSourceListClearAll([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserName, uint dwReserved = 0);
/// <summary>
/// The <c>MsiSourceListClearAllEx</c> function removes all the existing sources of a given source type for the specified product or
/// patch instance. The patch registration is also removed if the sole source of the patch gets removed and if the patch is not
/// installed as a new patch by any client in the same context. Specifying that <c>MsiSourceListClearAllEx</c> remove the current
/// source for this product or patch forces the installer to search the source list for a source the next time a source is required.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns ERROR_INVALID_PARAMETER. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// This parameter can be a string SID that specifies the user account that contains the product or patch. The SID is not validated
/// or resolved. An incorrect SID can return ERROR_UNKNOWN_PRODUCT or ERROR_UNKNOWN_PATCH. When referencing a machine context,
/// szUserSID must be <c>NULL</c> and dwContext must be MSIINSTALLCONTEXT_MACHINE. Using the machine SID ("S-1-5-18") returns
/// ERROR_INVALID PARAMETER. When referencing the current user account, szUserSID can be <c>NULL</c> and dwContext can be
/// MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>
/// The dwOptions value determines the interpretation of the szProductCodeOrPatchCode value and the type of sources to clear. This
/// parameter must be a combination of one of the following MSISOURCETYPE_* constants and one of the following MSICODE_* constants.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSISOURCETYPE_MEDIA</term>
/// <term>The source is media.</term>
/// </item>
/// <item>
/// <term>MSISOURCETYPE_NETWORK</term>
/// <term>The source is a network type.</term>
/// </item>
/// <item>
/// <term>MSISOURCETYPE_URL</term>
/// <term>The source is a URL type.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code.</term>
/// </item>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The user does not have the ability to add or move a source. Does not indicate whether the product or patch was found.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>Cannot access the Windows Installer service.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>All sources of the specified type were removed.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The specified product is unknown.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The specified patch is unknown.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Administrators can modify the installation of a product or patch instance that exists under the machine context or under their
/// own per-user context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under
/// any user's per-user-managed context. Administrators cannot modify another user's installation of a product or patch instance
/// that exists under that other user's per-user-unmanaged context.
/// </para>
/// <para>
/// Non-administrators cannot modify the installation of a product or patch instance that exists under another user's per-user
/// context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under their own
/// per-user-unmanaged context. They can modify the installation of a product or patch instance under the machine context or their
/// own per-user-managed context only if they are enabled to browse for a product or patch source. Users can be enabled to browse
/// for sources by setting policy, for more information, see DisableBrowse, AllowLockdownBrowse, and AlwaysInstallElevated policies.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistclearallexa UINT MsiSourceListClearAllExA( LPCSTR
// szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListClearAllExA")]
public static extern Win32Error MsiSourceListClearAllEx([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, uint dwOptions);
/// <summary>
/// The <c>MsiSourceListClearMediaDisk</c> function provides the ability to remove an existing registered disk under the media
/// source for a product or patch in a specific context.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns ERROR_INVALID_PARAMETER. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// This parameter can be a string SID that specifies the user account that contains the product or patch. The SID is not validated
/// or resolved. An incorrect SID can return ERROR_UNKNOWN_PRODUCT or ERROR_UNKNOWN_PATCH.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>
/// NULL denotes the currently logged on user. When referencing the current user account, szUserSID can be NULL and dwContext can be
/// MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>Specifies enumeration for a particular user in the system. An example of user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string s-1-5-18 (system) cannot be used to enumerate products or patches installed as per-machine.
/// Setting the SID value to s-1-5-18 returns ERROR_INVALID_PARAMETER. When dwContext is set to MSIINSTALLCONTEXT_MACHINE only,
/// szUserSid must be <c>NULL</c>.
/// </para>
/// <para>
/// <c>Note</c> The special SID string s-1-1-0 (everyone) should not be used. Setting the SID value to s-1-1-0 fails and returns ERROR_INVALID_PARAM.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>The dwOptions value specifies the meaning of szProductCodeOrPatchCode.</para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code GUID.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code GUID.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwDiskId">This parameter provides the ID of the disk being removed.</param>
/// <returns>
/// <para>The <c>MsiSourceListClearMediaDisk</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The user does not have the ability to read the specified media source or the specified product or patch. This does not indicate
/// whether a media source, product or patch was found.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>The Windows Installer service could not be accessed.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The value was successfully removed or not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Administrators can modify the installation of a product or patch instance that exists under the machine context or under their
/// own per-user context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under
/// any user's per-user-managed context. Administrators cannot modify another user's installation of a product or patch instance
/// that exists under that other user's per-user-unmanaged context.
/// </para>
/// <para>
/// Non-administrators cannot modify the installation of a product or patch instance that exists under another user's per-user
/// context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under their own
/// per-user-unmanaged context. They can modify the installation of a product or patch instance under the machine context or their
/// own per-user-managed context only if they are enabled to browse for a product or patch source. Users can be enabled to browse
/// for sources by setting policy. For more information, see the DisableBrowse, AllowLockdownBrowse, and AlwaysInstallElevated policies.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistclearmediadiska UINT MsiSourceListClearMediaDiskA(
// LPCSTR szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwDiskId );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListClearMediaDiskA")]
public static extern Win32Error MsiSourceListClearMediaDisk([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, MSICODE dwOptions, uint dwDiskId);
/// <summary>
/// The <c>MsiSourceListClearSource</c> function removes an existing source for a product or patch in a specified context. The patch
/// registration is also removed if the sole source of the patch gets removed and if the patch is not installed by any client in the
/// same context. Specifying that <c>MsiSourceListClearSource</c> remove the current source for this product or patch forces the
/// installer to search the source list for a source the next time a source is required.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns <c>ERROR_INVALID_PARAMETER</c>. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// This parameter can be a string SID that specifies the user account that contains the product or patch. The SID is not validated
/// or resolved. An incorrect SID can return <c>ERROR_UNKNOWN_PRODUCT</c> or <c>ERROR_UNKNOWN_PATCH</c>. When referencing a machine
/// context, szUserSID must be <c>NULL</c> and dwContext must be <c>MSIINSTALLCONTEXT_MACHINE</c>.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>
/// NULL denotes the currently logged on user. When referencing the current user account, szUserSID can be NULL and dwContext can be
/// MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>Specifies enumeration for a particular user in the system. An example of a user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string "S-1-5-18" (system) cannot be used to enumerate products or patches installed as per-machine.
/// Setting the SID value to "S-1-5-18" returns <c>ERROR_INVALID_PARAMETER</c>.
/// </para>
/// <para>
/// <c>Note</c> The special SID string "S-1-1-0" (everyone) should not be used. Setting the SID value to "S-1-1-0" fails and returns <c>ERROR_INVALID_PARAM</c>.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>
/// The dwOptions value determines the interpretation of the szProductCodeOrPatchCode value and the type of sources to clear. This
/// parameter must be a combination of one of the following <c>MSISOURCETYPE_</c> constants and one of the following <c>MSICODE_</c> constants.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSISOURCETYPE_NETWORK</term>
/// <term>The source is a network type.</term>
/// </item>
/// <item>
/// <term>MSISOURCETYPE_URL</term>
/// <term>The source is a URL type.</term>
/// </item>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szSource">
/// Source to remove. This parameter is expected to contain only the path without the filename. The filename is already registered
/// as "PackageName" and can be manipulated through MsiSourceListSetInfo. This argument is required.
/// </param>
/// <returns>
/// <para>The <c>MsiSourceListClearSource</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The user does not have the ability to remove a source. Does not indicate whether the product or patch was found.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>Could not access the Windows Installer service</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The source was removed or not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The specified patch is unknown.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The specified product is unknown.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Administrators can modify the installation of a product or patch instance that exists under the machine context or under their
/// own per-user context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under
/// any user's per-user-managed context. Administrators cannot modify another user's installation of a product or patch instance
/// that exists under that other user's per-user-unmanaged context.
/// </para>
/// <para>
/// Non-administrators cannot modify the installation of a product or patch instance that exists under another user's per-user
/// context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under their own
/// per-user-unmanaged context. They can modify the installation of a product or patch instance under the machine context or their
/// own per-user-managed context only if they are enabled to browse for a product or patch source. Users can be enabled to browse
/// for sources by setting policy. For more information, see the DisableBrowse, AllowLockdownBrowse, and AlwaysInstallElevated policies.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistclearsourcea UINT MsiSourceListClearSourceA( LPCSTR
// szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCSTR szSource );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListClearSourceA")]
public static extern Win32Error MsiSourceListClearSource([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, uint dwOptions,
[MarshalAs(UnmanagedType.LPTStr)] string szSource);
/// <summary>
/// The <c>MsiSourceListEnumMediaDisks</c> function enumerates the list of disks registered for the media source for a patch or product.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns ERROR_INVALID_PARAMETER. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// A string SID that specifies the user account that contains the product or patch. The SID is not validated or resolved. An
/// incorrect SID can return ERROR_UNKNOWN_PRODUCT or ERROR_UNKNOWN_PATCH. When referencing a machine context, szUserSID must be
/// <c>NULL</c> and dwContext must be MSIINSTALLCONTEXT_MACHINE.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>
/// A NULL denotes the currently logged on user. When referencing the current user account, szUserSID can be NULL and dwContext can
/// be MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>An enumeration for a specific user in the system. An example of a user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// <item>
/// <term>s-1-1-0</term>
/// <term>The special SID string s-1-1-0 (everyone) specifies enumeration across all users in the system.</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string s-1-5-18 (system) cannot be used to enumerate products or patches installed as per-machine.
/// Setting the SID value to s-1-5-18 returns ERROR_INVALID_PARAMETER.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>The dwOptions value that specifies the meaning of szProductCodeOrPatchCode.</para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code GUID.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code GUID.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwIndex">
/// The index of the source to retrieve. This parameter must be 0 (zero) for the first call to the
/// <c>MsiSourceListEnumMediaDisks</c> function, and then incremented for subsequent calls until the function returns ERROR_NO_MORE_ITEMS.
/// </param>
/// <param name="pdwDiskId">
/// On entry to <c>MsiSourceListEnumMediaDisks</c> this parameter provides a pointer to a <c>DWORD</c> to receive the ID of the disk
/// that is being enumerated. This parameter is optional.
/// </param>
/// <param name="szVolumeLabel">
/// <para>
/// An output buffer that receives the volume label of the disk that is being enumerated. This buffer should be large enough to
/// contain the information. If the buffer is too small, the function returns ERROR_MORE_DATA and sets *pcchVolumeLabel to the
/// number of <c>TCHAR</c> in the value, not including the terminating NULL character.
/// </para>
/// <para>
/// If szVolumeLabel and pcchVolumeLabel are both set to <c>NULL</c>, the function returns ERROR_SUCCESS if the value exists,
/// without retrieving the value.
/// </para>
/// </param>
/// <param name="pcchVolumeLabel">
/// <para>
/// A pointer to a variable that specifies the number of <c>TCHAR</c> in the szVolumeLabel buffer. When the function returns, this
/// parameter is the number of <c>TCHAR</c> in the received value, not including the terminating null character.
/// </para>
/// <para>This parameter can be set to <c>NULL</c> only if szVolumeLabel is also <c>NULL</c>, otherwise the function returns ERROR_INVALID_PARAMETER.</para>
/// </param>
/// <param name="szDiskPrompt">
/// <para>
/// An output buffer that receives the disk prompt of the disk that is being enumerated. This buffer should be large enough to
/// contain the information. If the buffer is too small, the function returns ERROR_MORE_DATA and sets *pcchDiskPrompt to the number
/// of <c>TCHAR</c> in the value, not including the terminating NULL character.
/// </para>
/// <para>
/// If the szDiskPrompt is set to <c>NULL</c> and pcchDiskPrompt is set to a valid pointer, the function returns ERROR_SUCCESS and
/// sets *pcchDiskPrompt to the number of <c>TCHAR</c> in the value, not including the terminating NULL character. The function can
/// then be called again to retrieve the value, with szDiskPrompt buffer large enough to contain *pcchDiskPrompt + 1 characters.
/// </para>
/// <para>
/// If szDiskPrompt and pcchDiskPrompt are both set to <c>NULL</c>, the function returns ERROR_SUCCESS if the value exists, without
/// retrieving the value.
/// </para>
/// </param>
/// <param name="pcchDiskPrompt">
/// <para>
/// A pointer to a variable that specifies the number of <c>TCHAR</c> in the szDiskPrompt buffer. When the function returns, this
/// parameter is set to the size of the requested value whether or not the function copies the value into the specified buffer. The
/// size is returned as the number of <c>TCHAR</c> in the requested value, not including the terminating null character.
/// </para>
/// <para>This parameter can be set to <c>NULL</c> only if szDiskPrompt is also <c>NULL</c>, otherwise the function returns ERROR_INVALID_PARAMETER.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiSourceListEnumMediaDisks</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The user does not have the ability to read the specified media source or the specified product or patch. This does not indicate
/// whether a media source, product, or patch is found.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_MORE_ITEMS</term>
/// <term>There are no more disks registered for this product or patch.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The value is enumerated successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch is not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product is not found.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The buffer that is provided is too small to contain the requested information.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// When making multiple calls to <c>MsiSourceListEnumMediaDisks</c> to enumerate all the sources for a single product instance,
/// each call must be made from the same thread.
/// </para>
/// <para>
/// An administrator can enumerate per-user unmanaged and managed installations for themselves, per-machine installations, and
/// per-user managed installations for any user. An administrator cannot enumerate per-user unmanaged installations for other users.
/// Non-administrators can only enumerate their own per-user unmanaged and managed installations and per-machine installations.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistenummediadisksa UINT MsiSourceListEnumMediaDisksA(
// LPCSTR szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwIndex, LPDWORD
// pdwDiskId, LPSTR szVolumeLabel, LPDWORD pcchVolumeLabel, LPSTR szDiskPrompt, LPDWORD pcchDiskPrompt );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListEnumMediaDisksA")]
public static extern Win32Error MsiSourceListEnumMediaDisks([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, MSICODE dwOptions, uint dwIndex,
out uint pdwDiskId, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szVolumeLabel, ref uint pcchVolumeLabel,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szDiskPrompt, ref uint pcchDiskPrompt);
/// <summary>
/// The <c>MsiSourceListEnumMediaDisks</c> function enumerates the list of disks registered for the media source for a patch or product.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns ERROR_INVALID_PARAMETER. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// A string SID that specifies the user account that contains the product or patch. The SID is not validated or resolved. An
/// incorrect SID can return ERROR_UNKNOWN_PRODUCT or ERROR_UNKNOWN_PATCH. When referencing a machine context, szUserSID must be
/// <c>NULL</c> and dwContext must be MSIINSTALLCONTEXT_MACHINE.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>
/// A NULL denotes the currently logged on user. When referencing the current user account, szUserSID can be NULL and dwContext can
/// be MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>An enumeration for a specific user in the system. An example of a user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// <item>
/// <term>s-1-1-0</term>
/// <term>The special SID string s-1-1-0 (everyone) specifies enumeration across all users in the system.</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string s-1-5-18 (system) cannot be used to enumerate products or patches installed as per-machine.
/// Setting the SID value to s-1-5-18 returns ERROR_INVALID_PARAMETER.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>The dwOptions value that specifies the meaning of szProductCodeOrPatchCode.</para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code GUID.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code GUID.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwIndex">
/// The index of the source to retrieve. This parameter must be 0 (zero) for the first call to the
/// <c>MsiSourceListEnumMediaDisks</c> function, and then incremented for subsequent calls until the function returns ERROR_NO_MORE_ITEMS.
/// </param>
/// <param name="pdwDiskId">
/// On entry to <c>MsiSourceListEnumMediaDisks</c> this parameter provides a pointer to a <c>DWORD</c> to receive the ID of the disk
/// that is being enumerated. This parameter is optional.
/// </param>
/// <param name="szVolumeLabel">
/// <para>
/// An output buffer that receives the volume label of the disk that is being enumerated. This buffer should be large enough to
/// contain the information. If the buffer is too small, the function returns ERROR_MORE_DATA and sets *pcchVolumeLabel to the
/// number of <c>TCHAR</c> in the value, not including the terminating NULL character.
/// </para>
/// <para>
/// If szVolumeLabel and pcchVolumeLabel are both set to <c>NULL</c>, the function returns ERROR_SUCCESS if the value exists,
/// without retrieving the value.
/// </para>
/// </param>
/// <param name="pcchVolumeLabel">
/// <para>
/// A pointer to a variable that specifies the number of <c>TCHAR</c> in the szVolumeLabel buffer. When the function returns, this
/// parameter is the number of <c>TCHAR</c> in the received value, not including the terminating null character.
/// </para>
/// <para>This parameter can be set to <c>NULL</c> only if szVolumeLabel is also <c>NULL</c>, otherwise the function returns ERROR_INVALID_PARAMETER.</para>
/// </param>
/// <param name="szDiskPrompt">
/// <para>
/// An output buffer that receives the disk prompt of the disk that is being enumerated. This buffer should be large enough to
/// contain the information. If the buffer is too small, the function returns ERROR_MORE_DATA and sets *pcchDiskPrompt to the number
/// of <c>TCHAR</c> in the value, not including the terminating NULL character.
/// </para>
/// <para>
/// If the szDiskPrompt is set to <c>NULL</c> and pcchDiskPrompt is set to a valid pointer, the function returns ERROR_SUCCESS and
/// sets *pcchDiskPrompt to the number of <c>TCHAR</c> in the value, not including the terminating NULL character. The function can
/// then be called again to retrieve the value, with szDiskPrompt buffer large enough to contain *pcchDiskPrompt + 1 characters.
/// </para>
/// <para>
/// If szDiskPrompt and pcchDiskPrompt are both set to <c>NULL</c>, the function returns ERROR_SUCCESS if the value exists, without
/// retrieving the value.
/// </para>
/// </param>
/// <param name="pcchDiskPrompt">
/// <para>
/// A pointer to a variable that specifies the number of <c>TCHAR</c> in the szDiskPrompt buffer. When the function returns, this
/// parameter is set to the size of the requested value whether or not the function copies the value into the specified buffer. The
/// size is returned as the number of <c>TCHAR</c> in the requested value, not including the terminating null character.
/// </para>
/// <para>This parameter can be set to <c>NULL</c> only if szDiskPrompt is also <c>NULL</c>, otherwise the function returns ERROR_INVALID_PARAMETER.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiSourceListEnumMediaDisks</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The user does not have the ability to read the specified media source or the specified product or patch. This does not indicate
/// whether a media source, product, or patch is found.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_MORE_ITEMS</term>
/// <term>There are no more disks registered for this product or patch.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The value is enumerated successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch is not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product is not found.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The buffer that is provided is too small to contain the requested information.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// When making multiple calls to <c>MsiSourceListEnumMediaDisks</c> to enumerate all the sources for a single product instance,
/// each call must be made from the same thread.
/// </para>
/// <para>
/// An administrator can enumerate per-user unmanaged and managed installations for themselves, per-machine installations, and
/// per-user managed installations for any user. An administrator cannot enumerate per-user unmanaged installations for other users.
/// Non-administrators can only enumerate their own per-user unmanaged and managed installations and per-machine installations.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistenummediadisksa UINT MsiSourceListEnumMediaDisksA(
// LPCSTR szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwIndex, LPDWORD
// pdwDiskId, LPSTR szVolumeLabel, LPDWORD pcchVolumeLabel, LPSTR szDiskPrompt, LPDWORD pcchDiskPrompt );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListEnumMediaDisksA")]
public static extern Win32Error MsiSourceListEnumMediaDisks([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, MSICODE dwOptions, uint dwIndex,
out uint pdwDiskId, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szVolumeLabel, [In, Optional] IntPtr pcchVolumeLabel,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szDiskPrompt, [In, Optional] IntPtr pcchDiskPrompt);
/// <summary>The <c>MsiSourceListEnumSources</c> function enumerates the sources in the source list of a specified patch or product.</summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns ERROR_INVALID_PARAMETER. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// A string SID that specifies the user account that contains the product or patch. The SID is not validated or resolved. An
/// incorrect SID can return ERROR_UNKNOWN_PRODUCT or ERROR_UNKNOWN_PATCH. When referencing a machine context, szUserSID must be
/// <c>NULL</c> and dwContext must be MSIINSTALLCONTEXT_MACHINE.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>
/// A NULL indicates the current user who is logged on. When referencing the current user account, szUserSID can be NULL and
/// dwContext can be MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>An enumeration for a specific user in the system. An example of a user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// <item>
/// <term>s-1-1-0</term>
/// <term>The special SID string s-1-1-0 (everyone) specifies enumeration across all users in the system.</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string s-1-5-18 (system) cannot be used to enumerate products or patches installed as per-machine.
/// Setting the SID value to s-1-5-18 returns ERROR_INVALID_PARAMETER.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>The context of the product or patch instance. This parameter can contain one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>
/// The dwOptions value determines the interpretation of the szProductCodeOrPatchCode value and the type of sources to clear. This
/// parameter must be a combination of one of the following MSISOURCETYPE_* constants and one of the following MSICODE_* constants.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSISOURCETYPE_NETWORK</term>
/// <term>The source is a network type.</term>
/// </item>
/// <item>
/// <term>MSISOURCETYPE_URL</term>
/// <term>The source is a URL type.</term>
/// </item>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwIndex">
/// The index of the source to retrieve. This parameter must be 0 (zero) for the first call to the <c>MsiSourceListEnumSources</c>
/// function, and then incremented for subsequent calls until the function returns ERROR_NO_MORE_ITEMS. The index should be
/// incremented only if the previous call returned ERROR_SUCCESS.
/// </param>
/// <param name="szSource">
/// <para>
/// A pointer to a buffer that receives the path to the source that is being enumerated. This buffer should be large enough to
/// contain the received value. If the buffer is too small, the function returns ERROR_MORE_DATA and sets *pcchSource to the number
/// of <c>TCHAR</c> in the value, not including the terminating NULL character.
/// </para>
/// <para>
/// If szSource is set to <c>NULL</c> and pcchSource is set to a valid pointer, the function returns ERROR_SUCCESS and sets
/// *pcchSource to the number of <c>TCHAR</c> in the value, not including the terminating NULL character. The function can then be
/// called again to retrieve the value, with szSource buffer large enough to contain *pcchSource + 1 characters.
/// </para>
/// <para>
/// If szSource and pcchSource are both set to <c>NULL</c>, the function returns ERROR_SUCCESS if the value exists, without
/// retrieving the value.
/// </para>
/// </param>
/// <param name="pcchSource">
/// <para>
/// A pointer to a variable that specifies the number of <c>TCHAR</c> in the szSource buffer. When the function returns, this
/// parameter is set to the size of the requested value whether or not the function copies the value into the specified buffer. The
/// size is returned as the number of <c>TCHAR</c> in the requested value, not including the terminating null character.
/// </para>
/// <para>This parameter can be set to <c>NULL</c> only if szSource is also <c>NULL</c>, otherwise the function returns ERROR_INVALID_PARAMETER.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiSourceListEnumSources</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The user does not have the ability to read the specified source list. This does not indicate whether a product or patch is found.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The provided buffer is not sufficient to contain the requested data.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_MORE_ITEMS</term>
/// <term>There are no more sources in the specified list to enumerate.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>A source is enumerated successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch specified is not installed on the computer in the specified contexts.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product specified is not installed on the computer in the specified contexts.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// When making multiple calls to <c>MsiSourceListEnumSources</c> to enumerate all sources for a single product instance, each call
/// must be made from the same thread.
/// </para>
/// <para>
/// An administrator can enumerate per-user unmanaged and managed installations for themselves, per-machine installations, and
/// per-user managed installations for any user. An administrator cannot enumerate per-user unmanaged installations for other users.
/// Non-administrators can only enumerate their own per-user unmanaged and managed installations and per-machine installations.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistenumsourcesa UINT MsiSourceListEnumSourcesA( LPCSTR
// szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwIndex, LPSTR szSource, LPDWORD
// pcchSource );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListEnumSourcesA")]
public static extern Win32Error MsiSourceListEnumSources([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, uint dwOptions, uint dwIndex,
[Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szSource, ref uint pcchSource);
/// <summary>
/// The <c>MsiSourceListForceResolution</c> function forces the installer to search the source list for a valid product source the
/// next time a source is required. For example, when the installer performs an installation or reinstallation, or when it requires
/// the path for a component that is set to run from source.
/// </summary>
/// <param name="szProduct">The ProductCode of the product to modify.</param>
/// <param name="szUserName">
/// <para>
/// The user name for a per-user installation. The user name should always be in the format of DOMAIN\USERNAME (or
/// MACHINENAME\USERNAME for a local user).
/// </para>
/// <para>An empty string or <c>NULL</c> for a per-machine installation.</para>
/// </param>
/// <param name="dwReserved">Reserved for future use. This value must be set to 0.</param>
/// <returns>
/// <para>The <c>MsiSourceListForceResolution</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The caller does not have sufficient access to force resolution for the product.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_USER_NAME</term>
/// <term>The specified user is not a valid user.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>The function could not complete.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>The installation service could not be accessed.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The specified product is unknown.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// An administrator can modify per-machine installations, their own per-user non-managed installations, and the per-user managed
/// installations for any user. A non-administrator can only modify per-machine installations and their own (managed or non-managed)
/// per-user installations.
/// </para>
/// <para>
/// If the user name is an empty string or <c>NULL</c>, the function operates on the per-machine installation of the product. In
/// this case, if the product is installed as per-user only, the function returns ERROR_UNKNOWN_PRODUCT.
/// </para>
/// <para>
/// If the user name is not an empty string or <c>NULL</c>, it specifies the name of the user whose product installation is
/// modified. If the user name is the current user name, the function first attempts to modify a non-managed installation of the
/// product. If no non-managed installation of the product can be found, the function then tries to modify a managed per-user
/// installation of the product. If no managed or unmanaged per-user installations of the product can be found, the function returns
/// ERROR_UNKNOWN_PRODUCT, even if the product is installed per-machine.
/// </para>
/// <para>
/// This function can not modify a non-managed installation for any user besides the current user. If the user name is not an empty
/// string or <c>NULL</c>, but is not the current user, the function only checks for a managed per-user installation of the product
/// for the specified user. If the product is not installed as managed per-user for the specified user, the function returns
/// ERROR_UNKNOWN_PRODUCT, even if the product is installed per-machine.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistforceresolutiona UINT MsiSourceListForceResolutionA(
// LPCSTR szProduct, LPCSTR szUserName, DWORD dwReserved );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListForceResolutionA")]
public static extern Win32Error MsiSourceListForceResolution([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserName, uint dwReserved = 0);
/// <summary>
/// The <c>MsiSourceListForceResolutionEx</c> function removes the registration of the property called "LastUsedSource". This
/// function does not affect the registered source list. Whenever the installer requires the source to reinstall a product or patch,
/// it first tries the source registered as "LastUsedSource". If that fails, or if that registration is missing, the installer
/// searches the other registered sources until it finds a valid source or until the list of sources is exhausted. Clearing the
/// "LastUsedSource" registration forces the installer to do a source resolution against the registered sources the next time it
/// requires the source.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns ERROR_INVALID_PARAMETER. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// This parameter can be a string SID that specifies the user account that contains the product or patch. The SID is not validated
/// or resolved. An incorrect SID can return ERROR_UNKNOWN_PRODUCT or ERROR_UNKNOWN_PATCH. When referencing a machine context,
/// szUserSID must be <c>NULL</c> and dwContext must be MSIINSTALLCONTEXT_MACHINE. Using the machine SID ("S-1-5-18") returns
/// ERROR_INVALID PARAMETER. When referencing the current user account, szUserSID can be <c>NULL</c> and dwContext can be
/// MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>The dwOptions value determines the interpretation of the szProductCodeOrPatchCode value .</para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>The <c>MsiSourceListForceResolutionEx</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The user does not have the ability to modify the specified source list. Does not indicate whether the product or patch was found.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>Could not access the Windows Installer service</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The "LastUsedSource" registration was cleared.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The specified product or patch was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Administrators can modify the installation of a product or patch instance that exists under the machine context or under their
/// own per-user context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under
/// any user's per-user-managed context. Administrators cannot modify another user's installation of a product or patch instance
/// that exists under that other user's per-user-unmanaged context.
/// </para>
/// <para>
/// Non-administrators cannot modify the installation of a product or patch instance that exists under another user's per-user
/// context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under their own
/// per-user-unmanaged context. They can modify the installation of a product or patch instance under the machine context or their
/// own per-user-managed context only if they are enabled to browse for a product or patch source. Users can be enabled to browse
/// for sources by setting policy, for more information, see DisableBrowse, AllowLockdownBrowse, and AlwaysInstallElevated policies.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistforceresolutionexa UINT
// MsiSourceListForceResolutionExA( LPCSTR szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListForceResolutionExA")]
public static extern Win32Error MsiSourceListForceResolutionEx([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, MSICODE dwOptions);
/// <summary>
/// The <c>MsiSourceListGetInfo</c> function retrieves information about the source list for a product or patch in a specific context.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns ERROR_INVALID_PARAMETER. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// This parameter can be a string security identifier (SID) that specifies the user account that contains the product or patch. The
/// SID is not validated or resolved. An incorrect SID can return ERROR_UNKNOWN_PRODUCT or ERROR_UNKNOWN_PATCH. When referencing a
/// machine context, szUserSID must be <c>NULL</c> and dwContext must be MSIINSTALLCONTEXT_MACHINE.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>
/// NULL denotes the currently logged on user. When referencing the current user account, szUserSID can be NULL and dwContext can be
/// MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>Specifies enumeration for a specific user in the system. An example of a user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string s-1-5-18 (system) cannot be used to enumerate products or patches installed as per-machine.
/// Setting the SID value to s-1-5-18 returns ERROR_INVALID_PARAMETER.
/// </para>
/// <para>
/// <c>Note</c> The special SID string s-1-1-0 (everyone) should not be used. Setting the SID value to s-1-1-0 fails and returns ERROR_INVALID_PARAM.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>The dwOptions value specifies the meaning of szProductCodeOrPatchCode.</para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code GUID.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code GUID.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szProperty">
/// <para>
/// A null-terminated string that specifies the property value to retrieve. The szProperty parameter can be one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Name</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLPROPERTY_MEDIAPACKAGEPATH "MediaPackagePath"</term>
/// <term>The path relative to the root of the installation media.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_DISKPROMPT "DiskPrompt"</term>
/// <term>The prompt template that is used when prompting the user for installation media.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_LASTUSEDSOURCE "LastUsedSource"</term>
/// <term>The most recently used source location for the product.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_LASTUSEDTYPE "LastUsedType"</term>
/// <term>
/// An "n" if the last-used source is a network location. A "u" if the last used source is a URL location. An "m" if the last used
/// source is media. An empty string ("") if there is no last used source.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PACKAGENAME "PackageName"</term>
/// <term>The name of the Windows Installer package or patch package on the source.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szValue">
/// <para>
/// An output buffer that receives the information. This buffer should be large enough to contain the information. If the buffer is
/// too small, the function returns ERROR_MORE_DATA and sets *pcchValue to the number of <c>TCHAR</c> in the value, not including
/// the terminating NULL character.
/// </para>
/// <para>
/// If the szValue is set to <c>NULL</c> and pcchValue is set to a valid pointer, the function returns ERROR_SUCCESS and sets
/// *pcchValue to the number of <c>TCHAR</c> in the value, not including the terminating NULL character. The function can then be
/// called again to retrieve the value, with szValue buffer large enough to contain *pcchValue + 1 characters.
/// </para>
/// <para>
/// If szValue and pcchValue are both set to <c>NULL</c>, the function returns ERROR_SUCCESS if the value exists, without retrieving
/// the value.
/// </para>
/// </param>
/// <param name="pcchValue">
/// <para>
/// A pointer to a variable that specifies the number of <c>TCHAR</c> in the szValue buffer. When the function returns, this
/// parameter is set to the size of the requested value whether or not the function copies the value into the specified buffer. The
/// size is returned as the number of <c>TCHAR</c> in the requested value, not including the terminating null character.
/// </para>
/// <para>This parameter can be set to <c>NULL</c> only if szValue is also <c>NULL</c>, otherwise the function returns ERROR_INVALID_PARAMETER.</para>
/// </param>
/// <returns>
/// <para>The <c>MsiSourceListGetInfo</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The user does not have the ability to read the specified source list. This does not indicate whether a product or patch is found.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter is passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_MORE_DATA</term>
/// <term>The provided buffer is not sufficient to contain the requested data.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The property is retrieved successfully.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch is not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product is not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PROPERTY</term>
/// <term>The source property is not found.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>An unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Administrators can modify the installation of a product or patch instance that exists under the machine context or under their
/// own per-user context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under
/// any user's per-user-managed context. Administrators cannot modify another user's installation of a product or patch instance
/// that exists under that other user's per-user-unmanaged context.
/// </para>
/// <para>
/// Non-administrators cannot modify the installation of a product or patch instance that exists under another user's per-user
/// context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under their own
/// per-user-unmanaged context. They can modify the installation of a product or patch instance under the machine context or their
/// own per-user-managed context only if they are enabled to browse for a product or patch source. Users can be enabled to browse
/// for sources by setting policy. For more information, see DisableBrowse, AllowLockdownBrowse, and AlwaysInstallElevated policies.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistgetinfoa UINT MsiSourceListGetInfoA( LPCSTR
// szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCSTR szProperty, LPSTR szValue,
// LPDWORD pcchValue );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListGetInfoA")]
public static extern Win32Error MsiSourceListGetInfo([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, MSICODE dwOptions,
[MarshalAs(UnmanagedType.LPTStr)] string szProperty, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szValue, ref uint pcchValue);
/// <summary>
/// The <c>MsiSourceListSetInfo</c> function sets information about the source list for a product or patch in a specific context.
/// </summary>
/// <param name="szProductCodeOrPatchCode">
/// The ProductCode or patch GUID of the product or patch. Use a null-terminated string. If the string is longer than 39 characters,
/// the function fails and returns <c>ERROR_INVALID_PARAMETER</c>. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="szUserSid">
/// <para>
/// This parameter can be a string SID that specifies the user account that contains the product or patch. The SID is not validated
/// or resolved. An incorrect SID can return <c>ERROR_UNKNOWN_PRODUCT</c> or <c>ERROR_UNKNOWN_PATCH</c>. When referencing a machine
/// context, szUserSID must be <c>NULL</c> and dwContext must be <c>MSIINSTALLCONTEXT_MACHINE</c>.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of SID</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>NULL</term>
/// <term>
/// NULL denotes the currently logged on user. When referencing the current user account, szUserSID can be NULL and dwContext can be
/// MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_USERUNMANAGED.
/// </term>
/// </item>
/// <item>
/// <term>User SID</term>
/// <term>Specifies enumeration for a particular user in the system. An example of a user SID is "S-1-3-64-2415071341-1358098788-3127455600-2561".</term>
/// </item>
/// </list>
/// <para>
/// <c>Note</c> The special SID string "S-1-5-18" (system) cannot be used to enumerate products or patches installed as per-machine.
/// Setting the SID value to "S-1-5-18" returns "ERROR_INVALID_PARAMETER".
/// </para>
/// <para>
/// <c>Note</c> The special SID string "S-1-1-0" (everyone) should not be used. Setting the SID value to "S-1-1-0" fails and returns <c>ERROR_INVALID_PARAM</c>.
/// </para>
/// </param>
/// <param name="dwContext">
/// <para>
/// This parameter specifies the context of the product or patch instance. This parameter can contain one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Type of context</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERMANAGED</term>
/// <term>The product or patch instance exists in the per-user-managed context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_USERUNMANAGED</term>
/// <term>The product or patch instance exists in the per-user-unmanaged context.</term>
/// </item>
/// <item>
/// <term>MSIINSTALLCONTEXT_MACHINE</term>
/// <term>The product or patch instance exists in the per-machine context.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwOptions">
/// <para>The dwOptions value specifies the meaning of szProductCodeOrPatchCode.</para>
/// <para>
/// If the property being set is "LastUsedSource", this parameter also specifies the type of source as network or URL. In this case,
/// the dwOptions parameter must be a combination of one of the following <c>MSISOURCETYPE_</c> constants and one of the following
/// <c>MSICODE_</c> constants.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>MSISOURCETYPE_NETWORK</term>
/// <term>The source is a network type.</term>
/// </item>
/// <item>
/// <term>MSISOURCETYPE_URL</term>
/// <term>The source is a URL type.</term>
/// </item>
/// <item>
/// <term>MSICODE_PRODUCT</term>
/// <term>szProductCodeOrPatchCode is a product code GUID.</term>
/// </item>
/// <item>
/// <term>MSICODE_PATCH</term>
/// <term>szProductCodeOrPatchCode is a patch code GUID.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szProperty">
/// <para>
/// The parameter szProperty indicates the property value to set. Not all properties that can be retrieved through
/// MsiSourceListGetInfo can be set via a call to <c>MsiSourceListSetInfo</c>. The szProperty value can be one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Name</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLPROPERTY_MEDIAPACKAGEPATH "MediaPackagePath"</term>
/// <term>The path relative to the root of the installation media.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_DISKPROMPT "DiskPrompt"</term>
/// <term>The prompt template used when prompting the user for installation media.</term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_LASTUSEDSOURCE "LastUsedSource"</term>
/// <term>
/// The most recently used source location for the product. If the source is not registered, the function calls
/// MsiSourceListAddSourceEx to register it. On successful registration, the function sets the source as the LastUsedSource.
/// </term>
/// </item>
/// <item>
/// <term>INSTALLPROPERTY_PACKAGENAME "PackageName"</term>
/// <term>The name of the Windows Installer package or patch package on the source.</term>
/// </item>
/// </list>
/// </param>
/// <param name="szValue">
/// The new value of the property. No validation of the new value is performed. This value cannot be <c>NULL</c>. It can be an empty string.
/// </param>
/// <returns>
/// <para>The <c>MsiSourceListSetInfo</c> function returns the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>The user does not have the ability to set the source list for the specified product.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_SERVICE_FAILURE</term>
/// <term>The Windows Installer service could not be accessed.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>An invalid parameter was passed to the function.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The property was set.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PATCH</term>
/// <term>The patch was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PRODUCT</term>
/// <term>The product was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_UNKNOWN_PROPERTY</term>
/// <term>The source property was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_FUNCTION_FAILED</term>
/// <term>Unexpected internal failure.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Administrators can modify the installation of a product or patch instance that exists under the machine context or under their
/// own per-user context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under
/// any user's per-user-managed context. Administrators cannot modify another user's installation of a product or patch instance
/// that exists under that other user's per-user-unmanaged context.
/// </para>
/// <para>
/// Non-administrators cannot modify the installation of a product or patch instance that exists under another user's per-user
/// context (managed or unmanaged.) They can modify the installation of a product or patch instance that exists under their own
/// per-user-unmanaged context. They can modify the installation of a product or patch instance under the machine context or their
/// own per-user-managed context only if they are enabled to browse for a product or patch source. Users can be enabled to browse
/// for sources by setting policy. For more information, see the DisableBrowse, AllowLockdownBrowse, and AlwaysInstallElevated policies.
/// </para>
/// <para>
/// An exception to the above rule is setting "LastUsedSource" to one of the registered sources. If the source is already
/// registered, a non-administrator can set "LastUsedSource" to their own installations (managed or non-managed) and per-machine
/// installations, irrespective of policies.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msisourcelistsetinfoa UINT MsiSourceListSetInfoA( LPCSTR
// szProductCodeOrPatchCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCSTR szProperty, LPCSTR szValue );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiSourceListSetInfoA")]
public static extern Win32Error MsiSourceListSetInfo([MarshalAs(UnmanagedType.LPTStr)] string szProductCodeOrPatchCode,
[Optional, MarshalAs(UnmanagedType.LPTStr)] string szUserSid, MSIINSTALLCONTEXT dwContext, uint dwOptions,
[MarshalAs(UnmanagedType.LPTStr)] string szProperty, [MarshalAs(UnmanagedType.LPTStr)] string szValue);
/// <summary>
/// The <c>MsiUseFeature</c> function increments the usage count for a particular feature and indicates the installation state for
/// that feature. This function should be used to indicate an application's intent to use a feature.
/// </summary>
/// <param name="szProduct">Specifies the product code for the product that owns the feature to be used.</param>
/// <param name="szFeature">Identifies the feature to be used.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// <term>The feature is not installed.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_ADVERTISED</term>
/// <term>The feature is advertised</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_BADCONFIG</term>
/// <term>The configuration data is corrupt.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_INVALIDARG</term>
/// <term>Invalid function argument.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_LOCAL</term>
/// <term>The feature is locally installed and available for use.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCE</term>
/// <term>The feature is installed from the source and available for use.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>The feature is not published.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// The <c>MsiUseFeature</c> function should only be used on features known to be published. INSTALLSTATE_UNKNOWN indicates that the
/// program is trying to use a feature that is not published. The application should determine whether the feature is published
/// before calling <c>MsiUseFeature</c> by calling MsiQueryFeatureState or MsiEnumFeatures. The application should make these calls
/// while it initializes. An application should only use features that are known to be published.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiusefeaturea INSTALLSTATE MsiUseFeatureA( LPCSTR szProduct,
// LPCSTR szFeature );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiUseFeatureA")]
public static extern INSTALLSTATE MsiUseFeature([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szFeature);
/// <summary>
/// The <c>MsiUseFeatureEx</c> function increments the usage count for a particular feature and indicates the installation state for
/// that feature. This function should be used to indicate an application's intent to use a feature.
/// </summary>
/// <param name="szProduct">Specifies the product code for the product that owns the feature to be used.</param>
/// <param name="szFeature">Identifies the feature to be used.</param>
/// <param name="dwInstallMode">
/// <para>This parameter can have the following value.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLMODE_NODETECTION</term>
/// <term>Return value indicates the installation state.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwReserved">Reserved for future use. This value must be set to 0.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>INSTALLSTATE_ABSENT</term>
/// <term>The feature is not installed.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_ADVERTISED</term>
/// <term>The feature is advertised</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_LOCAL</term>
/// <term>The feature is locally installed and available for use.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_SOURCE</term>
/// <term>The feature is installed from the source and available for use.</term>
/// </item>
/// <item>
/// <term>INSTALLSTATE_UNKNOWN</term>
/// <term>The feature is not published.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// The <c>MsiUseFeatureEx</c> function should only be used on features known to be published. INSTALLSTATE_UNKNOWN indicates that
/// the program is trying to use a feature that is not published. The application should determine whether the feature is published
/// before calling MsiUseFeature by calling MsiQueryFeatureState or MsiEnumFeatures. The application should make these calls while
/// it initializes. An application should only use features that are known to be published.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiusefeatureexa INSTALLSTATE MsiUseFeatureExA( LPCSTR szProduct,
// LPCSTR szFeature, DWORD dwInstallMode, DWORD dwReserved );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiUseFeatureExA")]
public static extern INSTALLSTATE MsiUseFeatureEx([MarshalAs(UnmanagedType.LPTStr)] string szProduct,
[MarshalAs(UnmanagedType.LPTStr)] string szFeature, INSTALLMODE dwInstallMode, uint dwReserved = 0);
/// <summary>The <c>MsiVerifyPackage</c> function verifies that the given file is an installation package.</summary>
/// <param name="szPackagePath">Specifies the path and file name of the package.</param>
/// <returns>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_INSTALL_PACKAGE_INVALID</term>
/// <term>The file is not a valid package.</term>
/// </item>
/// <item>
/// <term>ERROR_INSTALL_PACKAGE_OPEN_FAILED</term>
/// <term>The file could not be opened.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>The parameter is not valid.</term>
/// </item>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The file is a package.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/api/msi/nf-msi-msiverifypackagew UINT MsiVerifyPackageW( LPCWSTR szPackagePath );
[DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("msi.h", MSDNShortId = "NF:msi.MsiVerifyPackageW")]
public static extern Win32Error MsiVerifyPackage([MarshalAs(UnmanagedType.LPTStr)] string szPackagePath);
}
}