mirror of https://github.com/python/cpython
gh-104773: Remove the msilib package (GH-104911)
This commit is contained in:
parent
41768a2bd3
commit
98c4333e88
|
@ -1,565 +0,0 @@
|
||||||
:mod:`msilib` --- Read and write Microsoft Installer files
|
|
||||||
==========================================================
|
|
||||||
|
|
||||||
.. module:: msilib
|
|
||||||
:platform: Windows
|
|
||||||
:synopsis: Creation of Microsoft Installer files, and CAB files.
|
|
||||||
:deprecated:
|
|
||||||
|
|
||||||
.. moduleauthor:: Martin v. Löwis <martin@v.loewis.de>
|
|
||||||
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
|
|
||||||
|
|
||||||
**Source code:** :source:`Lib/msilib/__init__.py`
|
|
||||||
|
|
||||||
.. index:: single: msi
|
|
||||||
|
|
||||||
.. deprecated-removed:: 3.11 3.13
|
|
||||||
The :mod:`msilib` module is deprecated
|
|
||||||
(see :pep:`PEP 594 <594#msilib>` for details).
|
|
||||||
|
|
||||||
--------------
|
|
||||||
|
|
||||||
The :mod:`msilib` supports the creation of Microsoft Installer (``.msi``) files.
|
|
||||||
Because these files often contain an embedded "cabinet" file (``.cab``), it also
|
|
||||||
exposes an API to create CAB files. Support for reading ``.cab`` files is
|
|
||||||
currently not implemented; read support for the ``.msi`` database is possible.
|
|
||||||
|
|
||||||
This package aims to provide complete access to all tables in an ``.msi`` file,
|
|
||||||
therefore, it is a fairly low-level API. One primary application of this
|
|
||||||
package is the creation of Python installer package itself (although that currently
|
|
||||||
uses a different version of ``msilib``).
|
|
||||||
|
|
||||||
The package contents can be roughly split into four parts: low-level CAB
|
|
||||||
routines, low-level MSI routines, higher-level MSI routines, and standard table
|
|
||||||
structures.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: FCICreate(cabname, files)
|
|
||||||
|
|
||||||
Create a new CAB file named *cabname*. *files* must be a list of tuples, each
|
|
||||||
containing the name of the file on disk, and the name of the file inside the CAB
|
|
||||||
file.
|
|
||||||
|
|
||||||
The files are added to the CAB file in the order they appear in the list. All
|
|
||||||
files are added into a single CAB file, using the MSZIP compression algorithm.
|
|
||||||
|
|
||||||
Callbacks to Python for the various steps of MSI creation are currently not
|
|
||||||
exposed.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: UuidCreate()
|
|
||||||
|
|
||||||
Return the string representation of a new unique identifier. This wraps the
|
|
||||||
Windows API functions :c:func:`UuidCreate` and :c:func:`UuidToString`.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: OpenDatabase(path, persist)
|
|
||||||
|
|
||||||
Return a new database object by calling MsiOpenDatabase. *path* is the file
|
|
||||||
name of the MSI file; *persist* can be one of the constants
|
|
||||||
``MSIDBOPEN_CREATEDIRECT``, ``MSIDBOPEN_CREATE``, ``MSIDBOPEN_DIRECT``,
|
|
||||||
``MSIDBOPEN_READONLY``, or ``MSIDBOPEN_TRANSACT``, and may include the flag
|
|
||||||
``MSIDBOPEN_PATCHFILE``. See the Microsoft documentation for the meaning of
|
|
||||||
these flags; depending on the flags, an existing database is opened, or a new
|
|
||||||
one created.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: CreateRecord(count)
|
|
||||||
|
|
||||||
Return a new record object by calling :c:func:`MSICreateRecord`. *count* is the
|
|
||||||
number of fields of the record.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: init_database(name, schema, ProductName, ProductCode, ProductVersion, Manufacturer)
|
|
||||||
|
|
||||||
Create and return a new database *name*, initialize it with *schema*, and set
|
|
||||||
the properties *ProductName*, *ProductCode*, *ProductVersion*, and
|
|
||||||
*Manufacturer*.
|
|
||||||
|
|
||||||
*schema* must be a module object containing ``tables`` and
|
|
||||||
``_Validation_records`` attributes; typically, :mod:`msilib.schema` should be
|
|
||||||
used.
|
|
||||||
|
|
||||||
The database will contain just the schema and the validation records when this
|
|
||||||
function returns.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: add_data(database, table, records)
|
|
||||||
|
|
||||||
Add all *records* to the table named *table* in *database*.
|
|
||||||
|
|
||||||
The *table* argument must be one of the predefined tables in the MSI schema,
|
|
||||||
e.g. ``'Feature'``, ``'File'``, ``'Component'``, ``'Dialog'``, ``'Control'``,
|
|
||||||
etc.
|
|
||||||
|
|
||||||
*records* should be a list of tuples, each one containing all fields of a
|
|
||||||
record according to the schema of the table. For optional fields,
|
|
||||||
``None`` can be passed.
|
|
||||||
|
|
||||||
Field values can be ints, strings, or instances of the Binary class.
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: Binary(filename)
|
|
||||||
|
|
||||||
Represents entries in the Binary table; inserting such an object using
|
|
||||||
:func:`add_data` reads the file named *filename* into the table.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: add_tables(database, module)
|
|
||||||
|
|
||||||
Add all table content from *module* to *database*. *module* must contain an
|
|
||||||
attribute *tables* listing all tables for which content should be added, and one
|
|
||||||
attribute per table that has the actual content.
|
|
||||||
|
|
||||||
This is typically used to install the sequence tables.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: add_stream(database, name, path)
|
|
||||||
|
|
||||||
Add the file *path* into the ``_Stream`` table of *database*, with the stream
|
|
||||||
name *name*.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: gen_uuid()
|
|
||||||
|
|
||||||
Return a new UUID, in the format that MSI typically requires (i.e. in curly
|
|
||||||
braces, and with all hexdigits in uppercase).
|
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
|
||||||
|
|
||||||
`FCICreate <https://msdn.microsoft.com/en-us/library/bb432265.aspx>`_
|
|
||||||
`UuidCreate <https://msdn.microsoft.com/en-us/library/windows/desktop/aa379205.aspx>`_
|
|
||||||
`UuidToString <https://msdn.microsoft.com/en-us/library/windows/desktop/aa379352.aspx>`_
|
|
||||||
|
|
||||||
.. _database-objects:
|
|
||||||
|
|
||||||
Database Objects
|
|
||||||
----------------
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Database.OpenView(sql)
|
|
||||||
|
|
||||||
Return a view object, by calling :c:func:`MSIDatabaseOpenView`. *sql* is the SQL
|
|
||||||
statement to execute.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Database.Commit()
|
|
||||||
|
|
||||||
Commit the changes pending in the current transaction, by calling
|
|
||||||
:c:func:`MSIDatabaseCommit`.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Database.GetSummaryInformation(count)
|
|
||||||
|
|
||||||
Return a new summary information object, by calling
|
|
||||||
:c:func:`MsiGetSummaryInformation`. *count* is the maximum number of updated
|
|
||||||
values.
|
|
||||||
|
|
||||||
.. method:: Database.Close()
|
|
||||||
|
|
||||||
Close the database object, through :c:func:`MsiCloseHandle`.
|
|
||||||
|
|
||||||
.. versionadded:: 3.7
|
|
||||||
|
|
||||||
.. seealso::
|
|
||||||
|
|
||||||
`MSIDatabaseOpenView <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370082.aspx>`_
|
|
||||||
`MSIDatabaseCommit <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370075.aspx>`_
|
|
||||||
`MSIGetSummaryInformation <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370301.aspx>`_
|
|
||||||
`MsiCloseHandle <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370067.aspx>`_
|
|
||||||
|
|
||||||
.. _view-objects:
|
|
||||||
|
|
||||||
View Objects
|
|
||||||
------------
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: View.Execute(params)
|
|
||||||
|
|
||||||
Execute the SQL query of the view, through :c:func:`MSIViewExecute`. If
|
|
||||||
*params* is not ``None``, it is a record describing actual values of the
|
|
||||||
parameter tokens in the query.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: View.GetColumnInfo(kind)
|
|
||||||
|
|
||||||
Return a record describing the columns of the view, through calling
|
|
||||||
:c:func:`MsiViewGetColumnInfo`. *kind* can be either ``MSICOLINFO_NAMES`` or
|
|
||||||
``MSICOLINFO_TYPES``.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: View.Fetch()
|
|
||||||
|
|
||||||
Return a result record of the query, through calling :c:func:`MsiViewFetch`.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: View.Modify(kind, data)
|
|
||||||
|
|
||||||
Modify the view, by calling :c:func:`MsiViewModify`. *kind* can be one of
|
|
||||||
``MSIMODIFY_SEEK``, ``MSIMODIFY_REFRESH``, ``MSIMODIFY_INSERT``,
|
|
||||||
``MSIMODIFY_UPDATE``, ``MSIMODIFY_ASSIGN``, ``MSIMODIFY_REPLACE``,
|
|
||||||
``MSIMODIFY_MERGE``, ``MSIMODIFY_DELETE``, ``MSIMODIFY_INSERT_TEMPORARY``,
|
|
||||||
``MSIMODIFY_VALIDATE``, ``MSIMODIFY_VALIDATE_NEW``,
|
|
||||||
``MSIMODIFY_VALIDATE_FIELD``, or ``MSIMODIFY_VALIDATE_DELETE``.
|
|
||||||
|
|
||||||
*data* must be a record describing the new data.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: View.Close()
|
|
||||||
|
|
||||||
Close the view, through :c:func:`MsiViewClose`.
|
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
|
||||||
|
|
||||||
`MsiViewExecute <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370513.aspx>`_
|
|
||||||
`MSIViewGetColumnInfo <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370516.aspx>`_
|
|
||||||
`MsiViewFetch <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370514.aspx>`_
|
|
||||||
`MsiViewModify <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370519.aspx>`_
|
|
||||||
`MsiViewClose <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370510.aspx>`_
|
|
||||||
|
|
||||||
.. _summary-objects:
|
|
||||||
|
|
||||||
Summary Information Objects
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: SummaryInformation.GetProperty(field)
|
|
||||||
|
|
||||||
Return a property of the summary, through :c:func:`MsiSummaryInfoGetProperty`.
|
|
||||||
*field* is the name of the property, and can be one of the constants
|
|
||||||
``PID_CODEPAGE``, ``PID_TITLE``, ``PID_SUBJECT``, ``PID_AUTHOR``,
|
|
||||||
``PID_KEYWORDS``, ``PID_COMMENTS``, ``PID_TEMPLATE``, ``PID_LASTAUTHOR``,
|
|
||||||
``PID_REVNUMBER``, ``PID_LASTPRINTED``, ``PID_CREATE_DTM``,
|
|
||||||
``PID_LASTSAVE_DTM``, ``PID_PAGECOUNT``, ``PID_WORDCOUNT``, ``PID_CHARCOUNT``,
|
|
||||||
``PID_APPNAME``, or ``PID_SECURITY``.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: SummaryInformation.GetPropertyCount()
|
|
||||||
|
|
||||||
Return the number of summary properties, through
|
|
||||||
:c:func:`MsiSummaryInfoGetPropertyCount`.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: SummaryInformation.SetProperty(field, value)
|
|
||||||
|
|
||||||
Set a property through :c:func:`MsiSummaryInfoSetProperty`. *field* can have the
|
|
||||||
same values as in :meth:`GetProperty`, *value* is the new value of the property.
|
|
||||||
Possible value types are integer and string.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: SummaryInformation.Persist()
|
|
||||||
|
|
||||||
Write the modified properties to the summary information stream, using
|
|
||||||
:c:func:`MsiSummaryInfoPersist`.
|
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
|
||||||
|
|
||||||
`MsiSummaryInfoGetProperty <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370409.aspx>`_
|
|
||||||
`MsiSummaryInfoGetPropertyCount <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370488.aspx>`_
|
|
||||||
`MsiSummaryInfoSetProperty <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370491.aspx>`_
|
|
||||||
`MsiSummaryInfoPersist <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370490.aspx>`_
|
|
||||||
|
|
||||||
.. _record-objects:
|
|
||||||
|
|
||||||
Record Objects
|
|
||||||
--------------
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Record.GetFieldCount()
|
|
||||||
|
|
||||||
Return the number of fields of the record, through
|
|
||||||
:c:func:`MsiRecordGetFieldCount`.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Record.GetInteger(field)
|
|
||||||
|
|
||||||
Return the value of *field* as an integer where possible. *field* must
|
|
||||||
be an integer.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Record.GetString(field)
|
|
||||||
|
|
||||||
Return the value of *field* as a string where possible. *field* must
|
|
||||||
be an integer.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Record.SetString(field, value)
|
|
||||||
|
|
||||||
Set *field* to *value* through :c:func:`MsiRecordSetString`. *field* must be an
|
|
||||||
integer; *value* a string.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Record.SetStream(field, value)
|
|
||||||
|
|
||||||
Set *field* to the contents of the file named *value*, through
|
|
||||||
:c:func:`MsiRecordSetStream`. *field* must be an integer; *value* a string.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Record.SetInteger(field, value)
|
|
||||||
|
|
||||||
Set *field* to *value* through :c:func:`MsiRecordSetInteger`. Both *field* and
|
|
||||||
*value* must be an integer.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: Record.ClearData()
|
|
||||||
|
|
||||||
Set all fields of the record to 0, through :c:func:`MsiRecordClearData`.
|
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
|
||||||
|
|
||||||
`MsiRecordGetFieldCount <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370366.aspx>`_
|
|
||||||
`MsiRecordSetString <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370373.aspx>`_
|
|
||||||
`MsiRecordSetStream <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370372.aspx>`_
|
|
||||||
`MsiRecordSetInteger <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370371.aspx>`_
|
|
||||||
`MsiRecordClearData <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370364.aspx>`_
|
|
||||||
|
|
||||||
.. _msi-errors:
|
|
||||||
|
|
||||||
Errors
|
|
||||||
------
|
|
||||||
|
|
||||||
All wrappers around MSI functions raise :exc:`MSIError`; the string inside the
|
|
||||||
exception will contain more detail.
|
|
||||||
|
|
||||||
|
|
||||||
.. _cab:
|
|
||||||
|
|
||||||
CAB Objects
|
|
||||||
-----------
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: CAB(name)
|
|
||||||
|
|
||||||
The class :class:`CAB` represents a CAB file. During MSI construction, files
|
|
||||||
will be added simultaneously to the ``Files`` table, and to a CAB file. Then,
|
|
||||||
when all files have been added, the CAB file can be written, then added to the
|
|
||||||
MSI file.
|
|
||||||
|
|
||||||
*name* is the name of the CAB file in the MSI file.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: append(full, file, logical)
|
|
||||||
|
|
||||||
Add the file with the pathname *full* to the CAB file, under the name
|
|
||||||
*logical*. If there is already a file named *logical*, a new file name is
|
|
||||||
created.
|
|
||||||
|
|
||||||
Return the index of the file in the CAB file, and the new name of the file
|
|
||||||
inside the CAB file.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: commit(database)
|
|
||||||
|
|
||||||
Generate a CAB file, add it as a stream to the MSI file, put it into the
|
|
||||||
``Media`` table, and remove the generated file from the disk.
|
|
||||||
|
|
||||||
|
|
||||||
.. _msi-directory:
|
|
||||||
|
|
||||||
Directory Objects
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: Directory(database, cab, basedir, physical, logical, default, [componentflags])
|
|
||||||
|
|
||||||
Create a new directory in the Directory table. There is a current component at
|
|
||||||
each point in time for the directory, which is either explicitly created through
|
|
||||||
:meth:`start_component`, or implicitly when files are added for the first time.
|
|
||||||
Files are added into the current component, and into the cab file. To create a
|
|
||||||
directory, a base directory object needs to be specified (can be ``None``), the
|
|
||||||
path to the physical directory, and a logical directory name. *default*
|
|
||||||
specifies the DefaultDir slot in the directory table. *componentflags* specifies
|
|
||||||
the default flags that new components get.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: start_component(component=None, feature=None, flags=None, keyfile=None, uuid=None)
|
|
||||||
|
|
||||||
Add an entry to the Component table, and make this component the current
|
|
||||||
component for this directory. If no component name is given, the directory
|
|
||||||
name is used. If no *feature* is given, the current feature is used. If no
|
|
||||||
*flags* are given, the directory's default flags are used. If no *keyfile*
|
|
||||||
is given, the KeyPath is left null in the Component table.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: add_file(file, src=None, version=None, language=None)
|
|
||||||
|
|
||||||
Add a file to the current component of the directory, starting a new one
|
|
||||||
if there is no current component. By default, the file name in the source
|
|
||||||
and the file table will be identical. If the *src* file is specified, it
|
|
||||||
is interpreted relative to the current directory. Optionally, a *version*
|
|
||||||
and a *language* can be specified for the entry in the File table.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: glob(pattern, exclude=None)
|
|
||||||
|
|
||||||
Add a list of files to the current component as specified in the glob
|
|
||||||
pattern. Individual files can be excluded in the *exclude* list.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: remove_pyc()
|
|
||||||
|
|
||||||
Remove ``.pyc`` files on uninstall.
|
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
|
||||||
|
|
||||||
`Directory Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368295.aspx>`_
|
|
||||||
`File Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368596.aspx>`_
|
|
||||||
`Component Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368007.aspx>`_
|
|
||||||
`FeatureComponents Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368579.aspx>`_
|
|
||||||
|
|
||||||
.. _features:
|
|
||||||
|
|
||||||
Features
|
|
||||||
--------
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: Feature(db, id, title, desc, display, level=1, parent=None, directory=None, attributes=0)
|
|
||||||
|
|
||||||
Add a new record to the ``Feature`` table, using the values *id*, *parent.id*,
|
|
||||||
*title*, *desc*, *display*, *level*, *directory*, and *attributes*. The
|
|
||||||
resulting feature object can be passed to the :meth:`start_component` method of
|
|
||||||
:class:`Directory`.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: set_current()
|
|
||||||
|
|
||||||
Make this feature the current feature of :mod:`msilib`. New components are
|
|
||||||
automatically added to the default feature, unless a feature is explicitly
|
|
||||||
specified.
|
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
|
||||||
|
|
||||||
`Feature Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368585.aspx>`_
|
|
||||||
|
|
||||||
.. _msi-gui:
|
|
||||||
|
|
||||||
GUI classes
|
|
||||||
-----------
|
|
||||||
|
|
||||||
:mod:`msilib` provides several classes that wrap the GUI tables in an MSI
|
|
||||||
database. However, no standard user interface is provided.
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: Control(dlg, name)
|
|
||||||
|
|
||||||
Base class of the dialog controls. *dlg* is the dialog object the control
|
|
||||||
belongs to, and *name* is the control's name.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: event(event, argument, condition=1, ordering=None)
|
|
||||||
|
|
||||||
Make an entry into the ``ControlEvent`` table for this control.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: mapping(event, attribute)
|
|
||||||
|
|
||||||
Make an entry into the ``EventMapping`` table for this control.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: condition(action, condition)
|
|
||||||
|
|
||||||
Make an entry into the ``ControlCondition`` table for this control.
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: RadioButtonGroup(dlg, name, property)
|
|
||||||
|
|
||||||
Create a radio button control named *name*. *property* is the installer property
|
|
||||||
that gets set when a radio button is selected.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: add(name, x, y, width, height, text, value=None)
|
|
||||||
|
|
||||||
Add a radio button named *name* to the group, at the coordinates *x*, *y*,
|
|
||||||
*width*, *height*, and with the label *text*. If *value* is ``None``, it
|
|
||||||
defaults to *name*.
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: Dialog(db, name, x, y, w, h, attr, title, first, default, cancel)
|
|
||||||
|
|
||||||
Return a new :class:`Dialog` object. An entry in the ``Dialog`` table is made,
|
|
||||||
with the specified coordinates, dialog attributes, title, name of the first,
|
|
||||||
default, and cancel controls.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: control(name, type, x, y, width, height, attributes, property, text, control_next, help)
|
|
||||||
|
|
||||||
Return a new :class:`Control` object. An entry in the ``Control`` table is
|
|
||||||
made with the specified parameters.
|
|
||||||
|
|
||||||
This is a generic method; for specific types, specialized methods are
|
|
||||||
provided.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: text(name, x, y, width, height, attributes, text)
|
|
||||||
|
|
||||||
Add and return a ``Text`` control.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: bitmap(name, x, y, width, height, text)
|
|
||||||
|
|
||||||
Add and return a ``Bitmap`` control.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: line(name, x, y, width, height)
|
|
||||||
|
|
||||||
Add and return a ``Line`` control.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: pushbutton(name, x, y, width, height, attributes, text, next_control)
|
|
||||||
|
|
||||||
Add and return a ``PushButton`` control.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: radiogroup(name, x, y, width, height, attributes, property, text, next_control)
|
|
||||||
|
|
||||||
Add and return a ``RadioButtonGroup`` control.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: checkbox(name, x, y, width, height, attributes, property, text, next_control)
|
|
||||||
|
|
||||||
Add and return a ``CheckBox`` control.
|
|
||||||
|
|
||||||
|
|
||||||
.. seealso::
|
|
||||||
|
|
||||||
`Dialog Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368286.aspx>`_
|
|
||||||
`Control Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368044.aspx>`_
|
|
||||||
`Control Types <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368039.aspx>`_
|
|
||||||
`ControlCondition Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368035.aspx>`_
|
|
||||||
`ControlEvent Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368037.aspx>`_
|
|
||||||
`EventMapping Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa368559.aspx>`_
|
|
||||||
`RadioButton Table <https://msdn.microsoft.com/en-us/library/windows/desktop/aa370962.aspx>`_
|
|
||||||
|
|
||||||
.. _msi-tables:
|
|
||||||
|
|
||||||
Precomputed tables
|
|
||||||
------------------
|
|
||||||
|
|
||||||
:mod:`msilib` provides a few subpackages that contain only schema and table
|
|
||||||
definitions. Currently, these definitions are based on MSI version 2.0.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: schema
|
|
||||||
|
|
||||||
This is the standard MSI schema for MSI 2.0, with the *tables* variable
|
|
||||||
providing a list of table definitions, and *_Validation_records* providing the
|
|
||||||
data for MSI validation.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: sequence
|
|
||||||
|
|
||||||
This module contains table contents for the standard sequence tables:
|
|
||||||
*AdminExecuteSequence*, *AdminUISequence*, *AdvtExecuteSequence*,
|
|
||||||
*InstallExecuteSequence*, and *InstallUISequence*.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: text
|
|
||||||
|
|
||||||
This module contains definitions for the UIText and ActionText tables, for the
|
|
||||||
standard installer actions.
|
|
|
@ -15,6 +15,5 @@ backwards compatibility. They have been superseded by other modules.
|
||||||
chunk.rst
|
chunk.rst
|
||||||
crypt.rst
|
crypt.rst
|
||||||
imghdr.rst
|
imghdr.rst
|
||||||
msilib.rst
|
|
||||||
optparse.rst
|
optparse.rst
|
||||||
uu.rst
|
uu.rst
|
||||||
|
|
|
@ -161,7 +161,6 @@ Doc/library/logging.rst
|
||||||
Doc/library/lzma.rst
|
Doc/library/lzma.rst
|
||||||
Doc/library/mailbox.rst
|
Doc/library/mailbox.rst
|
||||||
Doc/library/mmap.rst
|
Doc/library/mmap.rst
|
||||||
Doc/library/msilib.rst
|
|
||||||
Doc/library/msvcrt.rst
|
Doc/library/msvcrt.rst
|
||||||
Doc/library/multiprocessing.rst
|
Doc/library/multiprocessing.rst
|
||||||
Doc/library/multiprocessing.shared_memory.rst
|
Doc/library/multiprocessing.shared_memory.rst
|
||||||
|
|
|
@ -1422,7 +1422,7 @@ complete list of changes, or look through the SVN logs for all the details.
|
||||||
(Contributed by Gregory K. Johnson. Funding was provided by Google's 2005
|
(Contributed by Gregory K. Johnson. Funding was provided by Google's 2005
|
||||||
Summer of Code.)
|
Summer of Code.)
|
||||||
|
|
||||||
* New module: the :mod:`msilib` module allows creating Microsoft Installer
|
* New module: the :mod:`!msilib` module allows creating Microsoft Installer
|
||||||
:file:`.msi` files and CAB files. Some support for reading the :file:`.msi`
|
:file:`.msi` files and CAB files. Some support for reading the :file:`.msi`
|
||||||
database is also included. (Contributed by Martin von Löwis.)
|
database is also included. (Contributed by Martin von Löwis.)
|
||||||
|
|
||||||
|
|
|
@ -3135,7 +3135,7 @@ Port-Specific Changes: Windows
|
||||||
registry reflection for 32-bit processes running on 64-bit systems.
|
registry reflection for 32-bit processes running on 64-bit systems.
|
||||||
(:issue:`1753245`)
|
(:issue:`1753245`)
|
||||||
|
|
||||||
* The :mod:`msilib` module's :class:`Record` object
|
* The :mod:`!msilib` module's :class:`Record` object
|
||||||
gained :meth:`GetInteger` and :meth:`GetString` methods that
|
gained :meth:`GetInteger` and :meth:`GetString` methods that
|
||||||
return field values as an integer or a string.
|
return field values as an integer or a string.
|
||||||
(Contributed by Floris Bruynooghe; :issue:`2125`.)
|
(Contributed by Floris Bruynooghe; :issue:`2125`.)
|
||||||
|
|
|
@ -1731,7 +1731,7 @@ Modules
|
||||||
slated for removal in Python 3.13:
|
slated for removal in Python 3.13:
|
||||||
|
|
||||||
+---------------------+---------------------+---------------------+---------------------+---------------------+
|
+---------------------+---------------------+---------------------+---------------------+---------------------+
|
||||||
| :mod:`aifc` | :mod:`chunk` | :mod:`msilib` | :mod:`!pipes` | :mod:`!telnetlib` |
|
| :mod:`aifc` | :mod:`chunk` | :mod:`!msilib` | :mod:`!pipes` | :mod:`!telnetlib` |
|
||||||
+---------------------+---------------------+---------------------+---------------------+---------------------+
|
+---------------------+---------------------+---------------------+---------------------+---------------------+
|
||||||
| :mod:`audioop` | :mod:`crypt` | :mod:`!nis` | :mod:`!sndhdr` | :mod:`uu` |
|
| :mod:`audioop` | :mod:`crypt` | :mod:`!nis` | :mod:`!sndhdr` | :mod:`uu` |
|
||||||
+---------------------+---------------------+---------------------+---------------------+---------------------+
|
+---------------------+---------------------+---------------------+---------------------+---------------------+
|
||||||
|
|
|
@ -894,7 +894,7 @@ Modules (see :pep:`594`):
|
||||||
* :mod:`crypt`
|
* :mod:`crypt`
|
||||||
* :mod:`imghdr`
|
* :mod:`imghdr`
|
||||||
* :mod:`!mailcap`
|
* :mod:`!mailcap`
|
||||||
* :mod:`msilib`
|
* :mod:`!msilib`
|
||||||
* :mod:`!nis`
|
* :mod:`!nis`
|
||||||
* :mod:`!nntplib`
|
* :mod:`!nntplib`
|
||||||
* :mod:`!ossaudiodev`
|
* :mod:`!ossaudiodev`
|
||||||
|
|
|
@ -198,6 +198,9 @@ Removed
|
||||||
* :pep:`594`: Remove the :mod:`!xdrlib` module, deprecated in Python 3.11.
|
* :pep:`594`: Remove the :mod:`!xdrlib` module, deprecated in Python 3.11.
|
||||||
(Contributed by Victor Stinner in :gh:`104773`.)
|
(Contributed by Victor Stinner in :gh:`104773`.)
|
||||||
|
|
||||||
|
* :pep:`594`: Remove the :mod:`!msilib` module, deprecated in Python 3.11.
|
||||||
|
(Contributed by Zachary Ware in :gh:`104773`.)
|
||||||
|
|
||||||
|
|
||||||
Porting to Python 3.13
|
Porting to Python 3.13
|
||||||
======================
|
======================
|
||||||
|
|
|
@ -1133,7 +1133,7 @@ The MIME type of .bmp has been changed from ``'image/x-ms-bmp'`` to
|
||||||
msilib
|
msilib
|
||||||
------
|
------
|
||||||
|
|
||||||
The new :meth:`Database.Close() <msilib.Database.Close>` method can be used
|
The new :meth:`!Database.Close()` method can be used
|
||||||
to close the :abbr:`MSI` database.
|
to close the :abbr:`MSI` database.
|
||||||
(Contributed by Berker Peksag in :issue:`20486`.)
|
(Contributed by Berker Peksag in :issue:`20486`.)
|
||||||
|
|
||||||
|
|
|
@ -1,484 +0,0 @@
|
||||||
# Copyright (C) 2005 Martin v. Löwis
|
|
||||||
# Licensed to PSF under a Contributor Agreement.
|
|
||||||
from _msi import *
|
|
||||||
import fnmatch
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
warnings._deprecated(__name__, remove=(3, 13))
|
|
||||||
|
|
||||||
AMD64 = "AMD64" in sys.version
|
|
||||||
# Keep msilib.Win64 around to preserve backwards compatibility.
|
|
||||||
Win64 = AMD64
|
|
||||||
|
|
||||||
# Partially taken from Wine
|
|
||||||
datasizemask= 0x00ff
|
|
||||||
type_valid= 0x0100
|
|
||||||
type_localizable= 0x0200
|
|
||||||
|
|
||||||
typemask= 0x0c00
|
|
||||||
type_long= 0x0000
|
|
||||||
type_short= 0x0400
|
|
||||||
type_string= 0x0c00
|
|
||||||
type_binary= 0x0800
|
|
||||||
|
|
||||||
type_nullable= 0x1000
|
|
||||||
type_key= 0x2000
|
|
||||||
# XXX temporary, localizable?
|
|
||||||
knownbits = datasizemask | type_valid | type_localizable | \
|
|
||||||
typemask | type_nullable | type_key
|
|
||||||
|
|
||||||
class Table:
|
|
||||||
def __init__(self, name):
|
|
||||||
self.name = name
|
|
||||||
self.fields = []
|
|
||||||
|
|
||||||
def add_field(self, index, name, type):
|
|
||||||
self.fields.append((index,name,type))
|
|
||||||
|
|
||||||
def sql(self):
|
|
||||||
fields = []
|
|
||||||
keys = []
|
|
||||||
self.fields.sort()
|
|
||||||
fields = [None]*len(self.fields)
|
|
||||||
for index, name, type in self.fields:
|
|
||||||
index -= 1
|
|
||||||
unk = type & ~knownbits
|
|
||||||
if unk:
|
|
||||||
print("%s.%s unknown bits %x" % (self.name, name, unk))
|
|
||||||
size = type & datasizemask
|
|
||||||
dtype = type & typemask
|
|
||||||
if dtype == type_string:
|
|
||||||
if size:
|
|
||||||
tname="CHAR(%d)" % size
|
|
||||||
else:
|
|
||||||
tname="CHAR"
|
|
||||||
elif dtype == type_short:
|
|
||||||
assert size==2
|
|
||||||
tname = "SHORT"
|
|
||||||
elif dtype == type_long:
|
|
||||||
assert size==4
|
|
||||||
tname="LONG"
|
|
||||||
elif dtype == type_binary:
|
|
||||||
assert size==0
|
|
||||||
tname="OBJECT"
|
|
||||||
else:
|
|
||||||
tname="unknown"
|
|
||||||
print("%s.%sunknown integer type %d" % (self.name, name, size))
|
|
||||||
if type & type_nullable:
|
|
||||||
flags = ""
|
|
||||||
else:
|
|
||||||
flags = " NOT NULL"
|
|
||||||
if type & type_localizable:
|
|
||||||
flags += " LOCALIZABLE"
|
|
||||||
fields[index] = "`%s` %s%s" % (name, tname, flags)
|
|
||||||
if type & type_key:
|
|
||||||
keys.append("`%s`" % name)
|
|
||||||
fields = ", ".join(fields)
|
|
||||||
keys = ", ".join(keys)
|
|
||||||
return "CREATE TABLE %s (%s PRIMARY KEY %s)" % (self.name, fields, keys)
|
|
||||||
|
|
||||||
def create(self, db):
|
|
||||||
v = db.OpenView(self.sql())
|
|
||||||
v.Execute(None)
|
|
||||||
v.Close()
|
|
||||||
|
|
||||||
class _Unspecified:pass
|
|
||||||
def change_sequence(seq, action, seqno=_Unspecified, cond = _Unspecified):
|
|
||||||
"Change the sequence number of an action in a sequence list"
|
|
||||||
for i in range(len(seq)):
|
|
||||||
if seq[i][0] == action:
|
|
||||||
if cond is _Unspecified:
|
|
||||||
cond = seq[i][1]
|
|
||||||
if seqno is _Unspecified:
|
|
||||||
seqno = seq[i][2]
|
|
||||||
seq[i] = (action, cond, seqno)
|
|
||||||
return
|
|
||||||
raise ValueError("Action not found in sequence")
|
|
||||||
|
|
||||||
def add_data(db, table, values):
|
|
||||||
v = db.OpenView("SELECT * FROM `%s`" % table)
|
|
||||||
count = v.GetColumnInfo(MSICOLINFO_NAMES).GetFieldCount()
|
|
||||||
r = CreateRecord(count)
|
|
||||||
for value in values:
|
|
||||||
assert len(value) == count, value
|
|
||||||
for i in range(count):
|
|
||||||
field = value[i]
|
|
||||||
if isinstance(field, int):
|
|
||||||
r.SetInteger(i+1,field)
|
|
||||||
elif isinstance(field, str):
|
|
||||||
r.SetString(i+1,field)
|
|
||||||
elif field is None:
|
|
||||||
pass
|
|
||||||
elif isinstance(field, Binary):
|
|
||||||
r.SetStream(i+1, field.name)
|
|
||||||
else:
|
|
||||||
raise TypeError("Unsupported type %s" % field.__class__.__name__)
|
|
||||||
try:
|
|
||||||
v.Modify(MSIMODIFY_INSERT, r)
|
|
||||||
except Exception:
|
|
||||||
raise MSIError("Could not insert "+repr(values)+" into "+table)
|
|
||||||
|
|
||||||
r.ClearData()
|
|
||||||
v.Close()
|
|
||||||
|
|
||||||
|
|
||||||
def add_stream(db, name, path):
|
|
||||||
v = db.OpenView("INSERT INTO _Streams (Name, Data) VALUES ('%s', ?)" % name)
|
|
||||||
r = CreateRecord(1)
|
|
||||||
r.SetStream(1, path)
|
|
||||||
v.Execute(r)
|
|
||||||
v.Close()
|
|
||||||
|
|
||||||
def init_database(name, schema,
|
|
||||||
ProductName, ProductCode, ProductVersion,
|
|
||||||
Manufacturer):
|
|
||||||
try:
|
|
||||||
os.unlink(name)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
ProductCode = ProductCode.upper()
|
|
||||||
# Create the database
|
|
||||||
db = OpenDatabase(name, MSIDBOPEN_CREATE)
|
|
||||||
# Create the tables
|
|
||||||
for t in schema.tables:
|
|
||||||
t.create(db)
|
|
||||||
# Fill the validation table
|
|
||||||
add_data(db, "_Validation", schema._Validation_records)
|
|
||||||
# Initialize the summary information, allowing atmost 20 properties
|
|
||||||
si = db.GetSummaryInformation(20)
|
|
||||||
si.SetProperty(PID_TITLE, "Installation Database")
|
|
||||||
si.SetProperty(PID_SUBJECT, ProductName)
|
|
||||||
si.SetProperty(PID_AUTHOR, Manufacturer)
|
|
||||||
if AMD64:
|
|
||||||
si.SetProperty(PID_TEMPLATE, "x64;1033")
|
|
||||||
else:
|
|
||||||
si.SetProperty(PID_TEMPLATE, "Intel;1033")
|
|
||||||
si.SetProperty(PID_REVNUMBER, gen_uuid())
|
|
||||||
si.SetProperty(PID_WORDCOUNT, 2) # long file names, compressed, original media
|
|
||||||
si.SetProperty(PID_PAGECOUNT, 200)
|
|
||||||
si.SetProperty(PID_APPNAME, "Python MSI Library")
|
|
||||||
# XXX more properties
|
|
||||||
si.Persist()
|
|
||||||
add_data(db, "Property", [
|
|
||||||
("ProductName", ProductName),
|
|
||||||
("ProductCode", ProductCode),
|
|
||||||
("ProductVersion", ProductVersion),
|
|
||||||
("Manufacturer", Manufacturer),
|
|
||||||
("ProductLanguage", "1033")])
|
|
||||||
db.Commit()
|
|
||||||
return db
|
|
||||||
|
|
||||||
def add_tables(db, module):
|
|
||||||
for table in module.tables:
|
|
||||||
add_data(db, table, getattr(module, table))
|
|
||||||
|
|
||||||
def make_id(str):
|
|
||||||
identifier_chars = string.ascii_letters + string.digits + "._"
|
|
||||||
str = "".join([c if c in identifier_chars else "_" for c in str])
|
|
||||||
if str[0] in (string.digits + "."):
|
|
||||||
str = "_" + str
|
|
||||||
assert re.match("^[A-Za-z_][A-Za-z0-9_.]*$", str), "FILE"+str
|
|
||||||
return str
|
|
||||||
|
|
||||||
def gen_uuid():
|
|
||||||
return "{"+UuidCreate().upper()+"}"
|
|
||||||
|
|
||||||
class CAB:
|
|
||||||
def __init__(self, name):
|
|
||||||
self.name = name
|
|
||||||
self.files = []
|
|
||||||
self.filenames = set()
|
|
||||||
self.index = 0
|
|
||||||
|
|
||||||
def gen_id(self, file):
|
|
||||||
logical = _logical = make_id(file)
|
|
||||||
pos = 1
|
|
||||||
while logical in self.filenames:
|
|
||||||
logical = "%s.%d" % (_logical, pos)
|
|
||||||
pos += 1
|
|
||||||
self.filenames.add(logical)
|
|
||||||
return logical
|
|
||||||
|
|
||||||
def append(self, full, file, logical):
|
|
||||||
if os.path.isdir(full):
|
|
||||||
return
|
|
||||||
if not logical:
|
|
||||||
logical = self.gen_id(file)
|
|
||||||
self.index += 1
|
|
||||||
self.files.append((full, logical))
|
|
||||||
return self.index, logical
|
|
||||||
|
|
||||||
def commit(self, db):
|
|
||||||
from tempfile import mktemp
|
|
||||||
filename = mktemp()
|
|
||||||
FCICreate(filename, self.files)
|
|
||||||
add_data(db, "Media",
|
|
||||||
[(1, self.index, None, "#"+self.name, None, None)])
|
|
||||||
add_stream(db, self.name, filename)
|
|
||||||
os.unlink(filename)
|
|
||||||
db.Commit()
|
|
||||||
|
|
||||||
_directories = set()
|
|
||||||
class Directory:
|
|
||||||
def __init__(self, db, cab, basedir, physical, _logical, default, componentflags=None):
|
|
||||||
"""Create a new directory in the Directory table. There is a current component
|
|
||||||
at each point in time for the directory, which is either explicitly created
|
|
||||||
through start_component, or implicitly when files are added for the first
|
|
||||||
time. Files are added into the current component, and into the cab file.
|
|
||||||
To create a directory, a base directory object needs to be specified (can be
|
|
||||||
None), the path to the physical directory, and a logical directory name.
|
|
||||||
Default specifies the DefaultDir slot in the directory table. componentflags
|
|
||||||
specifies the default flags that new components get."""
|
|
||||||
index = 1
|
|
||||||
_logical = make_id(_logical)
|
|
||||||
logical = _logical
|
|
||||||
while logical in _directories:
|
|
||||||
logical = "%s%d" % (_logical, index)
|
|
||||||
index += 1
|
|
||||||
_directories.add(logical)
|
|
||||||
self.db = db
|
|
||||||
self.cab = cab
|
|
||||||
self.basedir = basedir
|
|
||||||
self.physical = physical
|
|
||||||
self.logical = logical
|
|
||||||
self.component = None
|
|
||||||
self.short_names = set()
|
|
||||||
self.ids = set()
|
|
||||||
self.keyfiles = {}
|
|
||||||
self.componentflags = componentflags
|
|
||||||
if basedir:
|
|
||||||
self.absolute = os.path.join(basedir.absolute, physical)
|
|
||||||
blogical = basedir.logical
|
|
||||||
else:
|
|
||||||
self.absolute = physical
|
|
||||||
blogical = None
|
|
||||||
add_data(db, "Directory", [(logical, blogical, default)])
|
|
||||||
|
|
||||||
def start_component(self, component = None, feature = None, flags = None, keyfile = None, uuid=None):
|
|
||||||
"""Add an entry to the Component table, and make this component the current for this
|
|
||||||
directory. If no component name is given, the directory name is used. If no feature
|
|
||||||
is given, the current feature is used. If no flags are given, the directory's default
|
|
||||||
flags are used. If no keyfile is given, the KeyPath is left null in the Component
|
|
||||||
table."""
|
|
||||||
if flags is None:
|
|
||||||
flags = self.componentflags
|
|
||||||
if uuid is None:
|
|
||||||
uuid = gen_uuid()
|
|
||||||
else:
|
|
||||||
uuid = uuid.upper()
|
|
||||||
if component is None:
|
|
||||||
component = self.logical
|
|
||||||
self.component = component
|
|
||||||
if AMD64:
|
|
||||||
flags |= 256
|
|
||||||
if keyfile:
|
|
||||||
keyid = self.cab.gen_id(keyfile)
|
|
||||||
self.keyfiles[keyfile] = keyid
|
|
||||||
else:
|
|
||||||
keyid = None
|
|
||||||
add_data(self.db, "Component",
|
|
||||||
[(component, uuid, self.logical, flags, None, keyid)])
|
|
||||||
if feature is None:
|
|
||||||
feature = current_feature
|
|
||||||
add_data(self.db, "FeatureComponents",
|
|
||||||
[(feature.id, component)])
|
|
||||||
|
|
||||||
def make_short(self, file):
|
|
||||||
oldfile = file
|
|
||||||
file = file.replace('+', '_')
|
|
||||||
file = ''.join(c for c in file if not c in r' "/\[]:;=,')
|
|
||||||
parts = file.split(".")
|
|
||||||
if len(parts) > 1:
|
|
||||||
prefix = "".join(parts[:-1]).upper()
|
|
||||||
suffix = parts[-1].upper()
|
|
||||||
if not prefix:
|
|
||||||
prefix = suffix
|
|
||||||
suffix = None
|
|
||||||
else:
|
|
||||||
prefix = file.upper()
|
|
||||||
suffix = None
|
|
||||||
if len(parts) < 3 and len(prefix) <= 8 and file == oldfile and (
|
|
||||||
not suffix or len(suffix) <= 3):
|
|
||||||
if suffix:
|
|
||||||
file = prefix+"."+suffix
|
|
||||||
else:
|
|
||||||
file = prefix
|
|
||||||
else:
|
|
||||||
file = None
|
|
||||||
if file is None or file in self.short_names:
|
|
||||||
prefix = prefix[:6]
|
|
||||||
if suffix:
|
|
||||||
suffix = suffix[:3]
|
|
||||||
pos = 1
|
|
||||||
while 1:
|
|
||||||
if suffix:
|
|
||||||
file = "%s~%d.%s" % (prefix, pos, suffix)
|
|
||||||
else:
|
|
||||||
file = "%s~%d" % (prefix, pos)
|
|
||||||
if file not in self.short_names: break
|
|
||||||
pos += 1
|
|
||||||
assert pos < 10000
|
|
||||||
if pos in (10, 100, 1000):
|
|
||||||
prefix = prefix[:-1]
|
|
||||||
self.short_names.add(file)
|
|
||||||
assert not re.search(r'[\?|><:/*"+,;=\[\]]', file) # restrictions on short names
|
|
||||||
return file
|
|
||||||
|
|
||||||
def add_file(self, file, src=None, version=None, language=None):
|
|
||||||
"""Add a file to the current component of the directory, starting a new one
|
|
||||||
if there is no current component. By default, the file name in the source
|
|
||||||
and the file table will be identical. If the src file is specified, it is
|
|
||||||
interpreted relative to the current directory. Optionally, a version and a
|
|
||||||
language can be specified for the entry in the File table."""
|
|
||||||
if not self.component:
|
|
||||||
self.start_component(self.logical, current_feature, 0)
|
|
||||||
if not src:
|
|
||||||
# Allow relative paths for file if src is not specified
|
|
||||||
src = file
|
|
||||||
file = os.path.basename(file)
|
|
||||||
absolute = os.path.join(self.absolute, src)
|
|
||||||
assert not re.search(r'[\?|><:/*]"', file) # restrictions on long names
|
|
||||||
if file in self.keyfiles:
|
|
||||||
logical = self.keyfiles[file]
|
|
||||||
else:
|
|
||||||
logical = None
|
|
||||||
sequence, logical = self.cab.append(absolute, file, logical)
|
|
||||||
assert logical not in self.ids
|
|
||||||
self.ids.add(logical)
|
|
||||||
short = self.make_short(file)
|
|
||||||
full = "%s|%s" % (short, file)
|
|
||||||
filesize = os.stat(absolute).st_size
|
|
||||||
# constants.msidbFileAttributesVital
|
|
||||||
# Compressed omitted, since it is the database default
|
|
||||||
# could add r/o, system, hidden
|
|
||||||
attributes = 512
|
|
||||||
add_data(self.db, "File",
|
|
||||||
[(logical, self.component, full, filesize, version,
|
|
||||||
language, attributes, sequence)])
|
|
||||||
#if not version:
|
|
||||||
# # Add hash if the file is not versioned
|
|
||||||
# filehash = FileHash(absolute, 0)
|
|
||||||
# add_data(self.db, "MsiFileHash",
|
|
||||||
# [(logical, 0, filehash.IntegerData(1),
|
|
||||||
# filehash.IntegerData(2), filehash.IntegerData(3),
|
|
||||||
# filehash.IntegerData(4))])
|
|
||||||
# Automatically remove .pyc files on uninstall (2)
|
|
||||||
# XXX: adding so many RemoveFile entries makes installer unbelievably
|
|
||||||
# slow. So instead, we have to use wildcard remove entries
|
|
||||||
if file.endswith(".py"):
|
|
||||||
add_data(self.db, "RemoveFile",
|
|
||||||
[(logical+"c", self.component, "%sC|%sc" % (short, file),
|
|
||||||
self.logical, 2),
|
|
||||||
(logical+"o", self.component, "%sO|%so" % (short, file),
|
|
||||||
self.logical, 2)])
|
|
||||||
return logical
|
|
||||||
|
|
||||||
def glob(self, pattern, exclude = None):
|
|
||||||
"""Add a list of files to the current component as specified in the
|
|
||||||
glob pattern. Individual files can be excluded in the exclude list."""
|
|
||||||
try:
|
|
||||||
files = os.listdir(self.absolute)
|
|
||||||
except OSError:
|
|
||||||
return []
|
|
||||||
if pattern[:1] != '.':
|
|
||||||
files = (f for f in files if f[0] != '.')
|
|
||||||
files = fnmatch.filter(files, pattern)
|
|
||||||
for f in files:
|
|
||||||
if exclude and f in exclude: continue
|
|
||||||
self.add_file(f)
|
|
||||||
return files
|
|
||||||
|
|
||||||
def remove_pyc(self):
|
|
||||||
"Remove .pyc files on uninstall"
|
|
||||||
add_data(self.db, "RemoveFile",
|
|
||||||
[(self.component+"c", self.component, "*.pyc", self.logical, 2)])
|
|
||||||
|
|
||||||
class Binary:
|
|
||||||
def __init__(self, fname):
|
|
||||||
self.name = fname
|
|
||||||
def __repr__(self):
|
|
||||||
return 'msilib.Binary(os.path.join(dirname,"%s"))' % self.name
|
|
||||||
|
|
||||||
class Feature:
|
|
||||||
def __init__(self, db, id, title, desc, display, level = 1,
|
|
||||||
parent=None, directory = None, attributes=0):
|
|
||||||
self.id = id
|
|
||||||
if parent:
|
|
||||||
parent = parent.id
|
|
||||||
add_data(db, "Feature",
|
|
||||||
[(id, parent, title, desc, display,
|
|
||||||
level, directory, attributes)])
|
|
||||||
def set_current(self):
|
|
||||||
global current_feature
|
|
||||||
current_feature = self
|
|
||||||
|
|
||||||
class Control:
|
|
||||||
def __init__(self, dlg, name):
|
|
||||||
self.dlg = dlg
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
def event(self, event, argument, condition = "1", ordering = None):
|
|
||||||
add_data(self.dlg.db, "ControlEvent",
|
|
||||||
[(self.dlg.name, self.name, event, argument,
|
|
||||||
condition, ordering)])
|
|
||||||
|
|
||||||
def mapping(self, event, attribute):
|
|
||||||
add_data(self.dlg.db, "EventMapping",
|
|
||||||
[(self.dlg.name, self.name, event, attribute)])
|
|
||||||
|
|
||||||
def condition(self, action, condition):
|
|
||||||
add_data(self.dlg.db, "ControlCondition",
|
|
||||||
[(self.dlg.name, self.name, action, condition)])
|
|
||||||
|
|
||||||
class RadioButtonGroup(Control):
|
|
||||||
def __init__(self, dlg, name, property):
|
|
||||||
self.dlg = dlg
|
|
||||||
self.name = name
|
|
||||||
self.property = property
|
|
||||||
self.index = 1
|
|
||||||
|
|
||||||
def add(self, name, x, y, w, h, text, value = None):
|
|
||||||
if value is None:
|
|
||||||
value = name
|
|
||||||
add_data(self.dlg.db, "RadioButton",
|
|
||||||
[(self.property, self.index, value,
|
|
||||||
x, y, w, h, text, None)])
|
|
||||||
self.index += 1
|
|
||||||
|
|
||||||
class Dialog:
|
|
||||||
def __init__(self, db, name, x, y, w, h, attr, title, first, default, cancel):
|
|
||||||
self.db = db
|
|
||||||
self.name = name
|
|
||||||
self.x, self.y, self.w, self.h = x,y,w,h
|
|
||||||
add_data(db, "Dialog", [(name, x,y,w,h,attr,title,first,default,cancel)])
|
|
||||||
|
|
||||||
def control(self, name, type, x, y, w, h, attr, prop, text, next, help):
|
|
||||||
add_data(self.db, "Control",
|
|
||||||
[(self.name, name, type, x, y, w, h, attr, prop, text, next, help)])
|
|
||||||
return Control(self, name)
|
|
||||||
|
|
||||||
def text(self, name, x, y, w, h, attr, text):
|
|
||||||
return self.control(name, "Text", x, y, w, h, attr, None,
|
|
||||||
text, None, None)
|
|
||||||
|
|
||||||
def bitmap(self, name, x, y, w, h, text):
|
|
||||||
return self.control(name, "Bitmap", x, y, w, h, 1, None, text, None, None)
|
|
||||||
|
|
||||||
def line(self, name, x, y, w, h):
|
|
||||||
return self.control(name, "Line", x, y, w, h, 1, None, None, None, None)
|
|
||||||
|
|
||||||
def pushbutton(self, name, x, y, w, h, attr, text, next):
|
|
||||||
return self.control(name, "PushButton", x, y, w, h, attr, None, text, next, None)
|
|
||||||
|
|
||||||
def radiogroup(self, name, x, y, w, h, attr, prop, text, next):
|
|
||||||
add_data(self.db, "Control",
|
|
||||||
[(self.name, name, "RadioButtonGroup",
|
|
||||||
x, y, w, h, attr, prop, text, next, None)])
|
|
||||||
return RadioButtonGroup(self, name, prop)
|
|
||||||
|
|
||||||
def checkbox(self, name, x, y, w, h, attr, prop, text, next):
|
|
||||||
return self.control(name, "CheckBox", x, y, w, h, attr, prop, text, next, None)
|
|
1007
Lib/msilib/schema.py
1007
Lib/msilib/schema.py
File diff suppressed because it is too large
Load Diff
|
@ -1,126 +0,0 @@
|
||||||
AdminExecuteSequence = [
|
|
||||||
('InstallInitialize', None, 1500),
|
|
||||||
('InstallFinalize', None, 6600),
|
|
||||||
('InstallFiles', None, 4000),
|
|
||||||
('InstallAdminPackage', None, 3900),
|
|
||||||
('FileCost', None, 900),
|
|
||||||
('CostInitialize', None, 800),
|
|
||||||
('CostFinalize', None, 1000),
|
|
||||||
('InstallValidate', None, 1400),
|
|
||||||
]
|
|
||||||
|
|
||||||
AdminUISequence = [
|
|
||||||
('FileCost', None, 900),
|
|
||||||
('CostInitialize', None, 800),
|
|
||||||
('CostFinalize', None, 1000),
|
|
||||||
('ExecuteAction', None, 1300),
|
|
||||||
('ExitDialog', None, -1),
|
|
||||||
('FatalError', None, -3),
|
|
||||||
('UserExit', None, -2),
|
|
||||||
]
|
|
||||||
|
|
||||||
AdvtExecuteSequence = [
|
|
||||||
('InstallInitialize', None, 1500),
|
|
||||||
('InstallFinalize', None, 6600),
|
|
||||||
('CostInitialize', None, 800),
|
|
||||||
('CostFinalize', None, 1000),
|
|
||||||
('InstallValidate', None, 1400),
|
|
||||||
('CreateShortcuts', None, 4500),
|
|
||||||
('MsiPublishAssemblies', None, 6250),
|
|
||||||
('PublishComponents', None, 6200),
|
|
||||||
('PublishFeatures', None, 6300),
|
|
||||||
('PublishProduct', None, 6400),
|
|
||||||
('RegisterClassInfo', None, 4600),
|
|
||||||
('RegisterExtensionInfo', None, 4700),
|
|
||||||
('RegisterMIMEInfo', None, 4900),
|
|
||||||
('RegisterProgIdInfo', None, 4800),
|
|
||||||
]
|
|
||||||
|
|
||||||
InstallExecuteSequence = [
|
|
||||||
('InstallInitialize', None, 1500),
|
|
||||||
('InstallFinalize', None, 6600),
|
|
||||||
('InstallFiles', None, 4000),
|
|
||||||
('FileCost', None, 900),
|
|
||||||
('CostInitialize', None, 800),
|
|
||||||
('CostFinalize', None, 1000),
|
|
||||||
('InstallValidate', None, 1400),
|
|
||||||
('CreateShortcuts', None, 4500),
|
|
||||||
('MsiPublishAssemblies', None, 6250),
|
|
||||||
('PublishComponents', None, 6200),
|
|
||||||
('PublishFeatures', None, 6300),
|
|
||||||
('PublishProduct', None, 6400),
|
|
||||||
('RegisterClassInfo', None, 4600),
|
|
||||||
('RegisterExtensionInfo', None, 4700),
|
|
||||||
('RegisterMIMEInfo', None, 4900),
|
|
||||||
('RegisterProgIdInfo', None, 4800),
|
|
||||||
('AllocateRegistrySpace', 'NOT Installed', 1550),
|
|
||||||
('AppSearch', None, 400),
|
|
||||||
('BindImage', None, 4300),
|
|
||||||
('CCPSearch', 'NOT Installed', 500),
|
|
||||||
('CreateFolders', None, 3700),
|
|
||||||
('DeleteServices', 'VersionNT', 2000),
|
|
||||||
('DuplicateFiles', None, 4210),
|
|
||||||
('FindRelatedProducts', None, 200),
|
|
||||||
('InstallODBC', None, 5400),
|
|
||||||
('InstallServices', 'VersionNT', 5800),
|
|
||||||
('IsolateComponents', None, 950),
|
|
||||||
('LaunchConditions', None, 100),
|
|
||||||
('MigrateFeatureStates', None, 1200),
|
|
||||||
('MoveFiles', None, 3800),
|
|
||||||
('PatchFiles', None, 4090),
|
|
||||||
('ProcessComponents', None, 1600),
|
|
||||||
('RegisterComPlus', None, 5700),
|
|
||||||
('RegisterFonts', None, 5300),
|
|
||||||
('RegisterProduct', None, 6100),
|
|
||||||
('RegisterTypeLibraries', None, 5500),
|
|
||||||
('RegisterUser', None, 6000),
|
|
||||||
('RemoveDuplicateFiles', None, 3400),
|
|
||||||
('RemoveEnvironmentStrings', None, 3300),
|
|
||||||
('RemoveExistingProducts', None, 6700),
|
|
||||||
('RemoveFiles', None, 3500),
|
|
||||||
('RemoveFolders', None, 3600),
|
|
||||||
('RemoveIniValues', None, 3100),
|
|
||||||
('RemoveODBC', None, 2400),
|
|
||||||
('RemoveRegistryValues', None, 2600),
|
|
||||||
('RemoveShortcuts', None, 3200),
|
|
||||||
('RMCCPSearch', 'NOT Installed', 600),
|
|
||||||
('SelfRegModules', None, 5600),
|
|
||||||
('SelfUnregModules', None, 2200),
|
|
||||||
('SetODBCFolders', None, 1100),
|
|
||||||
('StartServices', 'VersionNT', 5900),
|
|
||||||
('StopServices', 'VersionNT', 1900),
|
|
||||||
('MsiUnpublishAssemblies', None, 1750),
|
|
||||||
('UnpublishComponents', None, 1700),
|
|
||||||
('UnpublishFeatures', None, 1800),
|
|
||||||
('UnregisterClassInfo', None, 2700),
|
|
||||||
('UnregisterComPlus', None, 2100),
|
|
||||||
('UnregisterExtensionInfo', None, 2800),
|
|
||||||
('UnregisterFonts', None, 2500),
|
|
||||||
('UnregisterMIMEInfo', None, 3000),
|
|
||||||
('UnregisterProgIdInfo', None, 2900),
|
|
||||||
('UnregisterTypeLibraries', None, 2300),
|
|
||||||
('ValidateProductID', None, 700),
|
|
||||||
('WriteEnvironmentStrings', None, 5200),
|
|
||||||
('WriteIniValues', None, 5100),
|
|
||||||
('WriteRegistryValues', None, 5000),
|
|
||||||
]
|
|
||||||
|
|
||||||
InstallUISequence = [
|
|
||||||
('FileCost', None, 900),
|
|
||||||
('CostInitialize', None, 800),
|
|
||||||
('CostFinalize', None, 1000),
|
|
||||||
('ExecuteAction', None, 1300),
|
|
||||||
('ExitDialog', None, -1),
|
|
||||||
('FatalError', None, -3),
|
|
||||||
('UserExit', None, -2),
|
|
||||||
('AppSearch', None, 400),
|
|
||||||
('CCPSearch', 'NOT Installed', 500),
|
|
||||||
('FindRelatedProducts', None, 200),
|
|
||||||
('IsolateComponents', None, 950),
|
|
||||||
('LaunchConditions', None, 100),
|
|
||||||
('MigrateFeatureStates', None, 1200),
|
|
||||||
('RMCCPSearch', 'NOT Installed', 600),
|
|
||||||
('ValidateProductID', None, 700),
|
|
||||||
]
|
|
||||||
|
|
||||||
tables=['AdminExecuteSequence', 'AdminUISequence', 'AdvtExecuteSequence', 'InstallExecuteSequence', 'InstallUISequence']
|
|
|
@ -1,129 +0,0 @@
|
||||||
import msilib,os;dirname=os.path.dirname(__file__)
|
|
||||||
|
|
||||||
ActionText = [
|
|
||||||
('InstallValidate', 'Validating install', None),
|
|
||||||
('InstallFiles', 'Copying new files', 'File: [1], Directory: [9], Size: [6]'),
|
|
||||||
('InstallAdminPackage', 'Copying network install files', 'File: [1], Directory: [9], Size: [6]'),
|
|
||||||
('FileCost', 'Computing space requirements', None),
|
|
||||||
('CostInitialize', 'Computing space requirements', None),
|
|
||||||
('CostFinalize', 'Computing space requirements', None),
|
|
||||||
('CreateShortcuts', 'Creating shortcuts', 'Shortcut: [1]'),
|
|
||||||
('PublishComponents', 'Publishing Qualified Components', 'Component ID: [1], Qualifier: [2]'),
|
|
||||||
('PublishFeatures', 'Publishing Product Features', 'Feature: [1]'),
|
|
||||||
('PublishProduct', 'Publishing product information', None),
|
|
||||||
('RegisterClassInfo', 'Registering Class servers', 'Class Id: [1]'),
|
|
||||||
('RegisterExtensionInfo', 'Registering extension servers', 'Extension: [1]'),
|
|
||||||
('RegisterMIMEInfo', 'Registering MIME info', 'MIME Content Type: [1], Extension: [2]'),
|
|
||||||
('RegisterProgIdInfo', 'Registering program identifiers', 'ProgId: [1]'),
|
|
||||||
('AllocateRegistrySpace', 'Allocating registry space', 'Free space: [1]'),
|
|
||||||
('AppSearch', 'Searching for installed applications', 'Property: [1], Signature: [2]'),
|
|
||||||
('BindImage', 'Binding executables', 'File: [1]'),
|
|
||||||
('CCPSearch', 'Searching for qualifying products', None),
|
|
||||||
('CreateFolders', 'Creating folders', 'Folder: [1]'),
|
|
||||||
('DeleteServices', 'Deleting services', 'Service: [1]'),
|
|
||||||
('DuplicateFiles', 'Creating duplicate files', 'File: [1], Directory: [9], Size: [6]'),
|
|
||||||
('FindRelatedProducts', 'Searching for related applications', 'Found application: [1]'),
|
|
||||||
('InstallODBC', 'Installing ODBC components', None),
|
|
||||||
('InstallServices', 'Installing new services', 'Service: [2]'),
|
|
||||||
('LaunchConditions', 'Evaluating launch conditions', None),
|
|
||||||
('MigrateFeatureStates', 'Migrating feature states from related applications', 'Application: [1]'),
|
|
||||||
('MoveFiles', 'Moving files', 'File: [1], Directory: [9], Size: [6]'),
|
|
||||||
('PatchFiles', 'Patching files', 'File: [1], Directory: [2], Size: [3]'),
|
|
||||||
('ProcessComponents', 'Updating component registration', None),
|
|
||||||
('RegisterComPlus', 'Registering COM+ Applications and Components', 'AppId: [1]{{, AppType: [2], Users: [3], RSN: [4]}}'),
|
|
||||||
('RegisterFonts', 'Registering fonts', 'Font: [1]'),
|
|
||||||
('RegisterProduct', 'Registering product', '[1]'),
|
|
||||||
('RegisterTypeLibraries', 'Registering type libraries', 'LibID: [1]'),
|
|
||||||
('RegisterUser', 'Registering user', '[1]'),
|
|
||||||
('RemoveDuplicateFiles', 'Removing duplicated files', 'File: [1], Directory: [9]'),
|
|
||||||
('RemoveEnvironmentStrings', 'Updating environment strings', 'Name: [1], Value: [2], Action [3]'),
|
|
||||||
('RemoveExistingProducts', 'Removing applications', 'Application: [1], Command line: [2]'),
|
|
||||||
('RemoveFiles', 'Removing files', 'File: [1], Directory: [9]'),
|
|
||||||
('RemoveFolders', 'Removing folders', 'Folder: [1]'),
|
|
||||||
('RemoveIniValues', 'Removing INI files entries', 'File: [1], Section: [2], Key: [3], Value: [4]'),
|
|
||||||
('RemoveODBC', 'Removing ODBC components', None),
|
|
||||||
('RemoveRegistryValues', 'Removing system registry values', 'Key: [1], Name: [2]'),
|
|
||||||
('RemoveShortcuts', 'Removing shortcuts', 'Shortcut: [1]'),
|
|
||||||
('RMCCPSearch', 'Searching for qualifying products', None),
|
|
||||||
('SelfRegModules', 'Registering modules', 'File: [1], Folder: [2]'),
|
|
||||||
('SelfUnregModules', 'Unregistering modules', 'File: [1], Folder: [2]'),
|
|
||||||
('SetODBCFolders', 'Initializing ODBC directories', None),
|
|
||||||
('StartServices', 'Starting services', 'Service: [1]'),
|
|
||||||
('StopServices', 'Stopping services', 'Service: [1]'),
|
|
||||||
('UnpublishComponents', 'Unpublishing Qualified Components', 'Component ID: [1], Qualifier: [2]'),
|
|
||||||
('UnpublishFeatures', 'Unpublishing Product Features', 'Feature: [1]'),
|
|
||||||
('UnregisterClassInfo', 'Unregister Class servers', 'Class Id: [1]'),
|
|
||||||
('UnregisterComPlus', 'Unregistering COM+ Applications and Components', 'AppId: [1]{{, AppType: [2]}}'),
|
|
||||||
('UnregisterExtensionInfo', 'Unregistering extension servers', 'Extension: [1]'),
|
|
||||||
('UnregisterFonts', 'Unregistering fonts', 'Font: [1]'),
|
|
||||||
('UnregisterMIMEInfo', 'Unregistering MIME info', 'MIME Content Type: [1], Extension: [2]'),
|
|
||||||
('UnregisterProgIdInfo', 'Unregistering program identifiers', 'ProgId: [1]'),
|
|
||||||
('UnregisterTypeLibraries', 'Unregistering type libraries', 'LibID: [1]'),
|
|
||||||
('WriteEnvironmentStrings', 'Updating environment strings', 'Name: [1], Value: [2], Action [3]'),
|
|
||||||
('WriteIniValues', 'Writing INI files values', 'File: [1], Section: [2], Key: [3], Value: [4]'),
|
|
||||||
('WriteRegistryValues', 'Writing system registry values', 'Key: [1], Name: [2], Value: [3]'),
|
|
||||||
('Advertise', 'Advertising application', None),
|
|
||||||
('GenerateScript', 'Generating script operations for action:', '[1]'),
|
|
||||||
('InstallSFPCatalogFile', 'Installing system catalog', 'File: [1], Dependencies: [2]'),
|
|
||||||
('MsiPublishAssemblies', 'Publishing assembly information', 'Application Context:[1], Assembly Name:[2]'),
|
|
||||||
('MsiUnpublishAssemblies', 'Unpublishing assembly information', 'Application Context:[1], Assembly Name:[2]'),
|
|
||||||
('Rollback', 'Rolling back action:', '[1]'),
|
|
||||||
('RollbackCleanup', 'Removing backup files', 'File: [1]'),
|
|
||||||
('UnmoveFiles', 'Removing moved files', 'File: [1], Directory: [9]'),
|
|
||||||
('UnpublishProduct', 'Unpublishing product information', None),
|
|
||||||
]
|
|
||||||
|
|
||||||
UIText = [
|
|
||||||
('AbsentPath', None),
|
|
||||||
('bytes', 'bytes'),
|
|
||||||
('GB', 'GB'),
|
|
||||||
('KB', 'KB'),
|
|
||||||
('MB', 'MB'),
|
|
||||||
('MenuAbsent', 'Entire feature will be unavailable'),
|
|
||||||
('MenuAdvertise', 'Feature will be installed when required'),
|
|
||||||
('MenuAllCD', 'Entire feature will be installed to run from CD'),
|
|
||||||
('MenuAllLocal', 'Entire feature will be installed on local hard drive'),
|
|
||||||
('MenuAllNetwork', 'Entire feature will be installed to run from network'),
|
|
||||||
('MenuCD', 'Will be installed to run from CD'),
|
|
||||||
('MenuLocal', 'Will be installed on local hard drive'),
|
|
||||||
('MenuNetwork', 'Will be installed to run from network'),
|
|
||||||
('ScriptInProgress', 'Gathering required information...'),
|
|
||||||
('SelAbsentAbsent', 'This feature will remain uninstalled'),
|
|
||||||
('SelAbsentAdvertise', 'This feature will be set to be installed when required'),
|
|
||||||
('SelAbsentCD', 'This feature will be installed to run from CD'),
|
|
||||||
('SelAbsentLocal', 'This feature will be installed on the local hard drive'),
|
|
||||||
('SelAbsentNetwork', 'This feature will be installed to run from the network'),
|
|
||||||
('SelAdvertiseAbsent', 'This feature will become unavailable'),
|
|
||||||
('SelAdvertiseAdvertise', 'Will be installed when required'),
|
|
||||||
('SelAdvertiseCD', 'This feature will be available to run from CD'),
|
|
||||||
('SelAdvertiseLocal', 'This feature will be installed on your local hard drive'),
|
|
||||||
('SelAdvertiseNetwork', 'This feature will be available to run from the network'),
|
|
||||||
('SelCDAbsent', "This feature will be uninstalled completely, you won't be able to run it from CD"),
|
|
||||||
('SelCDAdvertise', 'This feature will change from run from CD state to set to be installed when required'),
|
|
||||||
('SelCDCD', 'This feature will remain to be run from CD'),
|
|
||||||
('SelCDLocal', 'This feature will change from run from CD state to be installed on the local hard drive'),
|
|
||||||
('SelChildCostNeg', 'This feature frees up [1] on your hard drive.'),
|
|
||||||
('SelChildCostPos', 'This feature requires [1] on your hard drive.'),
|
|
||||||
('SelCostPending', 'Compiling cost for this feature...'),
|
|
||||||
('SelLocalAbsent', 'This feature will be completely removed'),
|
|
||||||
('SelLocalAdvertise', 'This feature will be removed from your local hard drive, but will be set to be installed when required'),
|
|
||||||
('SelLocalCD', 'This feature will be removed from your local hard drive, but will be still available to run from CD'),
|
|
||||||
('SelLocalLocal', 'This feature will remain on you local hard drive'),
|
|
||||||
('SelLocalNetwork', 'This feature will be removed from your local hard drive, but will be still available to run from the network'),
|
|
||||||
('SelNetworkAbsent', "This feature will be uninstalled completely, you won't be able to run it from the network"),
|
|
||||||
('SelNetworkAdvertise', 'This feature will change from run from network state to set to be installed when required'),
|
|
||||||
('SelNetworkLocal', 'This feature will change from run from network state to be installed on the local hard drive'),
|
|
||||||
('SelNetworkNetwork', 'This feature will remain to be run from the network'),
|
|
||||||
('SelParentCostNegNeg', 'This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.'),
|
|
||||||
('SelParentCostNegPos', 'This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.'),
|
|
||||||
('SelParentCostPosNeg', 'This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.'),
|
|
||||||
('SelParentCostPosPos', 'This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.'),
|
|
||||||
('TimeRemaining', 'Time remaining: {[1] minutes }{[2] seconds}'),
|
|
||||||
('VolumeCostAvailable', 'Available'),
|
|
||||||
('VolumeCostDifference', 'Difference'),
|
|
||||||
('VolumeCostRequired', 'Required'),
|
|
||||||
('VolumeCostSize', 'Disk Size'),
|
|
||||||
('VolumeCostVolume', 'Volume'),
|
|
||||||
]
|
|
||||||
|
|
||||||
tables=['ActionText', 'UIText']
|
|
|
@ -1,166 +0,0 @@
|
||||||
""" Test suite for the code in msilib """
|
|
||||||
import os
|
|
||||||
import unittest
|
|
||||||
from test.support.import_helper import import_module
|
|
||||||
from test.support.os_helper import TESTFN, unlink
|
|
||||||
import warnings
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore", DeprecationWarning)
|
|
||||||
msilib = import_module('msilib')
|
|
||||||
import msilib.schema
|
|
||||||
|
|
||||||
|
|
||||||
def init_database():
|
|
||||||
path = TESTFN + '.msi'
|
|
||||||
db = msilib.init_database(
|
|
||||||
path,
|
|
||||||
msilib.schema,
|
|
||||||
'Python Tests',
|
|
||||||
'product_code',
|
|
||||||
'1.0',
|
|
||||||
'PSF',
|
|
||||||
)
|
|
||||||
return db, path
|
|
||||||
|
|
||||||
|
|
||||||
class MsiDatabaseTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_view_fetch_returns_none(self):
|
|
||||||
db, db_path = init_database()
|
|
||||||
properties = []
|
|
||||||
view = db.OpenView('SELECT Property, Value FROM Property')
|
|
||||||
view.Execute(None)
|
|
||||||
while True:
|
|
||||||
record = view.Fetch()
|
|
||||||
if record is None:
|
|
||||||
break
|
|
||||||
properties.append(record.GetString(1))
|
|
||||||
view.Close()
|
|
||||||
db.Close()
|
|
||||||
self.assertEqual(
|
|
||||||
properties,
|
|
||||||
[
|
|
||||||
'ProductName', 'ProductCode', 'ProductVersion',
|
|
||||||
'Manufacturer', 'ProductLanguage',
|
|
||||||
]
|
|
||||||
)
|
|
||||||
self.addCleanup(unlink, db_path)
|
|
||||||
|
|
||||||
def test_view_non_ascii(self):
|
|
||||||
db, db_path = init_database()
|
|
||||||
view = db.OpenView("SELECT 'ß-розпад' FROM Property")
|
|
||||||
view.Execute(None)
|
|
||||||
record = view.Fetch()
|
|
||||||
self.assertEqual(record.GetString(1), 'ß-розпад')
|
|
||||||
view.Close()
|
|
||||||
db.Close()
|
|
||||||
self.addCleanup(unlink, db_path)
|
|
||||||
|
|
||||||
def test_summaryinfo_getproperty_issue1104(self):
|
|
||||||
db, db_path = init_database()
|
|
||||||
try:
|
|
||||||
sum_info = db.GetSummaryInformation(99)
|
|
||||||
title = sum_info.GetProperty(msilib.PID_TITLE)
|
|
||||||
self.assertEqual(title, b"Installation Database")
|
|
||||||
|
|
||||||
sum_info.SetProperty(msilib.PID_TITLE, "a" * 999)
|
|
||||||
title = sum_info.GetProperty(msilib.PID_TITLE)
|
|
||||||
self.assertEqual(title, b"a" * 999)
|
|
||||||
|
|
||||||
sum_info.SetProperty(msilib.PID_TITLE, "a" * 1000)
|
|
||||||
title = sum_info.GetProperty(msilib.PID_TITLE)
|
|
||||||
self.assertEqual(title, b"a" * 1000)
|
|
||||||
|
|
||||||
sum_info.SetProperty(msilib.PID_TITLE, "a" * 1001)
|
|
||||||
title = sum_info.GetProperty(msilib.PID_TITLE)
|
|
||||||
self.assertEqual(title, b"a" * 1001)
|
|
||||||
finally:
|
|
||||||
db = None
|
|
||||||
sum_info = None
|
|
||||||
os.unlink(db_path)
|
|
||||||
|
|
||||||
def test_database_open_failed(self):
|
|
||||||
with self.assertRaises(msilib.MSIError) as cm:
|
|
||||||
msilib.OpenDatabase('non-existent.msi', msilib.MSIDBOPEN_READONLY)
|
|
||||||
self.assertEqual(str(cm.exception), 'open failed')
|
|
||||||
|
|
||||||
def test_database_create_failed(self):
|
|
||||||
db_path = os.path.join(TESTFN, 'test.msi')
|
|
||||||
with self.assertRaises(msilib.MSIError) as cm:
|
|
||||||
msilib.OpenDatabase(db_path, msilib.MSIDBOPEN_CREATE)
|
|
||||||
self.assertEqual(str(cm.exception), 'create failed')
|
|
||||||
|
|
||||||
def test_get_property_vt_empty(self):
|
|
||||||
db, db_path = init_database()
|
|
||||||
summary = db.GetSummaryInformation(0)
|
|
||||||
self.assertIsNone(summary.GetProperty(msilib.PID_SECURITY))
|
|
||||||
db.Close()
|
|
||||||
self.addCleanup(unlink, db_path)
|
|
||||||
|
|
||||||
def test_directory_start_component_keyfile(self):
|
|
||||||
db, db_path = init_database()
|
|
||||||
self.addCleanup(unlink, db_path)
|
|
||||||
self.addCleanup(db.Close)
|
|
||||||
self.addCleanup(msilib._directories.clear)
|
|
||||||
feature = msilib.Feature(db, 0, 'Feature', 'A feature', 'Python')
|
|
||||||
cab = msilib.CAB('CAB')
|
|
||||||
dir = msilib.Directory(db, cab, None, TESTFN, 'TARGETDIR',
|
|
||||||
'SourceDir', 0)
|
|
||||||
dir.start_component(None, feature, None, 'keyfile')
|
|
||||||
|
|
||||||
def test_getproperty_uninitialized_var(self):
|
|
||||||
db, db_path = init_database()
|
|
||||||
self.addCleanup(unlink, db_path)
|
|
||||||
self.addCleanup(db.Close)
|
|
||||||
si = db.GetSummaryInformation(0)
|
|
||||||
with self.assertRaises(msilib.MSIError):
|
|
||||||
si.GetProperty(-1)
|
|
||||||
|
|
||||||
def test_FCICreate(self):
|
|
||||||
filepath = TESTFN + '.txt'
|
|
||||||
cabpath = TESTFN + '.cab'
|
|
||||||
self.addCleanup(unlink, filepath)
|
|
||||||
with open(filepath, 'wb'):
|
|
||||||
pass
|
|
||||||
self.addCleanup(unlink, cabpath)
|
|
||||||
msilib.FCICreate(cabpath, [(filepath, 'test.txt')])
|
|
||||||
self.assertTrue(os.path.isfile(cabpath))
|
|
||||||
|
|
||||||
|
|
||||||
class Test_make_id(unittest.TestCase):
|
|
||||||
#http://msdn.microsoft.com/en-us/library/aa369212(v=vs.85).aspx
|
|
||||||
"""The Identifier data type is a text string. Identifiers may contain the
|
|
||||||
ASCII characters A-Z (a-z), digits, underscores (_), or periods (.).
|
|
||||||
However, every identifier must begin with either a letter or an
|
|
||||||
underscore.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def test_is_no_change_required(self):
|
|
||||||
self.assertEqual(
|
|
||||||
msilib.make_id("short"), "short")
|
|
||||||
self.assertEqual(
|
|
||||||
msilib.make_id("nochangerequired"), "nochangerequired")
|
|
||||||
self.assertEqual(
|
|
||||||
msilib.make_id("one.dot"), "one.dot")
|
|
||||||
self.assertEqual(
|
|
||||||
msilib.make_id("_"), "_")
|
|
||||||
self.assertEqual(
|
|
||||||
msilib.make_id("a"), "a")
|
|
||||||
#self.assertEqual(
|
|
||||||
# msilib.make_id(""), "")
|
|
||||||
|
|
||||||
def test_invalid_first_char(self):
|
|
||||||
self.assertEqual(
|
|
||||||
msilib.make_id("9.short"), "_9.short")
|
|
||||||
self.assertEqual(
|
|
||||||
msilib.make_id(".short"), "_.short")
|
|
||||||
|
|
||||||
def test_invalid_any_char(self):
|
|
||||||
self.assertEqual(
|
|
||||||
msilib.make_id(".s\x82ort"), "_.s_ort")
|
|
||||||
self.assertEqual(
|
|
||||||
msilib.make_id(".s\x82o?*+rt"), "_.s_o___rt")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
|
@ -2986,7 +2986,7 @@ Update Windows release to include SQLite 3.32.3.
|
||||||
.. nonce: jpZzzh
|
.. nonce: jpZzzh
|
||||||
.. section: Windows
|
.. section: Windows
|
||||||
|
|
||||||
:mod:`msilib` now supports creating CAB files with non-ASCII file path and
|
:mod:`!msilib` now supports creating CAB files with non-ASCII file path and
|
||||||
adding files with non-ASCII file path to them.
|
adding files with non-ASCII file path to them.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
@ -2996,9 +2996,9 @@ adding files with non-ASCII file path to them.
|
||||||
.. nonce: gaQc3C
|
.. nonce: gaQc3C
|
||||||
.. section: Windows
|
.. section: Windows
|
||||||
|
|
||||||
Fixed support of non-ASCII names in functions :func:`msilib.OpenDatabase`
|
Fixed support of non-ASCII names in functions :func:`!msilib.OpenDatabase`
|
||||||
and :func:`msilib.init_database` and non-ASCII SQL in method
|
and :func:`!msilib.init_database` and non-ASCII SQL in method
|
||||||
:meth:`msilib.Database.OpenView`.
|
:meth:`!msilib.Database.OpenView`.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
||||||
|
|
|
@ -5400,7 +5400,7 @@ Update libffi to 3.4.3
|
||||||
.. nonce: kV4K_1
|
.. nonce: kV4K_1
|
||||||
.. section: Windows
|
.. section: Windows
|
||||||
|
|
||||||
Fixes a potential buffer overrun in :mod:`msilib`.
|
Fixes a potential buffer overrun in :mod:`!msilib`.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
||||||
|
|
|
@ -294,7 +294,7 @@ by Nir Soffer.
|
||||||
.. nonce: Nj3A0x
|
.. nonce: Nj3A0x
|
||||||
.. section: Library
|
.. section: Library
|
||||||
|
|
||||||
Make :meth:`msilib.SummaryInformation.GetProperty` return ``None`` when the
|
Make :meth:`!msilib.SummaryInformation.GetProperty` return ``None`` when the
|
||||||
value of property is ``VT_EMPTY``. Initial patch by Mark Mc Mahon.
|
value of property is ``VT_EMPTY``. Initial patch by Mark Mc Mahon.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
@ -316,7 +316,7 @@ Initial patch by Robin Wellner.
|
||||||
.. nonce: xWT9k0
|
.. nonce: xWT9k0
|
||||||
.. section: Library
|
.. section: Library
|
||||||
|
|
||||||
:func:`msilib.OpenDatabase` now raises a better exception message when it
|
:func:`!msilib.OpenDatabase` now raises a better exception message when it
|
||||||
couldn't open or create an MSI file. Initial patch by William Tisäter.
|
couldn't open or create an MSI file. Initial patch by William Tisäter.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
|
@ -350,7 +350,7 @@ the left most segment of hostname in second argument of
|
||||||
.. nonce: Nj3A0x
|
.. nonce: Nj3A0x
|
||||||
.. section: Library
|
.. section: Library
|
||||||
|
|
||||||
Make :meth:`msilib.SummaryInformation.GetProperty` return ``None`` when the
|
Make :meth:`!msilib.SummaryInformation.GetProperty` return ``None`` when the
|
||||||
value of property is ``VT_EMPTY``. Initial patch by Mark Mc Mahon.
|
value of property is ``VT_EMPTY``. Initial patch by Mark Mc Mahon.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
@ -396,7 +396,7 @@ Initial patch by Robin Wellner.
|
||||||
.. nonce: xWT9k0
|
.. nonce: xWT9k0
|
||||||
.. section: Library
|
.. section: Library
|
||||||
|
|
||||||
:func:`msilib.OpenDatabase` now raises a better exception message when it
|
:func:`!msilib.OpenDatabase` now raises a better exception message when it
|
||||||
couldn't open or create an MSI file. Initial patch by William Tisäter.
|
couldn't open or create an MSI file. Initial patch by William Tisäter.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
|
@ -509,7 +509,7 @@ Add SSLContext.num_tickets to control the number of TLSv1.3 session tickets.
|
||||||
.. nonce: nobzc9
|
.. nonce: nobzc9
|
||||||
.. section: Library
|
.. section: Library
|
||||||
|
|
||||||
Fix the error handling in :meth:`msilib.SummaryInformation.GetProperty`.
|
Fix the error handling in :meth:`!msilib.SummaryInformation.GetProperty`.
|
||||||
Patch by Zackery Spytz.
|
Patch by Zackery Spytz.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
@ -538,7 +538,7 @@ module.
|
||||||
.. nonce: TQFOR4
|
.. nonce: TQFOR4
|
||||||
.. section: Library
|
.. section: Library
|
||||||
|
|
||||||
:meth:`msilib.Directory.start_component()` no longer fails if *keyfile* is
|
:meth:`!msilib.Directory.start_component()` no longer fails if *keyfile* is
|
||||||
not ``None``.
|
not ``None``.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
:pep:`594`: Removed the :mod:`!msilib` package, deprecated in Python 3.11.
|
|
@ -1,698 +0,0 @@
|
||||||
/*[clinic input]
|
|
||||||
preserve
|
|
||||||
[clinic start generated code]*/
|
|
||||||
|
|
||||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
|
||||||
# include "pycore_gc.h" // PyGC_Head
|
|
||||||
# include "pycore_runtime.h" // _Py_ID()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_UuidCreate__doc__,
|
|
||||||
"UuidCreate($module, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return the string representation of a new unique identifier.");
|
|
||||||
|
|
||||||
#define _MSI_UUIDCREATE_METHODDEF \
|
|
||||||
{"UuidCreate", (PyCFunction)_msi_UuidCreate, METH_NOARGS, _msi_UuidCreate__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_UuidCreate_impl(PyObject *module);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_UuidCreate(PyObject *module, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return _msi_UuidCreate_impl(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_FCICreate__doc__,
|
|
||||||
"FCICreate($module, cabname, files, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Create a new CAB file.\n"
|
|
||||||
"\n"
|
|
||||||
" cabname\n"
|
|
||||||
" the name of the CAB file\n"
|
|
||||||
" files\n"
|
|
||||||
" a list of tuples, each containing the name of the file on disk,\n"
|
|
||||||
" and the name of the file inside the CAB file");
|
|
||||||
|
|
||||||
#define _MSI_FCICREATE_METHODDEF \
|
|
||||||
{"FCICreate", _PyCFunction_CAST(_msi_FCICreate), METH_FASTCALL, _msi_FCICreate__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_FCICreate_impl(PyObject *module, const char *cabname, PyObject *files);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_FCICreate(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
const char *cabname;
|
|
||||||
PyObject *files;
|
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("FCICreate", nargs, 2, 2)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
if (!PyUnicode_Check(args[0])) {
|
|
||||||
_PyArg_BadArgument("FCICreate", "argument 1", "str", args[0]);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
Py_ssize_t cabname_length;
|
|
||||||
cabname = PyUnicode_AsUTF8AndSize(args[0], &cabname_length);
|
|
||||||
if (cabname == NULL) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
if (strlen(cabname) != (size_t)cabname_length) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "embedded null character");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
files = args[1];
|
|
||||||
return_value = _msi_FCICreate_impl(module, cabname, files);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Database_Close__doc__,
|
|
||||||
"Close($self, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Close the database object.");
|
|
||||||
|
|
||||||
#define _MSI_DATABASE_CLOSE_METHODDEF \
|
|
||||||
{"Close", (PyCFunction)_msi_Database_Close, METH_NOARGS, _msi_Database_Close__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Database_Close_impl(msiobj *self);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Database_Close(msiobj *self, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return _msi_Database_Close_impl(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Record_GetFieldCount__doc__,
|
|
||||||
"GetFieldCount($self, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return the number of fields of the record.");
|
|
||||||
|
|
||||||
#define _MSI_RECORD_GETFIELDCOUNT_METHODDEF \
|
|
||||||
{"GetFieldCount", (PyCFunction)_msi_Record_GetFieldCount, METH_NOARGS, _msi_Record_GetFieldCount__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_GetFieldCount_impl(msiobj *self);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_GetFieldCount(msiobj *self, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return _msi_Record_GetFieldCount_impl(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Record_GetInteger__doc__,
|
|
||||||
"GetInteger($self, field, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return the value of field as an integer where possible.");
|
|
||||||
|
|
||||||
#define _MSI_RECORD_GETINTEGER_METHODDEF \
|
|
||||||
{"GetInteger", (PyCFunction)_msi_Record_GetInteger, METH_O, _msi_Record_GetInteger__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_GetInteger_impl(msiobj *self, unsigned int field);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_GetInteger(msiobj *self, PyObject *arg)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
unsigned int field;
|
|
||||||
|
|
||||||
field = (unsigned int)PyLong_AsUnsignedLongMask(arg);
|
|
||||||
if (field == (unsigned int)-1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_Record_GetInteger_impl(self, field);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Record_GetString__doc__,
|
|
||||||
"GetString($self, field, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return the value of field as a string where possible.");
|
|
||||||
|
|
||||||
#define _MSI_RECORD_GETSTRING_METHODDEF \
|
|
||||||
{"GetString", (PyCFunction)_msi_Record_GetString, METH_O, _msi_Record_GetString__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_GetString_impl(msiobj *self, unsigned int field);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_GetString(msiobj *self, PyObject *arg)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
unsigned int field;
|
|
||||||
|
|
||||||
field = (unsigned int)PyLong_AsUnsignedLongMask(arg);
|
|
||||||
if (field == (unsigned int)-1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_Record_GetString_impl(self, field);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Record_ClearData__doc__,
|
|
||||||
"ClearData($self, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Set all fields of the record to 0.");
|
|
||||||
|
|
||||||
#define _MSI_RECORD_CLEARDATA_METHODDEF \
|
|
||||||
{"ClearData", (PyCFunction)_msi_Record_ClearData, METH_NOARGS, _msi_Record_ClearData__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_ClearData_impl(msiobj *self);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_ClearData(msiobj *self, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return _msi_Record_ClearData_impl(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Record_SetString__doc__,
|
|
||||||
"SetString($self, field, value, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Set field to a string value.");
|
|
||||||
|
|
||||||
#define _MSI_RECORD_SETSTRING_METHODDEF \
|
|
||||||
{"SetString", _PyCFunction_CAST(_msi_Record_SetString), METH_FASTCALL, _msi_Record_SetString__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_SetString_impl(msiobj *self, int field, const Py_UNICODE *value);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_SetString(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
int field;
|
|
||||||
const Py_UNICODE *value = NULL;
|
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("SetString", nargs, 2, 2)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
field = _PyLong_AsInt(args[0]);
|
|
||||||
if (field == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
if (!PyUnicode_Check(args[1])) {
|
|
||||||
_PyArg_BadArgument("SetString", "argument 2", "str", args[1]);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
value = PyUnicode_AsWideCharString(args[1], NULL);
|
|
||||||
if (value == NULL) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_Record_SetString_impl(self, field, value);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
/* Cleanup for value */
|
|
||||||
PyMem_Free((void *)value);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Record_SetStream__doc__,
|
|
||||||
"SetStream($self, field, value, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Set field to the contents of the file named value.");
|
|
||||||
|
|
||||||
#define _MSI_RECORD_SETSTREAM_METHODDEF \
|
|
||||||
{"SetStream", _PyCFunction_CAST(_msi_Record_SetStream), METH_FASTCALL, _msi_Record_SetStream__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_SetStream_impl(msiobj *self, int field, const Py_UNICODE *value);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_SetStream(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
int field;
|
|
||||||
const Py_UNICODE *value = NULL;
|
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("SetStream", nargs, 2, 2)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
field = _PyLong_AsInt(args[0]);
|
|
||||||
if (field == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
if (!PyUnicode_Check(args[1])) {
|
|
||||||
_PyArg_BadArgument("SetStream", "argument 2", "str", args[1]);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
value = PyUnicode_AsWideCharString(args[1], NULL);
|
|
||||||
if (value == NULL) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_Record_SetStream_impl(self, field, value);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
/* Cleanup for value */
|
|
||||||
PyMem_Free((void *)value);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Record_SetInteger__doc__,
|
|
||||||
"SetInteger($self, field, value, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Set field to an integer value.");
|
|
||||||
|
|
||||||
#define _MSI_RECORD_SETINTEGER_METHODDEF \
|
|
||||||
{"SetInteger", _PyCFunction_CAST(_msi_Record_SetInteger), METH_FASTCALL, _msi_Record_SetInteger__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_SetInteger_impl(msiobj *self, int field, int value);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Record_SetInteger(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
int field;
|
|
||||||
int value;
|
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("SetInteger", nargs, 2, 2)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
field = _PyLong_AsInt(args[0]);
|
|
||||||
if (field == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
value = _PyLong_AsInt(args[1]);
|
|
||||||
if (value == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_Record_SetInteger_impl(self, field, value);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_SummaryInformation_GetProperty__doc__,
|
|
||||||
"GetProperty($self, field, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return a property of the summary.\n"
|
|
||||||
"\n"
|
|
||||||
" field\n"
|
|
||||||
" the name of the property, one of the PID_* constants");
|
|
||||||
|
|
||||||
#define _MSI_SUMMARYINFORMATION_GETPROPERTY_METHODDEF \
|
|
||||||
{"GetProperty", (PyCFunction)_msi_SummaryInformation_GetProperty, METH_O, _msi_SummaryInformation_GetProperty__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_SummaryInformation_GetProperty_impl(msiobj *self, int field);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_SummaryInformation_GetProperty(msiobj *self, PyObject *arg)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
int field;
|
|
||||||
|
|
||||||
field = _PyLong_AsInt(arg);
|
|
||||||
if (field == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_SummaryInformation_GetProperty_impl(self, field);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_SummaryInformation_GetPropertyCount__doc__,
|
|
||||||
"GetPropertyCount($self, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return the number of summary properties.");
|
|
||||||
|
|
||||||
#define _MSI_SUMMARYINFORMATION_GETPROPERTYCOUNT_METHODDEF \
|
|
||||||
{"GetPropertyCount", (PyCFunction)_msi_SummaryInformation_GetPropertyCount, METH_NOARGS, _msi_SummaryInformation_GetPropertyCount__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_SummaryInformation_GetPropertyCount_impl(msiobj *self);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_SummaryInformation_GetPropertyCount(msiobj *self, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return _msi_SummaryInformation_GetPropertyCount_impl(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_SummaryInformation_SetProperty__doc__,
|
|
||||||
"SetProperty($self, field, value, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Set a property.\n"
|
|
||||||
"\n"
|
|
||||||
" field\n"
|
|
||||||
" the name of the property, one of the PID_* constants\n"
|
|
||||||
" value\n"
|
|
||||||
" the new value of the property (integer or string)");
|
|
||||||
|
|
||||||
#define _MSI_SUMMARYINFORMATION_SETPROPERTY_METHODDEF \
|
|
||||||
{"SetProperty", _PyCFunction_CAST(_msi_SummaryInformation_SetProperty), METH_FASTCALL, _msi_SummaryInformation_SetProperty__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_SummaryInformation_SetProperty_impl(msiobj *self, int field,
|
|
||||||
PyObject *data);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_SummaryInformation_SetProperty(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
int field;
|
|
||||||
PyObject *data;
|
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("SetProperty", nargs, 2, 2)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
field = _PyLong_AsInt(args[0]);
|
|
||||||
if (field == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
data = args[1];
|
|
||||||
return_value = _msi_SummaryInformation_SetProperty_impl(self, field, data);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_SummaryInformation_Persist__doc__,
|
|
||||||
"Persist($self, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Write the modified properties to the summary information stream.");
|
|
||||||
|
|
||||||
#define _MSI_SUMMARYINFORMATION_PERSIST_METHODDEF \
|
|
||||||
{"Persist", (PyCFunction)_msi_SummaryInformation_Persist, METH_NOARGS, _msi_SummaryInformation_Persist__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_SummaryInformation_Persist_impl(msiobj *self);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_SummaryInformation_Persist(msiobj *self, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return _msi_SummaryInformation_Persist_impl(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_View_Execute__doc__,
|
|
||||||
"Execute($self, params, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Execute the SQL query of the view.\n"
|
|
||||||
"\n"
|
|
||||||
" params\n"
|
|
||||||
" a record describing actual values of the parameter tokens\n"
|
|
||||||
" in the query or None");
|
|
||||||
|
|
||||||
#define _MSI_VIEW_EXECUTE_METHODDEF \
|
|
||||||
{"Execute", (PyCFunction)_msi_View_Execute, METH_O, _msi_View_Execute__doc__},
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_View_Fetch__doc__,
|
|
||||||
"Fetch($self, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return a result record of the query.");
|
|
||||||
|
|
||||||
#define _MSI_VIEW_FETCH_METHODDEF \
|
|
||||||
{"Fetch", (PyCFunction)_msi_View_Fetch, METH_NOARGS, _msi_View_Fetch__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_View_Fetch_impl(msiobj *self);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_View_Fetch(msiobj *self, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return _msi_View_Fetch_impl(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_View_GetColumnInfo__doc__,
|
|
||||||
"GetColumnInfo($self, kind, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return a record describing the columns of the view.\n"
|
|
||||||
"\n"
|
|
||||||
" kind\n"
|
|
||||||
" MSICOLINFO_NAMES or MSICOLINFO_TYPES");
|
|
||||||
|
|
||||||
#define _MSI_VIEW_GETCOLUMNINFO_METHODDEF \
|
|
||||||
{"GetColumnInfo", (PyCFunction)_msi_View_GetColumnInfo, METH_O, _msi_View_GetColumnInfo__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_View_GetColumnInfo_impl(msiobj *self, int kind);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_View_GetColumnInfo(msiobj *self, PyObject *arg)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
int kind;
|
|
||||||
|
|
||||||
kind = _PyLong_AsInt(arg);
|
|
||||||
if (kind == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_View_GetColumnInfo_impl(self, kind);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_View_Modify__doc__,
|
|
||||||
"Modify($self, kind, data, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Modify the view.\n"
|
|
||||||
"\n"
|
|
||||||
" kind\n"
|
|
||||||
" one of the MSIMODIFY_* constants\n"
|
|
||||||
" data\n"
|
|
||||||
" a record describing the new data");
|
|
||||||
|
|
||||||
#define _MSI_VIEW_MODIFY_METHODDEF \
|
|
||||||
{"Modify", _PyCFunction_CAST(_msi_View_Modify), METH_FASTCALL, _msi_View_Modify__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_View_Modify_impl(msiobj *self, int kind, PyObject *data);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_View_Modify(msiobj *self, PyObject *const *args, Py_ssize_t nargs)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
int kind;
|
|
||||||
PyObject *data;
|
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("Modify", nargs, 2, 2)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
kind = _PyLong_AsInt(args[0]);
|
|
||||||
if (kind == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
data = args[1];
|
|
||||||
return_value = _msi_View_Modify_impl(self, kind, data);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_View_Close__doc__,
|
|
||||||
"Close($self, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Close the view.");
|
|
||||||
|
|
||||||
#define _MSI_VIEW_CLOSE_METHODDEF \
|
|
||||||
{"Close", (PyCFunction)_msi_View_Close, METH_NOARGS, _msi_View_Close__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_View_Close_impl(msiobj *self);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_View_Close(msiobj *self, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return _msi_View_Close_impl(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Database_OpenView__doc__,
|
|
||||||
"OpenView($self, sql, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return a view object.\n"
|
|
||||||
"\n"
|
|
||||||
" sql\n"
|
|
||||||
" the SQL statement to execute");
|
|
||||||
|
|
||||||
#define _MSI_DATABASE_OPENVIEW_METHODDEF \
|
|
||||||
{"OpenView", (PyCFunction)_msi_Database_OpenView, METH_O, _msi_Database_OpenView__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Database_OpenView_impl(msiobj *self, const Py_UNICODE *sql);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Database_OpenView(msiobj *self, PyObject *arg)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
const Py_UNICODE *sql = NULL;
|
|
||||||
|
|
||||||
if (!PyUnicode_Check(arg)) {
|
|
||||||
_PyArg_BadArgument("OpenView", "argument", "str", arg);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
sql = PyUnicode_AsWideCharString(arg, NULL);
|
|
||||||
if (sql == NULL) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_Database_OpenView_impl(self, sql);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
/* Cleanup for sql */
|
|
||||||
PyMem_Free((void *)sql);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Database_Commit__doc__,
|
|
||||||
"Commit($self, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Commit the changes pending in the current transaction.");
|
|
||||||
|
|
||||||
#define _MSI_DATABASE_COMMIT_METHODDEF \
|
|
||||||
{"Commit", (PyCFunction)_msi_Database_Commit, METH_NOARGS, _msi_Database_Commit__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Database_Commit_impl(msiobj *self);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Database_Commit(msiobj *self, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return _msi_Database_Commit_impl(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_Database_GetSummaryInformation__doc__,
|
|
||||||
"GetSummaryInformation($self, count, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return a new summary information object.\n"
|
|
||||||
"\n"
|
|
||||||
" count\n"
|
|
||||||
" the maximum number of updated values");
|
|
||||||
|
|
||||||
#define _MSI_DATABASE_GETSUMMARYINFORMATION_METHODDEF \
|
|
||||||
{"GetSummaryInformation", (PyCFunction)_msi_Database_GetSummaryInformation, METH_O, _msi_Database_GetSummaryInformation__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Database_GetSummaryInformation_impl(msiobj *self, int count);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_Database_GetSummaryInformation(msiobj *self, PyObject *arg)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
count = _PyLong_AsInt(arg);
|
|
||||||
if (count == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_Database_GetSummaryInformation_impl(self, count);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_OpenDatabase__doc__,
|
|
||||||
"OpenDatabase($module, path, persist, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return a new database object.\n"
|
|
||||||
"\n"
|
|
||||||
" path\n"
|
|
||||||
" the file name of the MSI file\n"
|
|
||||||
" persist\n"
|
|
||||||
" the persistence mode");
|
|
||||||
|
|
||||||
#define _MSI_OPENDATABASE_METHODDEF \
|
|
||||||
{"OpenDatabase", _PyCFunction_CAST(_msi_OpenDatabase), METH_FASTCALL, _msi_OpenDatabase__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_OpenDatabase_impl(PyObject *module, const Py_UNICODE *path, int persist);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_OpenDatabase(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
const Py_UNICODE *path = NULL;
|
|
||||||
int persist;
|
|
||||||
|
|
||||||
if (!_PyArg_CheckPositional("OpenDatabase", nargs, 2, 2)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
if (!PyUnicode_Check(args[0])) {
|
|
||||||
_PyArg_BadArgument("OpenDatabase", "argument 1", "str", args[0]);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
path = PyUnicode_AsWideCharString(args[0], NULL);
|
|
||||||
if (path == NULL) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
persist = _PyLong_AsInt(args[1]);
|
|
||||||
if (persist == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_OpenDatabase_impl(module, path, persist);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
/* Cleanup for path */
|
|
||||||
PyMem_Free((void *)path);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_msi_CreateRecord__doc__,
|
|
||||||
"CreateRecord($module, count, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Return a new record object.\n"
|
|
||||||
"\n"
|
|
||||||
" count\n"
|
|
||||||
" the number of fields of the record");
|
|
||||||
|
|
||||||
#define _MSI_CREATERECORD_METHODDEF \
|
|
||||||
{"CreateRecord", (PyCFunction)_msi_CreateRecord, METH_O, _msi_CreateRecord__doc__},
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_CreateRecord_impl(PyObject *module, int count);
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
_msi_CreateRecord(PyObject *module, PyObject *arg)
|
|
||||||
{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
count = _PyLong_AsInt(arg);
|
|
||||||
if (count == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _msi_CreateRecord_impl(module, count);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
/*[clinic end generated code: output=7d083c61679eed83 input=a9049054013a1b77]*/
|
|
|
@ -1,115 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|ARM">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>ARM</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|ARM64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>ARM64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="PGInstrument|ARM">
|
|
||||||
<Configuration>PGInstrument</Configuration>
|
|
||||||
<Platform>ARM</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="PGInstrument|ARM64">
|
|
||||||
<Configuration>PGInstrument</Configuration>
|
|
||||||
<Platform>ARM4</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="PGInstrument|Win32">
|
|
||||||
<Configuration>PGInstrument</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="PGInstrument|x64">
|
|
||||||
<Configuration>PGInstrument</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="PGUpdate|ARM">
|
|
||||||
<Configuration>PGUpdate</Configuration>
|
|
||||||
<Platform>ARM</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="PGUpdate|ARM64">
|
|
||||||
<Configuration>PGUpdate</Configuration>
|
|
||||||
<Platform>ARM64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="PGUpdate|Win32">
|
|
||||||
<Configuration>PGUpdate</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="PGUpdate|x64">
|
|
||||||
<Configuration>PGUpdate</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|ARM">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>ARM</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|ARM64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>ARM64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{31FFC478-7B4A-43E8-9954-8D03E2187E9C}</ProjectGuid>
|
|
||||||
<RootNamespace>_msi</RootNamespace>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
<SupportPGO>false</SupportPGO>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="python.props" />
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<CharacterSet>NotSet</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetExt>.pyd</TargetExt>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
<Import Project="pyproject.props" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>cabinet.lib;msi.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\PC\_msi.c" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="..\PC\python_nt.rc" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="pythoncore.vcxproj">
|
|
||||||
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
|
|
||||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="Source Files">
|
|
||||||
<UniqueIdentifier>{bdef7710-e433-4ac0-84e0-14f34454bd3e}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Resource Files">
|
|
||||||
<UniqueIdentifier>{8513f324-7c13-4657-b463-5d686a8a5371}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="..\PC\_msi.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ResourceCompile Include="..\PC\python_nt.rc">
|
|
||||||
<Filter>Resource Files</Filter>
|
|
||||||
</ResourceCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
|
@ -64,7 +64,7 @@
|
||||||
<!-- pyshellext.dll -->
|
<!-- pyshellext.dll -->
|
||||||
<Projects Include="pyshellext.vcxproj" />
|
<Projects Include="pyshellext.vcxproj" />
|
||||||
<!-- Extension modules -->
|
<!-- Extension modules -->
|
||||||
<ExtensionModules Include="_asyncio;_zoneinfo;_decimal;_elementtree;_msi;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound;_uuid;_wmi" />
|
<ExtensionModules Include="_asyncio;_zoneinfo;_decimal;_elementtree;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound;_uuid;_wmi" />
|
||||||
<ExtensionModules Include="_ctypes" Condition="$(IncludeCTypes)" />
|
<ExtensionModules Include="_ctypes" Condition="$(IncludeCTypes)" />
|
||||||
<!-- Extension modules that require external sources -->
|
<!-- Extension modules that require external sources -->
|
||||||
<ExternalModules Include="_bz2;_lzma;_sqlite3" />
|
<ExternalModules Include="_bz2;_lzma;_sqlite3" />
|
||||||
|
|
|
@ -68,8 +68,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ctypes_test", "_ctypes_tes
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_elementtree", "_elementtree.vcxproj", "{17E1E049-C309-4D79-843F-AE483C264AEA}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_elementtree", "_elementtree.vcxproj", "{17E1E049-C309-4D79-843F-AE483C264AEA}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_msi", "_msi.vcxproj", "{31FFC478-7B4A-43E8-9954-8D03E2187E9C}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_socket", "_socket.vcxproj", "{86937F53-C189-40EF-8CE8-8759D8E7D480}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_socket", "_socket.vcxproj", "{86937F53-C189-40EF-8CE8-8759D8E7D480}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_sqlite3", "_sqlite3.vcxproj", "{13CECB97-4119-4316-9D42-8534019A5A44}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_sqlite3", "_sqlite3.vcxproj", "{13CECB97-4119-4316-9D42-8534019A5A44}"
|
||||||
|
|
|
@ -138,7 +138,6 @@ _zoneinfo
|
||||||
_decimal
|
_decimal
|
||||||
_elementtree
|
_elementtree
|
||||||
_hashlib
|
_hashlib
|
||||||
_msi
|
|
||||||
_multiprocessing
|
_multiprocessing
|
||||||
_overlapped
|
_overlapped
|
||||||
_socket
|
_socket
|
||||||
|
|
|
@ -45,7 +45,6 @@ static const char* _Py_stdlib_module_names[] = {
|
||||||
"_lzma",
|
"_lzma",
|
||||||
"_markupbase",
|
"_markupbase",
|
||||||
"_md5",
|
"_md5",
|
||||||
"_msi",
|
|
||||||
"_multibytecodec",
|
"_multibytecodec",
|
||||||
"_multiprocessing",
|
"_multiprocessing",
|
||||||
"_opcode",
|
"_opcode",
|
||||||
|
@ -180,7 +179,6 @@ static const char* _Py_stdlib_module_names[] = {
|
||||||
"mimetypes",
|
"mimetypes",
|
||||||
"mmap",
|
"mmap",
|
||||||
"modulefinder",
|
"modulefinder",
|
||||||
"msilib",
|
|
||||||
"msvcrt",
|
"msvcrt",
|
||||||
"multiprocessing",
|
"multiprocessing",
|
||||||
"netrc",
|
"netrc",
|
||||||
|
|
|
@ -50,7 +50,6 @@ CORE_MODULES = {
|
||||||
|
|
||||||
# Windows-only modules
|
# Windows-only modules
|
||||||
WINDOWS_MODULES = {
|
WINDOWS_MODULES = {
|
||||||
"_msi",
|
|
||||||
"_overlapped",
|
"_overlapped",
|
||||||
"_testconsole",
|
"_testconsole",
|
||||||
"_winapi",
|
"_winapi",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||||
<?define exts=pyexpat;select;unicodedata;winsound;_bz2;_elementtree;_socket;_ssl;_msi;_ctypes;_hashlib;_multiprocessing;_lzma;_decimal;_overlapped;_sqlite3;_asyncio;_queue;_uuid;_wmi;_zoneinfo ?>
|
<?define exts=pyexpat;select;unicodedata;winsound;_bz2;_elementtree;_socket;_ssl;_ctypes;_hashlib;_multiprocessing;_lzma;_decimal;_overlapped;_sqlite3;_asyncio;_queue;_uuid;_wmi;_zoneinfo ?>
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<DirectoryRef Id="Lib_venv_scripts_nt" />
|
<DirectoryRef Id="Lib_venv_scripts_nt" />
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ OMIT_FILES = (
|
||||||
"concurrent/futures/thread.py",
|
"concurrent/futures/thread.py",
|
||||||
# Misc unused or large files
|
# Misc unused or large files
|
||||||
"pydoc_data/",
|
"pydoc_data/",
|
||||||
"msilib/",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Synchronous network I/O and protocols are not supported; for example,
|
# Synchronous network I/O and protocols are not supported; for example,
|
||||||
|
|
Loading…
Reference in New Issue