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; cabname
[i
]; i
++)
212 if (cabname
[i
] == '\\' || cabname
[i
] == '/')
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_cleardata(msiobj
* record
, PyObject
*args
)
344 int status
= MsiRecordClearData(record
->h
);
345 if (status
!= ERROR_SUCCESS
)
346 return msierror(status
);
353 record_setstring(msiobj
* record
, PyObject
*args
)
359 if (!PyArg_ParseTuple(args
, "is:SetString", &field
, &data
))
362 if ((status
= MsiRecordSetString(record
->h
, field
, data
)) != ERROR_SUCCESS
)
363 return msierror(status
);
370 record_setstream(msiobj
* record
, PyObject
*args
)
376 if (!PyArg_ParseTuple(args
, "is:SetStream", &field
, &data
))
379 if ((status
= MsiRecordSetStream(record
->h
, field
, data
)) != ERROR_SUCCESS
)
380 return msierror(status
);
387 record_setinteger(msiobj
* record
, PyObject
*args
)
393 if (!PyArg_ParseTuple(args
, "ii:SetInteger", &field
, &data
))
396 if ((status
= MsiRecordSetInteger(record
->h
, field
, data
)) != ERROR_SUCCESS
)
397 return msierror(status
);
405 static PyMethodDef record_methods
[] = {
406 { "GetFieldCount", (PyCFunction
)record_getfieldcount
, METH_NOARGS
,
407 PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")},
408 { "SetString", (PyCFunction
)record_setstring
, METH_VARARGS
,
409 PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")},
410 { "SetStream", (PyCFunction
)record_setstream
, METH_VARARGS
,
411 PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")},
412 { "SetInteger", (PyCFunction
)record_setinteger
, METH_VARARGS
,
413 PyDoc_STR("SetInteger(field,int) -> None\nWraps MsiRecordSetInteger")},
414 { "ClearData", (PyCFunction
)record_cleardata
, METH_NOARGS
,
415 PyDoc_STR("ClearData() -> int\nWraps MsiRecordGClearData")},
419 static PyTypeObject record_Type
= {
420 PyVarObject_HEAD_INIT(NULL
, 0)
421 "_msi.Record", /*tp_name*/
422 sizeof(msiobj
), /*tp_basicsize*/
425 (destructor
)msiobj_dealloc
, /*tp_dealloc*/
432 0, /*tp_as_sequence*/
437 PyObject_GenericGetAttr
,/*tp_getattro*/
438 PyObject_GenericSetAttr
,/*tp_setattro*/
440 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
444 0, /*tp_richcompare*/
445 0, /*tp_weaklistoffset*/
448 record_methods
, /*tp_methods*/
464 record_new(MSIHANDLE h
)
466 msiobj
*result
= PyObject_NEW(struct msiobj
, &record_Type
);
474 return (PyObject
*)result
;
477 /*************************** SummaryInformation objects **************/
480 summary_getproperty(msiobj
* si
, PyObject
*args
)
490 DWORD ssize
= sizeof(sval
);
492 if (!PyArg_ParseTuple(args
, "i:GetProperty", &field
))
495 status
= MsiSummaryInfoGetProperty(si
->h
, field
, &type
, &ival
,
496 &fval
, sval
, &ssize
);
497 if (status
== ERROR_MORE_DATA
) {
498 sval
= malloc(ssize
);
499 status
= MsiSummaryInfoGetProperty(si
->h
, field
, &type
, &ival
,
500 &fval
, sval
, &ssize
);
504 case VT_I2
: case VT_I4
:
505 return PyInt_FromLong(ival
);
507 PyErr_SetString(PyExc_NotImplementedError
, "FILETIME result");
510 result
= PyString_FromStringAndSize(sval
, ssize
);
515 PyErr_Format(PyExc_NotImplementedError
, "result of type %d", type
);
520 summary_getpropertycount(msiobj
* si
, PyObject
*args
)
525 status
= MsiSummaryInfoGetPropertyCount(si
->h
, &result
);
526 if (status
!= ERROR_SUCCESS
)
527 return msierror(status
);
529 return PyInt_FromLong(result
);
533 summary_setproperty(msiobj
* si
, PyObject
*args
)
539 if (!PyArg_ParseTuple(args
, "iO:SetProperty", &field
, &data
))
542 if (PyString_Check(data
)) {
543 status
= MsiSummaryInfoSetProperty(si
->h
, field
, VT_LPSTR
,
544 0, NULL
, PyString_AsString(data
));
545 } else if (PyInt_Check(data
)) {
546 status
= MsiSummaryInfoSetProperty(si
->h
, field
, VT_I4
,
547 PyInt_AsLong(data
), NULL
, NULL
);
549 PyErr_SetString(PyExc_TypeError
, "unsupported type");
553 if (status
!= ERROR_SUCCESS
)
554 return msierror(status
);
562 summary_persist(msiobj
* si
, PyObject
*args
)
566 status
= MsiSummaryInfoPersist(si
->h
);
567 if (status
!= ERROR_SUCCESS
)
568 return msierror(status
);
573 static PyMethodDef summary_methods
[] = {
574 { "GetProperty", (PyCFunction
)summary_getproperty
, METH_VARARGS
,
575 PyDoc_STR("GetProperty(propid) -> value\nWraps MsiSummaryInfoGetProperty")},
576 { "GetPropertyCount", (PyCFunction
)summary_getpropertycount
, METH_NOARGS
,
577 PyDoc_STR("GetProperty() -> int\nWraps MsiSummaryInfoGetPropertyCount")},
578 { "SetProperty", (PyCFunction
)summary_setproperty
, METH_VARARGS
,
579 PyDoc_STR("SetProperty(value) -> None\nWraps MsiSummaryInfoProperty")},
580 { "Persist", (PyCFunction
)summary_persist
, METH_NOARGS
,
581 PyDoc_STR("Persist() -> None\nWraps MsiSummaryInfoPersist")},
585 static PyTypeObject summary_Type
= {
586 PyVarObject_HEAD_INIT(NULL
, 0)
587 "_msi.SummaryInformation", /*tp_name*/
588 sizeof(msiobj
), /*tp_basicsize*/
591 (destructor
)msiobj_dealloc
, /*tp_dealloc*/
598 0, /*tp_as_sequence*/
603 PyObject_GenericGetAttr
,/*tp_getattro*/
604 PyObject_GenericSetAttr
,/*tp_setattro*/
606 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
610 0, /*tp_richcompare*/
611 0, /*tp_weaklistoffset*/
614 summary_methods
, /*tp_methods*/
629 /*************************** View objects **************/
632 view_execute(msiobj
*view
, PyObject
*args
)
635 MSIHANDLE params
= 0;
636 PyObject
*oparams
= Py_None
;
638 if (!PyArg_ParseTuple(args
, "O:Execute", &oparams
))
641 if (oparams
!= Py_None
) {
642 if (oparams
->ob_type
!= &record_Type
) {
643 PyErr_SetString(PyExc_TypeError
, "Execute argument must be a record");
646 params
= ((msiobj
*)oparams
)->h
;
649 status
= MsiViewExecute(view
->h
, params
);
650 if (status
!= ERROR_SUCCESS
)
651 return msierror(status
);
658 view_fetch(msiobj
*view
, PyObject
*args
)
663 if ((status
= MsiViewFetch(view
->h
, &result
)) != ERROR_SUCCESS
)
664 return msierror(status
);
666 return record_new(result
);
670 view_getcolumninfo(msiobj
*view
, PyObject
*args
)
676 if (!PyArg_ParseTuple(args
, "i:GetColumnInfo", &kind
))
679 if ((status
= MsiViewGetColumnInfo(view
->h
, kind
, &result
)) != ERROR_SUCCESS
)
680 return msierror(status
);
682 return record_new(result
);
686 view_modify(msiobj
*view
, PyObject
*args
)
692 if (!PyArg_ParseTuple(args
, "iO:Modify", &kind
, &data
))
695 if (data
->ob_type
!= &record_Type
) {
696 PyErr_SetString(PyExc_TypeError
, "Modify expects a record object");
700 if ((status
= MsiViewModify(view
->h
, kind
, ((msiobj
*)data
)->h
)) != ERROR_SUCCESS
)
701 return msierror(status
);
708 view_close(msiobj
*view
, PyObject
*args
)
712 if ((status
= MsiViewClose(view
->h
)) != ERROR_SUCCESS
)
713 return msierror(status
);
719 static PyMethodDef view_methods
[] = {
720 { "Execute", (PyCFunction
)view_execute
, METH_VARARGS
,
721 PyDoc_STR("Execute(params=None) -> None\nWraps MsiViewExecute")},
722 { "GetColumnInfo", (PyCFunction
)view_getcolumninfo
, METH_VARARGS
,
723 PyDoc_STR("GetColumnInfo() -> result\nWraps MsiGetColumnInfo")},
724 { "Fetch", (PyCFunction
)view_fetch
, METH_NOARGS
,
725 PyDoc_STR("Fetch() -> result\nWraps MsiViewFetch")},
726 { "Modify", (PyCFunction
)view_modify
, METH_VARARGS
,
727 PyDoc_STR("Modify(mode,record) -> None\nWraps MsiViewModify")},
728 { "Close", (PyCFunction
)view_close
, METH_NOARGS
,
729 PyDoc_STR("Close() -> result\nWraps MsiViewClose")},
733 static PyTypeObject msiview_Type
= {
734 PyVarObject_HEAD_INIT(NULL
, 0)
735 "_msi.View", /*tp_name*/
736 sizeof(msiobj
), /*tp_basicsize*/
739 (destructor
)msiobj_dealloc
, /*tp_dealloc*/
746 0, /*tp_as_sequence*/
751 PyObject_GenericGetAttr
,/*tp_getattro*/
752 PyObject_GenericSetAttr
,/*tp_setattro*/
754 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
758 0, /*tp_richcompare*/
759 0, /*tp_weaklistoffset*/
762 view_methods
, /*tp_methods*/
777 /*************************** Database objects **************/
780 msidb_openview(msiobj
*msidb
, PyObject
*args
)
787 if (!PyArg_ParseTuple(args
, "s:OpenView", &sql
))
790 if ((status
= MsiDatabaseOpenView(msidb
->h
, sql
, &hView
)) != ERROR_SUCCESS
)
791 return msierror(status
);
793 result
= PyObject_NEW(struct msiobj
, &msiview_Type
);
795 MsiCloseHandle(hView
);
800 return (PyObject
*)result
;
804 msidb_commit(msiobj
*msidb
, PyObject
*args
)
808 if ((status
= MsiDatabaseCommit(msidb
->h
)) != ERROR_SUCCESS
)
809 return msierror(status
);
816 msidb_getsummaryinformation(msiobj
*db
, PyObject
*args
)
823 if (!PyArg_ParseTuple(args
, "i:GetSummaryInformation", &count
))
826 status
= MsiGetSummaryInformation(db
->h
, NULL
, count
, &result
);
827 if (status
!= ERROR_SUCCESS
)
828 return msierror(status
);
830 oresult
= PyObject_NEW(struct msiobj
, &summary_Type
);
832 MsiCloseHandle(result
);
837 return (PyObject
*)oresult
;
840 static PyMethodDef db_methods
[] = {
841 { "OpenView", (PyCFunction
)msidb_openview
, METH_VARARGS
,
842 PyDoc_STR("OpenView(sql) -> viewobj\nWraps MsiDatabaseOpenView")},
843 { "Commit", (PyCFunction
)msidb_commit
, METH_NOARGS
,
844 PyDoc_STR("Commit() -> None\nWraps MsiDatabaseCommit")},
845 { "GetSummaryInformation", (PyCFunction
)msidb_getsummaryinformation
, METH_VARARGS
,
846 PyDoc_STR("GetSummaryInformation(updateCount) -> viewobj\nWraps MsiGetSummaryInformation")},
850 static PyTypeObject msidb_Type
= {
851 PyVarObject_HEAD_INIT(NULL
, 0)
852 "_msi.Database", /*tp_name*/
853 sizeof(msiobj
), /*tp_basicsize*/
856 (destructor
)msiobj_dealloc
, /*tp_dealloc*/
863 0, /*tp_as_sequence*/
868 PyObject_GenericGetAttr
,/*tp_getattro*/
869 PyObject_GenericSetAttr
,/*tp_setattro*/
871 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
875 0, /*tp_richcompare*/
876 0, /*tp_weaklistoffset*/
879 db_methods
, /*tp_methods*/
894 static PyObject
* msiopendb(PyObject
*obj
, PyObject
*args
)
902 if (!PyArg_ParseTuple(args
, "si:MSIOpenDatabase", &path
, &persist
))
905 status
= MsiOpenDatabase(path
, (LPCSTR
)persist
, &h
);
906 if (status
!= ERROR_SUCCESS
)
907 return msierror(status
);
909 result
= PyObject_NEW(struct msiobj
, &msidb_Type
);
915 return (PyObject
*)result
;
919 createrecord(PyObject
*o
, PyObject
*args
)
924 if (!PyArg_ParseTuple(args
, "i:CreateRecord", &count
))
927 h
= MsiCreateRecord(count
);
931 return record_new(h
);
935 static PyMethodDef msi_methods
[] = {
936 {"UuidCreate", (PyCFunction
)uuidcreate
, METH_NOARGS
,
937 PyDoc_STR("UuidCreate() -> string")},
938 {"FCICreate", (PyCFunction
)fcicreate
, METH_VARARGS
,
939 PyDoc_STR("fcicreate(cabname,files) -> None")},
940 {"OpenDatabase", (PyCFunction
)msiopendb
, METH_VARARGS
,
941 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiOpenDatabase")},
942 {"CreateRecord", (PyCFunction
)createrecord
, METH_VARARGS
,
943 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiCreateRecord")},
944 {NULL
, NULL
} /* sentinel */
947 static char msi_doc
[] = "Documentation";
954 m
= Py_InitModule3("_msi", msi_methods
, msi_doc
);
958 PyModule_AddIntConstant(m
, "MSIDBOPEN_CREATEDIRECT", (int)MSIDBOPEN_CREATEDIRECT
);
959 PyModule_AddIntConstant(m
, "MSIDBOPEN_CREATE", (int)MSIDBOPEN_CREATE
);
960 PyModule_AddIntConstant(m
, "MSIDBOPEN_DIRECT", (int)MSIDBOPEN_DIRECT
);
961 PyModule_AddIntConstant(m
, "MSIDBOPEN_READONLY", (int)MSIDBOPEN_READONLY
);
962 PyModule_AddIntConstant(m
, "MSIDBOPEN_TRANSACT", (int)MSIDBOPEN_TRANSACT
);
963 PyModule_AddIntConstant(m
, "MSIDBOPEN_PATCHFILE", (int)MSIDBOPEN_PATCHFILE
);
965 PyModule_AddIntConstant(m
, "MSICOLINFO_NAMES", MSICOLINFO_NAMES
);
966 PyModule_AddIntConstant(m
, "MSICOLINFO_TYPES", MSICOLINFO_TYPES
);
968 PyModule_AddIntConstant(m
, "MSIMODIFY_SEEK", MSIMODIFY_SEEK
);
969 PyModule_AddIntConstant(m
, "MSIMODIFY_REFRESH", MSIMODIFY_REFRESH
);
970 PyModule_AddIntConstant(m
, "MSIMODIFY_INSERT", MSIMODIFY_INSERT
);
971 PyModule_AddIntConstant(m
, "MSIMODIFY_UPDATE", MSIMODIFY_UPDATE
);
972 PyModule_AddIntConstant(m
, "MSIMODIFY_ASSIGN", MSIMODIFY_ASSIGN
);
973 PyModule_AddIntConstant(m
, "MSIMODIFY_REPLACE", MSIMODIFY_REPLACE
);
974 PyModule_AddIntConstant(m
, "MSIMODIFY_MERGE", MSIMODIFY_MERGE
);
975 PyModule_AddIntConstant(m
, "MSIMODIFY_DELETE", MSIMODIFY_DELETE
);
976 PyModule_AddIntConstant(m
, "MSIMODIFY_INSERT_TEMPORARY", MSIMODIFY_INSERT_TEMPORARY
);
977 PyModule_AddIntConstant(m
, "MSIMODIFY_VALIDATE", MSIMODIFY_VALIDATE
);
978 PyModule_AddIntConstant(m
, "MSIMODIFY_VALIDATE_NEW", MSIMODIFY_VALIDATE_NEW
);
979 PyModule_AddIntConstant(m
, "MSIMODIFY_VALIDATE_FIELD", MSIMODIFY_VALIDATE_FIELD
);
980 PyModule_AddIntConstant(m
, "MSIMODIFY_VALIDATE_DELETE", MSIMODIFY_VALIDATE_DELETE
);
982 PyModule_AddIntConstant(m
, "PID_CODEPAGE", PID_CODEPAGE
);
983 PyModule_AddIntConstant(m
, "PID_TITLE", PID_TITLE
);
984 PyModule_AddIntConstant(m
, "PID_SUBJECT", PID_SUBJECT
);
985 PyModule_AddIntConstant(m
, "PID_AUTHOR", PID_AUTHOR
);
986 PyModule_AddIntConstant(m
, "PID_KEYWORDS", PID_KEYWORDS
);
987 PyModule_AddIntConstant(m
, "PID_COMMENTS", PID_COMMENTS
);
988 PyModule_AddIntConstant(m
, "PID_TEMPLATE", PID_TEMPLATE
);
989 PyModule_AddIntConstant(m
, "PID_LASTAUTHOR", PID_LASTAUTHOR
);
990 PyModule_AddIntConstant(m
, "PID_REVNUMBER", PID_REVNUMBER
);
991 PyModule_AddIntConstant(m
, "PID_LASTPRINTED", PID_LASTPRINTED
);
992 PyModule_AddIntConstant(m
, "PID_CREATE_DTM", PID_CREATE_DTM
);
993 PyModule_AddIntConstant(m
, "PID_LASTSAVE_DTM", PID_LASTSAVE_DTM
);
994 PyModule_AddIntConstant(m
, "PID_PAGECOUNT", PID_PAGECOUNT
);
995 PyModule_AddIntConstant(m
, "PID_WORDCOUNT", PID_WORDCOUNT
);
996 PyModule_AddIntConstant(m
, "PID_CHARCOUNT", PID_CHARCOUNT
);
997 PyModule_AddIntConstant(m
, "PID_APPNAME", PID_APPNAME
);
998 PyModule_AddIntConstant(m
, "PID_SECURITY", PID_SECURITY
);
1000 MSIError
= PyErr_NewException ("_msi.MSIError", NULL
, NULL
);
1003 PyModule_AddObject(m
, "MSIError", MSIError
);