using System; using System.Runtime.InteropServices; using System.Text; using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; namespace Vanara.PInvoke { /// Items from the Msi.dll public static partial class Msi { /// /// A value returned from when the field is null or if the field is a string that cannot be /// converted to an integer. /// public const int MSI_NULL_INTEGER = unchecked((int)0x80000000); /// Create a new database, transact mode read/write. public static readonly IntPtr MSIDBOPEN_CREATE = (IntPtr)3; /// Create a new database, direct mode read/write. public static readonly IntPtr MSIDBOPEN_CREATEDIRECT = (IntPtr)4; /// Open a database direct read/write without transaction. public static readonly IntPtr MSIDBOPEN_DIRECT = (IntPtr)2; /// Add this flag to indicate a patch file. public static readonly IntPtr MSIDBOPEN_PATCHFILE = (IntPtr)(32 / IntPtr.Size); /// Open a database read-only, no persistent changes. public static readonly IntPtr MSIDBOPEN_READONLY = (IntPtr)0; /// Open a database read/write in transaction mode. public static readonly IntPtr MSIDBOPEN_TRANSACT = (IntPtr)1; /// Specifies a flag indicating what type of information is needed. [PInvokeData("msiquery.h")] public enum MSICOLINFO { /// Column names are returned. MSICOLINFO_NAMES = 0, // return column names /// Definitions are returned. MSICOLINFO_TYPES = 1, // return column definitions, datatype code followed by width } /// Evaluation result of a conditional expression. [PInvokeData("msiquery.h")] public enum MSICONDITION { /// Expression evaluates to False MSICONDITION_FALSE = 0, // expression evaluates to False /// Expression evaluates to True MSICONDITION_TRUE = 1, // expression evaluates to True /// No expression present MSICONDITION_NONE = 2, // no expression present /// Syntax error in expression MSICONDITION_ERROR = 3, // syntax error in expression } /// Specifies the value the function uses to determine disk space requirements. [PInvokeData("msiquery.h")] public enum MSICOSTTREE { /// The feature only is included in the cost. MSICOSTTREE_SELFONLY = 0, /// The children of the indicated feature are included in the cost. MSICOSTTREE_CHILDREN = 1, /// he parent features of the indicated feature are included in the cost. MSICOSTTREE_PARENTS = 2, /// Reserved for future use MSICOSTTREE_RESERVED = 3, // Reserved for future use } /// The error that occurred in the MsiViewModify function. [PInvokeData("msiquery.h")] public enum MSIDBERROR { /// An argument was invalid. MSIDBERROR_INVALIDARG = -3, // invalid argument /// The buffer was too small to receive data. MSIDBERROR_MOREDATA = -2, // buffer too small /// The function failed. MSIDBERROR_FUNCTIONERROR = -1, // function error /// The function completed successfully with no errors. MSIDBERROR_NOERROR = 0, // no error /// The new record duplicates primary keys of the existing record in a table. MSIDBERROR_DUPLICATEKEY = 1, // new record duplicates primary keys of existing record in table /// There are no null values allowed; or the column is about to be deleted, but is referenced by another row. MSIDBERROR_REQUIRED = 2, // non-nullable column, no null values allowed /// The corresponding record in a foreign table was not found. MSIDBERROR_BADLINK = 3, // corresponding record in foreign table not found /// The data is greater than the maximum value allowed. MSIDBERROR_OVERFLOW = 4, // data greater than maximum value allowed /// The data is less than the minimum value allowed. MSIDBERROR_UNDERFLOW = 5, // data less than minimum value allowed /// The data is not a member of the values permitted in the set. MSIDBERROR_NOTINSET = 6, // data not a member of the values permitted in the set /// An invalid version string was supplied. MSIDBERROR_BADVERSION = 7, // invalid version string /// The case was invalid. The case must be all uppercase or all lowercase. MSIDBERROR_BADCASE = 8, // invalid case, must be all upper-case or all lower-case /// An invalid GUID was supplied. MSIDBERROR_BADGUID = 9, // invalid GUID /// An invalid wildcard file name was supplied, or the use of wildcards was invalid. MSIDBERROR_BADWILDCARD = 10, // invalid wildcardfilename or use of wildcards /// An invalid identifier was supplied. MSIDBERROR_BADIDENTIFIER = 11, // bad identifier /// Invalid language IDs were supplied. MSIDBERROR_BADLANGUAGE = 12, // bad language Id(s) /// An invalid file name was supplied. MSIDBERROR_BADFILENAME = 13, // bad filename /// An invalid path was supplied. MSIDBERROR_BADPATH = 14, // bad path /// An invalid conditional statement was supplied. MSIDBERROR_BADCONDITION = 15, // bad conditional statement /// An invalid format string was supplied. MSIDBERROR_BADFORMATTED = 16, // bad format string /// An invalid template string was supplied. MSIDBERROR_BADTEMPLATE = 17, // bad template string /// An invalid string was supplied in the DefaultDir column of the Directory table. MSIDBERROR_BADDEFAULTDIR = 18, // bad string in DefaultDir column of Directory table /// An invalid registry path string was supplied. MSIDBERROR_BADREGPATH = 19, // bad registry path string /// An invalid string was supplied in the CustomSource column of the CustomAction table. MSIDBERROR_BADCUSTOMSOURCE = 20, // bad string in CustomSource column of CustomAction table /// An invalid property string was supplied. MSIDBERROR_BADPROPERTY = 21, // bad property string /// The _Validation table is missing a reference to a column. MSIDBERROR_MISSINGDATA = 22, // _Validation table missing reference to column /// The category column of the _Validation table for the column is invalid. MSIDBERROR_BADCATEGORY = 23, // Category column of _Validation table for column is invalid /// An invalid cabinet name was supplied. MSIDBERROR_BADKEYTABLE = 24, // table in KeyTable column of _Validation table could not be found/loaded /// The table in the Keytable column of the _Validation table was not found or loaded. MSIDBERROR_BADMAXMINVALUES = 25, // value in MaxValue column of _Validation table is less than value in MinValue column /// The value in the MaxValue column of the _Validation table is less than the value in the MinValue column. MSIDBERROR_BADCABINET = 26, // bad cabinet name /// An invalid shortcut target name was supplied. MSIDBERROR_BADSHORTCUT = 27, // bad shortcut target /// The string is too long for the length specified by the column definition. MSIDBERROR_STRINGOVERFLOW = 28, // string overflow (greater than length allowed in column def) /// An invalid localization attribute was supplied. (Primary keys cannot be localized.) MSIDBERROR_BADLOCALIZEATTRIB = 29 // invalid localization attribute (primary keys cannot be localized) } /// The state of the database. [PInvokeData("msiquery.h")] public enum MSIDBSTATE { /// Invalid database handle MSIDBSTATE_ERROR = -1, // invalid database handle /// Database open read-only, no persistent changes MSIDBSTATE_READ = 0, // database open read-only, no persistent changes /// The database is readable and updatable. MSIDBSTATE_WRITE = 1, // database readable and updatable } /// Specifies the modify mode. [PInvokeData("msiquery.h")] public enum MSIMODIFY { /// /// Refreshes the information in the supplied record without changing the position in the result set and without affecting /// subsequent fetch operations. The record may then be used for subsequent Update, Delete, and Refresh. All primary key columns /// of the table must be in the query and the record must have at least as many fields as the query. Seek cannot be used with /// multi-table queries. This mode cannot be used with a view containing joins. See also the remarks. /// MSIMODIFY_SEEK = -1, // reposition to current record primary key /// /// Refreshes the information in the record. Must first call MsiViewFetch with the same record. Fails for a deleted row. Works /// with read-write and read-only records. /// MSIMODIFY_REFRESH = 0, // refetch current record data /// /// Inserts a record. Fails if a row with the same primary keys exists. Fails with a read-only database. This mode cannot be /// used with a view containing joins. /// MSIMODIFY_INSERT = 1, // insert new record, fails if matching key exists /// /// Updates an existing record. Nonprimary keys only. Must first call MsiViewFetch. Fails with a deleted record. Works only with /// read-write records. /// MSIMODIFY_UPDATE = 2, // update existing non-key data of fetched record /// /// Writes current data in the cursor to a table row. Updates record if the primary keys match an existing row and inserts if /// they do not match. Fails with a read-only database. This mode cannot be used with a view containing joins. /// MSIMODIFY_ASSIGN = 3, // insert record, replacing any existing record /// /// Updates or deletes and inserts a record into a table. Must first call MsiViewFetch with the same record. Updates record if /// the primary keys are unchanged. Deletes old row and inserts new if primary keys have changed. Fails with a read-only /// database. This mode cannot be used with a view containing joins. /// MSIMODIFY_REPLACE = 4, // update record, delete old if primary key edit /// /// Inserts or validates a record in a table. Inserts if primary keys do not match any row and validates if there is a match. /// Fails if the record does not match the data in the table. Fails if there is a record with a duplicate key that is not /// identical. Works only with read-write records. This mode cannot be used with a view containing joins. /// MSIMODIFY_MERGE = 5, // fails if record with duplicate key not identical /// /// Remove a row from the table. You must first call the MsiViewFetch function with the same record. Fails if the row has been /// deleted. Works only with read-write records. This mode cannot be used with a view containing joins. /// MSIMODIFY_DELETE = 6, // remove row referenced by this record from table /// /// Inserts a temporary record. The information is not persistent. Fails if a row with the same primary key exists. Works only /// with read-write records. This mode cannot be used with a view containing joins. /// MSIMODIFY_INSERT_TEMPORARY = 7, // insert a temporary record /// /// Validates a record. Does not validate across joins. You must first call the MsiViewFetch function with the same record. /// Obtain validation errors with MsiViewGetError. Works with read-write and read-only records. This mode cannot be used with a /// view containing joins. /// MSIMODIFY_VALIDATE = 8, // validate a fetched record /// /// Validate a new record. Does not validate across joins. Checks for duplicate keys. Obtain validation errors by calling /// MsiViewGetError. Works with read-write and read-only records. This mode cannot be used with a view containing joins. /// MSIMODIFY_VALIDATE_NEW = 9, // validate a new record /// /// Validates fields of a fetched or new record. Can validate one or more fields of an incomplete record. Obtain validation /// errors by calling MsiViewGetError. Works with read-write and read-only records. This mode cannot be used with a view /// containing joins. /// MSIMODIFY_VALIDATE_FIELD = 10, // validate field(s) of an incomplete record /// /// Validates a record that will be deleted later. You must first call MsiViewFetch. Fails if another row refers to the primary /// keys of this row. Validation does not check for the existence of the primary keys of this row in properties or strings. Does /// not check if a column is a foreign key to multiple tables. Obtain validation errors by calling MsiViewGetError. Works with /// read-write and read-only records. This mode cannot be used with a view that contains joins. /// MSIMODIFY_VALIDATE_DELETE = 11, // validate before deleting record } /// Specifies the run mode. [PInvokeData("msiquery.h")] public enum MSIRUNMODE { /// The administrative mode is installing, or the product is installing. MSIRUNMODE_ADMIN = 0, // admin mode install, else product install /// The advertisements are installing or the product is installing or updating. MSIRUNMODE_ADVERTISE = 1, // installing advertisements, else installing or updating product /// An existing installation is being modified or there is a new installation. MSIRUNMODE_MAINTENANCE = 2, // modifying an existing installation, else new installation /// Rollback is enabled. MSIRUNMODE_ROLLBACKENABLED = 3, // rollback is enabled /// The log file is active. It was enabled prior to the installation session. MSIRUNMODE_LOGENABLED = 4, // log file active, enabled prior to install session /// Execute operations are in the determination phase. MSIRUNMODE_OPERATIONS = 5, // spooling execute operations, else in determination phase /// A reboot is necessary after a successful installation (settable). MSIRUNMODE_REBOOTATEND = 6, // reboot needed after successful installation (settable) /// A reboot is necessary to continue the installation (settable). MSIRUNMODE_REBOOTNOW = 7, // reboot needed to continue installation (settable) /// Files from cabinets and Media table files are installing. MSIRUNMODE_CABINET = 8, // installing files from cabinets and files using Media table /// The source LongFileNames is suppressed through the PID_MSISOURCE summary property. MSIRUNMODE_SOURCESHORTNAMES = 9, // source LongFileNames suppressed via PID_MSISOURCE summary property /// The target LongFileNames is suppressed through the SHORTFILENAMES property. MSIRUNMODE_TARGETSHORTNAMES = 10, // target LongFileNames suppressed via SHORTFILENAMES property /// Reserved for future use. MSIRUNMODE_RESERVED11 = 11, // future use /// The operating system is a 9x version. MSIRUNMODE_WINDOWS9X = 12, // operating systems is Windows9?, else Windows NT /// The operating system supports demand installation. MSIRUNMODE_ZAWENABLED = 13, // operating system supports demand installation /// Reserved for future use. MSIRUNMODE_RESERVED14 = 14, // future use /// Reserved for future use. MSIRUNMODE_RESERVED15 = 15, // future use /// A custom action called from install script execution. MSIRUNMODE_SCHEDULED = 16, // custom action call from install script execution /// A custom action called from rollback execution script. MSIRUNMODE_ROLLBACK = 17, // custom action call from rollback execution script /// A custom action called from commit execution script. MSIRUNMODE_COMMIT = 18, // custom action call from commit execution script } /// The error conditions that should be suppressed when the transform is applied. [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiCreateTransformSummaryInfoA")] [Flags] public enum MSITRANSFORM_ERROR { /// Adding a row that exists. MSITRANSFORM_ERROR_ADDEXISTINGROW = 0x00000001, /// Deleting a row that does not exist. MSITRANSFORM_ERROR_DELMISSINGROW = 0x00000002, /// Adding a table that exists. MSITRANSFORM_ERROR_ADDEXISTINGTABLE = 0x00000004, /// Deleting a table that does not exist. MSITRANSFORM_ERROR_DELMISSINGTABLE = 0x00000008, /// Updating a row that does not exist. MSITRANSFORM_ERROR_UPDATEMISSINGROW = 0x00000010, /// Transform and database code pages do not match, and their code pages are neutral. MSITRANSFORM_ERROR_CHANGECODEPAGE = 0x00000020, /// Create the temporary _TransformView table. MSITRANSFORM_ERROR_VIEWTRANSFORM = 0x00000100, } // Note: INSTALLMESSAGE_ERROR, INSTALLMESSAGE_WARNING, INSTALLMESSAGE_USER are to or'd with a message box style to indicate the // buttons to display and return: MB_OK,MB_OKCANCEL,MB_ABORTRETRYIGNORE,MB_YESNOCANCEL,MB_YESNO,MB_RETRYCANCEL the default button // (MB_DEFBUTTON1 is normal default): MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3 and optionally an icon style: MB_ICONERROR, // MB_ICONQUESTION, MB_ICONWARNING, MB_ICONINFORMATION /// Specifies the properties to be validated to verify that the transform can be applied to the database. [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiCreateTransformSummaryInfoA")] [Flags] public enum MSITRANSFORM_VALIDATE { /// Default language must match base database. MSITRANSFORM_VALIDATE_LANGUAGE = 0x00000001, /// Product must match base database. MSITRANSFORM_VALIDATE_PRODUCT = 0x00000002, /// MSITRANSFORM_VALIDATE_PLATFORM = 0x00000004, /// Check major version only. MSITRANSFORM_VALIDATE_MAJORVERSION = 0x00000008, /// Check major and minor versions only. MSITRANSFORM_VALIDATE_MINORVERSION = 0x00000010, /// Check major, minor, and update versions. MSITRANSFORM_VALIDATE_UPDATEVERSION = 0x00000020, /// Installed version < base version. MSITRANSFORM_VALIDATE_NEWLESSBASEVERSION = 0x00000040, /// Installed version <= base version. MSITRANSFORM_VALIDATE_NEWLESSEQUALBASEVERSION = 0x00000080, /// Installed version = base version. MSITRANSFORM_VALIDATE_NEWEQUALBASEVERSION = 0x00000100, /// Installed version >= base version. MSITRANSFORM_VALIDATE_NEWGREATEREQUALBASEVERSION = 0x00000200, /// Installed version > base version. MSITRANSFORM_VALIDATE_NEWGREATERBASEVERSION = 0x00000400, /// UpgradeCode must match base database. MSITRANSFORM_VALIDATE_UPGRADECODE = 0x00000800, } /// /// The MsiCreateRecord function creates a new record object with the specified number of fields. This function returns a /// handle that should be closed using MsiCloseHandle. /// /// /// Specifies the number of fields the record will have. The maximum number of fields in a record is limited to 65535. /// /// /// If the function succeeds, the return value is handle to a new record object. /// If the function fails, the return value is null. /// /// /// /// Field 0 of the record object created by the MsiCreateRecord function is used for format strings and operation codes and /// is not included in the count specified by cParams. All fields are initialized to null. /// /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msicreaterecord MSIHANDLE MsiCreateRecord( UINT cParams ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiCreateRecord")] public static extern PMSIHANDLE MsiCreateRecord(uint cParams); /// /// The MsiCreateTransformSummaryInfo function creates summary information of an existing transform to include validation and /// error conditions. Execution of this function sets the error record, which is accessible by using MsiGetLastErrorRecord. /// /// The handle to the database that contains the new database summary information. /// The handle to the database that contains the original summary information. /// The name of the transform to which the summary information is added. /// /// The error conditions that should be suppressed when the transform is applied. Use one or more of the following values. /// /// /// Error condition /// Meaning /// /// /// none 0x00000000 /// None of the following conditions. /// /// /// MSITRANSFORM_ERROR_ADDEXISTINGROW 0x00000001 /// Adding a row that exists. /// /// /// MSITRANSFORM_ERROR_DELMISSINGROW 0x00000002 /// Deleting a row that does not exist. /// /// /// MSITRANSFORM_ERROR_ADDEXISTINGTABLE 0x00000004 /// Adding a table that exists. /// /// /// MSITRANSFORM_ERROR_DELMISSINGTABLE 0x00000008 /// Deleting a table that does not exist. /// /// /// MSITRANSFORM_ERROR_UPDATEMISSINGROW 0x00000010 /// Updating a row that does not exist. /// /// /// MSITRANSFORM_ERROR_CHANGECODEPAGE 0x00000020 /// Transform and database code pages do not match, and their code pages are neutral. /// /// /// /// /// /// Specifies the properties to be validated to verify that the transform can be applied to the database. This parameter can be one /// or more of the following values. /// /// /// /// Validation flag /// Meaning /// /// /// none 0x00000000 /// Do not validate properties. /// /// /// MSITRANSFORM_VALIDATE_LANGUAGE 0x00000001 /// Default language must match base database. /// /// /// MSITRANSFORM_VALIDATE_PRODUCT 0x00000002 /// Product must match base database. /// /// /// Validate product version flags. /// /// /// Validation flag /// Meaning /// /// /// MSITRANSFORM_VALIDATE_MAJORVERSION 0x00000008 /// Check major version only. /// /// /// MSITRANSFORM_VALIDATE_MINORVERSION 0x00000010 /// Check major and minor versions only. /// /// /// MSITRANSFORM_VALIDATE_UPDATEVERSION 0x00000020 /// Check major, minor, and update versions. /// /// /// /// Product version relationship flags. In the following table the installed version is the version of the package that is being /// transformed, and the base version is the version of the package that is used to create the transform. /// /// /// /// Validation flag /// Meaning /// /// /// MSITRANSFORM_VALIDATE_NEWLESSBASEVERSION 0x00000040 /// Installed version < base version. /// /// /// MSITRANSFORM_VALIDATE_NEWLESSEQUALBASEVERSION 0x00000080 /// Installed version <= base version. /// /// /// MSITRANSFORM_VALIDATE_NEWEQUALBASEVERSION 0x00000100 /// Installed version = base version. /// /// /// MSITRANSFORM_VALIDATE_NEWGREATEREQUALBASEVERSION 0x00000200 /// Installed version >= base version. /// /// /// MSITRANSFORM_VALIDATE_NEWGREATERBASEVERSION 0x00000400 /// Installed version > base version. /// /// /// Upgrade code validation flags. /// /// /// Validation flag /// Meaning /// /// /// MSITRANSFORM_VALIDATE_UPGRADECODE 0x00000800 /// UpgradeCode must match base database. /// /// /// /// This function returns UINT. /// /// /// The ProductCode Property and ProductVersion Property must be defined in the Property Table of both the base and reference /// databases. If MSITRANSFORM_VALIDATE_UPGRADECODE is used, the UpgradeCode Property must also be defined in both databases. If /// these conditions are not met, MsiCreateTransformSummaryInfo returns ERROR_INSTALL_PACKAGE_INVALID. /// /// /// /// Do not use the semicolon for filenames or paths, because it is used as a list delimiter for transforms, sources, and patches. /// /// /// /// This function cannot be called from custom actions. A call to this function from a custom action causes the function to fail. /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msicreatetransformsummaryinfoa UINT // MsiCreateTransformSummaryInfoA( MSIHANDLE hDatabase, MSIHANDLE hDatabaseReference, LPCSTR szTransformFile, int iErrorConditions, // int iValidation ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiCreateTransformSummaryInfoA")] public static extern Win32Error MsiCreateTransformSummaryInfo(MSIHANDLE hDatabase, MSIHANDLE hDatabaseReference, [MarshalAs(UnmanagedType.LPTStr)] string szTransformFile, MSITRANSFORM_ERROR iErrorConditions, MSITRANSFORM_VALIDATE iValidation); /// The MsiDatabaseApplyTransform function applies a transform to a database. /// Handle to the database obtained from MsiOpenDatabase to the transform. /// Specifies the name of the transform file to apply. /// /// Error conditions that should be suppressed. This parameter is a bit field that can contain the following bits. /// /// /// Error condition /// Meaning /// /// /// MSITRANSFORM_ERROR_ADDEXISTINGROW 0x0001 /// Adding a row that already exists. /// /// /// MSITRANSFORM_ERROR_DELMISSINGROW 0x0002 /// Deleting a row that does not exist. /// /// /// MSITRANSFORM_ERROR_ADDEXISTINGTABLE 0x0004 /// Adding a table that already exists. /// /// /// MSITRANSFORM_ERROR_DELMISSINGTABLE 0x0008 /// Deleting a table that does not exist. /// /// /// MSITRANSFORM_ERROR_UPDATEMISSINGROW 0x0010 /// Updating a row that does not exist. /// /// /// MSITRANSFORM_ERROR_CHANGECODEPAGE 0x0020 /// Transform and database code pages do not match and neither has a neutral code page. /// /// /// MSITRANSFORM_ERROR_VIEWTRANSFORM 0x0100 /// Create the temporary _TransformView table. /// /// /// /// The MsiDatabaseApplyTransform function returns one of the following values: /// /// /// The MsiDatabaseApplyTransform function delays transforming tables until it is necessary. Any tables to be added or /// dropped are processed immediately. However, changes to the existing table are delayed until the table is loaded or the database /// is committed. /// /// An error occurs if MsiDatabaseApplyTransform is called when tables have already been loaded and saved to storage. /// /// Because the list delimiter for transforms, sources and patches is a semicolon, this character should not be used for filenames /// or paths. /// /// /// This function cannot be called from custom actions. A call to this function from a custom action causes the function to fail. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidatabaseapplytransforma UINT // MsiDatabaseApplyTransformA( MSIHANDLE hDatabase, LPCSTR szTransformFile, int iErrorConditions ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDatabaseApplyTransformA")] public static extern Win32Error MsiDatabaseApplyTransform(MSIHANDLE hDatabase, [MarshalAs(UnmanagedType.LPTStr)] string szTransformFile, MSITRANSFORM_ERROR iErrorConditions); /// The MsiDatabaseCommit function commits changes to a database. /// Handle to the database obtained from MsiOpenDatabase. /// The MsiDatabaseCommit function returns one of the following values: /// /// /// The MsiDatabaseCommit function finalizes the persistent form of the database. All persistent data is then written to the /// writable database. No temporary columns or rows are written. The MsiDatabaseCommit function has no effect on a database /// that is opened as read-only. You can call this function multiple times to save the current state of tables loaded into memory. /// When the database is finally closed, any changes made after the database is committed are rolled back. This function is normally /// called prior to shutdown when all database changes have been finalized. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidatabasecommit UINT MsiDatabaseCommit( MSIHANDLE // hDatabase ); [DllImport(Lib_Msi, SetLastError = true, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDatabaseCommit")] public static extern Win32Error MsiDatabaseCommit(MSIHANDLE hDatabase); /// /// The MsiDatabaseExport function exports a Microsoft Installer table from an open database to a Text Archive File. /// /// The handle to a database from MsiOpenDatabase. /// The name of the table to export. /// The name of the folder that contains archive files. /// The name of the exported table archive file. /// /// The MsiDatabaseExport function returns one of the following values: /// /// /// Return code /// Description /// /// /// ERROR_BAD_PATHNAME /// An invalid path is passed to the function. /// /// /// ERROR_FUNCTION_FAILED /// The function fails. /// /// /// ERROR_INVALID_HANDLE /// An invalid or inactive handle is supplied. /// /// /// ERROR_INVALID_PARAMETER /// An invalid parameter is passed to the function. /// /// /// ERROR_SUCCESS /// The function succeeds. /// /// /// /// /// If a table contains streams, MsiDatabaseExport exports each stream to a separate file. /// For more information, see MsiDatabaseImport. /// /// This function cannot be called from custom actions. A call to this function from a custom action causes the function to fail. /// /// If the function fails, you can get extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidatabaseexporta UINT MsiDatabaseExportA( MSIHANDLE // hDatabase, LPCSTR szTableName, LPCSTR szFolderPath, LPCSTR szFileName ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDatabaseExportA")] public static extern Win32Error MsiDatabaseExport(MSIHANDLE hDatabase, [MarshalAs(UnmanagedType.LPTStr)] string szTableName, [MarshalAs(UnmanagedType.LPTStr)] string szFolderPath, [MarshalAs(UnmanagedType.LPTStr)] string szFileName); /// /// The MsiDatabaseGenerateTransform function generates a transform file of differences between two databases. A transform is /// a way of recording changes to a database without altering the original database. You can also use /// MsiDatabaseGenerateTransform to test whether two databases are identical without creating a transform. /// /// Handle to the database obtained from MsiOpenDatabase that includes the changes. /// Handle to the database obtained from MsiOpenDatabase that does not include the changes. /// /// A null-terminated string that specifies the name of the transform file being generated. This parameter can be null. If /// szTransformFile is null, you can use MsiDatabaseGenerateTransform to test whether two databases are identical without /// creating a transform. If the databases are identical, the function returns ERROR_NO_DATA. If the databases are different the /// function returns NOERROR. /// /// This is a reserved argument and must be set to 0. /// This is a reserved argument and must be set to 0. /// The MsiDatabaseGenerateTransform function returns one of the following values: /// /// /// To generate a difference file between two databases, use the MsiDatabaseGenerateTransform function. A transform contains /// information regarding insertion and deletion of columns and rows. The validation flags are stored in the summary information /// stream of the transform file. /// /// /// For tables that exist in both databases, the only difference between the two schemas that is allowed is the addition of columns /// to the end of the reference table. You cannot add primary key columns to a table or change the order or names or column /// definitions of the existing columns as defined in the base table. In other words, if neither table contains data and columns are /// removed from the reference table, the resulting table is identical to the base table. /// /// /// Because the list delimiter for transforms, sources and patches is a semicolon, this character should not be used for filenames /// or paths. /// /// /// This function does not generate a Summary Information stream. Use MsiCreateTransformSummaryInfo to create the stream for an /// existing transform. /// /// /// If szTransformFile is null, you can test whether two databases are identical without creating a transform. If the databases are /// identical, ERROR_NO_DATA is returned, NOERROR is returned if differences are found. /// /// /// This function cannot be called from custom actions. A call to this function from a custom action causes the function to fail. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidatabasegeneratetransforma UINT // MsiDatabaseGenerateTransformA( MSIHANDLE hDatabase, MSIHANDLE hDatabaseReference, LPCSTR szTransformFile, int iReserved1, int // iReserved2 ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDatabaseGenerateTransformA")] public static extern Win32Error MsiDatabaseGenerateTransform(MSIHANDLE hDatabase, MSIHANDLE hDatabaseReference, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szTransformFile, int iReserved1 = 0, int iReserved2 = 0); /// /// The MsiDatabaseGetPrimaryKeys function returns a record containing the names of all the primary key columns for a /// specified table. This function returns a handle that should be closed using MsiCloseHandle. /// /// Handle to the database. See Obtaining a Database Handle. /// Specifies the name of the table from which to obtain primary key names. /// Pointer to the handle of the record that holds the primary key names. /// This function returns UINT. /// /// /// The field count of the returned record is the count of primary key columns returned by the MsiDatabaseGetPrimaryKeys /// function. The returned record contains the table name in Field (0) and the column names that make up the primary key names in /// succeeding fields. These primary key names correspond to the column numbers for the fields. /// /// This function cannot be used with the _Tables table or the _Columns table. /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidatabasegetprimarykeysa UINT // MsiDatabaseGetPrimaryKeysA( MSIHANDLE hDatabase, LPCSTR szTableName, MSIHANDLE *phRecord ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDatabaseGetPrimaryKeysA")] public static extern Win32Error MsiDatabaseGetPrimaryKeys(MSIHANDLE hDatabase, [MarshalAs(UnmanagedType.LPTStr)] string szTableName, out PMSIHANDLE phRecord); /// The MsiDatabaseImport function imports an installer text archive file into an open database table. /// Handle to the database obtained from MsiOpenDatabase. /// Specifies the path to the folder that contains archive files. /// Specifies the name of the file to import. /// The MsiDatabaseImport function returns one of the following values: /// /// /// When you use the MsiDatabaseImport function to import a text archive table named _SummaryInformation into an installer /// database, you write the "05SummaryInformation" stream. This stream contains standard properties that can be viewed using Windows /// Explorer and are defined by COM. The rows of the table are written to the property stream as pairs of property ID numbers and /// corresponding data values. See Summary Information Stream Property Set. Date and time in _SummaryInformation are in the format: /// YYYY/MM/DD hh::mm::ss. For example, 1999/03/22 15:25:45. If the table contains binary streams, the name of the stream is in the /// data field, and the actual stream is retrieved from a file of that name in a subfolder with the same name as the table. /// /// /// Text archive files that are exported from a database by MsiDatabaseExport are intended for use with version control systems, and /// are not intended to be used as a means of editing data. Use the database API functions and tools designed for that purpose. Note /// that control characters in text archive files are translated to avoid conflicts with file delimiters. If a text archive file /// contains non-ASCII data, it is stamped with the code page of the data, and can only be imported into a database of that exact /// code page, or into a neutral database. Neutral databases are set to the code page of the imported file. A database can be /// unconditionally set to a particular code page by importing a pseudo table named: _ForceCodepage. The format of such a file is: /// Two blank lines, followed by a line that contains the numeric code page, a tab delimiter and the exact string: _ForceCodepage /// /// /// This function cannot be called from custom actions. A call to this function from a custom action causes the function to fail. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidatabaseimporta UINT MsiDatabaseImportA( MSIHANDLE // hDatabase, LPCSTR szFolderPath, LPCSTR szFileName ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDatabaseImportA")] public static extern Win32Error MsiDatabaseImport(MSIHANDLE hDatabase, [MarshalAs(UnmanagedType.LPTStr)] string szFolderPath, [MarshalAs(UnmanagedType.LPTStr)] string szFileName); /// The MsiDatabaseIsTablePersistent function returns an enumeration that describes the state of a specific table. /// /// Handle to the database that belongs to the relevant table. For more information, see Obtaining a Database Handle. /// /// Specifies the name of the relevant table. /// This function returns MSICONDITION. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidatabaseistablepersistenta MSICONDITION // MsiDatabaseIsTablePersistentA( MSIHANDLE hDatabase, LPCSTR szTableName ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDatabaseIsTablePersistentA")] public static extern MSICONDITION MsiDatabaseIsTablePersistent(MSIHANDLE hDatabase, [MarshalAs(UnmanagedType.LPTStr)] string szTableName); /// The MsiDatabaseMerge function merges two databases together, which allows duplicate rows. /// The handle to the database obtained from MsiOpenDatabase. /// The handle to the database obtained from MsiOpenDatabase to merge into the base database. /// The name of the table to receive merge conflict information. /// /// The MsiDatabaseMerge function returns one of the following values: /// /// /// Return code /// Description /// /// /// ERROR_FUNCTION_FAILED /// Row merge conflicts were reported. /// /// /// ERROR_INVALID_HANDLE /// An invalid or inactive handle was supplied. /// /// /// ERROR_INVALID_TABLE /// An invalid table was supplied. /// /// /// ERROR_SUCCESS /// The function succeeded. /// /// /// ERROR_DATATYPE_MISMATCH /// Schema difference between the two databases. /// /// /// /// /// /// The MsiDatabaseMerge function and the Merge method of the Database object cannot be used to merge a module that is /// included in the installation package. They should not be used to merge Merge Modules into a Windows Installer package. To /// include a merge module in an installation package, authors of installation packages should follow the guidelines that are /// described in the Applying Merge Modules topic. /// /// /// MsiDatabaseMerge does not copy over embedded Cabinet Files or embedded transforms from the reference database into the /// target database. Embedded data streams that are listed in the Binary Table or Icon Table are copied from the reference database /// to the target database. Storage embedded in the reference database are not copied to the target database. /// /// /// The MsiDatabaseMerge function merges the data of two databases. These databases must have the same code page. /// MsiDatabaseMerge fails if any tables or rows in the databases conflict. A conflict exists if the data in any row in the /// first database differs from the data in the corresponding row of the second database. Corresponding rows are in the same table /// of both databases and have the same primary key in both databases. The tables of non-conflicting databases must have the same /// number of primary keys, same number of columns, same column types, same column names, and the same data in rows with identical /// primary keys. Temporary columns however don't matter in the column count and corresponding tables can have a different number of /// temporary columns without creating conflict as long as the persistent columns match. /// /// /// If the number, type, or name of columns in corresponding tables are different, the schema of the two databases are incompatible /// and the installer stops processing tables and the merge fails. The installer checks that the two databases have the same schema /// before checking for row merge conflicts. If ERROR_DATATYPE_MISMATCH is returned, you are guaranteed that the databases have not /// been changed. /// /// /// If the data in particular rows differ, this is a row merge conflict, the installer returns ERROR_FUNCTION_FAILED and creates a /// new table named szTableName. The first column of this table is the name of the table having the conflict. The second column /// gives the number of rows in the table having the conflict. The table that reports conflicts appears as follows. /// /// /// /// Column /// Type /// Key /// Nullable /// /// /// Table /// Text /// Y /// N /// /// /// NumRowMergeConflicts /// Integer /// /// N /// /// /// /// This function cannot be called from custom actions. A call to this function from a custom action causes the function to fail. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidatabasemergea UINT MsiDatabaseMergeA( MSIHANDLE // hDatabase, MSIHANDLE hDatabaseMerge, LPCSTR szTableName ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDatabaseMergeA")] public static extern Win32Error MsiDatabaseMerge(MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, [MarshalAs(UnmanagedType.LPTStr)] string szTableName); /// /// The MsiDatabaseOpenView function prepares a database query and creates a view object. This function returns a handle that /// should be closed using MsiCloseHandle. /// /// /// Handle to the database to which you want to open a view object. You can get the handle as described in Obtaining a Database Handle. /// /// Specifies a SQL query string for querying the database. For correct syntax, see SQL Syntax. /// Pointer to a handle for the returned view. /// The MsiDatabaseOpenView function returns one of the following values: /// /// /// The MsiDatabaseOpenView function opens a view object for a database. You must open a view object for a database before /// performing any execution or fetching. /// /// If an error occurs, you can call MsiGetLastErrorRecord for more information. /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidatabaseopenviewa UINT MsiDatabaseOpenViewA( MSIHANDLE // hDatabase, LPCSTR szQuery, MSIHANDLE *phView ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDatabaseOpenViewA")] public static extern Win32Error MsiDatabaseOpenView(MSIHANDLE hDatabase, [MarshalAs(UnmanagedType.LPTStr)] string szQuery, out PMSIHANDLE phView); /// The MsiDoAction function executes a built-in action, custom action, or user-interface wizard action. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the action to execute. /// This function returns UINT. /// /// /// The MsiDoAction function executes the action that corresponds to the name supplied. If the name is not recognized by the /// installer as a built-in action or as a custom action in the CustomAction table, the name is passed to the user-interface handler /// object, which can invoke a function or a dialog box. If a null action name is supplied, the installer uses the upper-case value /// of the ACTION property as the action to perform. If no property value is defined, the default action is performed, defined as "INSTALL". /// /// /// Actions that update the system, such as the InstallFiles and WriteRegistryValues actions, cannot be run by calling /// MsiDoAction. The exception to this rule is if MsiDoAction is called from a custom action that is scheduled in the /// InstallExecuteSequence table between the InstallInitialize and InstallFinalize actions. Actions that do not update the system, /// such as AppSearch or CostInitialize, can be called. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msidoactiona UINT MsiDoActionA( MSIHANDLE hInstall, // LPCSTR szAction ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiDoActionA")] public static extern Win32Error MsiDoAction(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szAction); /// /// The MsiEnableUIPreview function enables preview mode of the user interface to facilitate authoring of user-interface /// dialog boxes. This function returns a handle that should be closed using MsiCloseHandle. /// /// Handle to the database. /// Pointer to a returned handle for user-interface preview capability. /// This function returns UINT. /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msienableuipreview UINT MsiEnableUIPreview( MSIHANDLE // hDatabase, MSIHANDLE *phPreview ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiEnableUIPreview")] public static extern Win32Error MsiEnableUIPreview(MSIHANDLE hDatabase, out PMSIHANDLE phPreview); /// /// /// The MsiEnumComponentCosts function enumerates the disk-space per drive required to install a component. This information /// is needed to display the disk-space cost required for all drives in the user interface. The returned disk-space costs are /// expressed in multiples of 512 bytes. /// /// /// MsiEnumComponentCosts should only be run after the installer has completed file costing and after the CostFinalize /// action. For more information, see File Costing. /// /// /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// /// A null-terminated string specifying the component's name as it is listed in the Component column of the Component table. This /// parameter can be null. If szComponent is null or an empty string, MsiEnumComponentCosts enumerates the total disk-space /// per drive used during the installation. In this case, iState is ignored. The costs of the installer include those costs for /// caching the database in the secure folder as well as the cost to create the installation script. Note that the total disk-space /// used during the installation may be larger than the space used after the component is installed. /// /// /// 0-based index for drives. This parameter should be zero for the first call to the MsiEnumComponentCosts function and then /// incremented for subsequent calls. /// /// /// Requested component state to be enumerated. If szComponent is passed as Null or an empty string, the installer ignores the /// iState parameter. /// /// /// Buffer that holds the drive name including the null terminator. This is an empty string in case of an error. /// /// /// Pointer to a variable that specifies the size, in TCHARs, of the buffer pointed to by the lpDriveBuf parameter. This size should /// include the terminating null character. If the buffer provided is too small, the variable pointed to by pcchDriveBuf contains /// the count of characters not including the null terminator. /// /// /// Cost of the component per drive expressed in multiples of 512 bytes. This value is 0 if an error has occurred. The value /// returned in piCost is final disk-space used by the component after installation. If szComponent is passed as Null or an empty /// string, the installer sets the value at piCost to 0. /// /// /// The component cost per drive for the duration of the installation, or 0 if an error occurred. The value in *piTempCost /// represents the temporary space requirements for the duration of the installation. This temporary space requirement is space /// needed only for the duration of the installation. This does not affect the final disk space requirement. /// /// /// /// /// Return Value /// Meaning /// /// /// ERROR_INVALID_HANDLE_STATE /// The configuration data is corrupt. /// /// /// ERROR_INVALID_PARAMETER /// An invalid parameter was passed to the function. /// /// /// ERROR_NO_MORE_ITEMS /// There are no more drives to return. /// /// /// ERROR_SUCCESS /// A value was enumerated. /// /// /// ERROR_UNKNOWN_COMPONENT /// The component is missing. /// /// /// ERROR_FUNCTION_NOT_CALLED /// Costing is not complete. /// /// /// ERROR_MORE_DATA /// Buffer not large enough for the drive name. /// /// /// ERROR_INVALID_HANDLE /// The supplied handle is invalid or inactive. /// /// /// /// /// /// The recommended method for enumerating the disk-space costs per drive is as follows. Start with the dwIndex set to 0 and /// increment it by one after each call. Continue the enumeration as long as MsiEnumComponentCosts returns ERROR_SUCCESS. /// /// MsiEnumComponentCosts may be called from custom actions. /// /// The total final disk cost for the installation is the sum of the costs of all components plus the cost of the Windows Installer /// (szComponent = null). /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msienumcomponentcostsa UINT MsiEnumComponentCostsA( // MSIHANDLE hInstall, LPCSTR szComponent, DWORD dwIndex, INSTALLSTATE iState, LPSTR szDriveBuf, LPDWORD pcchDriveBuf, LPINT piCost, // LPINT piTempCost ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiEnumComponentCostsA")] public static extern Win32Error MsiEnumComponentCosts(MSIHANDLE hInstall, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szComponent, uint dwIndex, INSTALLSTATE iState, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szDriveBuf, ref uint pcchDriveBuf, out int piCost, out int piTempCost); /// The MsiEvaluateCondition function evaluates a conditional expression containing property names and values. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// /// Specifies the conditional expression. This parameter must not be NULL. For the syntax of conditional expressions see /// Conditional Statement Syntax. /// /// This function returns MSICONDITION. /// /// /// The following table shows the feature and component state values used by the MsiEvaluateCondition function. These states /// are not set until MsiSetInstallLevel is called, either directly or by the CostFinalize action. Therefore, state checking is /// generally only useful for conditional expressions in an action sequence table. /// /// /// /// Value /// Meaning /// /// /// INSTALLSTATE_ABSENT /// Feature or component not present. /// /// /// INSTALLSTATE_LOCAL /// Feature or component on local computer. /// /// /// INSTALLSTATE_SOURCE /// Feature or component run from source. /// /// /// (null value) /// No action to be taken on feature or component. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msievaluateconditiona MSICONDITION MsiEvaluateConditionA( // MSIHANDLE hInstall, LPCSTR szCondition ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiEvaluateConditionA")] public static extern MSICONDITION MsiEvaluateCondition(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szCondition); /// The MsiFormatRecord function formats record field data and properties using a format string. /// /// Handle to the installation. This may be omitted, in which case only the record field parameters are processed and properties are /// not available for substitution. /// /// /// Handle to the record to format. The template string must be stored in record field 0 followed by referenced data parameters. /// /// /// Pointer to the buffer that receives the null terminated formatted string. Do not attempt to determine the size of the buffer by /// passing in a null (value=0) for szResultBuf. You can get the size of the buffer by passing in an empty string (for example ""). /// The function then returns ERROR_MORE_DATA and pcchResultBuf contains the required buffer size in TCHAR s, not /// including the terminating null character. On return of ERROR_SUCCESS, pcchResultBuf contains the number of TCHAR s /// written to the buffer, not including the terminating null character. /// /// /// Pointer to the variable that specifies the size, in TCHAR s, of the buffer pointed to by the variable szResultBuf. When /// the function returns ERROR_SUCCESS, this variable contains the size of the data copied to szResultBuf, not including the /// terminating null character. If szResultBuf is not large enough, the function returns ERROR_MORE_DATA and stores the /// required size, not including the terminating null character, in the variable pointed to by pcchResultBuf. /// /// The MsiFormatRecord function returns one of the following values: /// /// The MsiFormatRecord function uses the following format process. /// /// Parameters that are to be formatted are enclosed in square brackets [...]. The square brackets can be iterated because the /// substitutions are resolved from the inside out. /// /// /// If a part of the string is enclosed in curly braces { } and contains no square brackets, it is left unchanged, including the /// curly braces. /// /// /// If a part of the string is enclosed in curly braces { } and contains one or more property names, and if all the properties are /// found, the text (with the resolved substitutions) is displayed without the curly braces. If any of the properties is not found, /// all the text in the braces and the braces themselves are removed. /// /// /// Note in the case of deferred execution custom actions, MsiFormatRecord only supports CustomActionData and /// ProductCode properties. For more information, see Obtaining Context Information for Deferred Execution Custom Actions. /// /// The following steps describe how to format strings using the MsiFormatRecord function: /// To format strings using the MsiFormatRecord function /// /// /// /// The numeric parameters are substituted by replacing the marker with the value of the corresponding record field, with missing or /// null values producing no text. /// /// /// /// The resultant string is processed by replacing the nonrecord parameters with the corresponding values, described next. /// /// /// /// If ERROR_MORE_DATA is returned, the parameter which is a pointer gives the size of the buffer required to hold the /// string. If ERROR_SUCCESS is returned, it gives the number of characters written to the string buffer. Therefore you can /// get the size of the buffer by passing in an empty string (for example "") for the parameter that specifies the buffer. Do not /// attempt to determine the size of the buffer by passing in a Null (value=0). /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiformatrecorda UINT MsiFormatRecordA( MSIHANDLE // hInstall, MSIHANDLE hRecord, LPSTR szResultBuf, LPDWORD pcchResultBuf ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiFormatRecordA")] public static extern Win32Error MsiFormatRecord([Optional] MSIHANDLE hInstall, MSIHANDLE hRecord, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder szResultBuf, ref uint pcchResultBuf); /// /// The MsiGetActiveDatabase function returns the active database for the installation. This function returns a read-only /// handle that should be closed using MsiCloseHandle. /// /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// /// If the function succeeds, it returns a read-only handle to the database currently in use by the installer. If the function /// fails, the function returns zero, 0. /// /// /// The MsiGetActiveDatabase function accesses the database in use by the running the installation. /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetactivedatabase MSIHANDLE MsiGetActiveDatabase( // MSIHANDLE hInstall ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetActiveDatabase")] public static extern PMSIHANDLE MsiGetActiveDatabase(MSIHANDLE hInstall); /// The MsiGetComponentState function obtains the state of a component. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// A null-terminated string that specifies the component name within the product. /// /// Receives the current installed state. This parameter must not be null. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// INSTALLSTATE_ABSENT /// The component is not installed. /// /// /// INSTALLSTATE_DEFAULT /// The component is installed in the default location: local or source. /// /// /// INSTALLSTATE_LOCAL /// The component is installed on the local drive. /// /// /// INSTALLSTATE_REMOVED /// The component is being removed. In action state and not settable. /// /// /// INSTALLSTATE_SOURCE /// The component runs from the source, CD-ROM, or network. /// /// /// INSTALLSTATE_UNKNOWN /// An unrecognized product or feature name was passed to the function. /// /// /// /// /// Receives the action taken during the installation. This parameter must not be null. For return values, see piInstalled. /// /// The MsiGetComponentState function returns the following values: /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// For more information, see Calling Database Functions From Programs. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetcomponentstatea UINT MsiGetComponentStateA( // MSIHANDLE hInstall, LPCSTR szComponent, INSTALLSTATE *piInstalled, INSTALLSTATE *piAction ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetComponentStateA")] public static extern Win32Error MsiGetComponentState(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szComponent, out INSTALLSTATE piInstalled, out INSTALLSTATE piAction); /// The MsiGetDatabaseState function returns the state of the database. /// Handle to the database obtained from MsiOpenDatabase. /// This function returns MSIDBSTATE. /// The MsiGetDatabaseState function returns the update state of the database. // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetdatabasestate MSIDBSTATE MsiGetDatabaseState( // MSIHANDLE hDatabase ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetDatabaseState")] public static extern MSIDBSTATE MsiGetDatabaseState(MSIHANDLE hDatabase); /// /// The MsiGetFeatureCost function returns the disk space required by a feature and its selected children and parent features. /// /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the name of the feature. /// /// /// Specifies the value the function uses to determine disk space requirements. This parameter can be one of the following values. /// /// /// /// Value /// Meaning /// /// /// MSICOSTTREE_CHILDREN /// The children of the indicated feature are included in the cost. /// /// /// MSICOSTTREE_PARENTS /// The parent features of the indicated feature are included in the cost. /// /// /// MSICOSTTREE_SELFONLY /// The feature only is included in the cost. /// /// /// /// /// Specifies the installation state. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// INSTALLSTATE_UNKNOWN /// The product or feature is unrecognized. /// /// /// INSTALLSTATE_ABSENT /// The product or feature is uninstalled. /// /// /// INSTALLSTATE_LOCAL /// The product or feature is installed on the local drive. /// /// /// INSTALLSTATE_SOURCE /// The product or feature is installed to run from source, CD, or network. /// /// /// INSTALLSTATE_DEFAULT /// The product or feature will be installed to use the default location: local or source. /// /// /// /// Receives the disk space requirements in units of 512 bytes. This parameter must not be null. /// The MsiGetFeatureCost function returns the following values: /// /// See Calling Database Functions From Programs. /// /// With the MsiGetFeatureCost function, the MSICOSTTREE_SELFONLY value indicates the total amount of disk space (in units of /// 512 bytes) required by the specified feature only. This returned value does not include the children or the parent features of /// the specified feature. This total cost is made up of the disk costs attributed to every component linked to the feature. /// /// /// The MSICOSTTREE_CHILDREN value indicates the total amount of disk space (in units of 512 bytes) required by the specified /// feature and its children. For each feature, the total cost is made up of the disk costs attributed to every component linked to /// the feature. /// /// /// The MSICOSTTREE_PARENTS value indicates the total amount of disk space (in units of 512 bytes) required by the specified feature /// and its parent features (up to the root of the Feature table). For each feature, the total cost is made up of the disk costs /// attributed to every component linked to the feature. /// /// /// MsiGetFeatureCost is dependent upon several other functions to be successful. The following example demonstrates the /// order in which these functions must be called: /// /// /// MSIHANDLE hInstall; //product handle, must be closed int iCost; //cost returned by MsiGetFeatureCost MsiOpenPackage("Path to package....",&hInstall); //"Path to package...." should be replaced with the full path to the package to be opened MsiDoAction(hInstall,"CostInitialize"); // MsiDoAction(hInstall,"FileCost"); MsiDoAction(hInstall,"CostFinalize"); MsiDoAction(hInstall,"InstallValidate"); MsiGetFeatureCost(hInstall,"FeatureName",MSICOSTTREE_SELFONLY,INSTALLSTATE_ABSENT,&iCost); MsiCloseHandle(hInstall); //close the open product handle /// /// The process to query the cost of features scheduled to be removed is slightly different: /// /// MSIHANDLE hInstall; //product handle, must be closed int iCost; //cost returned by MsiGetFeatureCost MsiOpenPackage("Path to package....",&hInstall); //"Path to package...." should be replaced with the full path to the package to be opened MsiDoAction(hInstall,"CostInitialize"); // MsiDoAction(hInstall,"FileCost"); MsiDoAction(hInstall,"CostFinalize"); MsiSetFeatureState(hInstall,"FeatureName",INSTALLSTATE_ABSENT); //set the feature's state to "not installed" MsiDoAction(hInstall,"InstallValidate"); MsiGetFeatureCost(hInstall,"FeatureName",MSICOSTTREE_SELFONLY,INSTALLSTATE_ABSENT,&iCost); MsiCloseHandle(hInstall); //close the open product handle /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetfeaturecosta UINT MsiGetFeatureCostA( MSIHANDLE // hInstall, LPCSTR szFeature, MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetFeatureCostA")] public static extern Win32Error MsiGetFeatureCost(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szFeature, MSICOSTTREE iCostTree, INSTALLSTATE iState, out int piCost); /// The MsiGetFeatureState function gets the requested state of a feature. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the feature name within the product. /// /// /// Specifies the returned current installed state. This parameter must not be null. This parameter can be one of the following values. /// /// /// /// Value /// Meaning /// /// /// INSTALLSTATE_BADCONFIG /// The configuration data is corrupt. /// /// /// INSTALLSTATE_INCOMPLETE /// The installation is suspended or in progress. /// /// /// INSTALLSTATE_SOURCEABSENT /// The feature must run from the source, and the source is unavailable. /// /// /// INSTALLSTATE_MOREDATA /// The return buffer is full. /// /// /// INSTALLSTATE_INVALIDARG /// An invalid parameter was passed to the function. /// /// /// INSTALLSTATE_UNKNOWN /// An unrecognized product or feature was specified. /// /// /// INSTALLSTATE_BROKEN /// The feature is broken. /// /// /// INSTALLSTATE_ADVERTISED /// The advertised feature. /// /// /// INSTALLSTATE_ABSENT /// The feature was uninstalled. /// /// /// INSTALLSTATE_LOCAL /// The feature was installed on the local drive. /// /// /// INSTALLSTATE_SOURCE /// The feature must run from the source, CD-ROM, or network. /// /// /// INSTALLSTATE_DEFAULT /// The feature is installed in the default location: local or source. /// /// /// /// /// Receives the action taken during the installation session. This parameter must not be null. For return values, see piInstalled. /// /// The MsiGetFeatureState function returns the following values: /// /// See Calling Database Functions From Programs. /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetfeaturestatea UINT MsiGetFeatureStateA( MSIHANDLE // hInstall, LPCSTR szFeature, INSTALLSTATE *piInstalled, INSTALLSTATE *piAction ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetFeatureStateA")] public static extern Win32Error MsiGetFeatureState(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szFeature, out INSTALLSTATE piInstalled, out INSTALLSTATE piAction); /// The MsiGetFeatureValidStates function returns a valid installation state. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the feature name. /// /// /// Receives the location to hold the valid installation states. For each valid installation state, the installer sets pInstallState /// to a combination of the following values. This parameter should not be null. /// /// /// /// Decimal Value /// Meaning /// /// /// 2 INSTALLSTATE_ADVERTISED /// The feature can be advertised. /// /// /// 4 INSTALLSTATE_ABSENT /// The feature can be absent. /// /// /// 8 INSTALLSTATE_LOCAL /// The feature can be installed on the local drive. /// /// /// 16 INSTALLSTATE_SOURCE /// The feature can be configured to run from source, CD-ROM, or network. /// /// /// 32 INSTALLSTATE_DEFAULT /// The feature can be configured to use the default location: local or source. /// /// /// /// The MsiGetFeatureValidStates function returns the following values: /// /// See Calling Database Functions From Programs. /// /// The MsiGetFeatureValidStates function determines state validity by querying all components that are linked to the /// specified feature without taking into account the current installed state of any component. /// /// The possible valid states for a feature are determined as follows: /// /// /// If the feature does not contain components, both INSTALLSTATE_LOCAL and INSTALLSTATE_SOURCE are valid states for the feature. /// /// /// /// If at least one component of the feature has an attribute of msidbComponentAttributesLocalOnly or /// msidbComponentAttributesOptional, INSTALLSTATE_LOCAL is a valid state for the feature. /// /// /// /// /// If at least one component of the feature has an attribute of msidbComponentAttributesSourceOnly or /// msidbComponentAttributesOptional, INSTALLSTATE_SOURCE is a valid state for the feature. /// /// /// /// /// If a file of a component that belongs to the feature is patched or from a compressed source, then INSTALLSTATE_SOURCE is not /// included as a valid state for the feature. /// /// /// /// /// INSTALLSTATE_ADVERTISE is not a valid state if the feature disallows advertisement (msidbFeatureAttributesDisallowAdvertise) or /// the feature requires platform support for advertisement (msidbFeatureAttributesNoUnsupportedAdvertise) and the platform does not /// support it. /// /// /// /// INSTALLSTATE_ABSENT is a valid state for the feature if its attributes do not include msidbFeatureAttributesUIDisallowAbsent. /// /// /// /// Valid states for child features marked to follow the parent feature (msidbFeatureAttributesFollowParent) are based upon the /// parent feature's action or installed state. /// /// /// /// /// After calling MsiGetFeatureValidStates a conditional statement may then be used to test the valid installation states of /// a feature. For example, the following call to MsiGetFeatureValidStates gets the installation state of Feature1. /// /// /// MsiGetFeatureValidStates(hProduct, "Feature1", &dwValidStates); /// /// /// If Feature1 has attributes of value 0 (favor local), and Feature1 has one component with attributes of value 0 (local only), the /// value of dwValidStates after the call is 14. This indicates that INSTALLSTATE_LOCAL, INSTALLSTATE_ABSENT,and /// INSTALLSTATE_ADVERTISED are valid states for Feature1. The following conditional statement evaluates to True if local is a valid /// state for this feature. /// /// ( ( dwValidStates & ( 1 << INSTALLSTATE_LOCAL ) ) == ( 1 << INSTALLSTATE_LOCAL ) ) /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetfeaturevalidstatesw UINT MsiGetFeatureValidStatesW( // MSIHANDLE hInstall, LPCWSTR szFeature, LPDWORD lpInstallStates ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetFeatureValidStatesW")] public static extern Win32Error MsiGetFeatureValidStates(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szFeature, out INSTALLSTATE lpInstallStates); /// The MsiGetLanguage function returns the numeric language of the installation that is currently running. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// /// If the function succeeds, the return value is the numeric LANGID for the install. /// If the function fails, the return value can be the following value. /// /// The MsiGetLanguage function returns 0 if an installation is not running. // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetlanguage LANGID MsiGetLanguage( MSIHANDLE hInstall ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetLanguage")] public static extern ushort MsiGetLanguage(MSIHANDLE hInstall); /// /// The MsiGetLastErrorRecord function returns the error record that was last returned for the calling process. This function /// returns a handle that should be closed using MsiCloseHandle. /// /// A handle to the error record. If the last function was successful, MsiGetLastErrorRecord returns a null MSIHANDLE. /// /// /// With the MsiGetLastErrorRecord function, field 1 of the record contains the installer error code. Other fields contain /// data specific to the particular error. The error record is released internally after this function is run. /// /// /// If the record is passed to MsiProcessMessage, it is formatted by looking up the string in the current database. If there is no /// installation session but a product database is open, the format string may be obtained by a query on the Error table using the /// error code, followed by a call to MsiFormatRecord. If the error code is known, the parameters may be individually interpreted. /// /// /// The following functions set the per-process error record or reset it to null if no error occurred. MsiGetLastErrorRecord /// also clears the error record after returning it. /// /// /// /// MsiOpenDatabase /// /// /// MsiDatabaseCommit /// /// /// MsiDatabaseOpenView /// /// /// MsiDatabaseImport /// /// /// MsiDatabaseExport /// /// /// MsiDatabaseMerge /// /// /// MsiDatabaseGenerateTransform /// /// /// MsiDatabaseApplyTransform /// /// /// MsiViewExecute /// /// /// MsiViewModify /// /// /// MsiRecordSetStream /// /// /// MsiGetSummaryInformation /// /// /// MsiGetSourcePath /// /// /// MsiGetTargetPath /// /// /// MsiSetTargetPath /// /// /// MsiGetComponentState /// /// /// MsiSetComponentState /// /// /// MsiGetFeatureState /// /// /// MsiSetFeatureState /// /// /// MsiGetFeatureCost /// /// /// MsiGetFeatureValidStates /// /// /// MsiSetInstallLevel /// /// /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// /// The following sample uses a call to MsiDatabaseOpenView to show how to obtain extended error information from one of the Windows /// Installer functions that supports MsiGetLastErrorRecord. The example, OpenViewOnDatabase, attempts to open a view on a /// database handle. The hDatabase handle can be obtained by a call to MsiOpenDatabase. If opening the view fails, the function then /// tries to obtain extended error information by using MsiGetLastErrorRecord. /// /// /// #include <windows.h> #include <Msiquery.h> #pragma comment(lib, "msi.lib") //------------------------------------------------------------------- // Function: OpenViewOnDatabase // // Arguments: hDatabase - handle to a MSI package obtained // via a call to MsiOpenDatabase // // Returns: UINT status code. ERROR_SUCCESS for success. //-------------------------------------------------------------------------------------------------- UINT __stdcall OpenViewOnDatabase(MSIHANDLE hDatabase) { if (!hDatabase) return ERROR_INVALID_PARAMETER; PMSIHANDLE hView = 0; UINT uiReturn = MsiDatabaseOpenView(hDatabase, TEXT("SELECT * FROM `UnknownTable`"), &hView); if (ERROR_SUCCESS != uiReturn) { // try to obtain extended error information. PMSIHANDLE hLastErrorRec = MsiGetLastErrorRecord(); TCHAR* szExtendedError = NULL; DWORD cchExtendedError = 0; if (hLastErrorRec) { // Since we are not currently calling MsiFormatRecord during an // install session, hInstall is NULL. If MsiFormatRecord was called // via a DLL custom action, the hInstall handle provided to the DLL // custom action entry point could be used to further resolve // properties that might be contained within the error record. // To determine the size of the buffer required for the text, // szResultBuf must be provided as an empty string with // *pcchResultBuf set to 0. UINT uiStatus = MsiFormatRecord(NULL, hLastErrorRec, TEXT(""), &cchExtendedError); if (ERROR_MORE_DATA == uiStatus) { // returned size does not include null terminator. cchExtendedError++; szExtendedError = new TCHAR[cchExtendedError]; if (szExtendedError) { uiStatus = MsiFormatRecord(NULL, hLastErrorRec, szExtendedError, &cchExtendedError); if (ERROR_SUCCESS == uiStatus) { // We now have an extended error // message to report. // PLACE ADDITIONAL CODE HERE // TO LOG THE ERROR MESSAGE // IN szExtendedError. } delete [] szExtendedError; szExtendedError = NULL; } } } } return uiReturn; } /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetlasterrorrecord MSIHANDLE MsiGetLastErrorRecord(); [DllImport(Lib_Msi, SetLastError = true, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetLastErrorRecord")] public static extern PMSIHANDLE MsiGetLastErrorRecord(); /// /// The MsiGetMode function is used to determine whether the installer is currently running in a specified mode, as listed in /// the table. The function returns a Boolean value of TRUE or FALSE, indicating whether the specific property passed /// into the function is currently set ( TRUE) or not set ( FALSE). /// /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// /// Specifies the run mode. This parameter must have one of the following values. /// /// /// Value /// Meaning /// /// /// MSIRUNMODE_ADMIN /// The administrative mode is installing, or the product is installing. /// /// /// MSIRUNMODE_ADVERTISE /// The advertisements are installing or the product is installing or updating. /// /// /// MSIRUNMODE_MAINTENANCE /// An existing installation is being modified or there is a new installation. /// /// /// MSIRUNMODE_ROLLBACKENABLED /// Rollback is enabled. /// /// /// MSIRUNMODE_LOGENABLED /// The log file is active. It was enabled prior to the installation session. /// /// /// MSIRUNMODE_OPERATIONS /// Execute operations are in the determination phase. /// /// /// MSIRUNMODE_REBOOTATEND /// A reboot is necessary after a successful installation (settable). /// /// /// MSIRUNMODE_REBOOTNOW /// A reboot is necessary to continue the installation (settable). /// /// /// MSIRUNMODE_CABINET /// Files from cabinets and Media table files are installing. /// /// /// MSIRUNMODE_SOURCESHORTNAMES /// The source LongFileNames is suppressed through the PID_MSISOURCE summary property. /// /// /// MSIRUNMODE_TARGETSHORTNAMES /// The target LongFileNames is suppressed through the SHORTFILENAMES property. /// /// /// MSIRUNMODE_RESERVED11 /// Reserved for future use. /// /// /// MSIRUNMODE_WINDOWS9X /// The operating system is a 9x version. /// /// /// MSIRUNMODE_ZAWENABLED /// The operating system supports demand installation. /// /// /// MSIRUNMODE_RESERVED14 /// Reserved for future use. /// /// /// MSIRUNMODE_RESERVED15 /// Reserved for future use. /// /// /// MSIRUNMODE_SCHEDULED /// A custom action called from install script execution. /// /// /// MSIRUNMODE_ROLLBACK /// A custom action called from rollback execution script. /// /// /// MSIRUNMODE_COMMIT /// A custom action called from commit execution script. /// /// /// /// /// TRUE indicates the specific property passed into the function is currently set. /// FALSE indicates the specific property passed into the function is currently not set. /// /// /// Note that not all the run mode values of iRunMode are available when calling MsiGetMode from a deferred custom action. /// For details, see Obtaining Context Information for Deferred Execution Custom Actions. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetmode BOOL MsiGetMode( MSIHANDLE hInstall, // MSIRUNMODE eRunMode ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetMode")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE eRunMode); /// The MsiGetProperty function gets the value for an installer property. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// A null-terminated string that specifies the name of the property. /// /// Pointer to the buffer that receives the null terminated string containing the value of the property. Do not attempt to determine /// the size of the buffer by passing in a null (value=0) for szValueBuf. You can get the size of the buffer by passing in an empty /// string (for example ""). The function will then return ERROR_MORE_DATA and pchValueBuf will contain the required buffer size in /// TCHARs, not including the terminating null character. On return of ERROR_SUCCESS, pcchValueBuf contains the number of TCHARs /// written to the buffer, not including the terminating null character. /// /// /// Pointer to the variable that specifies the size, in TCHARs, of the buffer pointed to by the variable szValueBuf. When the /// function returns ERROR_SUCCESS, this variable contains the size of the data copied to szValueBuf, not including the terminating /// null character. If szValueBuf is not large enough, the function returns ERROR_MORE_DATA and stores the required size, not /// including the terminating null character, in the variable pointed to by pchValueBuf. /// /// This function returns UINT. /// /// /// If the value for the property retrieved by the MsiGetProperty function is not defined, it is equivalent to a 0-length /// value. It is not an error. /// /// /// If ERROR_MORE_DATA is returned, the parameter which is a pointer gives the size of the buffer required to hold the string. If /// ERROR_SUCCESS is returned, it gives the number of characters written to the string buffer. Therefore you can get the size of the /// buffer by passing in an empty string (for example "") for the parameter that specifies the buffer. Do not attempt to determine /// the size of the buffer by passing in a Null (value=0). /// /// /// The following example shows how a DLL custom action could access the value of a property by dynamically determining the size of /// the value buffer. /// /// /// UINT __stdcall MyCustomAction(MSIHANDLE hInstall) { TCHAR* szValueBuf = NULL; DWORD cchValueBuf = 0; UINT uiStat = MsiGetProperty(hInstall, TEXT("MyProperty"), TEXT(""), &cchValueBuf); //cchValueBuf now contains the size of the property's string, without null termination if (ERROR_MORE_DATA == uiStat) { ++cchValueBuf; // add 1 for null termination szValueBuf = new TCHAR[cchValueBuf]; if (szValueBuf) { uiStat = MsiGetProperty(hInstall, TEXT("MyProperty"), szValueBuf, &cchValueBuf); } } if (ERROR_SUCCESS != uiStat) { if (szValueBuf != NULL) delete[] szValueBuf; return ERROR_INSTALL_FAILURE; } // custom action uses MyProperty // ... delete[] szValueBuf; return ERROR_SUCCESS; } /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetpropertya UINT MsiGetPropertyA( MSIHANDLE hInstall, // LPCSTR szName, LPSTR szValueBuf, LPDWORD pcchValueBuf ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetPropertyA")] public static extern Win32Error MsiGetProperty(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szName, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szValueBuf, ref uint pcchValueBuf); /// The MsiGetSourcePath function returns the full source path for a folder in the Directory table. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// /// A null-terminated string that specifies a record of the Directory table. If the directory is a root directory, this can be a /// value from the DefaultDir column. Otherwise it must be a value from the Directory column. /// /// /// Pointer to the buffer that receives the null terminated full source path. Do not attempt to determine the size of the buffer by /// passing in a null (value=0) for szPathBuf. You can get the size of the buffer by passing in an empty string (for example ""). /// The function then returns ERROR_MORE_DATA and pcchPathBuf contains the required buffer size in TCHARs, not including the /// terminating null character. On return of ERROR_SUCCESS, pcchPathBuf contains the number of TCHARs written to the buffer, not /// including the terminating null character. /// /// /// Pointer to the variable that specifies the size, in TCHARs, of the buffer pointed to by the variable szPathBuf. When the /// function returns ERROR_SUCCESS, this variable contains the size of the data copied to szPathBuf, not including the terminating /// null character. If szPathBuf is not large enough, the function returns ERROR_MORE_DATA and stores the required size, not /// including the terminating null character, in the variable pointed to by pcchPathBuf. /// /// The MsiGetSourcePath function returns the following values: /// /// /// Before calling this function, the installer must first run the CostInitialize action, FileCost action, and CostFinalize action. /// For more information, see Calling Database Functions from Programs. /// /// /// If ERROR_MORE_DATA is returned, the parameter which is a pointer gives the size of the buffer required to hold the string. If /// ERROR_SUCCESS is returned, it gives the number of characters written to the string buffer. Therefore you can get the size of the /// buffer by passing in an empty string (for example "") for the parameter that specifies the buffer. Do not attempt to determine /// the size of the buffer by passing in a Null (value=0). /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetsourcepatha UINT MsiGetSourcePathA( MSIHANDLE // hInstall, LPCSTR szFolder, LPSTR szPathBuf, LPDWORD pcchPathBuf ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetSourcePathA")] public static extern Win32Error MsiGetSourcePath(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szFolder, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szPathBuf, ref uint pcchPathBuf); /// /// The MsiGetSummaryInformation function obtains a handle to the _SummaryInformation stream for an installer database. This /// function returns a handle that should be closed using MsiCloseHandle. /// /// Handle to the database. /// Specifies the path to the database. /// Specifies the maximum number of updated values. /// Pointer to the location from which to receive the summary information handle. /// The MsiGetSummaryInformation function returns the following values: /// /// /// If the database specified by the MsiGetSummaryInformation function is not open, you must specify 0 for hDatabase and /// specify the path to the database in szDatabasePath. If the database is open, you must set szDatabasePath to 0. /// /// /// If a value of uiUpdateCount greater than 0 is used to open an existing summary information stream, MsiSummaryInfoPersist must be /// called before closing the phSummaryInfo handle. Failing to do this will lose the existing stream information. /// /// /// To view the summary information of a patch using MsiGetSummaryInformation, set szDatabasePath to the path to the patch. /// Alternately, you can create a handle to the patch using MsiOpenDatabase and then pass that handle to /// MsiGetSummaryInformation as the hDatabase parameter. /// /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigetsummaryinformationw UINT MsiGetSummaryInformationW( // MSIHANDLE hDatabase, LPCWSTR szDatabasePath, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetSummaryInformationW")] public static extern Win32Error MsiGetSummaryInformation(MSIHANDLE hDatabase, [MarshalAs(UnmanagedType.LPTStr)] string szDatabasePath, uint uiUpdateCount, out PMSIHANDLE phSummaryInfo); /// The MsiGetTargetPath function returns the full target path for a folder in the Directory table. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// /// A null-terminated string that specifies a record of the Directory table. If the directory is a root directory, this can be a /// value from the DefaultDir column. Otherwise it must be a value from the Directory column. /// /// /// Pointer to the buffer that receives the null terminated full target path. Do not attempt to determine the size of the buffer by /// passing in a null (value=0) for szPathBuf. You can get the size of the buffer by passing in an empty string (for example ""). /// The function then returns ERROR_MORE_DATA and pcchPathBuf contains the required buffer size in TCHARs, not including the /// terminating null character. On return of ERROR_SUCCESS, pcchPathBuf contains the number of TCHARs written to the buffer, not /// including the terminating null character. /// /// /// Pointer to the variable that specifies the size, in TCHARs, of the buffer pointed to by the variable szPathBuf When the /// function returns ERROR_SUCCESS, this variable contains the size of the data copied to szPathBuf, not including the terminating /// null character. If szPathBuf is not large enough, the function returns ERROR_MORE_DATA and stores the required size, not /// including the terminating null character, in the variable pointed to by pcchPathBuf. /// /// The MsiGetTargetPath function returns the following values: /// /// /// If ERROR_MORE_DATA is returned, the parameter which is a pointer gives the size of the buffer required to hold the string. If /// ERROR_SUCCESS is returned, it gives the number of characters written to the string buffer. Therefore you can get the size of the /// buffer by passing in an empty string (for example "") for the parameter that specifies the buffer. Do not attempt to determine /// the size of the buffer by passing in a Null (value=0). /// /// /// Before calling this function, the installer must first run the CostInitialize action, FileCost action, and CostFinalize action. /// For more information, see Calling Database Functions from Programs. /// /// /// MsiGetTargetPath returns the default path of the target directory authored in the package if the target's current /// location is unavailable for an installation. For example, if during a Maintenance Installation a target directory at a network /// location is unavailable, the installer resets the target directory paths back to their defaults. To get the actual path of the /// target directory in this case call MsiProvideComponent for a component that is known to have been previously installed into the /// searched for directory and set dwInstallMode to INSTALLMODE_NODETECTION. /// /// For more information, see Calling Database Functions From Programs. /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msigettargetpatha UINT MsiGetTargetPathA( MSIHANDLE // hInstall, LPCSTR szFolder, LPSTR szPathBuf, LPDWORD pcchPathBuf ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiGetTargetPathA")] public static extern Win32Error MsiGetTargetPath(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szFolder, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szPathBuf, ref uint pcchPathBuf); /// /// The MsiOpenDatabase function opens a database file for data access. This function returns a handle that should be closed /// using MsiCloseHandle. /// /// Specifies the full path or relative path to the database file. /// /// /// Receives the full path to the file or the persistence mode. You can use the szPersist parameter to direct the persistent output /// to a new file or to specify one of the following predefined persistence modes. /// /// /// /// Value /// Meaning /// /// /// MSIDBOPEN_CREATEDIRECT /// Create a new database, direct mode read/write. /// /// /// MSIDBOPEN_CREATE /// Create a new database, transact mode read/write. /// /// /// MSIDBOPEN_DIRECT /// Open a database direct read/write without transaction. /// /// /// MSIDBOPEN_READONLY /// Open a database read-only, no persistent changes. /// /// /// MSIDBOPEN_TRANSACT /// Open a database read/write in transaction mode. /// /// /// MSIDBOPEN_PATCHFILE /// Add this flag to indicate a patch file. /// /// /// /// Pointer to the location of the returned database handle. /// The MsiOpenDatabase function returns the following values: /// /// /// To make and save changes to a database first open the database in transaction (MSIDBOPEN_TRANSACT), create (MSIDBOPEN_CREATE or /// MSIDBOPEN_CREATEDIRECT), or direct (MSIDBOPEN_DIRECT) mode. After making the changes, always call MsiDatabaseCommit before /// closing the database handle. MsiDatabaseCommit flushes all buffers. /// /// /// Always call MsiDatabaseCommit on a database that has been opened in direct mode (MSIDBOPEN_DIRECT or MSIDBOPEN_CREATEDIRECT) /// before closing the database's handle. Failure to do this may corrupt the database. /// /// Because MsiOpenDatabase initiates database access, it cannot be used with a running installation. /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// /// Note When a database is opened as the output of another database, the summary information stream of the output database /// is actually a read-only mirror of the original database, and, thus, cannot be changed. Additionally, it is not persisted with /// the database. To create or modify the summary information for the output database, it must be closed and reopened. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiopendatabasea UINT MsiOpenDatabaseA( LPCSTR // szDatabasePath, LPCSTR szPersist, MSIHANDLE *phDatabase ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiOpenDatabaseA")] public static extern Win32Error MsiOpenDatabase([MarshalAs(UnmanagedType.LPTStr)] string szDatabasePath, [MarshalAs(UnmanagedType.LPTStr)] string szPersist, out PMSIHANDLE phDatabase); /// /// The MsiOpenDatabase function opens a database file for data access. This function returns a handle that should be closed /// using MsiCloseHandle. /// /// Specifies the full path or relative path to the database file. /// /// /// Receives the full path to the file or the persistence mode. You can use the szPersist parameter to direct the persistent output /// to a new file or to specify one of the following predefined persistence modes. /// /// /// /// Value /// Meaning /// /// /// MSIDBOPEN_CREATEDIRECT /// Create a new database, direct mode read/write. /// /// /// MSIDBOPEN_CREATE /// Create a new database, transact mode read/write. /// /// /// MSIDBOPEN_DIRECT /// Open a database direct read/write without transaction. /// /// /// MSIDBOPEN_READONLY /// Open a database read-only, no persistent changes. /// /// /// MSIDBOPEN_TRANSACT /// Open a database read/write in transaction mode. /// /// /// MSIDBOPEN_PATCHFILE /// Add this flag to indicate a patch file. /// /// /// /// Pointer to the location of the returned database handle. /// The MsiOpenDatabase function returns the following values: /// /// /// To make and save changes to a database first open the database in transaction (MSIDBOPEN_TRANSACT), create (MSIDBOPEN_CREATE or /// MSIDBOPEN_CREATEDIRECT), or direct (MSIDBOPEN_DIRECT) mode. After making the changes, always call MsiDatabaseCommit before /// closing the database handle. MsiDatabaseCommit flushes all buffers. /// /// /// Always call MsiDatabaseCommit on a database that has been opened in direct mode (MSIDBOPEN_DIRECT or MSIDBOPEN_CREATEDIRECT) /// before closing the database's handle. Failure to do this may corrupt the database. /// /// Because MsiOpenDatabase initiates database access, it cannot be used with a running installation. /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// /// Note When a database is opened as the output of another database, the summary information stream of the output database /// is actually a read-only mirror of the original database, and, thus, cannot be changed. Additionally, it is not persisted with /// the database. To create or modify the summary information for the output database, it must be closed and reopened. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiopendatabasea UINT MsiOpenDatabaseA( LPCSTR // szDatabasePath, LPCSTR szPersist, MSIHANDLE *phDatabase ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiOpenDatabaseA")] public static extern Win32Error MsiOpenDatabase([MarshalAs(UnmanagedType.LPTStr)] string szDatabasePath, [In] IntPtr szPersist, out PMSIHANDLE phDatabase); // Database open read-only, no persistent changes // Database read/write in transaction mode // Database direct read/write without transaction // Create new database, transact mode read/write // Create new database, direct mode read/write // add flag to indicate patch file /// The MsiPreviewBillboard function displays a billboard with the host control in the displayed dialog box. /// Handle to the preview. /// Specifies the name of the host control. /// Specifies the name of the billboard to display. /// This function returns UINT. /// Supplying a null billboard name in the MsiPreviewBillboard function removes any billboard displayed. // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msipreviewbillboarda UINT MsiPreviewBillboardA( MSIHANDLE // hPreview, LPCSTR szControlName, LPCSTR szBillboard ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiPreviewBillboardA")] public static extern Win32Error MsiPreviewBillboard(MSIHANDLE hPreview, [MarshalAs(UnmanagedType.LPTStr)] string szControlName, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szBillboard); /// The MsiPreviewDialog function displays a dialog box as modeless and inactive. /// Handle to the preview. /// Specifies the name of the dialog box to preview. /// This function returns UINT. /// Supplying a null name in the MsiPreviewDialog function removes any current dialog box. // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msipreviewdialogw UINT MsiPreviewDialogW( MSIHANDLE // hPreview, LPCWSTR szDialogName ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiPreviewDialogW")] public static extern Win32Error MsiPreviewDialog(MSIHANDLE hPreview, [MarshalAs(UnmanagedType.LPTStr)] string szDialogName); /// The MsiProcessMessage function sends an error record to the installer for processing. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// /// /// The eMessage parameter must be a value specifying one of the following message types. To display a message box with push buttons /// or icons, use OR-operators to add INSTALLMESSAGE_ERROR, INSTALLMESSAGE_WARNING, or INSTALLMESSAGE_USER to the standard message /// box styles used by the MessageBox and MessageBoxEx functions. For more information, see the Remarks below. /// /// /// /// Value /// Meaning /// /// /// INSTALLMESSAGE_FATALEXIT /// Premature termination, possibly fatal out of memory. /// /// /// INSTALLMESSAGE_ERROR /// Formatted error message,[1] is message number in Error table. /// /// /// INSTALLMESSAGE_WARNING /// Formatted warning message,[1] is message number in Error table. /// /// /// INSTALLMESSAGE_USER /// User request message,[1] is message number in Error table. /// /// /// INSTALLMESSAGE_INFO /// Informative message for log,not to be displayed. /// /// /// INSTALLMESSAGE_FILESINUSE /// List of files currently in use that must be closed before being replaced. /// /// /// INSTALLMESSAGE_RESOLVESOURCE /// Request to determine a valid source location. /// /// /// INSTALLMESSAGE_RMFILESINUSE /// /// List of files currently in use that must be closed before being replaced. Available beginning with Windows Installer version /// 4.0. For more information about this message see Using Restart Manager with an External UI. /// /// /// /// INSTALLMESSAGE_OUTOFDISKSPACE /// Insufficient disk space message. /// /// /// INSTALLMESSAGE_ACTIONSTART /// Progress: start of action,[1] action name,[2] description,[3] template for ACTIONDATA messages. /// /// /// INSTALLMESSAGE_ACTIONDATA /// Action data. Record fields correspond to the template of ACTIONSTART message. /// /// /// INSTALLMESSAGE_PROGRESS /// Progress bar information. See the description of record fields below. /// /// /// INSTALLMESSAGE_COMMONDATA /// To enable the Cancel button set [1] to 2 and [2] to 1. To disable the Cancel button set [1] to 2 and [2] to 0 /// /// /// /// Handle to a record containing message format and data. /// This function returns int. /// /// /// The MsiProcessMessage function performs any enabled logging operations and defers execution. You can selectively enable /// logging for various message types. /// /// /// For INSTALLMESSAGE_FATALEXIT, INSTALLMESSAGE_ERROR, INSTALLMESSAGE_WARNING, and INSTALLMESSAGE_USER messages, if field 0 is not /// set field 1 must be set to the error code corresponding to the error message in the Error table. Then, the message is formatted /// using the template from the Error table before passing it to the user-interface handler for display. /// /// Record Fields for Progress Bar Messages /// /// The following describes the record fields when eMessageType is set to INSTALLMESSAGE_PROGRESS. Field 1 specifies the type of the /// progress message. The meaning of the other fields depend upon the value in this field. The possible values that can be set into /// Field 1 are as follows. /// /// /// /// Field 1 value /// Field 1 description /// /// /// 0 /// Resets progress bar and sets the expected total number of ticks in the bar. /// /// /// 1 /// Provides information related to progress messages to be sent by the current action. /// /// /// 2 /// Increments the progress bar. /// /// /// 3 /// Enables an action (such as CustomAction) to add ticks to the expected total number of progress of the progress bar. /// /// /// The meaning of Field 2 depends upon the value in Field 1 as follows. /// /// /// Field 1 value /// Field 2 description /// /// /// 0 /// Expected total number of ticks in the progress bar. /// /// /// 1 /// /// Number of ticks the progress bar moves for each ActionData message that is sent by the current action. This field is ignored if /// Field 3 is 0. /// /// /// /// 2 /// Number of ticks the progress bar has moved. /// /// /// 3 /// Number of ticks to add to total expected progress. /// /// /// The meaning of Field 3 depends upon the value in Field 1 as follows. /// /// /// Field 1 value /// Field 3 value /// Field 3 description /// /// /// 0 /// 0 /// Forward progress bar (left to right) /// /// /// /// 1 /// Backward progress bar (right to left) /// /// /// 1 /// 0 /// The current action will send explicit ProgressReport messages. /// /// /// /// 1 /// /// Increment the progress bar by the number of ticks specified in Field 2 each time an ActionData message is sent by the current action. /// /// /// /// 2 /// Unused /// /// /// /// 3 /// Unused /// /// /// /// The meaning of Field 4 depends upon the value in Field 1 as follows. /// /// /// Field 1 value /// Field 4 value /// Field 4 description /// /// /// 0 /// 0 /// Execution is in progress. In this case, the UI could calculate and display the time remaining. /// /// /// /// 1 /// /// Creating the execution script. In this case, the UI could display a message to please wait while the installer finishes /// preparing the installation. /// /// /// /// 1 /// Unused /// /// /// /// 2 /// Unused /// /// /// /// 3 /// Unused /// /// /// /// For more information and a code sample, see Adding Custom Actions to the ProgressBar. /// Display of Message Boxes /// /// To display a message box with push buttons or icons, use OR-operators to add INSTALLMESSAGE_ERROR, INSTALLMESSAGE_WARNING, or /// INSTALLMESSAGE_USER with the message box options used by MessageBox and MessageBoxEx. The available push button options are /// MB_OK, MB_OKCANCEL, MB_ABORTRETRYIGNORE, MB_YESNOCANCEL, MB_YESNO, and MB_RETRYCANCEL. The available default button options are /// MB_DEFBUTTON1, MB_DEFBUTTON2, and MB_DEFBUTTON3. The available icon options are MB_ICONERROR, MB_ICONQUESTION, MB_ICONWARNING, /// and MB_ICONINFORMATION. If no icon options is specified, Windows Installer chooses a default icon style based upon the message type. /// /// /// For example, the following call to MsiProcessMessage sends an INSTALLMESSAGE_ERROR message with the MB_ICONWARNING icon /// and the MB_ABORTRETRYCANCEL buttons. /// /// /// PMSIHANDLE hInstall; PMSIHANDLE hRec; MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR|MB_ABORTRETRYIGNORE|MB_ICONWARNING), hRec); /// /// /// If a custom action calls MsiProcessMessage, the custom action should be capable of handling a cancellation by the user /// and should return ERROR_INSTALL_USEREXIT. /// /// /// For more information on sending messages with MsiProcessMessage, see the Sending Messages to Windows Installer Using MsiProcessMessage. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiprocessmessage int MsiProcessMessage( MSIHANDLE // hInstall, INSTALLMESSAGE eMessageType, MSIHANDLE hRecord ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiProcessMessage")] public static extern int MsiProcessMessage(MSIHANDLE hInstall, INSTALLMESSAGE eMessageType, MSIHANDLE hRecord); /// The MsiRecordClearData function sets all fields in a record to null. /// Handle to the record. /// This function returns UINT. // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecordcleardata UINT MsiRecordClearData( MSIHANDLE // hRecord ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordClearData")] public static extern Win32Error MsiRecordClearData(MSIHANDLE hRecord); /// /// The MsiRecordDataSize function returns the length of a record field. The count does not include the terminating null character. /// /// Handle to the record. /// Specifies a field of the record. /// /// /// The MsiRecordDataSize function returns 0 if the field is null, nonexistent, or an internal object pointer. The function /// also returns 0 if the handle is not a valid record handle. /// /// If the data is in integer format, the function returns sizeof(int). /// If the data is in string format, the function returns the character count (not including the null character). /// If the data is in stream format, the function returns the byte count. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecorddatasize UINT MsiRecordDataSize( MSIHANDLE // hRecord, UINT iField ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordDataSize")] public static extern uint MsiRecordDataSize(MSIHANDLE hRecord, uint iField); /// The MsiRecordGetFieldCount function returns the number of fields in a record. /// Handle to a record. /// If the function succeeds, the return value is the number of fields in the record. /// /// The count returned by the MsiRecordGetFieldCount parameter does not include field 0. Read access to fields beyond this /// count returns null values. Write access fails. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecordgetfieldcount UINT MsiRecordGetFieldCount( // MSIHANDLE hRecord ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordGetFieldCount")] public static extern uint MsiRecordGetFieldCount(MSIHANDLE hRecord); /// The MsiRecordGetInteger function returns the integer value from a record field. /// Handle to a record. /// Specifies the field of the record from which to obtain the value. /// If the function succeeds, the return value is the integer value of the field. /// /// The MsiRecordGetInteger function returns MSI_NULL_INTEGER if the field is null or if the field is a string that /// cannot be converted to an integer. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecordgetinteger int MsiRecordGetInteger( MSIHANDLE // hRecord, UINT iField ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordGetInteger")] public static extern int MsiRecordGetInteger(MSIHANDLE hRecord, uint iField); // integer value reserved for null /// The MsiRecordGetString function returns the string value of a record field. /// Handle to the record. /// Specifies the field requested. /// /// Pointer to the buffer that receives the null terminated string containing the value of the record field. Do not attempt to /// determine the size of the buffer by passing in a null (value=0) for szValueBuf. You can get the size of the buffer by passing in /// an empty string (for example ""). The function then returns ERROR_MORE_DATA and pcchValueBuf contains the required buffer /// size in TCHARs, not including the terminating null character. On return of ERROR_SUCCESS, pcchValueBuf contains the /// number of TCHARs written to the buffer, not including the terminating null character. /// /// /// Pointer to the variable that specifies the size, in TCHAR s, of the buffer pointed to by the variable szValueBuf. When /// the function returns ERROR_SUCCESS, this variable contains the size of the data copied to szValueBuf, not including the /// terminating null character. If szValueBuf is not large enough, the function returns ERROR_MORE_DATA and stores the /// required size, not including the terminating null character, in the variable pointed to by pcchValueBuf. /// /// The MsiRecordGetString function returns one of the following values: /// /// If ERROR_MORE_DATA is returned, the parameter which is a pointer gives the size of the buffer required to hold the /// string. If ERROR_SUCCESS is returned, it gives the number of characters written to the string buffer. To get the size of /// the buffer, pass in the address of a 1 character buffer as szValueBuf and specify the size of the buffer with pcchValueBuf as 0. /// This ensures that no string value returned by the function fits into the buffer. Do not attempt to determine the size of the /// buffer by passing in a Null (value=0). /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecordgetstringa UINT MsiRecordGetStringA( MSIHANDLE // hRecord, UINT iField, LPSTR szValueBuf, LPDWORD pcchValueBuf ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordGetStringA")] public static extern Win32Error MsiRecordGetString(MSIHANDLE hRecord, uint iField, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szValueBuf, ref uint pcchValueBuf); /// The MsiRecordIsNull function reports a null record field. /// Handle to a record. /// Specifies the field to check. /// This function returns BOOL. /// The iField parameter is based on 1 (one). // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecordisnull BOOL MsiRecordIsNull( MSIHANDLE hRecord, // UINT iField ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordIsNull")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool MsiRecordIsNull(MSIHANDLE hRecord, uint iField); /// The MsiRecordReadStream function reads bytes from a record stream field into a buffer. /// Handle to the record. /// Specifies the field of the record. /// /// A buffer to receive the stream field. You should ensure the destination buffer is the same size or larger than the source /// buffer. See the Remarks section. /// /// /// Specifies the in and out buffer count. On input, this is the full size of the buffer. On output, this is the number of bytes /// that were actually written to the buffer. See the Remarks section. /// /// This function returns UINT. /// /// /// To read a stream, set pcbDataBuf to the number of bytes that are to be transferred from stream to buffer each time the function /// is called. On return, the MsiRecordReadStream resets pcbDataBuf to the number of bytes that were actually transferred. If /// the buffer is smaller than the stream, the stream is repositioned when the buffer becomes full such that the next data in the /// stream is transferred by the next call to the function. When no more bytes are available, MsiRecordReadStream returns ERROR_SUCCESS. /// /// If you pass 0 for szDataBuf then pcbDataBuf is reset to the number of bytes in the stream remaining to be read. /// /// The following code sample reads from a stream that is in field 1 of a record specified by hRecord and reads the entire stream 8 /// bytes at a time. /// /// /// char szBuffer[8]; PMSIHANDLE hRecord; DWORD cbBuf = sizeof(szBuffer); do { if (MsiRecordReadStream(hRecord, 1, szBuffer, &cbBuf) != ERROR_SUCCESS) break; /* error */ } while (cbBuf == 8); //continue reading the stream while you receive a full buffer //cbBuf will be less once you reach the end of the stream and cannot fill your //buffer with stream data /// /// See also OLE Limitations on Streams. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecordreadstream UINT MsiRecordReadStream( MSIHANDLE // hRecord, UINT iField, char *szDataBuf, LPDWORD pcbDataBuf ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordReadStream")] public static extern Win32Error MsiRecordReadStream(MSIHANDLE hRecord, uint iField, [Out] IntPtr szDataBuf, ref uint pcbDataBuf); /// The MsiRecordSetInteger function sets a record field to an integer field. /// Handle to the record. /// Specifies the field of the record to set. /// Specifies the value to which to set the field. /// This function returns UINT. /// /// /// In the MsiRecordSetInteger function, attempting to store a value in a nonexistent field causes an error. Note that the /// following code returns ERROR_INVALID_PARAMETER. /// /// /// MSIHANDLE hRecord; UINT lReturn; //create an msirecord with no fields hRecord = MsiCreateRecord(0); //attempting to set the first field's value gives you ERROR_INVALID_PARAMETER lReturn = MsiRecordSetInteger(hRecord, 1, 0); /// /// To set a record integer field to NULL_INTEGER, set iValue to MSI_NULL_INTEGER. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecordsetinteger UINT MsiRecordSetInteger( MSIHANDLE // hRecord, UINT iField, int iValue ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordSetInteger")] public static extern Win32Error MsiRecordSetInteger(MSIHANDLE hRecord, uint iField, int iValue); /// /// The MsiRecordSetStream function sets a record stream field from a file. Stream data cannot be inserted into temporary fields. /// /// Handle to the record. /// Specifies the field of the record to set. /// Specifies the path to the file containing the stream. /// The MsiRecordSetStream function returns the following values: /// /// /// The contents of the file specified in the MsiRecordSetStream function is read into a stream object. The stream persists /// if the record is inserted into the database and the database is committed. /// /// /// To reset the stream to its beginning you must pass in a Null pointer for szFilePath. Do not pass a pointer to an empty string, /// "", to reset the stream. /// /// See also OLE Limitations on Streams. /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecordsetstreama UINT MsiRecordSetStreamA( MSIHANDLE // hRecord, UINT iField, LPCSTR szFilePath ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordSetStreamA")] public static extern Win32Error MsiRecordSetStream(MSIHANDLE hRecord, uint iField, [MarshalAs(UnmanagedType.LPTStr)] string szFilePath); /// The MsiRecordSetString function copies a string into the designated field. /// Handle to the record. /// Specifies the field of the record to set. /// Specifies the string value of the field. /// This function returns UINT. /// /// /// In the MsiRecordSetString function, a null string pointer and an empty string both set the field to null. Attempting to /// store a value in a nonexistent field causes an error. /// /// To set a record string field to null, set szValue to either a null string or an empty string. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msirecordsetstringa UINT MsiRecordSetStringA( MSIHANDLE // hRecord, UINT iField, LPCSTR szValue ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiRecordSetStringA")] public static extern Win32Error MsiRecordSetString(MSIHANDLE hRecord, uint iField, [MarshalAs(UnmanagedType.LPTStr)] string szValue); /// The MsiSequence function executes another action sequence, as described in the specified table. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the name of the table containing the action sequence. /// This parameter is currently unimplemented. It is reserved for future use and must be 0. /// This function returns UINT. /// /// /// The MsiSequence function queries the specified table, ordering the actions by the numbers in the Sequence column. For /// each row retrieved, an action is executed, provided that any supplied condition expression does not evaluate to FALSE. /// /// /// An action sequence containing any actions that update the system, such as the InstallFiles and WriteRegistryValues actions, /// cannot be run by calling MsiSequence. The exception to this rule is if MsiSequence is called from a custom action /// that is scheduled in the InstallExecuteSequence table between the InstallInitialize and InstallFinalize actions. Actions that do /// not update the system, such as AppSearch or CostInitialize, can be called. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisequencew UINT MsiSequenceW( MSIHANDLE hInstall, // LPCWSTR szTable, INT iSequenceMode ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSequenceW")] public static extern Win32Error MsiSequence(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szTable, int iSequenceMode = 0); /// The MsiSetComponentState function sets a component to the requested state. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the name of the component. /// /// Specifies the state to set. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// INSTALLSTATE_ABSENT /// The component was uninstalled. /// /// /// INSTALLSTATE_LOCAL /// The component was installed on the local drive. /// /// /// INSTALLSTATE_SOURCE /// The component will run from source, CD, or network. /// /// /// /// The MsiSetComponentState function returns the following values: /// /// The MsiSetComponentState function requests a change in the Action state of a record in the Component table. /// For more information, see Calling Database Functions From Programs. /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisetcomponentstatea UINT MsiSetComponentStateA( // MSIHANDLE hInstall, LPCSTR szComponent, INSTALLSTATE iState ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSetComponentStateA")] public static extern Win32Error MsiSetComponentState(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szComponent, INSTALLSTATE iState); /// /// The MsiSetFeatureAttributes function can modify the default attributes of a feature at runtime. Note that the default /// attributes of features are authored in the Attributes column of the Feature table. /// /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the feature name within the product. /// /// Feature attributes specified at run time as a set of bit flags: /// /// /// Constant /// Meaning /// /// /// INSTALLFEATUREATTRIBUTE_FAVORLOCAL 1 /// /// Modifies default feature attributes to msidbFeatureAttributesFavorLocal at run time. See Attributes column of the Feature table /// for a description. /// /// /// /// INSTALLFEATUREATTRIBUTE_FAVORSOURCE 2 /// /// Modifies default feature attributes to msidbFeatureAttributesFavorSource at run time. See Attributes column of the Feature table /// for a description. /// /// /// /// INSTALLFEATUREATTRIBUTE_FOLLOWPARENT 4 /// /// Modifies default feature attributes to msidbFeatureAttributesFollowParent at run time. Note that this is not a valid attribute /// to be set for top-level features. See Attributes column of the Feature table for a description. /// /// /// /// INSTALLFEATUREATTRIBUTE_FAVORADVERTISE 8 /// /// Modifies default feature attributes to msidbFeatureAttributesFavorAdvertise at run time. See Attributes column of the Feature /// table for a description. /// /// /// /// INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE 16 /// /// Modifies default feature attributes to msidbFeatureAttributesDisallowAdvertise at run time. See Attributes column of the Feature /// table for a description. /// /// /// /// INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE 32 /// /// Modifies default feature attributes to msidbFeatureAttributesNoUnsupportedAdvertise at run time. See Attributes column of the /// Feature table for a description. /// /// /// /// /// This function returns UINT. /// /// /// MsiSetFeatureAttributes must be called after CostInitialize action and before CostFinalize action. The function returns /// ERROR_FUNCTION_FAILED if called at any other time. /// /// /// The INSTALLFEATUREATTRIBUTE_FAVORLOCAL, INSTALLFEATUREATTRIBUTE_FAVORSOURCE, and INSTALLFEATUREATTRIBUTE_FOLLOWPARENT flags are /// mutually exclusive. Only one of these bits can be set for any feature. If more than one of these flags is set, the behavior of /// that feature is undefined. /// /// See Calling Database Functions From Programs. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisetfeatureattributesa UINT MsiSetFeatureAttributesA( // MSIHANDLE hInstall, LPCSTR szFeature, DWORD dwAttributes ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSetFeatureAttributesA")] public static extern Win32Error MsiSetFeatureAttributes(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szFeature, INSTALLFEATUREATTRIBUTE dwAttributes); /// The MsiSetFeatureState function sets a feature to a specified state. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the name of the feature. /// /// Specifies the state to set. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// INSTALLSTATE_ABSENT /// The feature is not installed. /// /// /// INSTALLSTATE_LOCAL /// The feature is installed on the local drive. /// /// /// INSTALLSTATE_SOURCE /// The feature is run from the source, CD, or network. /// /// /// INSTALLSTATE_ADVERTISED /// The feature is advertised. /// /// /// /// The MsiSetFeatureState function returns the following values: /// /// /// The MsiSetFeatureState function requests a change in the select state of a feature in the Feature table and its children. /// In turn, the action state of all the components linked to the changed feature records are also updated appropriately, based on /// the new feature select state. /// /// The MsiSetInstallLevel function must be called before calling MsiSetFeatureState. /// /// When MsiSetFeatureState is called, the installer attempts to set the action state of each component tied to the specified /// feature to the specified state. However, there are common situations when the request cannot be fully implemented. For example, /// if a feature is tied to two components, component A and component B, through the FeatureComponents table, and component A has /// the msidbComponentAttributesLocalOnly attribute and component B has the msidbComponentAttributesSourceOnly /// attribute. In this case, if MsiSetFeatureState is called with a requested state of either INSTALLSTATE_LOCAL or /// INSTALLSTATE_SOURCE, the request cannot be fully implemented for both components. In this case, both components are turned ON, /// with component A set to Local and component B set to Source. /// /// /// If more than one feature is linked to a single component (a common scenario), the final action state of that component is /// determined as follows: /// /// /// /// If at least one feature requires the component to be installed locally, the feature is installed with a state of local. /// /// /// If at least one feature requires the component to be run from the source, the feature is installed with a state of source. /// /// /// If at least one feature requires the removal of the component, the action state is absent. /// /// /// See Calling Database Functions from Programs. /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisetfeaturestatea UINT MsiSetFeatureStateA( MSIHANDLE // hInstall, LPCSTR szFeature, INSTALLSTATE iState ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSetFeatureStateA")] public static extern Win32Error MsiSetFeatureState(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szFeature, INSTALLSTATE iState); /// The MsiSetInstallLevel function sets the installation level for a full product installation. /// /// Handle to the installation that is provided to a DLL custom action or obtained by using MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// The installation level. /// The MsiSetInstallLevel function returns one of the following values: /// /// The MsiSetInstallLevel function sets the following: /// /// /// The installation level for the current installation to a specified value. /// /// /// The Select and Installed states for all features in the Feature table. /// /// /// The Action state of each component in the Component table, based on the new level. /// /// /// /// For any installation, there is a defined install level, which is an integral value from 1 to 32,767. The initial value is /// determined by the INSTALLLEVEL property, which is set in the Property Table. /// /// /// If 0 (zero) or a negative number is passed in the iInstallLevel parameter, the current installation level does not change, but /// all features are still updated based on the current installation level. For more information, see Calling Database Functions /// From Programs. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisetinstalllevel UINT MsiSetInstallLevel( MSIHANDLE // hInstall, int iInstallLevel ); [DllImport(Lib_Msi, SetLastError = true, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSetInstallLevel")] public static extern Win32Error MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel); /// The MsiSetMode function sets an internal engine Boolean state. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// /// /// Specifies the run mode. This parameter must be one of the following values. While there are many values for this parameter, as /// described in MsiGetMode, only one of the following values can be set. /// /// /// /// Value /// Meaning /// /// /// MSIRUNMODE_REBOOTATEND /// A reboot is necessary after a successful installation. /// /// /// MSIRUNMODE_REBOOTNOW /// A reboot is necessary to continue installation. /// /// /// /// Specifies the state to set to TRUE or FALSE. /// This function returns UINT. // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisetmode UINT MsiSetMode( MSIHANDLE hInstall, // MSIRUNMODE eRunMode, BOOL fState ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSetMode")] public static extern Win32Error MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE eRunMode, [MarshalAs(UnmanagedType.Bool)] bool fState); /// The MsiSetProperty function sets the value for an installation property. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the name of the property. /// Specifies the value of the property. /// This function returns UINT. /// /// If the property is not defined, it is created by the MsiSetProperty function. If the value is null or an empty string, /// the property is removed. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisetpropertya UINT MsiSetPropertyA( MSIHANDLE hInstall, // LPCSTR szName, LPCSTR szValue ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSetPropertyA")] public static extern Win32Error MsiSetProperty(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szName, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szValue); /// The MsiSetTargetPath function sets the full target path for a folder in the Directory table. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// Specifies the folder identifier. This is a primary key in the Directory table. /// Specifies the full path for the folder, ending in a directory separator. /// The MsiSetTargetPath function returns the following values: /// /// /// The MsiSetTargetPath function changes the path specification for the target directory named in the in-memory Directory /// table. Also, the path specifications of all other path objects in the table that are either subordinate or equivalent to the /// changed path are updated to reflect the change. The properties for each affected path are also updated. /// /// MsiSetTargetPath fails if the selected directory is read only. /// /// If an error occurs in this function, all updated paths and properties revert to their previous values. Therefore, it is safe to /// treat errors returned by this function as nonfatal. /// /// /// Do not attempt to configure the target path if the components using those paths are already installed for the current user or /// for a different user. Check the ProductState property before calling MsiSetTargetPath to determine if the product /// containing this component is installed. /// /// See Calling Database Functions From Programs. /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisettargetpatha UINT MsiSetTargetPathA( MSIHANDLE // hInstall, LPCSTR szFolder, LPCSTR szFolderPath ); [DllImport(Lib_Msi, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSetTargetPathA")] public static extern Win32Error MsiSetTargetPath(MSIHANDLE hInstall, [MarshalAs(UnmanagedType.LPTStr)] string szFolder, [MarshalAs(UnmanagedType.LPTStr)] string szFolderPath); /// /// The MsiSummaryInfoGetProperty function gets a single property from the summary information stream. /// /// Note The meaning of the property value depends on whether the summary information stream is for an installation database /// (.msi file), transform (.mst file) or patch (.msp file). See Summary Property Descriptions and Summary Information Stream /// Property Set for more information about summary information properties. /// /// /// Handle to summary information. /// /// Specifies the property ID of the summary property. This parameter can be a property ID listed in the Summary Information Stream /// Property Set. This function does not return values for PID_DICTIONARY OR PID_THUMBNAIL property. /// /// /// Receives the returned property type. This parameter can be a type listed in the Summary Information Stream Property Set. /// /// Receives the returned integer property data. /// Pointer to a file value. /// /// Pointer to the buffer that receives the null terminated summary information property value. Do not attempt to determine the size /// of the buffer by passing in a null (value=0) for szValueBuf. You can get the size of the buffer by passing in an empty string /// (for example ""). The function then returns ERROR_MORE_DATA and pcchValueBuf contains the required buffer size in TCHARs, /// not including the terminating null character. On return of ERROR_SUCCESS, pcchValueBuf contains the number of TCHARs /// written to the buffer, not including the terminating null character. This parameter is an empty string if there are no errors. /// /// /// Pointer to the variable that specifies the size, in TCHARs, of the buffer pointed to by the variable szValueBuf. When the /// function returns ERROR_SUCCESS, this variable contains the size of the data copied to szValueBuf, not including the terminating /// null character. If szValueBuf is not large enough, the function returns ERROR_MORE_DATA and stores the required size, not /// including the terminating null character, in the variable pointed to by pcchValueBuf. /// /// The MsiSummaryInfoGetProperty function returns one of the following values: /// /// /// If ERROR_MORE_DATA is returned, the parameter which is a pointer gives the size of the buffer required to hold the string. If /// ERROR_SUCCESS is returned, it gives the number of characters written to the string buffer. Therefore you can get the size of the /// buffer by passing in an empty string (for example "") for the parameter that specifies the buffer. Do not attempt to determine /// the size of the buffer by passing in a Null (value=0). /// /// /// Windows Installer functions that return data in a user provided memory location should not be called with null as the value for /// the pointer. These functions return a string or return data as integer pointers, but return inconsistent values when passing /// null as the value for the output argument. For more information, see Passing Null as the Argument of Windows Installer Functions. /// /// /// The property information returned by the MsiSummaryInfoGetProperty function is received by the piValue, pftValue, or /// szValueBuf parameter depending upon the type of property value that has been specified in the puiDataType parameter. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisummaryinfogetpropertya UINT // MsiSummaryInfoGetPropertyA( MSIHANDLE hSummaryInfo, UINT uiProperty, PUINT puiDataType, LPINT piValue, FILETIME *pftValue, LPSTR // szValueBuf, LPDWORD pcchValueBuf ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSummaryInfoGetPropertyA")] public static extern Win32Error MsiSummaryInfoGetProperty(MSIHANDLE hSummaryInfo, uint uiProperty, out uint puiDataType, out int piValue, out FILETIME pftValue, [Out, Optional, MarshalAs(UnmanagedType.LPTStr)] StringBuilder szValueBuf, ref uint pcchValueBuf); /// /// The MsiSummaryInfoGetPropertyCount function returns the number of existing properties in the summary information stream. /// /// Handle to summary information. /// Location to receive the total property count. /// This function returns UINT. // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisummaryinfogetpropertycount UINT // MsiSummaryInfoGetPropertyCount( MSIHANDLE hSummaryInfo, PUINT puiPropertyCount ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSummaryInfoGetPropertyCount")] public static extern Win32Error MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, out uint puiPropertyCount); /// The MsiSummaryInfoPersist function writes changed summary information back to the summary information stream. /// Handle to summary information. /// This function returns UINT. // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisummaryinfopersist UINT MsiSummaryInfoPersist( // MSIHANDLE hSummaryInfo ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSummaryInfoPersist")] public static extern Win32Error MsiSummaryInfoPersist(MSIHANDLE hSummaryInfo); /// /// The MsiSummaryInfoSetProperty function sets a single summary information property. /// /// Note The meaning of the property value depends on whether the summary information stream is for an installation database /// (.msi file), transform (.mst file) or patch (.msp file). See Summary Property Descriptions and Summary Information Stream /// Property Set for more information about summary information properties. /// /// /// Handle to summary information. /// /// Specifies the property ID of the summary property being set. This parameter can be a property ID listed in the Summary /// Information Stream Property Set. This function does not set values for PID_DICTIONARY OR PID_THUMBNAIL property. /// /// /// Specifies the type of property to set. This parameter can be a type listed in the Summary Information Stream Property Set. /// /// Specifies the integer value. /// Specifies the file-time value. /// Specifies the text value. /// The MsiSummaryInfoSetProperty function returns the following values: /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisummaryinfosetpropertya UINT // MsiSummaryInfoSetPropertyA( MSIHANDLE hSummaryInfo, UINT uiProperty, UINT uiDataType, INT iValue, FILETIME *pftValue, LPCSTR // szValue ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSummaryInfoSetPropertyA")] public static extern Win32Error MsiSummaryInfoSetProperty(MSIHANDLE hSummaryInfo, uint uiProperty, uint uiDataType, [Optional] int iValue, in FILETIME pftValue, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szValue); /// /// The MsiSummaryInfoSetProperty function sets a single summary information property. /// /// Note The meaning of the property value depends on whether the summary information stream is for an installation database /// (.msi file), transform (.mst file) or patch (.msp file). See Summary Property Descriptions and Summary Information Stream /// Property Set for more information about summary information properties. /// /// /// Handle to summary information. /// /// Specifies the property ID of the summary property being set. This parameter can be a property ID listed in the Summary /// Information Stream Property Set. This function does not set values for PID_DICTIONARY OR PID_THUMBNAIL property. /// /// /// Specifies the type of property to set. This parameter can be a type listed in the Summary Information Stream Property Set. /// /// Specifies the integer value. /// Specifies the file-time value. /// Specifies the text value. /// The MsiSummaryInfoSetProperty function returns the following values: /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msisummaryinfosetpropertya UINT // MsiSummaryInfoSetPropertyA( MSIHANDLE hSummaryInfo, UINT uiProperty, UINT uiDataType, INT iValue, FILETIME *pftValue, LPCSTR // szValue ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiSummaryInfoSetPropertyA")] public static extern Win32Error MsiSummaryInfoSetProperty(MSIHANDLE hSummaryInfo, uint uiProperty, uint uiDataType, [Optional] int iValue, [In, Optional] IntPtr pftValue, [Optional, MarshalAs(UnmanagedType.LPTStr)] string szValue); /// The MsiVerifyDiskSpace function checks to see if sufficient disk space is present for the current installation. /// /// Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct. /// /// This function returns UINT. /// See Calling Database Functions From Programs. // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiverifydiskspace UINT MsiVerifyDiskSpace( MSIHANDLE // hInstall ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiVerifyDiskSpace")] public static extern Win32Error MsiVerifyDiskSpace(MSIHANDLE hInstall); /// The MsiViewClose function releases the result set for an executed view. /// Handle to a view that is set to release. /// Note that in low memory situations, this function can raise a STATUS_NO_MEMORY exception. /// /// The MsiViewClose function must be called before the MsiViewExecute function is called again on the view, unless all rows /// of the result set have been obtained with the MsiViewFetch function. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiviewclose UINT MsiViewClose( MSIHANDLE hView ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiViewClose")] public static extern Win32Error MsiViewClose(MSIHANDLE hView); /// /// The MsiViewExecute function executes a SQL view query and supplies any required parameters. The query uses the question /// mark token to represent parameters as described in SQL Syntax. The values of these parameters are passed in as the corresponding /// fields of a parameter record. /// /// Handle to the view upon which to execute the query. /// /// Handle to a record that supplies the parameters. This parameter contains values to replace the parameter tokens in the SQL /// query. It is optional, so hRecord can be zero. For a reference on syntax, see SQL Syntax. /// /// Note that in low memory situations, this function can raise a STATUS_NO_MEMORY exception. /// /// The MsiViewExecute function must be called before any calls to MsiViewFetch. /// /// If the SQL query specifies values with parameter markers (?), a record must be supplied that contains all of the replacement /// values in the exact order and of compatible data types. When used with INSERT and UPDATE queries all the parameterized values /// must precede all nonparameterized values. /// /// For example, these queries are valid. /// UPDATE {table-list} SET {column}= ? , {column}= {constant} /// INSERT INTO {table} ({column-list}) VALUES (?, {constant-list}) /// However these queries are invalid. /// UPDATE {table-list} SET {column}= {constant}, {column}=? /// INSERT INTO {table} ({column-list}) VALUES ({constant-list}, ? ) /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiviewexecute UINT MsiViewExecute( MSIHANDLE hView, // MSIHANDLE hRecord ); [DllImport(Lib_Msi, SetLastError = true, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiViewExecute")] public static extern Win32Error MsiViewExecute(MSIHANDLE hView, [Optional] MSIHANDLE hRecord); /// /// The MsiViewFetch function fetches the next sequential record from the view. This function returns a handle that should be /// closed using MsiCloseHandle. /// /// Handle to the view to fetch from. /// Pointer to the handle for the fetched record. /// Note that in low memory situations, this function can raise a STATUS_NO_MEMORY exception. /// /// /// If the MsiViewFetch function returns ERROR_FUNCTION_FAILED, it is possible that the MsiViewExecute function was not /// called first. If more rows are available in the result set, MsiViewFetch returns phRecord as a handle to a record /// containing the requested column data, or phRecord is 0. For maximum performance, the same record should be used for all /// retrievals, or the record should be released by going out of scope. /// /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiviewfetch UINT MsiViewFetch( MSIHANDLE hView, // MSIHANDLE *phRecord ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiViewFetch")] public static extern Win32Error MsiViewFetch(MSIHANDLE hView, out PMSIHANDLE phRecord); /// /// The MsiViewGetColumnInfo function returns a record containing column names or definitions. This function returns a handle /// that should be closed using MsiCloseHandle. /// /// Handle to the view from which to obtain column information. /// /// Specifies a flag indicating what type of information is needed. This parameter must be one of the following values. /// /// /// Value /// Meaning /// /// /// MSICOLINFO_NAMES /// Column names are returned. /// /// /// MSICOLINFO_TYPES /// Definitions are returned. /// /// /// /// Pointer to a handle to receive the column information data record. /// Note that in low memory situations, this function can raise a STATUS_NO_MEMORY exception. /// /// /// The column description returned by MsiViewGetColumnInfo is in the format described in the section: Column Definition /// Format. Each column is described by a string in the corresponding record field. The definition string consists of a single /// letter representing the data type followed by the width of the column (in characters when applicable, bytes otherwise). A width /// of zero designates an unbounded width (for example, long text fields and streams). An uppercase letter indicates that null /// values are allowed in the column. /// /// /// Note that it is recommended to use variables of type PMSIHANDLE because the installer closes PMSIHANDLE objects as they go out /// of scope, whereas you must close MSIHANDLE objects by calling MsiCloseHandle. For more information see Use PMSIHANDLE instead of /// HANDLE section in the Windows Installer Best Practices. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiviewgetcolumninfo UINT MsiViewGetColumnInfo( MSIHANDLE // hView, MSICOLINFO eColumnInfo, MSIHANDLE *phRecord ); [DllImport(Lib_Msi, SetLastError = false, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiViewGetColumnInfo")] public static extern Win32Error MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO eColumnInfo, out PMSIHANDLE phRecord); /// The MsiViewGetError function returns the error that occurred in the MsiViewModify function. /// Handle to the view. /// /// Pointer to the buffer that receives the null-terminated column name. Do not attempt to determine the size of the buffer by /// passing in a null (value=0) for szColumnName. You can get the size of the buffer by passing in an empty string (for example ""). /// The function then returns MSIDBERROR_MOREDATA and pcchBuf contains the required buffer size in TCHARs, not including the /// terminating null character. On return of MSIDBERROR_NOERROR, pcchBuf contains the number of TCHARs written to the buffer, not /// including the terminating null character. This parameter is an empty string if there are no errors. /// /// /// Pointer to the variable that specifies the size, in TCHARs, of the buffer pointed to by the variable szColumnNameBuffer. When /// the function returns MSIDBERROR_NOERROR, this variable contains the size of the data copied to szColumnNameBuffer, not including /// the terminating null character. If szColumnNameBuffer is not large enough, the function returns MSIDBERROR_MOREDATA and stores /// the required size, not including the terminating null character, in the variable pointed to by pcchBuf. /// /// /// This function returns one of the following values. /// /// /// Error code /// Meaning /// /// /// MSIDBERROR_INVALIDARG /// An argument was invalid. /// /// /// MSIDBERROR_MOREDATA /// The buffer was too small to receive data. /// /// /// MSIDBERROR_FUNCTIONERROR /// The function failed. /// /// /// MSIDBERROR_NOERROR /// The function completed successfully with no errors. /// /// /// MSIDBERROR_DUPLICATEKEY /// The new record duplicates primary keys of the existing record in a table. /// /// /// MSIDBERROR_REQUIRED /// There are no null values allowed; or the column is about to be deleted, but is referenced by another row. /// /// /// MSIDBERROR_BADLINK /// The corresponding record in a foreign table was not found. /// /// /// MSIDBERROR_OVERFLOW /// The data is greater than the maximum value allowed. /// /// /// MSIDBERROR_UNDERFLOW /// The data is less than the minimum value allowed. /// /// /// MSIDBERROR_NOTINSET /// The data is not a member of the values permitted in the set. /// /// /// MSIDBERROR_BADVERSION /// An invalid version string was supplied. /// /// /// MSIDBERROR_BADCASE /// The case was invalid. The case must be all uppercase or all lowercase. /// /// /// MSIDBERROR_BADGUID /// An invalid GUID was supplied. /// /// /// MSIDBERROR_BADWILDCARD /// An invalid wildcard file name was supplied, or the use of wildcards was invalid. /// /// /// MSIDBERROR_BADIDENTIFIER /// An invalid identifier was supplied. /// /// /// MSIDBERROR_BADLANGUAGE /// Invalid language IDs were supplied. /// /// /// MSIDBERROR_BADFILENAME /// An invalid file name was supplied. /// /// /// MSIDBERROR_BADPATH /// An invalid path was supplied. /// /// /// MSIDBERROR_BADCONDITION /// An invalid conditional statement was supplied. /// /// /// MSIDBERROR_BADFORMATTED /// An invalid format string was supplied. /// /// /// MSIDBERROR_BADTEMPLATE /// An invalid template string was supplied. /// /// /// MSIDBERROR_BADDEFAULTDIR /// An invalid string was supplied in the DefaultDir column of the Directory table. /// /// /// MSIDBERROR_BADREGPATH /// An invalid registry path string was supplied. /// /// /// MSIDBERROR_BADCUSTOMSOURCE /// An invalid string was supplied in the CustomSource column of the CustomAction table. /// /// /// MSIDBERROR_BADPROPERTY /// An invalid property string was supplied. /// /// /// MSIDBERROR_MISSINGDATA /// The _Validation table is missing a reference to a column. /// /// /// MSIDBERROR_BADCATEGORY /// The category column of the _Validation table for the column is invalid. /// /// /// MSIDBERROR_BADCABINET /// An invalid cabinet name was supplied. /// /// /// MSIDBERROR_BADKEYTABLE /// The table in the Keytable column of the _Validation table was not found or loaded. /// /// /// MSIDBERROR_BADMAXMINVALUES /// The value in the MaxValue column of the _Validation table is less than the value in the MinValue column. /// /// /// MSIDBERROR_BADSHORTCUT /// An invalid shortcut target name was supplied. /// /// /// MSIDBERROR_STRINGOVERFLOW /// The string is too long for the length specified by the column definition. /// /// /// MSIDBERROR_BADLOCALIZEATTRIB /// An invalid localization attribute was supplied. (Primary keys cannot be localized.) /// /// /// Note that in low memory situations, this function can raise a STATUS_NO_MEMORY exception. /// /// /// /// You should only call the MsiViewGetError function when MsiViewModify returns ERROR_INVALID_DATA, indicating that the data /// is invalid. Errors are only recorded for MSIMODIFY_VALIDATE, MSIMODIFY_VALIDATE_NEW, and MSIMODIFY_VALIDATEFIELD. /// /// /// If ERROR_MORE_DATA is returned, the parameter that is a pointer gives the size of the buffer required to hold the string. Upon /// success, it gives the number of characters written to the string buffer. Therefore you can get the required size of the buffer /// by passing a small buffer (one character minimum) and examining the value at pcchPathBuf when the function returns /// MSIDBERROR_MOREDATA. Do not attempt to determine the size of the buffer by passing in null as szColumnNameBuffer or a buffer /// size of 0 in the DWORD referenced by pcchBuf. /// /// /// Once MSIDBERROR_NOERROR is returned, no more validation errors remain. The MSIDBERROR return value indicates the type of /// validation error that occurred for the value located in the column identified by the szColumnNameBuffer. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiviewgeterrorw MSIDBERROR MsiViewGetErrorW( MSIHANDLE // hView, LPWSTR szColumnNameBuffer, LPDWORD pcchBuf ); [DllImport(Lib_Msi, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiViewGetErrorW")] public static extern MSIDBERROR MsiViewGetError(MSIHANDLE hView, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder szColumnNameBuffer, ref uint pcchBuf); /// The MsiViewModify function updates a fetched record. /// Handle to a view. /// /// Specifies the modify mode. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// MSIMODIFY_SEEK -1 /// /// Refreshes the information in the supplied record without changing the position in the result set and without affecting /// subsequent fetch operations. The record may then be used for subsequent Update, Delete, and Refresh. All primary key columns of /// the table must be in the query and the record must have at least as many fields as the query. Seek cannot be used with /// multi-table queries. This mode cannot be used with a view containing joins. See also the remarks. /// /// /// /// MSIMODIFY_REFRESH 0 /// /// Refreshes the information in the record. Must first call MsiViewFetch with the same record. Fails for a deleted row. Works with /// read-write and read-only records. /// /// /// /// MSIMODIFY_INSERT 1 /// /// Inserts a record. Fails if a row with the same primary keys exists. Fails with a read-only database. This mode cannot be used /// with a view containing joins. /// /// /// /// MSIMODIFY_UPDATE 2 /// /// Updates an existing record. Nonprimary keys only. Must first call MsiViewFetch. Fails with a deleted record. Works only with /// read-write records. /// /// /// /// MSIMODIFY_ASSIGN 3 /// /// Writes current data in the cursor to a table row. Updates record if the primary keys match an existing row and inserts if they /// do not match. Fails with a read-only database. This mode cannot be used with a view containing joins. /// /// /// /// MSIMODIFY_REPLACE 4 /// /// Updates or deletes and inserts a record into a table. Must first call MsiViewFetch with the same record. Updates record if the /// primary keys are unchanged. Deletes old row and inserts new if primary keys have changed. Fails with a read-only database. This /// mode cannot be used with a view containing joins. /// /// /// /// MSIMODIFY_MERGE 5 /// /// Inserts or validates a record in a table. Inserts if primary keys do not match any row and validates if there is a match. Fails /// if the record does not match the data in the table. Fails if there is a record with a duplicate key that is not identical. Works /// only with read-write records. This mode cannot be used with a view containing joins. /// /// /// /// MSIMODIFY_DELETE 6 /// /// Remove a row from the table. You must first call the MsiViewFetch function with the same record. Fails if the row has been /// deleted. Works only with read-write records. This mode cannot be used with a view containing joins. /// /// /// /// MSIMODIFY_INSERT_TEMPORARY 7 /// /// Inserts a temporary record. The information is not persistent. Fails if a row with the same primary key exists. Works only with /// read-write records. This mode cannot be used with a view containing joins. /// /// /// /// MSIMODIFY_VALIDATE 8 /// /// Validates a record. Does not validate across joins. You must first call the MsiViewFetch function with the same record. Obtain /// validation errors with MsiViewGetError. Works with read-write and read-only records. This mode cannot be used with a view /// containing joins. /// /// /// /// MSIMODIFY_VALIDATE_NEW 9 /// /// Validate a new record. Does not validate across joins. Checks for duplicate keys. Obtain validation errors by calling /// MsiViewGetError. Works with read-write and read-only records. This mode cannot be used with a view containing joins. /// /// /// /// MSIMODIFY_VALIDATE_FIELD 10 /// /// Validates fields of a fetched or new record. Can validate one or more fields of an incomplete record. Obtain validation errors /// by calling MsiViewGetError. Works with read-write and read-only records. This mode cannot be used with a view containing joins. /// /// /// /// MSIMODIFY_VALIDATE_DELETE 11 /// /// Validates a record that will be deleted later. You must first call MsiViewFetch. Fails if another row refers to the primary keys /// of this row. Validation does not check for the existence of the primary keys of this row in properties or strings. Does not /// check if a column is a foreign key to multiple tables. Obtain validation errors by calling MsiViewGetError. Works with /// read-write and read-only records. This mode cannot be used with a view that contains joins. /// /// /// /// /// Handle to the record to modify. /// /// The MsiViewModify function returns the following values: /// Note that in low memory situations, this function can raise a STATUS_NO_MEMORY exception. /// /// /// /// The MSIMODIFY_VALIDATE, MSIMODIFY_VALIDATE_NEW, MSIMODIFY_VALIDATE_FIELD, and MSIMODIFY_VALIDATE_DELETE values of the /// MsiViewModify function do not perform actual updates; they ensure that the data in the record is valid. Use of these /// validation enumerations requires that the database contains the _Validation table. /// /// /// You can call MSIMODIFY_UPDATE or MSIMODIFY_DELETE with a record immediately after using MSIMODIFY_INSERT, /// MSIMODIFY_INSERT_TEMPORARY, or MSIMODIFY_SEEK provided you have NOT modified the 0th field of the inserted or sought record. /// /// /// To execute any SQL statement, a view must be created. However, a view that does not create a result set, such as CREATE TABLE, /// or INSERT INTO, cannot be used with MsiViewModify to update tables though the view. /// /// /// You cannot fetch a record that contains binary data from one database and then use that record to insert the data into another /// database. To move binary data from one database to another, you should export the data to a file and then import it into the new /// database using a query and the MsiRecordSetStream. This ensures that each database has its own copy of the binary data. /// /// /// Note that custom actions can only add, modify, or remove temporary rows, columns, or tables from a database. Custom actions /// cannot modify persistent data in a database, such as data that is a part of the database stored on disk. For more information, /// see Accessing the Current Installer Session from Inside a Custom Action. /// /// If the function fails, you can obtain extended error information by using MsiGetLastErrorRecord. /// // https://docs.microsoft.com/en-us/windows/win32/api/msiquery/nf-msiquery-msiviewmodify UINT MsiViewModify( MSIHANDLE hView, // MSIMODIFY eModifyMode, MSIHANDLE hRecord ); [DllImport(Lib_Msi, SetLastError = true, ExactSpelling = true)] [PInvokeData("msiquery.h", MSDNShortId = "NF:msiquery.MsiViewModify")] public static extern Win32Error MsiViewModify(MSIHANDLE hView, MSIMODIFY eModifyMode, MSIHANDLE hRecord); } }