@
#$KInstaller Table Archive Format
	Msi Objects	Database Tables
Database tables are normally maintained individually as text archive files of the format below with the default extension ".idt". The MsiDatabase object has ExportTable and ImportTable functions that transfer these file to and from the physical database.
File Format
Lines composed of tab-delimited text fields, terminated with CR and LF.
1st line contains the columns names as stored in the database.
2nd line contains the column specifications as described below.
3rd line contains the table name and all the primary keys for the table.
Subsequent lines contain the data values for each row in the table.
Integer, datetime, and bit fields are all converted to integer text.
Control characters (CR,LF,Tab,Null) are remapped to avoid delimiter conflict.
Memo and BLOB fields stored as separate files, filename used as column data.
Memo filename: 1st 8 chars from row data + ".imd".
BLOB filename: 1st 8 chars from row data + ".ibd".

Datatype Codes
An upper case letter indicate that Null values are allowed in the column. The '?' indicates that the maximum width of the column must be specified.
b? 	Binary bytes(not supported), SQL_BINARY
c? 	Character array (1-255), SQL_CHAR
d6 	Date, SQL_DATE
d16	Datetime, SQL_TIMESTAMP
i0 	Boolean, SQL_BIT
i1 	Byte, SQL_TINYINT
i2 	Short, SQL_SMALLINT
i4 	Integer, SQL_INTEGER
k4 	Counter, SQL_INTEGER (SQL_AUTO_INCREMENT)
s0 	Memo, SQL_LONGVARCHAR
s? 	String, variable length (n=1-255), SQL_VARCHAR
v0 	BLOB, SQL_LONGVARBINARY
v? 	VarBinary (1-255), SQL_LONGBINARY (not supported)

#$Installer Table Archive Format
	Msi Objects	Database Tables
Database tables are normally maintained individually as text archive files of the format below with the default extension ".idt". The MsiDatabase object has ExportTable and ImportTable functions that transfer these file to and from the physical database. The format is designed to support both MSI and ODBC database specifications.
File Format
Lines are composed of tab-delimited text fields, terminated with CR and LF.
The 1st line contains the table name followed by the columns names.
The 2nd line contains the primary key count followed by the column specifications.
Subsequent lines contain the data values for each row in the table.
The first data value contains the persistent row attributes, stored as characters.
Integer, datetime, and bit fields are all converted to integer text.
Control characters (CR,LF,Tab,Null) are remapped to avoid delimiter conflict.
Memo and BLOB fields stored as separate files; the filename used as column data.
Memo filename: 1st 8 chars from row data + ".imd".
BLOB filename: 1st 8 chars from row data + ".ibd".
Primary key columns must be specified first in priority order.

Row Status attribute specification
Upper case letters are use to indicate each attribute tat is in the True state.

T 	iraTemporary   	not persisted with table unless explicitly forced
P 	iraProvisional 	with T, persisted only when database state dumped
		may be used alone by external client to mark row as incomplete
U 	iraUserInfo    	for use by external client to mark rows
		not used by database engine
R 	iraReadOnly    	prevents rows from being updated

Datatype Column Specification
Lower case letters are used to indicate a non-nullable column.
Upper case letters would indicate that Null values are allowed in the column.

Code	MSI type 	SQL type
b0 	icdObject 	binary stream, SQL_LONGVARBINARY
d6 	icdShort 	date, SQL_DATE
d16	icdLong 	datetime, SQL_TIMESTAMP
i0 	icdShort 	boolean, SQL_BIT
i1 	icdShort 	byte, SQL_TINYINT
i2 	icdShort 	short, SQL_SMALLINT
i4 	icdLong 	integer, SQL_INTEGER
s0 	icdString 	memo, SQL_LONGVARCHAR
s? 	icdString 	string, variable length (?=1-255), SQL_VARCHAR

#$KDatabase Engine Overview and Features
	MsiDatabase Object	Database Tables
The MSI database engine has been designed for small size, high query performance, and very compact persistent file size, as well as to support the special requirements of the installer such as object and stream datatypes, tree-walking cursors, merges and diffs, and temporary tables, columns, and rows. The engine supports two levels of access: Very high-performance direct table access via cursors, and high-level access via SQL queries. The persistent file format uses OLE structured storage, which is used to support the limited transaction capability. Due to the performance and size constraints, we do not purport to be a complete SQL DBMS. The implementation is identical between Win32 and Macintosh PPC, except for some minor differences at the OLE interface level.
Features
Tables are indexed by primary keys. Natural fetch order is by primary key.
Any column may be specified to accept or reject null values, including primary keys.
Tables may be linked as a tree through any column, and may be walked from any node.
Strings are pooled; only one copy of each unique string is kept and stored per database.
String columns are unsized and may hold strings up to 64K bytes.
Streams are persisted and are accessed via stream objects.
Databases may be opened from files, resources, and IStorage interfaces.Columns may be dynamically added to tables, and may be non-persistent.
SummaryInformation stream properties are individually readable and writable.
The database engine is exposed as a set of COM objects that support OLE automation.
Rows may be marked non-persistent and/or read-only.
Row attibutes may be queried: inserted, modified, non-persistent, merge failure, locked.
Multiple update modes: Insert(new row), Update(existing row), Assign(force), Merge(insert or match).
Temporary tables may be created. Even a temporary database can be created.
Databases can be diffed, creating a transform file that can be applied to a database.
COM objects may be stored in tables in non-persistent columns.
Tables may optionally be locked in memory for increased performance.
Stream objects may be used in tables, and are persisted as streams.
A separate output database may be specified to avoid writing to original database.
SQL updates and sorts through joins are supported.
SQL parameterized queries can be re-executed with new parameters.
Access and SQL Server databases and ODBC data sources are supported through ODBCS.
Temporary tables may be use with ODBC databases and may be joined with SQL queries.
ODBC driver available to expose MSI database as an ODBC data source.
Table may be imported and exported to text archives by both MSI and ODBC databases.

Low-level interface
The low-level interface consists of two primary objects: MsiTable which handles the schema, and MsiCursor which handles external data transfer. The cursor object communicates to the table object at the row level such that table updates are performed on complete rows. String objects and stream objects are used to transfer non-integer data. Row filtering can be performed only by matching column values for equality.
High-level interface
The high-level interface is accessed through the MsiView object, which is constructed with a SQL SELECT statement. The statement can contain parameter markers, "?", literal column values, a predicate expression consisting of logical and comparison operators (including equi-joins), and an ORDER BY column list. Queries with ORDER BY that doesn't specify the primary key are slower to execute, as a temporary table must be constructed. Data is transferred using MsiRecord objects, which contain the set of values transferred. The values may be integers, strings, streams, or COM objects.
Persistent storage
OLE structured storage is used to persist the database. Each table, including catalog tables, is stored as a separate stream. Stream data values are also stored as unique streams. The standard \005SummaryStream property values are supported for use by the database client. Transforms may be stored as substorages, typically to provide updates and language transformations. The persistent files are compatible between the Win32 and Macintosh database engine. Both direct and transaction modes are supported, and temporary rows may optionally be persisted. For archiving purposes, the database engine can import and export tables as tab-delimited text files, with stream data values exported as separate files.
SQL limitations
Currently only SELECT statements are supported.
Update and delete are performed following SELECT execution; positioned update and delete are supported.
Only equi-joins are supported, using equality comparison; subqueries are not supported.
Only logical and comparison predicate operators are supported, no functions, arithmetic operators, GROUP BY.

Schema limitations
Datatypes supported: string, short integer, long integer, stream, object(non-persistent).
Tables may contain from 1 to 32 columns. Tree-linked tables are limited to 64K rows and 256 nesting levels.
Primary keys columns must be defined first in their priority order, followed by any non-primary key columns.
Persistent columns must be defined before temporary columns.
Text collating sequence is undefined; however identical text values will always group together.
Table and column names are not contrained; however to export tables, their names must be unique in the first 8 characters.
 
*#$K+MsiDatabase Object
	Msi Objects	Database Tables
The database object accesses a particular database, which may be either an Access database file, a SQL Server database, an ODBC data source, or a Microsoft Installer database. A low-level database engine is provided by the MsiTable and MsiCursor objects, providing the basis of the Installer database and also providing support for ODBC tables loaded into memory. Some of the capabilities of the internal engine are object storage, dynamic addition of temporary columns, high performance, and tree representation.
In the Microsoft Installer database, strings are stored in a common pool as an array of MsiString objects. Database fields simply store indices to this private array of unique strings. Internally, string uses are reference counted as part of the string management. Functions are provided for converting string objects to and from string indices. A string that returns zero for its index does not exist in the current database.
Persistent tables are normally loaded into memory when a table object is created and removed from memory when the last reference to the table object is released. The LockTable function is used to keep a frequently used table in memory independently of reference counts. As long as the lock calls are greater than the unlock calls, the table remains in memory until the database is closed.
Before the MsiDatabase object that is created for update is destructed (by releasing all references), the Persist method must be called to either record all changes or to back out all changes, else an implicit rollback is performed at object destruction. MSI, Access, and SQLServer all support transactions and require this call. Some ODBC data source may not support transactions, in which case changeds cannot be rolled back (most non-transaction data source do not support update, so this is moot point).
Properties
UpdateState
Storage
TableState
ANSICodePage

Methods
OpenView
GetPrimaryKeys
ImportTable
ExportTable
DropTable
FindTable
LoadTable
CreateTable
LockTable
GetCatalogTable
EncodeString
DecodeString
CreateTempTableName
Commit
CreateOutputDatabase
GenerateTransform
SetTransform
MergeDatabase
Query API Sequencing
The normally course of data access is summarized below:
1. The client obtains a database object (MsiServices.CreateDatabase).
2. OpenView is called, specifying the view name and intended actions.
3. View.Excecute is called, supplying any parameters in an MsiRecord object.
4. View.Fetch is called repeatedly, returns MsiRecord objects until exhausted.
5. View.Close is called, which releases the query and unfetched records.
6. Database.Persist is called to persist any database updates or to back out changes.
*#$K+IMsiDatabase Object
	Msi Classes	Database Tables
