1 /* Helper library for MSI creation with Python.
2 * Copyright (C) 2005 Martin v. Löwis
3 * Licensed to PSF under a contributor agreement.
15 static PyObject
*MSIError
;
18 uuidcreate(PyObject
* obj
, PyObject
*args
)
24 /* May return ok, local only, and no address.
25 For local only, the documentation says we still get a uuid.
26 For RPC_S_UUID_NO_ADDRESS, it's not clear whether we can
28 if (UuidCreate(&result
) == RPC_S_UUID_NO_ADDRESS
) {
29 PyErr_SetString(PyExc_NotImplementedError
, "processing 'no address' result");
33 if (UuidToString(&result
, &cresult
) == RPC_S_OUT_OF_MEMORY
) {
34 PyErr_SetString(PyExc_MemoryError
, "out of memory in uuidgen");
38 oresult
= PyString_FromString(cresult
);
39 RpcStringFree(&cresult
);
44 /* FCI callback functions */
46 static FNFCIALLOC(cb_alloc
)
51 static FNFCIFREE(cb_free
)
56 static FNFCIOPEN(cb_open
)
58 int result
= _open(pszFile
, oflag
, pmode
);
64 static FNFCIREAD(cb_read
)
66 UINT result
= (UINT
)_read(hf
, memory
, cb
);
72 static FNFCIWRITE(cb_write
)
74 UINT result
= (UINT
)_write(hf
, memory
, cb
);
80 static FNFCICLOSE(cb_close
)
82 int result
= _close(hf
);
88 static FNFCISEEK(cb_seek
)
90 long result
= (long)_lseek(hf
, dist
, seektype
);
96 static FNFCIDELETE(cb_delete
)
98 int result
= remove(pszFile
);
104 static FNFCIFILEPLACED(cb_fileplaced
)
109 static FNFCIGETTEMPFILE(cb_gettempfile
)
111 char *name
= _tempnam("", "tmp");
112 if ((name
!= NULL
) && ((int)strlen(name
) < cbTempName
)) {
113 strcpy(pszTempName
, name
);
118 if (name
) free(name
);
122 static FNFCISTATUS(cb_status
)
125 PyObject
*result
= PyObject_CallMethod(pv
, "status", "iii", typeStatus
, cb1
, cb2
);
133 static FNFCIGETNEXTCABINET(cb_getnextcabinet
)
136 PyObject
*result
= PyObject_CallMethod(pv
, "getnextcabinet", "i", pccab
->iCab
);
139 if (!PyString_Check(result
)) {
140 PyErr_Format(PyExc_TypeError
,
141 "Incorrect return type %s from getnextcabinet",
142 result
->ob_type
->tp_name
);
146 strncpy(pccab
->szCab
, PyString_AsString(result
), sizeof(pccab
->szCab
));
152 static FNFCIGETOPENINFO(cb_getopeninfo
)
154 BY_HANDLE_FILE_INFORMATION bhfi
;
158 /* Need Win32 handle to get time stamps */
159 handle
= CreateFile(pszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
160 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
161 if (handle
== INVALID_HANDLE_VALUE
)
164 if (GetFileInformationByHandle(handle
, &bhfi
) == FALSE
)
170 FileTimeToLocalFileTime(&bhfi
.ftLastWriteTime
, &filetime
);
171 FileTimeToDosDateTime(&filetime
, pdate
, ptime
);
173 *pattribs
= (int)(bhfi
.dwFileAttributes
&
174 (_A_RDONLY
| _A_SYSTEM
| _A_HIDDEN
| _A_ARCH
));
178 return _open(pszName
, _O_RDONLY
| _O_BINARY
);
181 static PyObject
* fcicreate(PyObject
* obj
, PyObject
* args
)
191 if (!PyArg_ParseTuple(args
, "sO:FCICreate", &cabname
, &files
))
194 if (!PyList_Check(files
)) {
195 PyErr_SetString(PyExc_TypeError
, "FCICreate expects a list");
199 ccab
.cb
= INT_MAX
; /* no need to split CAB into multiple media */
200 ccab
.cbFolderThresh
= 1000000; /* flush directory after this many bytes */
201 ccab
.cbReserveCFData
= 0;
202 ccab
.cbReserveCFFolder
= 0;
203 ccab
.cbReserveCFHeader
= 0;
209 ccab
.szDisk
[0] = '\0';
211 for (i
= 0, p
= cabname
; *p
; p
= CharNext(p
))
212 if (*p
== '\\' || *p
== '/')
215 if (i
>= sizeof(ccab
.szCabPath
) ||
216 strlen(cabname
+i
) >= sizeof(ccab
.szCab
)) {
217 PyErr_SetString(PyExc_ValueError
, "path name too long");
222 memcpy(ccab
.szCabPath
, cabname
, i
);
223 ccab
.szCabPath
[i
] = '\0';
224 strcpy(ccab
.szCab
, cabname
+i
);
226 strcpy(ccab
.szCabPath
, ".\\");
227 strcpy(ccab
.szCab
, cabname
);
230 hfci
= FCICreate(&erf
, cb_fileplaced
, cb_alloc
, cb_free
,
231 cb_open
, cb_read
, cb_write
, cb_close
, cb_seek
, cb_delete
,
232 cb_gettempfile
, &ccab
, NULL
);
235 PyErr_Format(PyExc_ValueError
, "FCI error %d", erf
.erfOper
);
239 for (i
=0; i
< PyList_GET_SIZE(files
); i
++) {
240 PyObject
*item
= PyList_GET_ITEM(files
, i
);
241 char *filename
, *cabname
;
242 if (!PyArg_ParseTuple(item
, "ss", &filename
, &cabname
))
244 if (!FCIAddFile(hfci
, filename
, cabname
, FALSE
,
245 cb_getnextcabinet
, cb_status
, cb_getopeninfo
,
250 if (!FCIFlushCabinet(hfci
, FALSE
, cb_getnextcabinet
, cb_status
))
253 if (!FCIDestroy(hfci
))
259 PyErr_Format(PyExc_ValueError
, "FCI error %d", erf
.erfOper
); /* XXX better error type */
264 typedef struct msiobj
{
270 msiobj_dealloc(msiobj
* msidb
)
272 MsiCloseHandle(msidb
->h
);
277 msiobj_close(msiobj
* msidb
, PyObject
*args
)
279 MsiCloseHandle(msidb
->h
);
291 DWORD size
= sizeof(buf
);
292 MSIHANDLE err
= MsiGetLastErrorRecord();
296 case ERROR_ACCESS_DENIED
:
297 PyErr_SetString(MSIError
, "access denied");
299 case ERROR_FUNCTION_FAILED
:
300 PyErr_SetString(MSIError
, "function failed");
302 case ERROR_INVALID_DATA
:
303 PyErr_SetString(MSIError
, "invalid data");
305 case ERROR_INVALID_HANDLE
:
306 PyErr_SetString(MSIError
, "invalid handle");
308 case ERROR_INVALID_STATE
:
309 PyErr_SetString(MSIError
, "invalid state");
311 case ERROR_INVALID_PARAMETER
:
312 PyErr_SetString(MSIError
, "invalid parameter");
315 PyErr_Format(MSIError
, "unknown error %x", status
);
320 code
= MsiRecordGetInteger(err
, 1); /* XXX code */
321 if (MsiFormatRecord(0, err
, res
, &size
) == ERROR_MORE_DATA
) {
322 res
= malloc(size
+1);
323 MsiFormatRecord(0, err
, res
, &size
);
327 PyErr_SetString(MSIError
, res
);
333 /*************************** Record objects **********************/
336 record_getfieldcount(msiobj
* record
, PyObject
* args
)
338 return PyInt_FromLong(MsiRecordGetFieldCount(record
->h
));
342 record_getinteger(msiobj
* record
, PyObject
* args
)
347 if (!PyArg_ParseTuple(args
, "I:GetInteger", &field
))
349 status
= MsiRecordGetInteger(record
->h
, field
);
350 if (status
== MSI_NULL_INTEGER
){
351 PyErr_SetString(MSIError
, "could not convert record field to integer");
354 return PyInt_FromLong((long) status
);
358 record_getstring(msiobj
* record
, PyObject
* args
)
364 DWORD size
= sizeof(buf
);
367 if (!PyArg_ParseTuple(args
, "I:GetString", &field
))
369 status
= MsiRecordGetString(record
->h
, field
, res
, &size
);
370 if (status
== ERROR_MORE_DATA
) {
371 res
= (char*) malloc(size
+ 1);
373 return PyErr_NoMemory();
374 status
= MsiRecordGetString(record
->h
, field
, res
, &size
);
376 if (status
!= ERROR_SUCCESS
)
377 return msierror((int) status
);
378 string
= PyString_FromString(res
);
385 record_cleardata(msiobj
* record
, PyObject
*args
)
387 int status
= MsiRecordClearData(record
->h
);
388 if (status
!= ERROR_SUCCESS
)
389 return msierror(status
);
396 record_setstring(msiobj
* record
, PyObject
*args
)
402 if (!PyArg_ParseTuple(args
, "is:SetString", &field
, &data
))
405 if ((status
= MsiRecordSetString(record
->h
, field
, data
)) != ERROR_SUCCESS
)
406 return msierror(status
);
413 record_setstream(msiobj
* record
, PyObject
*args
)
419 if (!PyArg_ParseTuple(args
, "is:SetStream", &field
, &data
))
422 if ((status
= MsiRecordSetStream(record
->h
, field
, data
)) != ERROR_SUCCESS
)
423 return msierror(status
);
430 record_setinteger(msiobj
* record
, PyObject
*args
)
436 if (!PyArg_ParseTuple(args
, "ii:SetInteger", &field
, &data
))
439 if ((status
= MsiRecordSetInteger(record
->h
, field
, data
)) != ERROR_SUCCESS
)
440 return msierror(status
);
448 static PyMethodDef record_methods
[] = {
449 { "GetFieldCount", (PyCFunction
)record_getfieldcount
, METH_NOARGS
,
450 PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")},
451 { "GetInteger", (PyCFunction
)record_getinteger
, METH_VARARGS
,
452 PyDoc_STR("GetInteger(field) -> int\nWraps MsiRecordGetInteger")},
453 { "GetString", (PyCFunction
)record_getstring
, METH_VARARGS
,
454 PyDoc_STR("GetString(field) -> string\nWraps MsiRecordGetString")},
455 { "SetString", (PyCFunction
)record_setstring
, METH_VARARGS
,
456 PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")},
457 { "SetStream", (PyCFunction
)record_setstream
, METH_VARARGS
,
458 PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")},
459 { "SetInteger", (PyCFunction
)record_setinteger
, METH_VARARGS
,
460 PyDoc_STR("SetInteger(field,int) -> None\nWraps MsiRecordSetInteger")},
461 { "ClearData", (PyCFunction
)record_cleardata
, METH_NOARGS
,
462 PyDoc_STR("ClearData() -> int\nWraps MsiRecordGClearData")},
466 static PyTypeObject record_Type
= {
467 PyVarObject_HEAD_INIT(NULL
, 0)
468 "_msi.Record", /*tp_name*/
469 sizeof(msiobj
), /*tp_basicsize*/
472 (destructor
)msiobj_dealloc
, /*tp_dealloc*/
479 0, /*tp_as_sequence*/
484 PyObject_GenericGetAttr
,/*tp_getattro*/
485 PyObject_GenericSetAttr
,/*tp_setattro*/
487 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
491 0, /*tp_richcompare*/
492 0, /*tp_weaklistoffset*/
495 record_methods
, /*tp_methods*/
511 record_new(MSIHANDLE h
)
513 msiobj
*result
= PyObject_NEW(struct msiobj
, &record_Type
);
521 return (PyObject
*)result
;
524 /*************************** SummaryInformation objects **************/
527 summary_getproperty(msiobj
* si
, PyObject
*args
)
537 DWORD ssize
= sizeof(sval
);
539 if (!PyArg_ParseTuple(args
, "i:GetProperty", &field
))
542 status
= MsiSummaryInfoGetProperty(si
->h
, field
, &type
, &ival
,
543 &fval
, sval
, &ssize
);
544 if (status
== ERROR_MORE_DATA
) {
545 sval
= malloc(ssize
);
546 status
= MsiSummaryInfoGetProperty(si
->h
, field
, &type
, &ival
,
547 &fval
, sval
, &ssize
);
551 case VT_I2
: case VT_I4
:
552 return PyInt_FromLong(ival
);
554 PyErr_SetString(PyExc_NotImplementedError
, "FILETIME result");
557 result
= PyString_FromStringAndSize(sval
, ssize
);
562 PyErr_Format(PyExc_NotImplementedError
, "result of type %d", type
);
567 summary_getpropertycount(msiobj
* si
, PyObject
*args
)
572 status
= MsiSummaryInfoGetPropertyCount(si
->h
, &result
);
573 if (status
!= ERROR_SUCCESS
)
574 return msierror(status
);
576 return PyInt_FromLong(result
);
580 summary_setproperty(msiobj
* si
, PyObject
*args
)
586 if (!PyArg_ParseTuple(args
, "iO:SetProperty", &field
, &data
))
589 if (PyString_Check(data
)) {
590 status
= MsiSummaryInfoSetProperty(si
->h
, field
, VT_LPSTR
,
591 0, NULL
, PyString_AsString(data
));
592 } else if (PyInt_Check(data
)) {
593 status
= MsiSummaryInfoSetProperty(si
->h
, field
, VT_I4
,
594 PyInt_AsLong(data
), NULL
, NULL
);
596 PyErr_SetString(PyExc_TypeError
, "unsupported type");
600 if (status
!= ERROR_SUCCESS
)
601 return msierror(status
);
609 summary_persist(msiobj
* si
, PyObject
*args
)
613 status
= MsiSummaryInfoPersist(si
->h
);
614 if (status
!= ERROR_SUCCESS
)
615 return msierror(status
);
620 static PyMethodDef summary_methods
[] = {
621 { "GetProperty", (PyCFunction
)summary_getproperty
, METH_VARARGS
,
622 PyDoc_STR("GetProperty(propid) -> value\nWraps MsiSummaryInfoGetProperty")},
623 { "GetPropertyCount", (PyCFunction
)summary_getpropertycount
, METH_NOARGS
,
624 PyDoc_STR("GetProperty() -> int\nWraps MsiSummaryInfoGetPropertyCount")},
625 { "SetProperty", (PyCFunction
)summary_setproperty
, METH_VARARGS
,
626 PyDoc_STR("SetProperty(value) -> None\nWraps MsiSummaryInfoProperty")},
627 { "Persist", (PyCFunction
)summary_persist
, METH_NOARGS
,
628 PyDoc_STR("Persist() -> None\nWraps MsiSummaryInfoPersist")},
632 static PyTypeObject summary_Type
= {
633 PyVarObject_HEAD_INIT(NULL
, 0)
634 "_msi.SummaryInformation", /*tp_name*/
635 sizeof(msiobj
), /*tp_basicsize*/
638 (destructor
)msiobj_dealloc
, /*tp_dealloc*/
645 0, /*tp_as_sequence*/
650 PyObject_GenericGetAttr
,/*tp_getattro*/
651 PyObject_GenericSetAttr
,/*tp_setattro*/
653 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
657 0, /*tp_richcompare*/
658 0, /*tp_weaklistoffset*/
661 summary_methods
, /*tp_methods*/
676 /*************************** View objects **************/
679 view_execute(msiobj
*view
, PyObject
*args
)
682 MSIHANDLE params
= 0;
683 PyObject
*oparams
= Py_None
;
685 if (!PyArg_ParseTuple(args
, "O:Execute", &oparams
))
688 if (oparams
!= Py_None
) {
689 if (oparams
->ob_type
!= &record_Type
) {
690 PyErr_SetString(PyExc_TypeError
, "Execute argument must be a record");
693 params
= ((msiobj
*)oparams
)->h
;
696 status
= MsiViewExecute(view
->h
, params
);
697 if (status
!= ERROR_SUCCESS
)
698 return msierror(status
);
705 view_fetch(msiobj
*view
, PyObject
*args
)
710 if ((status
= MsiViewFetch(view
->h
, &result
)) != ERROR_SUCCESS
)
711 return msierror(status
);
713 return record_new(result
);
717 view_getcolumninfo(msiobj
*view
, PyObject
*args
)
723 if (!PyArg_ParseTuple(args
, "i:GetColumnInfo", &kind
))
726 if ((status
= MsiViewGetColumnInfo(view
->h
, kind
, &result
)) != ERROR_SUCCESS
)
727 return msierror(status
);
729 return record_new(result
);
733 view_modify(msiobj
*view
, PyObject
*args
)
739 if (!PyArg_ParseTuple(args
, "iO:Modify", &kind
, &data
))
742 if (data
->ob_type
!= &record_Type
) {
743 PyErr_SetString(PyExc_TypeError
, "Modify expects a record object");
747 if ((status
= MsiViewModify(view
->h
, kind
, ((msiobj
*)data
)->h
)) != ERROR_SUCCESS
)
748 return msierror(status
);
755 view_close(msiobj
*view
, PyObject
*args
)
759 if ((status
= MsiViewClose(view
->h
)) != ERROR_SUCCESS
)
760 return msierror(status
);
766 static PyMethodDef view_methods
[] = {
767 { "Execute", (PyCFunction
)view_execute
, METH_VARARGS
,
768 PyDoc_STR("Execute(params=None) -> None\nWraps MsiViewExecute")},
769 { "GetColumnInfo", (PyCFunction
)view_getcolumninfo
, METH_VARARGS
,
770 PyDoc_STR("GetColumnInfo() -> result\nWraps MsiGetColumnInfo")},
771 { "Fetch", (PyCFunction
)view_fetch
, METH_NOARGS
,
772 PyDoc_STR("Fetch() -> result\nWraps MsiViewFetch")},
773 { "Modify", (PyCFunction
)view_modify
, METH_VARARGS
,
774 PyDoc_STR("Modify(mode,record) -> None\nWraps MsiViewModify")},
775 { "Close", (PyCFunction
)view_close
, METH_NOARGS
,
776 PyDoc_STR("Close() -> result\nWraps MsiViewClose")},
780 static PyTypeObject msiview_Type
= {
781 PyVarObject_HEAD_INIT(NULL
, 0)
782 "_msi.View", /*tp_name*/
783 sizeof(msiobj
), /*tp_basicsize*/
786 (destructor
)msiobj_dealloc
, /*tp_dealloc*/
793 0, /*tp_as_sequence*/
798 PyObject_GenericGetAttr
,/*tp_getattro*/
799 PyObject_GenericSetAttr
,/*tp_setattro*/
801 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
805 0, /*tp_richcompare*/
806 0, /*tp_weaklistoffset*/
809 view_methods
, /*tp_methods*/
824 /*************************** Database objects **************/
827 msidb_openview(msiobj
*msidb
, PyObject
*args
)
834 if (!PyArg_ParseTuple(args
, "s:OpenView", &sql
))
837 if ((status
= MsiDatabaseOpenView(msidb
->h
, sql
, &hView
)) != ERROR_SUCCESS
)
838 return msierror(status
);
840 result
= PyObject_NEW(struct msiobj
, &msiview_Type
);
842 MsiCloseHandle(hView
);
847 return (PyObject
*)result
;
851 msidb_commit(msiobj
*msidb
, PyObject
*args
)
855 if ((status
= MsiDatabaseCommit(msidb
->h
)) != ERROR_SUCCESS
)
856 return msierror(status
);
863 msidb_getsummaryinformation(msiobj
*db
, PyObject
*args
)
870 if (!PyArg_ParseTuple(args
, "i:GetSummaryInformation", &count
))
873 status
= MsiGetSummaryInformation(db
->h
, NULL
, count
, &result
);
874 if (status
!= ERROR_SUCCESS
)
875 return msierror(status
);
877 oresult
= PyObject_NEW(struct msiobj
, &summary_Type
);
879 MsiCloseHandle(result
);
884 return (PyObject
*)oresult
;
887 static PyMethodDef db_methods
[] = {
888 { "OpenView", (PyCFunction
)msidb_openview
, METH_VARARGS
,
889 PyDoc_STR("OpenView(sql) -> viewobj\nWraps MsiDatabaseOpenView")},
890 { "Commit", (PyCFunction
)msidb_commit
, METH_NOARGS
,
891 PyDoc_STR("Commit() -> None\nWraps MsiDatabaseCommit")},
892 { "GetSummaryInformation", (PyCFunction
)msidb_getsummaryinformation
, METH_VARARGS
,
893 PyDoc_STR("GetSummaryInformation(updateCount) -> viewobj\nWraps MsiGetSummaryInformation")},
897 static PyTypeObject msidb_Type
= {
898 PyVarObject_HEAD_INIT(NULL
, 0)
899 "_msi.Database", /*tp_name*/
900 sizeof(msiobj
), /*tp_basicsize*/
903 (destructor
)msiobj_dealloc
, /*tp_dealloc*/
910 0, /*tp_as_sequence*/
915 PyObject_GenericGetAttr
,/*tp_getattro*/
916 PyObject_GenericSetAttr
,/*tp_setattro*/
918 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
922 0, /*tp_richcompare*/
923 0, /*tp_weaklistoffset*/
926 db_methods
, /*tp_methods*/
941 static PyObject
* msiopendb(PyObject
*obj
, PyObject
*args
)
949 if (!PyArg_ParseTuple(args
, "si:MSIOpenDatabase", &path
, &persist
))
952 status
= MsiOpenDatabase(path
, (LPCSTR
)persist
, &h
);
953 if (status
!= ERROR_SUCCESS
)
954 return msierror(status
);
956 result
= PyObject_NEW(struct msiobj
, &msidb_Type
);
962 return (PyObject
*)result
;
966 createrecord(PyObject
*o
, PyObject
*args
)
971 if (!PyArg_ParseTuple(args
, "i:CreateRecord", &count
))
974 h
= MsiCreateRecord(count
);
978 return record_new(h
);
982 static PyMethodDef msi_methods
[] = {
983 {"UuidCreate", (PyCFunction
)uuidcreate
, METH_NOARGS
,
984 PyDoc_STR("UuidCreate() -> string")},
985 {"FCICreate", (PyCFunction
)fcicreate
, METH_VARARGS
,
986 PyDoc_STR("fcicreate(cabname,files) -> None")},
987 {"OpenDatabase", (PyCFunction
)msiopendb
, METH_VARARGS
,
988 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiOpenDatabase")},
989 {"CreateRecord", (PyCFunction
)createrecord
, METH_VARARGS
,
990 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiCreateRecord")},
991 {NULL
, NULL
} /* sentinel */
994 static char msi_doc
[] = "Documentation";
1001 m
= Py_InitModule3("_msi", msi_methods
, msi_doc
);
1005 PyModule_AddIntConstant(m
, "MSIDBOPEN_CREATEDIRECT", (int)MSIDBOPEN_CREATEDIRECT
);
1006 PyModule_AddIntConstant(m
, "MSIDBOPEN_CREATE", (int)MSIDBOPEN_CREATE
);
1007 PyModule_AddIntConstant(m
, "MSIDBOPEN_DIRECT", (int)MSIDBOPEN_DIRECT
);
1008 PyModule_AddIntConstant(m
, "MSIDBOPEN_READONLY", (int)MSIDBOPEN_READONLY
);
1009 PyModule_AddIntConstant(m
, "MSIDBOPEN_TRANSACT", (int)MSIDBOPEN_TRANSACT
);
1010 PyModule_AddIntConstant(m
, "MSIDBOPEN_PATCHFILE", (int)MSIDBOPEN_PATCHFILE
);
1012 PyModule_AddIntConstant(m
, "MSICOLINFO_NAMES", MSICOLINFO_NAMES
);
1013 PyModule_AddIntConstant(m
, "MSICOLINFO_TYPES", MSICOLINFO_TYPES
);
1015 PyModule_AddIntConstant(m
, "MSIMODIFY_SEEK", MSIMODIFY_SEEK
);
1016 PyModule_AddIntConstant(m
, "MSIMODIFY_REFRESH", MSIMODIFY_REFRESH
);
1017 PyModule_AddIntConstant(m
, "MSIMODIFY_INSERT", MSIMODIFY_INSERT
);
1018 PyModule_AddIntConstant(m
, "MSIMODIFY_UPDATE", MSIMODIFY_UPDATE
);
1019 PyModule_AddIntConstant(m
, "MSIMODIFY_ASSIGN", MSIMODIFY_ASSIGN
);
1020 PyModule_AddIntConstant(m
, "MSIMODIFY_REPLACE", MSIMODIFY_REPLACE
);
1021 PyModule_AddIntConstant(m
, "MSIMODIFY_MERGE", MSIMODIFY_MERGE
);
1022 PyModule_AddIntConstant(m
, "MSIMODIFY_DELETE", MSIMODIFY_DELETE
);
1023 PyModule_AddIntConstant(m
, "MSIMODIFY_INSERT_TEMPORARY", MSIMODIFY_INSERT_TEMPORARY
);
1024 PyModule_AddIntConstant(m
, "MSIMODIFY_VALIDATE", MSIMODIFY_VALIDATE
);
1025 PyModule_AddIntConstant(m
, "MSIMODIFY_VALIDATE_NEW", MSIMODIFY_VALIDATE_NEW
);
1026 PyModule_AddIntConstant(m
, "MSIMODIFY_VALIDATE_FIELD", MSIMODIFY_VALIDATE_FIELD
);
1027 PyModule_AddIntConstant(m
, "MSIMODIFY_VALIDATE_DELETE", MSIMODIFY_VALIDATE_DELETE
);
1029 PyModule_AddIntConstant(m
, "PID_CODEPAGE", PID_CODEPAGE
);
1030 PyModule_AddIntConstant(m
, "PID_TITLE", PID_TITLE
);
1031 PyModule_AddIntConstant(m
, "PID_SUBJECT", PID_SUBJECT
);
1032 PyModule_AddIntConstant(m
, "PID_AUTHOR", PID_AUTHOR
);
1033 PyModule_AddIntConstant(m
, "PID_KEYWORDS", PID_KEYWORDS
);
1034 PyModule_AddIntConstant(m
, "PID_COMMENTS", PID_COMMENTS
);
1035 PyModule_AddIntConstant(m
, "PID_TEMPLATE", PID_TEMPLATE
);
1036 PyModule_AddIntConstant(m
, "PID_LASTAUTHOR", PID_LASTAUTHOR
);
1037 PyModule_AddIntConstant(m
, "PID_REVNUMBER", PID_REVNUMBER
);
1038 PyModule_AddIntConstant(m
, "PID_LASTPRINTED", PID_LASTPRINTED
);
1039 PyModule_AddIntConstant(m
, "PID_CREATE_DTM", PID_CREATE_DTM
);
1040 PyModule_AddIntConstant(m
, "PID_LASTSAVE_DTM", PID_LASTSAVE_DTM
);
1041 PyModule_AddIntConstant(m
, "PID_PAGECOUNT", PID_PAGECOUNT
);
1042 PyModule_AddIntConstant(m
, "PID_WORDCOUNT", PID_WORDCOUNT
);
1043 PyModule_AddIntConstant(m
, "PID_CHARCOUNT", PID_CHARCOUNT
);
1044 PyModule_AddIntConstant(m
, "PID_APPNAME", PID_APPNAME
);
1045 PyModule_AddIntConstant(m
, "PID_SECURITY", PID_SECURITY
);
1047 MSIError
= PyErr_NewException ("_msi.MSIError", NULL
, NULL
);
1050 PyModule_AddObject(m
, "MSIError", MSIError
);