The database object accesses a particular database, which may be either an Access database file, a SQL Server database, an ODBC data source, or a Microsoft Installer database. A low-level database engine is provided by the IMsiTable and IMsiCursor objects, providing the basis of the Installer database and also providing support for ODBC tables loaded into memory. Some of the capabilities of the internal engine are object storage, dynamic addition of temporary columns, high performance, and tree representation.
In the Microsoft Installer database, strings are stored in a common pool as an array of IMsiString objects. Database fields simply store indices to this private array of unique strings. Internally, string uses are reference counted as part of the string management. Functions are provided for converting string objects to and from string indices. A string that returns zero for its index does not exist in the current database.
Persistent tables are normally loaded into memory when a table object is created and removed from memory when the last reference to the table object is released. The LockTable function is used to keep a frequently used table in memory independently of reference counts. As long as the lock calls are greater than the unlock calls, the table remains in memory until the database is closed.
Methods
OpenView
GetPrimaryKeys
ImportTable
ExportTable
DropTable
FindTable
LoadTable
CreateTable
LockTable
GetCatalogTable
EncodeString
DecodeString
CreateTempTableName
Query API Sequencing
The normally course of data access is summarized below:
1. The client obtains a database object (IMsiServices::GetDatabase)
2. OpenView is called, specifying the view name and intended actions.
3. View->Excecute is called, supplying any parameters in an IMsiRecord.
4. View->Fetch is called repeatedly, returns records until exhausted.
5. View->Close is called, which releases the query and unfetched records.
#$+KKOpenView Method
	MsiDatabase Object	Msi Objects	Database Tables
Returns an MsiView object representing the query specified by a SQL string.
Syntax
object.OpenView(sql, intent)
object
Required. The MsiDatabase object.
sql
Required. The SQL query string.
intent
Required. The combination of ALL operations intended on the MsiView object:
 ivcNoData   - No data access, can get column information only.
 ivcFetch    - Fetch data from rows into MsiRecord objects.
 ivcUpdate   - Update rows from modified MsiRecord objects.
 ivcInsert   - Insert rows using data in MsiRecord objects.
 ivcDelete   - Delete rows using fetched MsiRecord objects.
SQL Syntax
The SQL query strings are restricted to the format:
The select SQL query.
SELECT [DISTINCT]{column-list} FROM {table-list} [WHERE {operation-list}] [ORDER BY {column-list}].
{table-list} is a comma delimited list of one or more table names hereby refered to as {table} in the join. Table names that clash with SQL keywords need to be quoted within ``.
{column-list} is a comma delimited list of one or more table columns hereby refered to as {column} selected. Ambiguous columns may be further qualified as {tablename.column}. Column names that clash with SQL keywords need to be quoted within ``. In case the column is qualified as {tablename.column} and if there is a need to escape the identifier then the tablename and the column need to be individually escaped as {`tablename`.`column`}
{operation-list} clause is optional and is a grouping of operations to be used to filter the selection. The operations can be of the type -
{column} = {column}
{column} <> {column}
{column} > {column}
{column} < {column}
{column} >= {column}
{column} <= {column}
{column} = {constant}
{column} <> {constant}
{column} > {constant}
{column} < {constant}
{column} >= {constant}
{column} <= {constant}
{column} is null
{column} is not null
individual operations can be grouped be AND or OR operators. Ordering can be imposed by use of ()
{constant} is either a string or an integer. A string has to be quoted within ''.
The BY clause is optional and will cause an initial delay during sorting.
The DISTINCT clause is optional and will not repeat identical records in the return result set.
 The table and column names are case sensitive, even if ODBC databases are used. However, SQL keywords are case-insensitive. Only inner joins are supported, specified by a comparison of columns from different tables.
The delete SQL query.
DELETE FROM {table} [WHERE {operation-list}].
The update SQL query.
UPDATE {table-list} SET {column}= {constant} [, {column}= {constant}]* [WHERE {operation-list}].
The insert SQL query.
INSERT INTO {table} {(column-list)} VALUES {(constant-list)}.
The * implies 0 or more repitition.
The create SQL query.
CREATE TABLE {table} ( {column} [CHAR [( {size} )] | CHARACTER [( {size} )] | LONGCHAR  | SHORT | INT | INTEGER | LONG | OBJECT ]  [NOT NULL] [TEMPORARY] [, column...]* PRIMARY KEY  column [, column]* ).
The * implies 0 or more repitition.
The alter SQL query.
ALTER TABLE {table} ADD  {column} [CHAR [( {size} )] | CHARACTER [( {size} )] | LONGCHAR  | SHORT | INT | INTEGER | LONG | OBJECT ]  [NOT NULL] [TEMPORARY].

#$+KGetPrimaryKeys Method
	MsiDatabase Object	Msi Objects	Database Tables
Returns a MsiRecord object containing table name in Field(0) and the columns names comprising the primary keys in succeeding fields, corresponding their column numbers. The field count of the record is the count of primary key columns.
Syntax
object.GetPrimaryKeys table
object
Required. The MsiDatabase object.
table
Required. Name of an existing table. An error is generated if the table does not exist.
#$+KImportTable Method
	MsiDatabase Object	Msi Objects	Database Tables
Imports a database table from a text archive file, dropping any existing table.
Syntax
object.ImportTable path, file
object
Required. The MsiDatabase object.
path
Required. An MsiPath object set to the folder where the text file is present.
file
Required. The name of the file to be imported. This does not include the folder, as that must be set in the path object. The table name is specified within the file.
Archive File Format
SummaryInformation Stream
For .MSI databases only, not ODBC, a special stream "05SummaryInformation" is written containing standardized properties defined by OLE and browsable by the Explorer. If the table name in the text archive file is named exactly "_SummaryInformation", the table rows consisting of pairs of Property Id numbers with corresponding data values will be written to the property stream. For ODBC databases, a normal table will be created. If the data value is a valid integer, it is taken to be an integer property. Else if it can be parsed as a date or date/time value (consisting of digits separated by slashes) it is taken to be a data/time value. Otherwise it is assumed to be a string value. Date values may have two formats: yyyy/mm/dd  (time is entered as 0) or yyyy/mm/dd/hh/mm/ss (24 hr. time). The summary information is customarily generated for new files by the release build process.
#$+KExportTable Method
	MsiDatabase Object	Msi Objects	Database Tables
Copies the structure and data from a specified table to a text archive file.
Syntax
object.ExportTable table, path, file
object
Required. The MsiDatabase object.
table
Required. The name of the database table, case-sensitive if MSI database.
path
Required. An MsiPath object set to the folder where the text file will be placed.
file
Required. The name of the file to be created. This does not include the folder, as that must be set in the path object. Keep to the 8.3 format if SLM is used.
Archive File Format
#$+KLoadTable Method
	MsiDatabase Object	Msi Objects	Database Tables
The LoadTable method creates and returns a database table object in memory by reading a table from the persistent database. Additional temporary columns may be added if desired using the CreateColumn of the created table. This table remains in memory as long as there are outstanding references to the MsiTable object, or outstanding locks from the LockTable method. If an Access, SQL Server, or ODBC table is specified, database operations will be performed on the in-memory table, and any update operations on persistent columns will be replicated in the persistent table.
Syntax
object.LoadTable(table, addColumns)
object
Required. The MsiDatabase object.
table
Required. Name of an existing table. An error is generated if the table does not exist in the current database.
addColumns
Optional. The anticipated number of columns that will be added after the data is loaded. This is for optimization only. Columns may be added beyond this number, but will require reallocation of the data rows.
Remarks
If the requested table is already loaded into memory, a reference to that table will be returned. When processing SQL queries on an Msi database, tables will be loaded if necessary during the processing of the query, and will remain loaded until the MsiView object is released. If a table is known to be accessed repeatedly, LockTable may be called to hold the table in memory once loaded.
A table loaded from an ODBC database must have a primary key defined and the composite columns must specified in order as the first columns in the table. (In the future the column order to be altered when loaded into memory.)
#$+KCreateTable Method
	MsiDatabase Object	Msi Objects	Database Tables
Creates a temporary, in-memory table, and returns it as a MsiTable object. If columns are marked as persistent, the table will be created in the persistent database when the database is closed.
Syntax
object.CreateTable(table, initRows)
object
Required. The MsiDatabase object.
table
Required. Name to be given to table. An error will be generated if a table by that name already exists in the current database.
rowCount
Optional. The suggested number of rows to allocate initially. This is an optimization only. If this argument is omitted or has a value of zero, the default number of rows will be initially allocated. The data array will grow as required as more rows are inserted.
#$+KLockTable Method
	MsiDatabase Object	Msi Objects	Database Tables
The LockTable method will lock a specified table in memory once it is loaded, or will release a lock on a table that has been locked. When all locks are released and there are no outstanding references to the table object, it will be released from memory. Any outstanding locks will be removed when the database object is destroyed. The method returns a boolean indicating whether the lock operation succeeded.
Syntax
object.LockTable(table, lock)
object
Required. The MsiDatabase object.
table
Required. The name of the table to lock.
lock
Required. Boolean value, TRUE to lock, FALSE to unlock.
Remarks
Locking a table that is not loaded into memory will not attempt to load that table into memory, but will hold it in memory once loaded. Locks are cumulative, and the loaded table is held in memory until the lock count returns to zero. Locking is a performance hint to the database engine and may not always be honored.
#$+K DropTable Method
	MsiDatabase Object	Msi Objects	Database Tables
Removes a table from the persistent database along with its data. This method will fail if the table does not exist or if the database is not an MSI database and the table is in use. Dropping an MSI database table that is in use will remove it from the system catalogs, but the now-anonymous MsiTable object will remain until all references are released. Temporary tables, created with CreateTable, cannot be dropped, but will be destroyed when all references are released. ODBC databases generally do not perform Drop Table within the transaction, preventing this operation from being rolled back.
Syntax
object.DropTable table
object
Required. The MsiDatabase object.
table
Required. The name of the database table, case-sensitive if MSI database.
#$+KK FindTable Method
	MsiDatabase Object	Msi Objects	Database Tables
Returns the status of a table in this database, one of the enum itsEnum:
 itsUnknown   = 0  named table is not in database
 itsTemporary = 1  table is temporary, not persistent !!marked obsolete
 itsUnloaded  = 2  table exists in database but is not loaded
 itsLoaded    = 3  table is loaded into memory from database
 itsOutput    = 6  table copied to output database (itsUnloaded + 4)
 itsSaveError = 7  unable to write table to storage (itsLoaded + 4) !!marked obsolete
 itsTransform = 10 table need to have tranform applied when loaded !!marked obsolete
Syntax
object.FindTable table
object
Required. The MsiDatabase object.
table
Required. The name of the database table, case-sensitive.
#$+KKTableState Property
	MsiDatabase Object	Msi Objects	Database Tables
Returns a selected attribute of a table in this database. Read-only.
Syntax
object.TableState(table, state)
object
Required. The MsiDatabase object.
table
Required. The name of the database table, case-sensitive.
state
Required. The particular attribute to be queried, one of the enum itsEnum:
 itsPermanent   = 0   table has persistent columns
 itsTemporary   = 1   temporary table, no persistent columns
 itsTableExists = 2   table currently defined in system catalog
 itsDataLoaded  = 3   table currently present in memory
 itsUserClear   = 4   user state flag reset, not used internally
 itsUserSet     = 5   user state flag set, not used internally
 itsOutputDb    = 6   persistence transferred to output database
 itsSaveError   = 7   error saving table, will retry at Commit
 itsUnlockTable = 8   table is not locked in memory
 itsLockTable   = 9   table locked in memory
 itsTransform   = 10  table needs to be transformed when loaded
#$+KGetCatalogTable Method
	MsiDatabase Object	Msi Objects	Database Tables
Returns one of the MsiTable objects maintained by the MsiDatabase object that contain the table definitions for the database. The returned MsiTable object is read-only, and its data can be queried by creating an MsiCursor object on the table. The table structures are given below.
Syntax
object.GetCatalogTable(table)
object
Required. The MsiDatabase object.
table
Required. Table to access: 0 = _Tables, 1 = _Columns.
Tables Catalog Table Definition
  1 - Table name, primary key for this catalog table
  2 - MsiTable object, only if table is loaded into memory
Columns Catalog Table Definition
  1 - Table name, 1st column of primary key for this catalog table
  2 - Column number, remainder of primary key
  3 - Column name, may be Null
  4 - Column type, integer containing packed size and type information
Remarks
These tables are maintained for ODBC databases as well as MSI databases, and will also contain definitions for any temporary tables created.
#$+KDecodeString Method
	MsiDatabase Object	Msi Objects	Database Tables
This function converts a database string index into its referenced string.
Syntax
object.DecodeString(index)
object
Required. The MsiDatabase object.
index
Required. The database string index, 0 is always the null string.
#$+KEncodeString Method
	MsiDatabase Object	Msi Objects	Database Tables
This function converts a string into its corresponding database string index. If the string is not used in the database the value 0 will be returned. An empty string is treated as a Null in the database and not stored. Consequently, this functions returns 0 for an empty string.
Syntax
object.EncodeString(text)
object
Required. The MsiDatabase object.
text
Required. The string for which the string index is requested.
#$+KCreateTempTableName Method
	MsiDatabase Object	Msi Objects	Database Tables
Returns a unique table name that can be used for a temporary database table using the CreateTable method.
Syntax
object.CreateTempTableName
object
Required. The MsiDatabase object.
#$+KPersist Method
	MsiDatabase Object	Msi Objects	Database Tables
 --This method is OBSOLETE.-- use Commit instead. Finalizes the persistent form of the database. Depending upon the action specified, changes made to the database since it was opened can be committed or rolled back, or the database can be physically deleted when the current object is destructed. If the MsiDatabase object has been created read-only, this method will have no effect and no error will be generated. If the CreateOutputDatabase method has be called, any unloaded input database tables will be transferred to the output database. This method is normally called prior to shutdown when all database changes have been finalized. If this method is never explicitly called, the database will be rolled back when the Database object is destructed, with action set to idpRollback.
Syntax
object.Persist action
object
Required. The MsiDatabase object.
action
Required. The action to be taken on the persistent format, on of the enum idpEnum:
 idpRollback  = 0 = FALSE  NO-OP (rollback performed at database destruction)
 idpCommit    = 1 = TRUE   current updates committed, further updates allowed
 idpDelete    = 2          file is to be deleted when all references released
 idpSave      = 3          NOT SUPPORTED
#$+KCommit Method
	MsiDatabase Object	Msi Objects	Database Tables
Finalizes the persistent form of the database. All persistent data will be written to the writable database. No temporary columns or rows are written. This method has no effect on a database opened read-only. This method can be call multiple times to save the current state of tables loaded into memory. When the database is finally closed, any changes made subsequent to the last Commit will be rolled back. If the CreateOutputDatabase method has be called, any unloaded input database tables will be transferred to the output database, applying transforms as required.. This method is normally called prior to shutdown when all database changes have been finalized.
Syntax
object.Commit
object
Required. The MsiDatabase object.
#$+KCreateOutputDatabase Method
	MsiDatabase Object	Msi Objects	Database Tables
Specifies the name of the output database to be created that will contain the original database as modified by all update operations. This method will fail if called after any modifications have been written to the original database. This does not apply to changes made to tables loaded into memory, as the changes are not written to the persistent database until the tables are released from memory.
Syntax
object.CreateOutputDatabase file, saveTempRows
object
Required. The MsiDatabase object.
file
Required. The name of the database to be created. Only .msi database format is currently supported.
saveTempRows
Optional. True to persist temporary table rows, False to drop them from persistent storage.
Remarks
The method in provided to avoid unnecessary copying of the database. Often the final location of the updated database is not known without processing the information in the database itself, and the database could be significantly updated. If this method is used, the original database can be opened read-only, and thus may reside on a CD or a read-only server. This method must be called before the first update to the persistent database, i.e. released a modified table from memory, or performing a update on a non-loaded table using any of the update methods of the MsiView object. When this MsiDatabase object is released, all unmodified tables, along with associated binary stream data, will be copied to the output database.
#$+KGenerateTransform Method
	MsiDatabase Object	Msi Objects
Creates a transform which, when applied to the object database, will result in the reference database. The transform is stored in the storage object.
Syntax
object.GenerateTransform(reference, storage, long errorConditions, long validation)
object
Required. The MsiDatabase object.
reference
Required. The reference MsiDatabase object.
storage
Required. The MsiStorage object where the transform is to be stored.
errorConditions
Required. The conditions that should be ignored as errors when the transform is applied.
Choose either:
 iteNone                - None of the following conditions.
Or combine one or more of the following:
 iteAddExistingRow      - Adding a row that already exists.
 iteDelNonExistingRow   - Deleting a row that doesn't exist.
 iteAddExistingTable    - Adding a table that already exists.
 iteDelNonExistingTable - Deleting a table that doesn't exist.
 iteUpdNonExistingRow   - Updating a row that doesn't exist.
validation
Required. When the transform is applied to a database, which properties should be validated to verify that this transform can be applied to the database. The properties are all contained in the Summary Information stream.
 itvNone           - Validate no properties.
Or combine one or more of the following
 itvLanguage       - Default language must match base database.
 itvProduct        - Product must match base database.
 itvPlatform       - Platform must match base database.
To validate product version, first choose one or more of these three flags to indicate how much of the version is to be verified.
 itvMajVer         - Check major version only.
 itvMinVer         - Check major and minor version only.
 itvUpdVer         - Check major, minor, and update version.
Then choose one of the following to indicate the required relationship between the product version of the database the transform is being applied to, and that of the base database.
 itvLess           - Applied db version <  base db version
 itvLessOrEqual    - Applied db version <= base db version
 itvEqual          - Applied db version =  base db version
 itvGreaterOrEqual - Applied db version >= base db version
 itvGreater        - Applied db version >  base db version
Remarks
!! The error and validation conditions may or may not work !!

	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. This means that you cannot add primary key columns to a table or change the order or names or column definitions of the existng columns as defined in the base table.  Therefore, the reference table must contain the exact same table schema, but it can have some additional/extra columns.  These columns must come after the columns defined in the base table though.  In other words, if neither table contained data and the extra columns were removed from the reference table, the resulting refernce table would be identifcal to the base table.  No deletion of columns, addition of primary keys, or changing of column definitions is allowed.
#$+KSetTransform Method
	MsiDatabase Object	Msi Objects
SetTransform will apply the given transform to this database.
Syntax
object.SetTransform(storage, errorConditions)
object
Required. The MsiDatabase object.
storage
Required. The MsiStorage object containing the transform.
treatAsError
Required. The conditions that should be ignored as errors, specified as an integer combination of the values below.
 iteAddExistingRow        Adding a row that already exists.
 iteDelNonExistingRow     Deleting a row that doesn't exist.
 iteAddExistingTable      Adding a table that already exists.
 iteDelNonExistingTable   Deleting a table that doesn't exist.
 iteUpdNonExistingRow     Updating a row that doesn't exist.
Remarks
SetTransform delays transforming tables until the last possible moment.  The steps taken in SetTransform are to immediately transform the table and column catalogs for the database.  The table and column catalogs are updating according to what table is added or deleted and what column is added (no deletion of columns is allowed).  If a table is currently loaded in memory and needs to be transformed, it will be transformed then.  Else, the table's state will be set to that requiring a transform so that when it is loaded or when the database is committed the transform will be applied.  Transform in this instance means that the actual data (row data) of the table is added, deleted, or updated.
If SetTransform is called when tables have already been saved to storage, an error will occur.
#$+KMergeDatabase Method
	MsiDatabase Object	Msi Objects
MergeDatabase will merge the reference database in with the base database.
Syntax
object.MergeDatabase(reference, errorTable)
object
Required. The MsiDatabase object.
reference
Required. The MsiDatabase object to be merged into the base.
errorTable
Optional. A table object to contain the names of the tables containing merge conflicts, the number of conflicting rows within the table, and a reference to the table with the merge conflict.
Remarks
	If no table is provided, the general error message provides the number of tables containing merge conflicts.  Any table can be passed in, but all other columns must be nullable as the operation to update the error table will fail if a column is not nullable.  A newly created table can be passed in as well since the MergeDatabase method will automatically create the columns it uses if merge conflicts are found.  Three columns are used for presenting merge conflicts.  The first column is the table's name.  It's also the primary key column.  Column two is the number of rows of that table that had merge failures.  Column three is a temporary column that is not persisted/saved.  It contains the reference to the table that can be obtained by cursor.ObjectData on that column and then asking for the iidMsiTable interface.  This reference enables one to go through the table and output those rows where merge failures occurred [using iraMergeFailed bit.]  If this is not done, that bit for that row will be cleared, as the iraMergeFailed bit is not a persistent bit.  It should be noted that Column three is not a persistent column, so upon commitance of the database that contains this table, only column one and column two will remain. 
If tables of the same name in both databases do not match in the number of primary keys, the column types, the number of columns, or the column names,  the MergeDatabase method will fail, and will post an error message pertaining to which mismatch  occurred. 
For the error table to remain, the error handler must commit the database to which the error table  belongs.  However, this commit should be done after using the third column to obtain the references  to those tables where merge conflicts occurred.  When the database is committed, the third column will  be lost as it is not a persistent column since it temporarily stores an object [the reference to  the table].
#$+KUpdateState Property
	MsiDatabase Object	Msi Objects	Database Tables
Returns the current persistence state of the database, as one of enum idsEnum:
 idsRead     = 0 database open read-only, changes are not saved
 idsWrite    = 1 database fully operational for read and write
Syntax
object.UpdateState
object
Required. The MsiDatabase object.
#$+KANSICodePage Property
	MsiDatabase Object	Msi Objects	Database Tables
Returns the ANSI codepage of the current database, 0 if language neutral
Syntax
object.ANSICodePage
object
Required. The MsiDatabase object.
Remarks
	The string data in a persisted database is stored in a single codepage, in order to support Win9x and to optimize storage. If the strings have no extended characters, then the codepage is defaulted to 0, language-neutral. Table import, merge, or transform operations will set a neutral database to any non-neutral merged data, and will be rejected if a codepage conflict occurs.
#$+KStorage Property
	MsiDatabase Object	Msi Objects	Database Tables
Returns the designated MsiStorage object if present, else returns an empty (Nothing) object,
Syntax
object.Storage(index)
object
Required. The MsiDatabase object.
index
Required. An integer designating which storage to return.
 0 The output database storage if  CreateOutputDatabase succeeded.
 1 The original storage if the database was created from an MsiStorage or from an MSI database file.
>1 Auxiliary storages used for transforms (not implemented yet).
#$K+MsiView Object
	Msi Objects	Database Tables
This object represents a result set obtained processing a query using the MsiDatabase method OpenView. Before any data can be transferred the query must be executed using the Execute method, passing to it all replaceable parameters designated within the SQL query string. The query may be reexecuted, with different parameters if desired, but only after freeing the result set either by fetching all the records or by calling the Close method. The data transfer methods will fail if the corresponding intent flags were not specified in the OpenView call.  
Methods
Execute
Fetch
GetColumnNames
GetColumnTypes
Update
Insert
Delete
Modify
Close
GetError

Properties
FieldCount
RowCount
State

#$+KExecute Method
	MsiView Object	Msi Objects	Database Tables
Accepts replaceable query parameters and executes the database query, producing a result set that can be fetched or updated.
Syntax
object.Execute record
object
Required. The MsiView object.
record
Optional. MsiRecord objects containing values to replace parameter markers, "?", in the SQL query.
Remarks
This method must be called before any calls to Fetch. If the SQL query specifies values in the predicate expression with parameter markers (question marks), then a record must be supplied containing all of the replacement values in the exact order and of compatible data types.
#$+KFieldCount Property
	MsiView Object	Msi Objects	Database Tables
A long indicating the number of columns the will be fetched into MsiRecord fields.
Syntax
object.FieldCount
object
Required. The MsiView object.
#$+KRowCount Property
	MsiView Object	Msi Objects	Database Tables
A long indicating the number of rows affected by MsiView.Execute.
Syntax
object.RowCount
object
Required. The MsiView object.
Remarks
Should be called only after the MsiView.Execute and before a MsiView.Close.Would return error otherwise
#$+KState Property
	MsiView Object	Msi Objects	Database Tables
A long indicating the current cursor state for the MsiView object. Is one of 
dvcsClosed
The MsiView object is currently in the state closed.
dvcsPrepared
The MsiView object has been prepared i.e. the SQL query has been parsed. 
dvcsExecuted
Internal use only.
dvcsBound
Parameters to the SQL query, if any have been bound to the SQL query. This is the state before the first Fetch. (The MsiView::Execute() function has been executed).
dvcsFetched
Atleast one record has been successfully fetched from the MsiView object (via the MsiView::Fetch() function).
dvcsDestructor
Internal use only.

Syntax
object.RowCount
object
Required. The MsiView object.
Remarks

#$+KFetch Method
	MsiView Object	Msi Objects	Database Tables
Returns an MsiRecord object containing the requested column data if more rows are available in the result set, else returns an object of value Nothing.
Syntax
object.Fetch
object
Required. The MsiView object.
Remarks
This method must be called after Execute. For maximum performance, the same record object should be used for all fetches, or else it should be released by going out of scope. The returned record can be tested for the end of the result set using the syntax: "If FetchRecord Is Nothing".
#$+KGetColumnNames Method
	MsiView Object	Msi Objects	Database Tables
Returns an MsiRecord object containing the columns names corresponding to the fetched record fields.
Syntax
object.GetColumnNames
object
Required. The MsiView object.
#$+KGetColumnTypes Method
	MsiView Object	Msi Objects	Database Tables
Returns an MsiRecord objects with text fields containing the data types of the corresponding database columns, in the  Archive File Format used by ExportTable.
Syntax
object.GetColumnTypes
object
Required. The MsiView object.
Remarks

#$+KUpdate Method
	MsiView Object	Msi Objects	Database Tables
Updates a database row with a modified MsiRecord object obtained by the Fetch method.
Syntax
object.Update record
object
Required. The MsiView object.
record
Required. The MsiRecord object obtained by the Fetch method, with modified field data.
Remarks
Only the record fields that have been updated will be written to the database. Thus multiple threads can update the same rows independently as long as they have modified different database columns.
#$+KInsert Method
	MsiView Object	Msi Objects	Database Tables
Inserts a new row into the database with values in an MsiRecord object. This method will fail if the primary key columns contain any Null values or as a group match any existing row in the table.
Syntax
object.Insert record
object
Required. The MsiView object.
record
Required. An MsiRecord object containing values for a new database row.
Remarks
The values in the record fields must match the query specification in sequence and in data types (same as would be obtained by the Fetch method). Null values may be supplied in the record fields as long as they are not part of the primary key.
#$+KDelete Method
	MsiView Object	Msi Objects	Database Tables
Removes the row corresponding the MsiRecord just obtained with the Fetch method.
Syntax
object.Delete record
object
Required. The MsiView object.
record
Required. The MsiRecord object obtained by the Fetch method.
Remarks
This method will fail if the primary key fields are modified, or if the primary key no longer exists in the database.
#$+KModify Method
	MsiView Object	Msi Objects	Database Tables
Modifies a database row with a modified MsiRecord object obtained by the Fetch method.
Syntax
object.Modify record action
object
Required. The MsiView object.
record
Required. The MsiRecord object obtained by the Fetch method, with modified field data.
action
Required. Indicates the action to be performed on the database row. The operation map on to one with the modification operation that can be performed on the MsiCursor object. Is one of - 

irmSeek
Completes the record data.  Seek requires that the primary key fields be filled in and then fills in the rest of the data, allowing one to seek to a particular entry in the table (instead of having to fetch and compare).  The record must contain all columns of the table.  Corresponds to the MsiCursor.Seek operation.  One can Insert/Update/Delete the record after seeking.
irmInsert
Inserts the information into the database table. The operation does not require a MsiView.Fetch to have been performed before its calling. The function will fail if a row with the same primary key(s) exist in the table. Corresponds to the MsiCursor.Insert operation.  The database must be open for modification. 
irmInsertTemporary
Temporarily inserts the information into the database table. The operation does not require a MsiView.Fetch to have been performed before its calling and the database does not have to be open for modification. The function will fail if a row with the same primary key(s) exist in the table. Corresponds to the MsiCursor.InsertTemporary operation 
irmUpdate
Updates the information already existing in the database allowing modification of non-primary keys only. The operation does not require a MsiView.Fetch  to have been performed before its calling and has to be called with the same record as that returned by the fetch. The function will fail if the row has been deleted from the table. Corresponds to the MsiCursor.Update operation.  Requires that the database be open for modification. Update can occur on a fetched, inserted, or deleted record.
irmDelete
Deletes the information already existing in the database (that is open for modification). The operation does not require a MsiView.Fetch  to have been performed before its calling and has to be called with the same record as that returned by the fetch. The function will fail if the row has been deleted from the table. Corresponds to the MsiCursor.Delete operation.  Delete can be done on a fetched, inserted, or seeked record. 
irmRefresh
Refreshes the information in the record from the database. The operation requires a MsiView.Fetch  to have been performed before its calling and has to be called with the same record as that returned by the fetch. The function will fail if the row has been deleted from the table. Corresponds to the MsiCursor.Refresh operation 
irmAssign
Inserts/updates the information into the database table. The operation does not require a MsiView.Fetch to have been performed before its calling.  An update operation takes place if primary keys match an existing row. An insert operation takes place if primary keys do not match any row. In either case the current data in the cursor are written to a table row. Corresponds to the MsiCursor.Assign operation. Requires that the database be open for modification.
irmMerge
Inserts/validates the information into the database table. The operation does not require a MsiView.Fetch to have been performed before its calling. An insert operation takes place if primary keys do not match any row. A validation operation takes place if primary keys match an existing row. The operation fails if the record data does not match the data in the table. Corresponds to the MsiCursor.Merge operation.Requires that the database be open for modification. 
irmReplace
Updates/Delete-Inserts the information into the database table. The operation requires a MsiView.Fetch to have been performed before its calling and has to be called with the same record as that returned by the fetch. If the primary key(s) have not been changed then an update of the table row occurs. If the primary key(s) have been changed the old table row is deleted and a new row corresponding to the record is inserted. Corresponds to the MsiCursor.Replace operation.  Requires that the database be open for modification. 
irmValidate
Validates a record.  Will not validate across joins. The operation requires a MsiView.Fetch performed before its calling and has to be called with the same record as that returned by the fetch.  Validation errors can be obtained by subsequent callings to MsiView.GetError MsiView_GetError. Corresponds to the MsiCursor.Validate operation passing in 0 as the value for iCol.
irmValidateNew
Validates a record as a new record.  Requires the database to be open for modification. Will not validate across joins. This differs from irmValidate in that it checks for duplicate keys.  The operation requires that MsiDatabase.OpenView be called with a modify value.  Validation errors can be obtained by subsequent callings to MsiView.GetError.  Corresponds to the MsiCursor.Validate operation passing in -1 as the value for iCol.
irmValidateField
Validates a field(s) of a fetched or new record.  Will not validate across joins. The validation depends upon the number of fields in the record.  If only one field exists, it will validate the one field.  It can also validate more fields.  It should be used when the fetched/new record does not represent every column of the table. Makes repeated calls to MsiCursor.Validate depending upon the number of fields in the record.
irmValidateDelete
Validates a fetched record.  Will not validate across joins. The validation depends upon the _Validation table and in particular the 'KeyTable' and 'KeyColumn' columns of the table.  Validate delete returns an error if a row in the same table or another table explicitly references the primary key(s) of the row to be deleted.  It requires that the database be open for modification and the operation requires a MsiView.Fetch performed before its calling and has to be called with the same record as that returned by the fetch. Corresponds to the MsiCursor.Validate operation passing in a -2 as the value for iCol.

Remarks

#$+KClose Method
	MsiView Object	Msi Objects	Database Tables
Terminates query execution and releases database resources.
Syntax
object.Close
object
Required. The MsiView object.
Remarks
This method must be called before the Execute method is called again on the MsiView object, unless all rows of the result set have been obtained with the Fetch method. It will be called internally when the view is destroyed.
#$+KGetError Method
	MsiView Object	Msi Objects	Database Tables
Returns the Validation error and the column name for which the error occured.  In automation, the return is a string of the form ColumnName,Error.  It returns the first error it finds in the view's error array.  So, once a return of ColumnName,0 [zero does not show up in automation], no more errors exist.  See MsiCursor_Validate for error enums.
Syntax
object.GetError
object
Required. The MsiView object.
Remarks

#$K+MsiTable Object
This object represents a database table loaded into memory and is accessed by a very efficient internal query engine. The table may be an image of a persistent table with option temporary columns added, or may be totally composed of temporary columns. If column names are not supplied, they are not accessible for joins or by SQL. To access table data, an MsiCursor object is created that can be positioned sequentially or can seek to a particular set of data values. The cursor seek operation will be slower when the search values do not include the primary key columns. When a cursor object is created or when its Reset method is called, it will be logically positioned just before the first table row. The Next method always moves forward from the current cursor position. If a table is linked as a tree, a tree-walking cursor can be created that will advance  to the next node in a depth-first traversal.
Persistent tables are normally loaded into memory when a table object is created and removed from memory when the last reference to the table object is released. The LockTable function is used to keep a frequently used table in memory independently of reference counts. As long as the lock calls are greater than the unlock calls, the table remains in memory until the database is closed.
For performance reasons, strings are not stored in the table data. Rather, integer indices are stored which reference a common string pool maintained by the database. Internally, string uses are reference counted as part of the string management. Functions are provided in the MsiDatabase object to convert strings to and from string indices. A string index of 0 indicates a Null string value.
Properties
Database
RowCount
ColumnCount
PrimaryKeyCount
ReadOnly
ColumnName
ColumnType

Methods
GetColumnIndex
CreateColumn
CreateCursor
LinkTree

#$+KDatabase Property
	MsiTable Object	Msi Objects	Database Tables
Returns the MsiDatabase object that owns this table.
Syntax
object.Database
object
Required. The MsiTable object.
#$+KRowCount Property
	MsiTable Object	Msi Objects	Database Tables
Returns the number of rows that are currently contained in the table.
Syntax
object.RowCount
object
Required. The MsiTable object.
#$+KColumnCount Property
	MsiTable Object	Msi Objects	Database Tables
Returns the number of columns defined in the table.
Syntax
object.ColumnCount
object
Required. The MsiTable object.
#$+KPrimaryKeyCount Property
	MsiTable Object	Msi Objects	Database Tables
Returns the number of columns that comprise the primary key for the table.
Syntax
object.PrimaryKeyCount
object
Required. The MsiTable object.
#$+KReadOnly Property
	MsiTable Object	Msi Objects	Database Tables
Returns a boolean, True if table is not updatable, False if the table can be updated provided the database is not read-only.
Syntax
object.ReadOnly(column)
object
Required. The MsiTable object.
#$+KColumnName Property
	MsiTable Object	Msi Objects	Database Tables
Returns the string index for the name of the designated column, or 0 if the column does not exist or if it has no name.
Syntax
object.ColumnName(column)
object
Required. The MsiTable object.
column
Required. Column index, 1-based.
Remarks
The string index may be converted to the corresponding string using the MsiDatabase method DecodeString.
#$+KKColumnType Property
	MsiTable Object	Msi Objects	Database Tables
Returns the column definition for the designated column, as an integer containing bit flags:
 icdObject      some type of object if 1, else integer if 0
 icdShort       if icdObject: 1=string, 0=other object; else 1=16-bit integer, 0=32-bit integer
 icdPersistent  persistent column if 1 (objects are streams), temporary if 0
 icdNullable    if 1, column will accept null values
 icdPrimaryKey  if 1, column comprises part of primary key
The SQL data width for persistent columns is returned in the lower 8 bits (AND with 255).
Syntax
object.ColumnType(column)
object
Required. The MsiTable object.
column
Required. Column index, 1-based.
Remarks
Three types of objects, all derived from MsiData, can be stored:
 Strings stored as indices into the string pool, icdObject+icdShort
 Persistent stream objects, accessible via MsiCursor.StreamData, icdObject+icdPersistent
 Other objects derived from MsiData, accessible via MsiCursor.ObjectData, icdObject
#$+KGetColumnIndex Method
	MsiTable Object	Msi Objects	Database Tables
Returns the column number for a column name supplied as a string index. Returns 0 if the column name does not exist for the table.
Syntax
object.GetColumnIndex(nameIndex)
object
Required. The MsiTable object.
nameIndex
Required. The database string index for column name.
Remarks
Use the MsiDatabase method EncodeString to convert a string into a string index. This method returns 0 if the column name does not exist in the table, or if the string index is 0.
#$+KKKCreateColumn Method
	MsiTable Object	Msi Objects	Database Tables
 Defines column parameters for a new column for an MsiTable object created with CreateTable or LoadTable. Returns the column number for the created column if successful. Fails if the column could not be created or if the a column by the same name already exists.
Syntax
object.CreateColumn(columnDef, name)
object
Required. The MsiTable object.
columnDef
Required. The column attributes, an integer combination of the values below.
The datatype of the column, comprising the bit flags icdObject and icdShort:
 icdLong      32-bit integer value (icdLong = 0, for readability only)
 icdShort     16-bit integer value, for persistent integer columns
 icdObject    MsiData object (non-persistent), MsiStream (persistent)
 icdString    string, stored as index to database string cache (icdObject+icdShort)
Column characteristics:
 icdPrimaryKey    column is part of primary key
 icdNullable      column will accept null values
 icdNoNulls       value required (icdNoNulls = 0, for readability only)
Persistence:
 icdPersistent    column saved in persistent database
 icdTemporary     temporary column (icdTemporary = 0, for readability only)
SQL column width in bytes, a number between 0 and 255, persistent columns only
name
Optional. Column name, unique within the table. Persistent columns must be given a name. Anonymous columns cannot be accessed via SQL queries.
Remarks
All persistent columns must be defined before any non-persistent columns. At least one column must be designated as the primary key column, and the primary key columns must be the first columns in the table, with the most-significant columns first. Persistent columns cannot contain object references, but may contain binary streams. Avoid 32-bit integers when possible for persistent columns, as the storage is inefficient. Use 32-bit integers for termporary columns, as there is no bounds checking. Persistent primary key columns cannot accept the icdNullable attribute. Each row in the table must have a unique set of primary key values. A maximum of 32 columns may be defined for a database table. The number of rows is limited by the available memory.
#$+KCreateCursor Method
	MsiTable Object	Msi Objects	Database Tables
Returns an MsiCursor object that is in the reset state.
Syntax
object.CreateCursor(tree)
object
Required. The MsiTable object.
tree
Optional. Boolean indicating whether to create a tree-walking cursor. A True value will create a cursor that will walk a tree-linked table in tree traversal order, whereas a False, or missing, value will create a normal cursor that will advance by row order. The two types behave identically if the table is not tree-linked.
Remarks
To avoid excessive processing, mimimize the number of active cursors on a table that is subject to frequent row insertions and deletions.
#$+KLinkTree Method
	MsiTable Object	Msi Objects	Database Tables
Links the table in depth-first tree-traveral order to support a tree-walking cursor. If the tree cannot be fully resolved the method will fail, returning -1. If the method succeeds, the number of tree roots will be returned (a return value of 0 indicates that the table is empty). A row parented to itself or having a Null parent indicates a root node.
Syntax
object.LinkTree(parentColumn)
object
Required. The MsiTable object.
parentColumn
Required. The column number specifying the tree parent data. This column must contain values referencing the single primary key column of the table.
Remarks
 This method requires that the primary key be composed of a single column. The method will fail if any of the values in the specified column do not match a primary key value currently in the table. Once the table is linked, only leaf node rows may be deleted (those that are not the parent of another row). Rows may be inserted, provided that their parent values are present in the table. Specifying a parentColumn value of zero will unlink the table, and all cursors will then advance sequentially through the rows.
#$K+MsiCursor Object
To access table data, an MsiCursor object is created that can be positioned sequentially or can seek to a particular set of data values. The cursor seek operation will be slower when table's primary key columns are not specified. When a cursor object is created or when its Reset method is called, or when the Next method fails to find a qualifying row, it will be logically positioned just before the first table row. The Next method always moves forward from the current cursor position. If a table is linked as a tree, a cursor can be created that advances to the next node in a depth-first traversal.
The cursor contains a snapshot of a table row, and its data is transferred to and from the table as an atomic operation. On update, only columns with changed data will be transferred, thus allowing other columns to be updated via other cursor objects.
Properties
Table
Filter
IntegerData
StringData
DateData
ObjectData
StreamData
RowState
Moniker

Methods
PutNull
Reset
Next
Update
Insert
InsertTemporary
Assign
Replace
Merge
Refresh
Delete
Seek
Validate

#$+KIntegerData Property
	MsiCursor Object	Msi Objects	Database Tables
Transfers integer data to or from a column value in the cursor object. Read-write.
Syntax
object.IntegerData(column)
object
Required. The MsiCursor object.
column
Required. Column index, 1-based.
Remarks
A null value in an integer column will be returned as the defined constant iMsiNullInteger. If the column is designated as a primary key or a non-null column, attempting to set its value to iMsiNullInteger will produce an error.
The IntegerData property will transfer data of all types as integers. This method will fail if the column is type itdShort and the integers is outside the 16-bit range. String data will be transferred using the database string index, and object data will transferred as an integer containing the actual address of the object. Care must exercised when passing objects as integers, as no validation can be done at this low level. The integer returned for an object is not reference counted, but when an object is set into the cursor using an integer, its AddRef method is called because the cursor, and ultimately the database table, is keeping a copy of that pointer. A null value for a non-integer column returned as an integer will be zero.
#$+KStringData Property
	MsiCursor Object	Msi Objects	Database Tables
Transfers string data to or from a string column value in the cursor object. Read-write.
Syntax
object.StringData(column)
object
Required. The MsiCursor object.
column
Required. Column index, 1-based.
Remarks
Setting StringData property on a non-string column will fail. Returning the property on a non-string column will return an empty string.
#$+KDateData Property
	MsiCursor Object	Msi Objects	Database Tables
Transfers date/time data to or from a string or long integer column value in the cursor object. Read-write.
Syntax
object.DateData(column)
object
Required. The MsiCursor object.
column
Required. Column index, 1-based.
Remarks
Returning the property on a non-date value may fail or return an invalid date.
#$+KObjectData Property
	MsiCursor Object	Msi Objects	Database Tables
Transfers object references to or from a column value in the cursor object. Read-write.
Syntax
object.ObjectData(column)
object
Required. The MsiCursor object.
column
Required. Column index, 1-based.
Remarks
Objects stored in the database tables must be derived from the MsiData base object and cannot be stored in persistent columns. A Null value for an object has pointer value of zero, but is set and tested in BASIC using the Missing keyword. If the column is designated as a primary key or a non-null column, attempting to set its value to a null object will produce an error. Objects are reference counted when stored in the MsiCursor and the MsiTable objects.
#$+KStreamData Property
	MsiCursor Object	Msi Objects	Database Tables
Transfers MsiStream objects to or from a column value in the cursor object. Read-write.
Syntax
object.StreamData(column)
object
Required. The MsiCursor object.
column
Required. Column index, 1-based.
Remarks
This property may only be used with persistent columns typed as icdObject.
#$+KTable Property
	MsiCursor Object	Msi Objects	Database Tables
Returns the MsiTable object that owns this cursor object.
Syntax
object.Table
object
Required. The MsiCursor object.
#$+KReset Method
	MsiCursor Object	Msi Objects	Database Tables
Positions cursor before first row, and clears all data to Null.
Syntax
object.Reset
object
Required. The MsiCursor object.
Remarks
Because the Next method always progresses forward through the data rows, Reset must be called first to insure that all rows are found. When inserting new rows, Reset may    be called on the cursor to clear any existing data  if the cursor is not in the reset state.
#$+KPutNull Method
	MsiCursor Object	Msi Objects	Database Tables
Sets the designated column value to the Null value appropriate for the data type.
Syntax
object.PutNull column
object
Required. The MsiCursor object.
column
Required. Column index, 1-based.
Remarks
This method will fail unless the column has the icdNullable attribute.
#$+KNext Method
	MsiCursor Object	Msi Objects	Database Tables
Positions this cursor to next database record in the table that matches the specified filter values. If not filter columns are designated, the next sequential record in primary key order will be returned. If the table is linked as a tree and a tree-walking cursor has been created, the cursor will advance in tree traveral order. Returns 0 if no more qualifying rows exist in the table, else returns the tree level of the new row, 1 if the table is not linked as a tree.
Syntax
object.Next
object
Required. The MsiCursor object.
Remarks
The filter mask, set by the Filter property, designates columns in the cursor that contains values that must be matched. If the mask is non-zero, rows will be skipped if the designated columns contain data that does not match the values in the cursor.
#$+KFilter Property
	MsiCursor Object	Msi Objects	Database Tables
A long integer containing bit flags for all defined columns. Marks data columns in the MsiCursor object to be used to match corresponding data in the database table. Each bit in the filter corresponds to a database column, with the low order bit (value=1) corresponding to the first column. A value of zero removes all filter attributes from the columns. Read-write.
Syntax
object.Filter
object
Required. The MsiCursor object.
Remarks
The Next method will skip over rows where the columns designated by the filter mask do not match those in the cursor. If the filter includes primary key columns, the search will be vastly improved because the table rows are sorted by primary key. If the cursor was created as a tree-walking cursor, it will advance to matching records in tree order, and it will be optimized if the filter includes the primary key.
Usage
In order to selectively filter rows in a table, the values to match must be set into the corresponding columns in the MsiCursor object. The corresponding bits must also be set in the filter mask to prevent fetching data into those columns. When the cursor is reset, or reaches the end of the table, all data is cleared, including the filter data, but the filter mask is not affected. To remove the filter mask, this property value must be set to zero.
#$+KRowState Property
	MsiCursor Object	Msi Objects	Database Tables
Allows individual row attributes in a table row to read read or set.
Syntax
object.RowState(attribute)
object
Required. The MsiCursor object.
attribute
Required. The row attribute to be read or set, one of iraEnum.
object

Row attributes
!!Not finished!!
Remarks
!!Not finished!!
#$+KUpdate Method
	MsiCursor Object	Msi Objects	Database Tables
Updates changed cursor data to the corresponding table row. Returns True if the row was successfully updated.
Syntax
object.Update
object
Required. The MsiCursor object.
Remarks
The table row to update is determined by set of primary key values. If the primary key values to not match any existing row, the function will fail and return False.
#$+KInsert Method
	MsiCursor Object	Msi Objects	Database Tables
Inserts a new table row using the current cursor data. The table must be writable for this method to succeed. Returns True if the row was successfully inserted.
Syntax
object.Insert
object
Required. The MsiCursor object.
Remarks
The table row position is determined by the primary key values. If the primary key columns contain any Null values, or if the set of primary key values matches an existing row, the method will fail and return False. If the table is tree-linked, the inserted row will be linked into the tree as a leaf node under the row specified by its parent column (the column specified by LinkTree).
#$+KInsertTemporary Method
	MsiCursor Object	Msi Objects	Database Tables
Inserts a new non-persistent table row using the current cursor data. This method may be called on tables loaded from a read-only database. Returns True if the row was successfully inserted.
Syntax
object.InsertTemporary
object
Required. The MsiCursor object.
Remarks
See Remarks under MsiCursor.Insert
#$+KAssign Method
	MsiCursor Object	Msi Objects	Database Tables
Either updates an existing table row or inserts a new table row  using the current cursor data. Returns True if either an update or an insert was successful.
Syntax
object.Assign
object
Required. The MsiCursor object.
Remarks
The table row position is determined by the primary key values. An update operation takes place if primary keys match an existing row. An insert operation takes place if primary keys do not match any row. In either case the current data in the cursor are written to a table row. If any of the primary key values are Null, the method will fail and return False.
#$+KReplace Method
	MsiCursor Object	Msi Objects	Database Tables
Updates a fetched row using current cursor data, allowing primary key changes. Returns True if either an update or an insert+delete was successful.
Syntax
object.Replace
object
Required. The MsiCursor object.
Remarks
The table row position is determined by the primary key values. An update operation takes place if primary keys match an existing row. An insert operation takes place if primary keys do not match any row, in which case the row referenced by the previous key value will be delete (if not already deleted). If any of the primary key values are Null, the method will fail and return False.
#$+KMerge Method
	MsiCursor Object	Msi Objects	Database Tables
Either inserts a new record into the table, or insures that an existing record is identical.  Returns True if the insert was successful, or an existing record with the same key is completely matched. If an existing record is not identical, the row attribute bit iraMergeFailed is set.
Syntax
object.Merge
object
Required. The MsiCursor object.
Remarks
The table row position is determined by the primary key values. An insert operation takes place if primary keys do not match any row. A validation operation takes place if primary keys match an existing row. Since matched rows are never replaced, they may be marked as read-only.
#$+KRefresh Method
	MsiCursor Object	Msi Objects	Database Tables
Reloads the cursor with data from the current table row, replacing any changes made to the cursor data and updating data that has been update via other cursors. If the row has been deleted, all data will be set to null and the method will return False. False will also be returned if the cursor is not positioned on a row, i.e. in a Reset state. Returns True if the row is still present.
Syntax
object.Refresh
object
Required. The MsiCursor object.
#$+KDelete Method
	MsiCursor Object	Msi Objects	Database Tables
Deletes current cursor row from table. The row to be deleted is determined by the primary key data, not by the current position in the table. Returns True if successful, else False if the row could not be deleted.
Syntax
object.Delete
object
Required. The MsiCursor object.
Remarks
The delete will fail if the any of the primary key fields in the cursor are null, or if the primary key does not exist in the table, or if a non-leaf node is specified in a tree-linked table. In this cursor and any other MsiCursor objects positioned at the deleted row, all non-updated data fields will be refreshed with Null values. The logical positions of such cursors will be maintained such that the Next method will advance to the next row following the deleted row. An attempt to call Delete a second time without advancing the cursor will fail and return False.
#$+KSeek Method
	MsiCursor Object	Msi Objects	Database Tables
Positions the cursor to the table row corresponding the the current primary key values. If the row is not present, the method will return False. Returns True if the row is present, and reloads the cursor with data from the table row.
Syntax
object.Seek
object
Required. The MsiCursor object.
#$+KValidate Method
	MsiCursor Object	Msi Objects	Database Tables
Returns an MsiRecord object where each field represents a column of the table.  All invalid fields will contain the iveEnum associated describing the invalid data.  For valid data, it returns an object of Nothing.  For invalid data, the zeroeth (0th) field of the record will contain the number of columns that were invalid.  If however the cursor was in a bad state (set to be deleted or reset if you aren't validating a new row), the zeroeth (0th) field will be null.  
Syntax
object.Validate(Table, Cursor, Column)
object
Required. The MsiCursor object.
Table
Required. The Validation table object.
Cursor
Required.  The Validation table cursor object.
Column
Required.  -2 = Delete row, -1 = New row, 0 = row, or column number.
Remarks
Delete validation ensures that no row is explicitly referencing the row to be deleted.  This means that it ensures that any column with the foreign key to the table of the row to be deleted (data obtained from the 'KeyTable' column of the _Validation table) reference the primary key(s) of the row to be deleted.  This validation is however limited and does not include checking for properties referencing the row to be deleted nor for the delimited list of tables value allowed in the 'KeyTable' column of the _Validation table.  In this instance, those strings (delimited list ones) are ignored. New row validation should be done prior to insertion.  This will ensure that no duplicate primary keys exist.  Row validation validates the entire row. Field validation validates the particular field, but field/column validation does not permit validation of foreign key fields.  If an invalid field is found, its field in the data record will contain the iveEnum describing the error.  Valid columns will be null.  The size of the record object is determined by the number of columns in the table to which the cursor belongs.
iveEnum
iveNoError: 0 Valid data
iveDuplicateKey: 1 Duplicate Primary Key
iveRequired: 2 Not a nullable column
iveBadLink: 3 Not a valid foreign key
iveOverFlow: 4 Value exceeds MaxValue
iveUnderFlow: 5 Value below MinValue
iveNotInSet: 6  Not member of set
iveBadVersion: 7 Invalid version string
iveBadCase: 8 Invalid case, must be all upper or all lower case
iveBadGuid: 9 Invalid GUID
iveBadWildCard: 10 Invalid wildcard or wildcard usage
iveBadIdentifier: 11 Invalid identifier
iveBadLanguage: 12 Invalid LangId
iveBadFilename: 13 Invalid filename
iveBadPath: 14 Invalid path
iveBadCondition: 15 Invalid condition string
iveBadFormatted: 16 Invalid format string
iveBadTemplate: 17 Invalid template string
iveBadDefaultDir: 18 Invalid DefaultDir string (special for Directory table)
iveBadRegPath: 19 Invalid registry path (Key col in Registry table for example)
iveBadCustomSource: 20 Invalid CustomSource string (special for CustomAction table)
iveBadProperty: 21 Bad property string
iveMissingData: 22 Validation table: missing data
iveMissingTable: 23 NO LONGER USED!!
iveBadCategory: 24 Validation table: invalid category string
iveBadKeyTable: 25 Validation table: bad key table name [table could not be loaded]
iveBadMaxMinValues: 26 Validation table:  case where value in Max col is < value in Min col
iveNonExistingCol: 27 NO LONGER USED!!
iveBadCabinet: 28 Bad cabinet string, special for Media.Cabinet column
iveBadShortcut: 29 Bad shortcut target string, special for Shortcut.Target column
iveStringOverflow: 30 String overflow, length of string greater than size allowed by col def

#$+KMoniker Property
	MsiCursor Object	Msi Objects	Database Tables
Returns the unique identifier for the current row of the cursor.
Syntax
object.GetMoniker()
object
Required. The MsiCursor object.
Remarks
Identifier in form of table.key1(.key2 ...etc).  If cursor is not on a row, will get the name of the table to which the cursor belongs.
#$K+MsiStorage Object
The MsiStorage object represents a persistent storage unit, typically a file, but may also be implemented on memory or a resource, or as child of a parent storage. The current implementation is a thin layer on top of OLE structured storage. The same data format is used for Win32 and PPCMAC, with integers stored little-endian. All data access is via MsiStream objects, with byte-swapping required for the PPCMAC performed by the MsiStream integer access functions. Special handling is provided to generate and read the SummaryInformation stream, where standardized document properties are stored.
Properties
Class
Name

Methods
OpenStream
OpenStorage
Streams
Storages
RemoveElement
Commit
Rollback
DeleteOnRelease
CreateSummaryInfo
CopyTo

#$+KClass Property
	MsiStorage Object	Msi Objects	Database Tables
Read/write. The class ID (CLSID) associated with this storage, represented as the string form of a GUID. Return an empty value if the storage has no class ID. Generates an error if attempting to set an invalid GUID string. This is a thin wrapper on the OLE methods: IStorage::SetClass and IStorage::Stat. Microsoft Installer uses this for identification of the storage usage.
Syntax
object.Class
object
Required. The MsiStorage object.
#$+KName Property
	MsiStorage Object	Msi Objects	Database Tables
Read-only. The name of the storage. This is a thin wrapper on the OLE method: IStorage::Stat.
Syntax
object.Name
object
Required. The MsiStorage object.
#$+KOpenStream Method
	MsiStorage Object	Msi Objects	Database Tables
Creates and returns an MsiStream object that allows data to be read or written to the storage.
Syntax
object.OpenStream(name, fWrite)
object
Required. The MsiStorage object.
name
Required. The name of the stream as it is known in the storage. If fWrite is set to True, the stream will be created if it does not already exist.
fWrite
Required. True to create a writable stream, which will overwrite any existing stream. False to read a read-only stream.
Remarks
The stream object must be released in order to flush all changes to the storage.
#$+KOpenStorage Method
	MsiStorage Object	Msi Objects	Database Tables
Creates and returns an MsiStorage object represents a child storage under this storage.
Syntax
object.OpenStorage(name, openMode)
object
Required. The MsiStorage object.
name
Required. The name of the storage as it is known in the storage, or a unique name if it is to be created. to True, the stream will be created if it does not already exist.
openMode
Required. Mode in which to create or open, see CreateStorage.
Remarks
The child storage object must be released and/or committed in order to flush all changes to the parent storage.
#$+KStreams Method
	MsiStorage Object	Msi Objects	Database Tables
Returns a collection of strings containing the names of all streams in this storage object.
Syntax
object.Streams
object
Required. The MsiStorage object.
#$+KStorages Method
	MsiStorage Object	Msi Objects	Database Tables
Returns a collection of strings containing the names of all child storages in this storage object.
Syntax
object.Storages
object
Required. The MsiStorage object.
#$+KRemoveElement Method
	MsiStorage Object	Msi Objects	Database Tables
Removes a stream or child storage matching the supplied name. This method will fail if the name is not found or if the storage is opened read-only.
Syntax
object.RemoveElement name, fStorage
object
Required. The MsiStorage object.
name
Required. The name of the stream or child storage.
fStorage
Optional. True if a storage, False if a stream. Defaults to False.
#$+KRenameElement Method
	MsiStorage Object	Msi Objects	Database Tables
Renames a stream or child storage from the supplied old name to a new name. This method will fail if the old name is not found or if the storage is opened read-only.
Syntax
object.RenameElement oldName, newName, fStorage
object
Required. The MsiStorage object.
oldName
Required. The original name of the stream or child storage.
newName
Required. The new name of the stream or child storage.
fStorage
Optional. True if a storage, False if a stream. Defaults to False.
#$+KCommit Method
	MsiStorage Object	Msi Objects	Database Tables
Forces all persistent data to be written to the persistent storage. No action is taken if the storage is opened read-only (ismReadOnly).
Syntax
object.Commit
object
Required. The MsiStorage object.
#$+KRollback Method
	MsiStorage Object	Msi Objects	Database Tables
Backs out any changes made to the storage since the MsiStorage object was created or last committed.. This method only succeeds if the MsiStorage object was created in transacted mode using ismTransact; otherwise an error will be generated.
Syntax
object.Rollback
object
Required. The MsiStorage object.
#$+KDeleteOnRelease Method
	MsiStorage Object	Msi Objects	Database Tables
Forces the storage to be physically removed after all the references to the MsiStorage object are released. Fails if the storage is opened read-only, or if the storage was created from an existing IStorage interface (rather than from Msi services).
Syntax
object.DeleteOnRelease
object
Required. The MsiStorage object.
#$+KCreateSummaryInfo Method
	MsiStorage Object	Msi Objects	Database Tables
Returns a MsiCreateSummaryInfo object that can be used examine, update, and add properties to the SummaryInformation stream.
Syntax
object.CreateSummaryInfo(maxProperties)
object
Required. The MsiStorage object.
maxProperties
Required. The maximum number of properties to be added or modified, used solely to allocate sufficent working memory during the stream generation. It is not required to actually store this number of properties. A value of zero prevents the stream from being updated.
Remarks
If the MsiStorage object is opened read-only, no properties may be added or updated.
#$+KCopyTo Method
	MsiStorage Object	Msi Objects	Database Tables
Copies the contents of the storage to another storage, optionally excluding some streams or substorages from the copy.
Syntax
object.CopyTo(destStorage, excludedElements)
object
Required. The MsiStorage object to which the contents of the current object should be copied.
destStorage
Required. The destination storage for the copy. 
excludedElements
Optional. A recording containing the names of elements (streams or storages) that should not be copied.
Remarks

#$K+MsiStream Object
The MsiStream object is used to transfer table data and large binary objects (BLOB) to and from the persistent database. The use of streams to manage loading and saving of table data is wholely managed by the database. However large binary data items are not loaded into memory when their table is loaded, but only on demand when the StreamData property is requested for the data item, which returns a read-only MsiStream object which is used to access the data sequentially.
When transferring data to and from stream that may be shared between Windows and PPCMAC, use the integer tranfer routines which automatically take care of the byte-swapping issues.
Properties
Length
Remaining
Error

Methods
GetData
PutData
GetInt16
GetInt32
PutInt16
PutInt32
Seek
Reset
Clone

#$+KLength Property
	MsiStream Object	Msi Objects	Database Tables
Returns the current length of the stream in bytes.
Syntax
object.Length
object
Required. The MsiStream object.
#$+KRemaining Property
	MsiStream Object	Msi Objects	Database Tables
Returns the remaining length of the stream in bytes. When writing to the stream, this value will be zero.
Syntax
object.Remaining
object
Required. The MsiStream object.
#$+KError Property
	MsiStream Object	Msi Objects	Database Tables
Returns a boolean indicating when any transfer error occurred when reading or writing to the stream. The error state is then cleared in the stream.
Syntax
object.Error
object
Required. The MsiStream object.
#$+KGetData Method
	MsiStream Object	Msi Objects	Database Tables
Copies the indicated number of bytes from the stream into a buffer. For automation, the bytes are returned as a string, with the length equal to the byte count copied. If the end of the stream is reached before the requested number of bytes, the stream error state is set and a smaller string is returned. On DBCS-enabled systems, byte values corresponding to lead byte characters may be lost due to the intermediate Unicode translation.
Syntax
object.GetData(count)
object
Required. The MsiStream object.
count
Required. The number of bytes to copy from the stream
#$+KPutData Method
	MsiStream Object	Msi Objects	Database Tables
Copies the indicated number of bytes from the supplied buffer to the stream. For automation, a string is passed in containing the bytes. The size of the string is used for the count of bytes to write to the stream. The string may contain any binary byte values, including null. On DBCS-enabled systems, byte values corresponding to lead byte characters may be lost due to the intermediate Unicode translation.
Syntax
object.PutData(buffer)
object
Required. The MsiStream object.
buffer
Required. String containing the bytes to copy. The string length is used for the count.
#$+KGetInt16 Method
	MsiStream Object	Msi Objects	Database Tables
Returns the next two bytes from the stream as a 16-bit integer, the first byte becoming the low-order byte of the integer.
Syntax
object.GetInt16
object
Required. The MsiStream object.
#$+KGetInt32 Method
	MsiStream Object	Msi Objects	Database Tables
Returns the next four bytes from the stream as a 32-bit integer, the first byte becoming the low-order byte of the integer.
Syntax
object.GetInt32
object
Required. The MsiStream object.
#$+KPutInt16 Method
	MsiStream Object	Msi Objects	Database Tables
Writes a 16-bit integer to the stream, low-order byte first.
Syntax
object.PutInt16(value)
object
Required. The MsiStream object.
value
Required. The short integer to be written to the stream.
#$+KSeek Method
	MsiStream Object	Msi Objects	Database Tables
Moves the stream pointer to a new position in the stream.
Syntax
object.Seek(position)
object
Required. The MsiStream object.
position
Required. The new position in the stream, relative to the beginning of the stream.
#$+KPutInt32 Method
	MsiStream Object	Msi Objects	Database Tables
Writes a 32-bit integer to the stream, low-order byte first.
Syntax
object.PutInt32(value)
object
Required. The MsiStream object.
value
Required. The long integer to be written to the stream.
#$+KReset Method
	MsiStream Object	Msi Objects	Database Tables
Resets the stream to the beginning, allow it to be read or written again. Using this method before writing simply replaces previous data, but does not remove old data beyond what is newly written. To completely replace a stream, simply reopen the stream.
Syntax
object.Reset
object
Required. The MsiStream object.
#$+KClone Method
	MsiStream Object	Msi Objects	Database Tables
Creates and returns an MsiStream object that accesses the same data as the current object, but which has an independent seek pointer. The new stream object will be in the reset state, i.e. seek pointer at the beginning. Any clones used for writing must be kept positioned further than streams that are current reading to avoid errors. More than one close currently writing (not recommended) produces system-defined behavior; for file streams all writes will be appended to the end of the stream. For storage streams, the behavior is dependent upon the OLE implementation.
Syntax
object.Clone
object
Required. The MsiStream object.
#$K+MsiSummaryInfo Object
The MsiSummaryInfo object is used to read, create, and update document properties from the SummaryInformation stream of the storage object.
Properties
Property
PropertyCount
PropertyType

Methods
WritePropertyStream

#$+KPropertyCount Property
	MsiSummaryInfo Object	Msi Objects	Database Tables
The current number of property values in the summary information object. This takes into account properties that have been added, deleted, or replaced. Read-only.
Syntax
object.PropertyCount
object
Required. The MsiSummaryInfo object.
#$+KPropertyType Property
	MsiSummaryInfo Object	Msi Objects	Database Tables
Returns an integer containing the property type for the supplied property ID. If the property does not exist, the value 0 (VT_EMPTY) is returned. Standard property types are listed in MsiSummaryInfo.Property. Read-only.
Syntax
object.PropertyType(pid)
object
Required. The MsiSummaryInfo object.
pid
Required. The property ID of one of the summary properties.
#$+KProperty Property
	MsiSummaryInfo Object	Msi Objects	Database Tables
Sets or gets the value for the specified property in the summary information stream. The properties are read when the MsiSummaryInfo object is created, but they are not written until WritePropertyStream is called.    Setting a property to Empty will cause its removal; likewise requesting a non-existent property will return an Empty value. Otherwise values may be transferred as strings, integers, or date (datetime) types.
Syntax
object.Property(pid)
object
Required. The MsiSummaryInfo object.
pid
Required. The property ID of one of the summary properties.
Standard Summary Property IDs (not an enumeration)
 PID_DICTIONARY    0  special format, not support by MsiSummaryInfo
 PID_CODEPAGE      1  VT_I2
 PID_TITLE         2  VT_LPSTR
 PID_SUBJECT       3  VT_LPSTR
 PID_AUTHOR        4  VT_LPSTR
 PID_KEYWORDS      5  VT_LPSTR
 PID_COMMENTS      6  VT_LPSTR
 PID_TEMPLATE      7  VT_LPSTR
 PID_LASTAUTHOR    8  VT_LPSTR
 PID_REVNUMBER     9  VT_LPSTR
 PID_EDITTIME     10  VT_FILETIME
 PID_LASTPRINTED  11  VT_FILETIME
 PID_CREATE_DTM   12  VT_FILETIME
 PID_LASTSAVE_DTM 13  VT_FILETIME
 PID_PAGECOUNT    14  VT_I4
 PID_WORDCOUNT    15  VT_I4
 PID_CHARCOUNT    16  VT_I4
 PID_THUMBNAIL    17  VT_CF  (not supported)
 PID_APPNAME      18  VT_LPSTR
 PID_SECURITY     19  VT_I4
MSI-specific Summary Property IDs
 PID_MSITAG       30  VT_LPSTR  MSI FileType
 PID_MSIPID       31  VT_LPSTR  MSI Product ID
 PID_MSIUSER      32  VT_LPSTR  MSI Registered User
 PID_MSIORG       33  VT_LPSTR  MSI Organization
 PID_MSICHECK     34  VT_LPSTR  MSI Checksum
Property Data Types (not an enumeration)
 VT_I2        2  16-bit integer
 VT_I4        3  32-bit integer
 VT_LPSTR    30  string
 VT_FILETIME 64  date/time (FILETIME, converted to Variant time)
 VT_CF       71  clipboard format + data, not handled by MsiSummaryInfo
#$+KWritePropertyStream Method
	MsiSummaryInfo Object	Msi Objects	Database Tables
Formats and writes the previously stored properties into the standard SummaryInformation stream. Generates an error if the stream could not be successfully written. This method may only be called once, after all the property values have been set. Properties may still be read after the stream is written.
Syntax
object.WritePropertyStream
object
Required. The MsiSummaryInfo object.