/* Helper library for MSI creation with Python.* Copyright (C) 2005 Martin v. Löwis* Licensed to PSF under a contributor agreement.*/#include <Python.h>#include <fci.h>#include <fcntl.h>#include <windows.h>#include <msi.h>#include <msiquery.h>#include <msidefs.h>#include <rpc.h>static PyObject *MSIError;static PyObject*uuidcreate(PyObject* obj, PyObject*args){UUID result;wchar_t *cresult;PyObject *oresult;/* May return ok, local only, and no address.For local only, the documentation says we still get a uuid.For RPC_S_UUID_NO_ADDRESS, it's not clear whether we canuse the result. */if (UuidCreate(&result) == RPC_S_UUID_NO_ADDRESS) {PyErr_SetString(PyExc_NotImplementedError, "processing 'no address' result");return NULL;}if (UuidToStringW(&result, &cresult) == RPC_S_OUT_OF_MEMORY) {PyErr_SetString(PyExc_MemoryError, "out of memory in uuidgen");return NULL;}oresult = PyUnicode_FromWideChar(cresult, wcslen(cresult));RpcStringFreeW(&cresult);return oresult;}/* FCI callback functions */static FNFCIALLOC(cb_alloc){return malloc(cb);}static FNFCIFREE(cb_free){free(memory);}static FNFCIOPEN(cb_open){int result = _open(pszFile, oflag | O_NOINHERIT, pmode);if (result == -1)*err = errno;return result;}static FNFCIREAD(cb_read){UINT result = (UINT)_read((int)hf, memory, cb);if (result != cb)*err = errno;return result;}static FNFCIWRITE(cb_write){UINT result = (UINT)_write((int)hf, memory, cb);if (result != cb)*err = errno;return result;}static FNFCICLOSE(cb_close){int result = _close((int)hf);if (result != 0)*err = errno;return result;}static FNFCISEEK(cb_seek){long result = (long)_lseek((int)hf, dist, seektype);if (result == -1)*err = errno;return result;}static FNFCIDELETE(cb_delete){int result = remove(pszFile);if (result != 0)*err = errno;return result;}static FNFCIFILEPLACED(cb_fileplaced){return 0;}static FNFCIGETTEMPFILE(cb_gettempfile){char *name = _tempnam("", "tmp");if ((name != NULL) && ((int)strlen(name) < cbTempName)) {strcpy(pszTempName, name);free(name);return TRUE;}if (name) free(name);return FALSE;}static FNFCISTATUS(cb_status){if (pv) {_Py_IDENTIFIER(status);PyObject *result = _PyObject_CallMethodId(pv, &PyId_status, "iii", typeStatus, cb1, cb2);if (result == NULL)return -1;Py_DECREF(result);}return 0;}static FNFCIGETNEXTCABINET(cb_getnextcabinet){if (pv) {_Py_IDENTIFIER(getnextcabinet);PyObject *result = _PyObject_CallMethodId(pv, &PyId_getnextcabinet, "i", pccab->iCab);if (result == NULL)return -1;if (!PyBytes_Check(result)) {PyErr_Format(PyExc_TypeError,"Incorrect return type %s from getnextcabinet",result->ob_type->tp_name);Py_DECREF(result);return FALSE;}strncpy(pccab->szCab, PyBytes_AsString(result), sizeof(pccab->szCab));return TRUE;}return FALSE;}static FNFCIGETOPENINFO(cb_getopeninfo){BY_HANDLE_FILE_INFORMATION bhfi;FILETIME filetime;HANDLE handle;/* Need Win32 handle to get time stamps */handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (handle == INVALID_HANDLE_VALUE)return -1;if (GetFileInformationByHandle(handle, &bhfi) == FALSE){CloseHandle(handle);return -1;}FileTimeToLocalFileTime(&bhfi.ftLastWriteTime, &filetime);FileTimeToDosDateTime(&filetime, pdate, ptime);*pattribs = (int)(bhfi.dwFileAttributes &(_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH));CloseHandle(handle);return _open(pszName, _O_RDONLY | _O_BINARY | O_NOINHERIT);}static PyObject* fcicreate(PyObject* obj, PyObject* args){char *cabname, *p;PyObject *files;CCAB ccab;HFCI hfci;ERF erf;Py_ssize_t i;if (!PyArg_ParseTuple(args, "sO:FCICreate", &cabname, &files))return NULL;if (!PyList_Check(files)) {PyErr_SetString(PyExc_TypeError, "FCICreate expects a list");return NULL;}ccab.cb = INT_MAX; /* no need to split CAB into multiple media */ccab.cbFolderThresh = 1000000; /* flush directory after this many bytes */ccab.cbReserveCFData = 0;ccab.cbReserveCFFolder = 0;ccab.cbReserveCFHeader = 0;ccab.iCab = 1;ccab.iDisk = 1;ccab.setID = 0;ccab.szDisk[0] = '0円';for (i = 0, p = cabname; *p; p = CharNext(p))if (*p == '\\' || *p == '/')i = p - cabname + 1;if (i >= sizeof(ccab.szCabPath) ||strlen(cabname+i) >= sizeof(ccab.szCab)) {PyErr_SetString(PyExc_ValueError, "path name too long");return 0;}if (i > 0) {memcpy(ccab.szCabPath, cabname, i);ccab.szCabPath[i] = '0円';strcpy(ccab.szCab, cabname+i);} else {strcpy(ccab.szCabPath, ".\\");strcpy(ccab.szCab, cabname);}hfci = FCICreate(&erf, cb_fileplaced, cb_alloc, cb_free,cb_open, cb_read, cb_write, cb_close, cb_seek, cb_delete,cb_gettempfile, &ccab, NULL);if (hfci == NULL) {PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper);return NULL;}for (i=0; i < PyList_GET_SIZE(files); i++) {PyObject *item = PyList_GET_ITEM(files, i);char *filename, *cabname;if (!PyArg_ParseTuple(item, "ss", &filename, &cabname)) {PyErr_SetString(PyExc_TypeError, "FCICreate expects a list of tuples containing two strings");FCIDestroy(hfci);return NULL;}if (!FCIAddFile(hfci, filename, cabname, FALSE,cb_getnextcabinet, cb_status, cb_getopeninfo,tcompTYPE_MSZIP))goto err;}if (!FCIFlushCabinet(hfci, FALSE, cb_getnextcabinet, cb_status))goto err;if (!FCIDestroy(hfci))goto err;Py_RETURN_NONE;err:if(erf.fError)PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */elsePyErr_SetString(PyExc_ValueError, "FCI general error");FCIDestroy(hfci);return NULL;}typedef struct msiobj{PyObject_HEADMSIHANDLE h;}msiobj;static voidmsiobj_dealloc(msiobj* msidb){MsiCloseHandle(msidb->h);msidb->h = 0;PyObject_Del(msidb);}static PyObject*msierror(int status){int code;char buf[2000];char *res = buf;DWORD size = sizeof(buf);MSIHANDLE err = MsiGetLastErrorRecord();if (err == 0) {switch(status) {case ERROR_ACCESS_DENIED:PyErr_SetString(MSIError, "access denied");return NULL;case ERROR_FUNCTION_FAILED:PyErr_SetString(MSIError, "function failed");return NULL;case ERROR_INVALID_DATA:PyErr_SetString(MSIError, "invalid data");return NULL;case ERROR_INVALID_HANDLE:PyErr_SetString(MSIError, "invalid handle");return NULL;case ERROR_INVALID_STATE:PyErr_SetString(MSIError, "invalid state");return NULL;case ERROR_INVALID_PARAMETER:PyErr_SetString(MSIError, "invalid parameter");return NULL;case ERROR_OPEN_FAILED:PyErr_SetString(MSIError, "open failed");return NULL;case ERROR_CREATE_FAILED:PyErr_SetString(MSIError, "create failed");return NULL;default:PyErr_Format(MSIError, "unknown error %x", status);return NULL;}}code = MsiRecordGetInteger(err, 1); /* XXX code */if (MsiFormatRecord(0, err, res, &size) == ERROR_MORE_DATA) {res = malloc(size+1);if (res == NULL) {MsiCloseHandle(err);return PyErr_NoMemory();}MsiFormatRecord(0, err, res, &size);res[size]='0円';}MsiCloseHandle(err);PyErr_SetString(MSIError, res);if (res != buf)free(res);return NULL;}static PyObject*msidb_close(msiobj* msidb, PyObject *args){int status;if ((status = MsiCloseHandle(msidb->h)) != ERROR_SUCCESS) {return msierror(status);}msidb->h = 0;Py_RETURN_NONE;}/*************************** Record objects **********************/static PyObject*record_getfieldcount(msiobj* record, PyObject* args){return PyLong_FromLong(MsiRecordGetFieldCount(record->h));}static PyObject*record_getinteger(msiobj* record, PyObject* args){unsigned int field;int status;if (!PyArg_ParseTuple(args, "I:GetInteger", &field))return NULL;status = MsiRecordGetInteger(record->h, field);if (status == MSI_NULL_INTEGER){PyErr_SetString(MSIError, "could not convert record field to integer");return NULL;}return PyLong_FromLong((long) status);}static PyObject*record_getstring(msiobj* record, PyObject* args){unsigned int field;unsigned int status;WCHAR buf[2000];WCHAR *res = buf;DWORD size = sizeof(buf);PyObject* string;if (!PyArg_ParseTuple(args, "I:GetString", &field))return NULL;status = MsiRecordGetStringW(record->h, field, res, &size);if (status == ERROR_MORE_DATA) {res = (WCHAR*) malloc((size + 1)*sizeof(WCHAR));if (res == NULL)return PyErr_NoMemory();status = MsiRecordGetStringW(record->h, field, res, &size);}if (status != ERROR_SUCCESS)return msierror((int) status);string = PyUnicode_FromWideChar(res, size);if (buf != res)free(res);return string;}static PyObject*record_cleardata(msiobj* record, PyObject *args){int status = MsiRecordClearData(record->h);if (status != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyObject*record_setstring(msiobj* record, PyObject *args){int status;int field;wchar_t *data;if (!PyArg_ParseTuple(args, "iu:SetString", &field, &data))return NULL;if ((status = MsiRecordSetStringW(record->h, field, data)) != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyObject*record_setstream(msiobj* record, PyObject *args){int status;int field;wchar_t *data;if (!PyArg_ParseTuple(args, "iu:SetStream", &field, &data))return NULL;if ((status = MsiRecordSetStreamW(record->h, field, data)) != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyObject*record_setinteger(msiobj* record, PyObject *args){int status;int field;int data;if (!PyArg_ParseTuple(args, "ii:SetInteger", &field, &data))return NULL;if ((status = MsiRecordSetInteger(record->h, field, data)) != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyMethodDef record_methods[] = {{ "GetFieldCount", (PyCFunction)record_getfieldcount, METH_NOARGS,PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")},{ "GetInteger", (PyCFunction)record_getinteger, METH_VARARGS,PyDoc_STR("GetInteger(field) -> int\nWraps MsiRecordGetInteger")},{ "GetString", (PyCFunction)record_getstring, METH_VARARGS,PyDoc_STR("GetString(field) -> string\nWraps MsiRecordGetString")},{ "SetString", (PyCFunction)record_setstring, METH_VARARGS,PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")},{ "SetStream", (PyCFunction)record_setstream, METH_VARARGS,PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")},{ "SetInteger", (PyCFunction)record_setinteger, METH_VARARGS,PyDoc_STR("SetInteger(field,int) -> None\nWraps MsiRecordSetInteger")},{ "ClearData", (PyCFunction)record_cleardata, METH_NOARGS,PyDoc_STR("ClearData() -> int\nWraps MsiRecordGClearData")},{ NULL, NULL }};static PyTypeObject record_Type = {PyVarObject_HEAD_INIT(NULL, 0)"_msi.Record", /*tp_name*/sizeof(msiobj), /*tp_basicsize*/0, /*tp_itemsize*//* methods */(destructor)msiobj_dealloc, /*tp_dealloc*/0, /*tp_vectorcall_offset*/0, /*tp_getattr*/0, /*tp_setattr*/0, /*tp_as_async*/0, /*tp_repr*/0, /*tp_as_number*/0, /*tp_as_sequence*/0, /*tp_as_mapping*/0, /*tp_hash*/0, /*tp_call*/0, /*tp_str*/PyObject_GenericGetAttr,/*tp_getattro*/PyObject_GenericSetAttr,/*tp_setattro*/0, /*tp_as_buffer*/Py_TPFLAGS_DEFAULT, /*tp_flags*/0, /*tp_doc*/0, /*tp_traverse*/0, /*tp_clear*/0, /*tp_richcompare*/0, /*tp_weaklistoffset*/0, /*tp_iter*/0, /*tp_iternext*/record_methods, /*tp_methods*/0, /*tp_members*/0, /*tp_getset*/0, /*tp_base*/0, /*tp_dict*/0, /*tp_descr_get*/0, /*tp_descr_set*/0, /*tp_dictoffset*/0, /*tp_init*/0, /*tp_alloc*/0, /*tp_new*/0, /*tp_free*/0, /*tp_is_gc*/};static PyObject*record_new(MSIHANDLE h){msiobj *result = PyObject_NEW(struct msiobj, &record_Type);if (!result) {MsiCloseHandle(h);return NULL;}result->h = h;return (PyObject*)result;}/*************************** SummaryInformation objects **************/static PyObject*summary_getproperty(msiobj* si, PyObject *args){int status;int field;PyObject *result;UINT type;INT ival;FILETIME fval;char sbuf[1000];char *sval = sbuf;DWORD ssize = sizeof(sbuf);if (!PyArg_ParseTuple(args, "i:GetProperty", &field))return NULL;status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,&fval, sval, &ssize);if (status == ERROR_MORE_DATA) {ssize++;sval = malloc(ssize);if (sval == NULL) {return PyErr_NoMemory();}status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,&fval, sval, &ssize);}if (status != ERROR_SUCCESS) {return msierror(status);}switch(type) {case VT_I2:case VT_I4:result = PyLong_FromLong(ival);break;case VT_FILETIME:PyErr_SetString(PyExc_NotImplementedError, "FILETIME result");result = NULL;break;case VT_LPSTR:result = PyBytes_FromStringAndSize(sval, ssize);break;case VT_EMPTY:Py_INCREF(Py_None);result = Py_None;break;default:PyErr_Format(PyExc_NotImplementedError, "result of type %d", type);result = NULL;break;}if (sval != sbuf)free(sval);return result;}static PyObject*summary_getpropertycount(msiobj* si, PyObject *args){int status;UINT result;status = MsiSummaryInfoGetPropertyCount(si->h, &result);if (status != ERROR_SUCCESS)return msierror(status);return PyLong_FromLong(result);}static PyObject*summary_setproperty(msiobj* si, PyObject *args){int status;int field;PyObject* data;if (!PyArg_ParseTuple(args, "iO:SetProperty", &field, &data))return NULL;if (PyUnicode_Check(data)) {const WCHAR *value = _PyUnicode_AsUnicode(data);if (value == NULL) {return NULL;}status = MsiSummaryInfoSetPropertyW(si->h, field, VT_LPSTR,0, NULL, value);} else if (PyLong_CheckExact(data)) {long value = PyLong_AsLong(data);if (value == -1 && PyErr_Occurred()) {return NULL;}status = MsiSummaryInfoSetProperty(si->h, field, VT_I4,value, NULL, NULL);} else {PyErr_SetString(PyExc_TypeError, "unsupported type");return NULL;}if (status != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyObject*summary_persist(msiobj* si, PyObject *args){int status;status = MsiSummaryInfoPersist(si->h);if (status != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyMethodDef summary_methods[] = {{ "GetProperty", (PyCFunction)summary_getproperty, METH_VARARGS,PyDoc_STR("GetProperty(propid) -> value\nWraps MsiSummaryInfoGetProperty")},{ "GetPropertyCount", (PyCFunction)summary_getpropertycount, METH_NOARGS,PyDoc_STR("GetProperty() -> int\nWraps MsiSummaryInfoGetPropertyCount")},{ "SetProperty", (PyCFunction)summary_setproperty, METH_VARARGS,PyDoc_STR("SetProperty(value) -> None\nWraps MsiSummaryInfoProperty")},{ "Persist", (PyCFunction)summary_persist, METH_NOARGS,PyDoc_STR("Persist() -> None\nWraps MsiSummaryInfoPersist")},{ NULL, NULL }};static PyTypeObject summary_Type = {PyVarObject_HEAD_INIT(NULL, 0)"_msi.SummaryInformation", /*tp_name*/sizeof(msiobj), /*tp_basicsize*/0, /*tp_itemsize*//* methods */(destructor)msiobj_dealloc, /*tp_dealloc*/0, /*tp_vectorcall_offset*/0, /*tp_getattr*/0, /*tp_setattr*/0, /*tp_as_async*/0, /*tp_repr*/0, /*tp_as_number*/0, /*tp_as_sequence*/0, /*tp_as_mapping*/0, /*tp_hash*/0, /*tp_call*/0, /*tp_str*/PyObject_GenericGetAttr,/*tp_getattro*/PyObject_GenericSetAttr,/*tp_setattro*/0, /*tp_as_buffer*/Py_TPFLAGS_DEFAULT, /*tp_flags*/0, /*tp_doc*/0, /*tp_traverse*/0, /*tp_clear*/0, /*tp_richcompare*/0, /*tp_weaklistoffset*/0, /*tp_iter*/0, /*tp_iternext*/summary_methods, /*tp_methods*/0, /*tp_members*/0, /*tp_getset*/0, /*tp_base*/0, /*tp_dict*/0, /*tp_descr_get*/0, /*tp_descr_set*/0, /*tp_dictoffset*/0, /*tp_init*/0, /*tp_alloc*/0, /*tp_new*/0, /*tp_free*/0, /*tp_is_gc*/};/*************************** View objects **************/static PyObject*view_execute(msiobj *view, PyObject*args){int status;MSIHANDLE params = 0;PyObject *oparams = Py_None;if (!PyArg_ParseTuple(args, "O:Execute", &oparams))return NULL;if (oparams != Py_None) {if (oparams->ob_type != &record_Type) {PyErr_SetString(PyExc_TypeError, "Execute argument must be a record");return NULL;}params = ((msiobj*)oparams)->h;}status = MsiViewExecute(view->h, params);if (status != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyObject*view_fetch(msiobj *view, PyObject*args){int status;MSIHANDLE result;status = MsiViewFetch(view->h, &result);if (status == ERROR_NO_MORE_ITEMS) {Py_RETURN_NONE;} else if (status != ERROR_SUCCESS) {return msierror(status);}return record_new(result);}static PyObject*view_getcolumninfo(msiobj *view, PyObject *args){int status;int kind;MSIHANDLE result;if (!PyArg_ParseTuple(args, "i:GetColumnInfo", &kind))return NULL;if ((status = MsiViewGetColumnInfo(view->h, kind, &result)) != ERROR_SUCCESS)return msierror(status);return record_new(result);}static PyObject*view_modify(msiobj *view, PyObject *args){int kind;PyObject *data;int status;if (!PyArg_ParseTuple(args, "iO:Modify", &kind, &data))return NULL;if (data->ob_type != &record_Type) {PyErr_SetString(PyExc_TypeError, "Modify expects a record object");return NULL;}if ((status = MsiViewModify(view->h, kind, ((msiobj*)data)->h)) != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyObject*view_close(msiobj *view, PyObject*args){int status;if ((status = MsiViewClose(view->h)) != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyMethodDef view_methods[] = {{ "Execute", (PyCFunction)view_execute, METH_VARARGS,PyDoc_STR("Execute(params=None) -> None\nWraps MsiViewExecute")},{ "GetColumnInfo", (PyCFunction)view_getcolumninfo, METH_VARARGS,PyDoc_STR("GetColumnInfo() -> result\nWraps MsiGetColumnInfo")},{ "Fetch", (PyCFunction)view_fetch, METH_NOARGS,PyDoc_STR("Fetch() -> result\nWraps MsiViewFetch")},{ "Modify", (PyCFunction)view_modify, METH_VARARGS,PyDoc_STR("Modify(mode,record) -> None\nWraps MsiViewModify")},{ "Close", (PyCFunction)view_close, METH_NOARGS,PyDoc_STR("Close() -> result\nWraps MsiViewClose")},{ NULL, NULL }};static PyTypeObject msiview_Type = {PyVarObject_HEAD_INIT(NULL, 0)"_msi.View", /*tp_name*/sizeof(msiobj), /*tp_basicsize*/0, /*tp_itemsize*//* methods */(destructor)msiobj_dealloc, /*tp_dealloc*/0, /*tp_vectorcall_offset*/0, /*tp_getattr*/0, /*tp_setattr*/0, /*tp_as_async*/0, /*tp_repr*/0, /*tp_as_number*/0, /*tp_as_sequence*/0, /*tp_as_mapping*/0, /*tp_hash*/0, /*tp_call*/0, /*tp_str*/PyObject_GenericGetAttr,/*tp_getattro*/PyObject_GenericSetAttr,/*tp_setattro*/0, /*tp_as_buffer*/Py_TPFLAGS_DEFAULT, /*tp_flags*/0, /*tp_doc*/0, /*tp_traverse*/0, /*tp_clear*/0, /*tp_richcompare*/0, /*tp_weaklistoffset*/0, /*tp_iter*/0, /*tp_iternext*/view_methods, /*tp_methods*/0, /*tp_members*/0, /*tp_getset*/0, /*tp_base*/0, /*tp_dict*/0, /*tp_descr_get*/0, /*tp_descr_set*/0, /*tp_dictoffset*/0, /*tp_init*/0, /*tp_alloc*/0, /*tp_new*/0, /*tp_free*/0, /*tp_is_gc*/};/*************************** Database objects **************/static PyObject*msidb_openview(msiobj *msidb, PyObject *args){int status;char *sql;MSIHANDLE hView;msiobj *result;if (!PyArg_ParseTuple(args, "s:OpenView", &sql))return NULL;if ((status = MsiDatabaseOpenView(msidb->h, sql, &hView)) != ERROR_SUCCESS)return msierror(status);result = PyObject_NEW(struct msiobj, &msiview_Type);if (!result) {MsiCloseHandle(hView);return NULL;}result->h = hView;return (PyObject*)result;}static PyObject*msidb_commit(msiobj *msidb, PyObject *args){int status;if ((status = MsiDatabaseCommit(msidb->h)) != ERROR_SUCCESS)return msierror(status);Py_RETURN_NONE;}static PyObject*msidb_getsummaryinformation(msiobj *db, PyObject *args){int status;int count;MSIHANDLE result;msiobj *oresult;if (!PyArg_ParseTuple(args, "i:GetSummaryInformation", &count))return NULL;status = MsiGetSummaryInformation(db->h, NULL, count, &result);if (status != ERROR_SUCCESS)return msierror(status);oresult = PyObject_NEW(struct msiobj, &summary_Type);if (!oresult) {MsiCloseHandle(result);return NULL;}oresult->h = result;return (PyObject*)oresult;}static PyMethodDef db_methods[] = {{ "OpenView", (PyCFunction)msidb_openview, METH_VARARGS,PyDoc_STR("OpenView(sql) -> viewobj\nWraps MsiDatabaseOpenView")},{ "Commit", (PyCFunction)msidb_commit, METH_NOARGS,PyDoc_STR("Commit() -> None\nWraps MsiDatabaseCommit")},{ "GetSummaryInformation", (PyCFunction)msidb_getsummaryinformation, METH_VARARGS,PyDoc_STR("GetSummaryInformation(updateCount) -> viewobj\nWraps MsiGetSummaryInformation")},{ "Close", (PyCFunction)msidb_close, METH_NOARGS,PyDoc_STR("Close() -> None\nWraps MsiCloseHandle")},{ NULL, NULL }};static PyTypeObject msidb_Type = {PyVarObject_HEAD_INIT(NULL, 0)"_msi.Database", /*tp_name*/sizeof(msiobj), /*tp_basicsize*/0, /*tp_itemsize*//* methods */(destructor)msiobj_dealloc, /*tp_dealloc*/0, /*tp_vectorcall_offset*/0, /*tp_getattr*/0, /*tp_setattr*/0, /*tp_as_async*/0, /*tp_repr*/0, /*tp_as_number*/0, /*tp_as_sequence*/0, /*tp_as_mapping*/0, /*tp_hash*/0, /*tp_call*/0, /*tp_str*/PyObject_GenericGetAttr,/*tp_getattro*/PyObject_GenericSetAttr,/*tp_setattro*/0, /*tp_as_buffer*/Py_TPFLAGS_DEFAULT, /*tp_flags*/0, /*tp_doc*/0, /*tp_traverse*/0, /*tp_clear*/0, /*tp_richcompare*/0, /*tp_weaklistoffset*/0, /*tp_iter*/0, /*tp_iternext*/db_methods, /*tp_methods*/0, /*tp_members*/0, /*tp_getset*/0, /*tp_base*/0, /*tp_dict*/0, /*tp_descr_get*/0, /*tp_descr_set*/0, /*tp_dictoffset*/0, /*tp_init*/0, /*tp_alloc*/0, /*tp_new*/0, /*tp_free*/0, /*tp_is_gc*/};#define Py_NOT_PERSIST(x, flag) \(x != (SIZE_T)(flag) && \x != ((SIZE_T)(flag) | MSIDBOPEN_PATCHFILE))#define Py_INVALID_PERSIST(x) \(Py_NOT_PERSIST(x, MSIDBOPEN_READONLY) && \Py_NOT_PERSIST(x, MSIDBOPEN_TRANSACT) && \Py_NOT_PERSIST(x, MSIDBOPEN_DIRECT) && \Py_NOT_PERSIST(x, MSIDBOPEN_CREATE) && \Py_NOT_PERSIST(x, MSIDBOPEN_CREATEDIRECT))static PyObject* msiopendb(PyObject *obj, PyObject *args){int status;char *path;int persist;MSIHANDLE h;msiobj *result;if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist))return NULL;/* We need to validate that persist is a valid MSIDBOPEN_* value. Otherwise,MsiOpenDatabase may treat the value as a pointer, leading to unexpectedbehavior. */if (Py_INVALID_PERSIST(persist))return msierror(ERROR_INVALID_PARAMETER);status = MsiOpenDatabase(path, (LPCSTR)(SIZE_T)persist, &h);if (status != ERROR_SUCCESS)return msierror(status);result = PyObject_NEW(struct msiobj, &msidb_Type);if (!result) {MsiCloseHandle(h);return NULL;}result->h = h;return (PyObject*)result;}static PyObject*createrecord(PyObject *o, PyObject *args){int count;MSIHANDLE h;if (!PyArg_ParseTuple(args, "i:CreateRecord", &count))return NULL;h = MsiCreateRecord(count);if (h == 0)return msierror(0);return record_new(h);}static PyMethodDef msi_methods[] = {{"UuidCreate", (PyCFunction)uuidcreate, METH_NOARGS,PyDoc_STR("UuidCreate() -> string")},{"FCICreate", (PyCFunction)fcicreate, METH_VARARGS,PyDoc_STR("fcicreate(cabname,files) -> None")},{"OpenDatabase", (PyCFunction)msiopendb, METH_VARARGS,PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiOpenDatabase")},{"CreateRecord", (PyCFunction)createrecord, METH_VARARGS,PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiCreateRecord")},{NULL, NULL} /* sentinel */};static char msi_doc[] = "Documentation";static struct PyModuleDef _msimodule = {PyModuleDef_HEAD_INIT,"_msi",msi_doc,-1,msi_methods,NULL,NULL,NULL,NULL};PyMODINIT_FUNCPyInit__msi(void){PyObject *m;m = PyModule_Create(&_msimodule);if (m == NULL)return NULL;PyModule_AddIntConstant(m, "MSIDBOPEN_CREATEDIRECT", (long)(SIZE_T)MSIDBOPEN_CREATEDIRECT);PyModule_AddIntConstant(m, "MSIDBOPEN_CREATE", (long)(SIZE_T)MSIDBOPEN_CREATE);PyModule_AddIntConstant(m, "MSIDBOPEN_DIRECT", (long)(SIZE_T)MSIDBOPEN_DIRECT);PyModule_AddIntConstant(m, "MSIDBOPEN_READONLY", (long)(SIZE_T)MSIDBOPEN_READONLY);PyModule_AddIntConstant(m, "MSIDBOPEN_TRANSACT", (long)(SIZE_T)MSIDBOPEN_TRANSACT);PyModule_AddIntConstant(m, "MSIDBOPEN_PATCHFILE", (long)(SIZE_T)MSIDBOPEN_PATCHFILE);PyModule_AddIntMacro(m, MSICOLINFO_NAMES);PyModule_AddIntMacro(m, MSICOLINFO_TYPES);PyModule_AddIntMacro(m, MSIMODIFY_SEEK);PyModule_AddIntMacro(m, MSIMODIFY_REFRESH);PyModule_AddIntMacro(m, MSIMODIFY_INSERT);PyModule_AddIntMacro(m, MSIMODIFY_UPDATE);PyModule_AddIntMacro(m, MSIMODIFY_ASSIGN);PyModule_AddIntMacro(m, MSIMODIFY_REPLACE);PyModule_AddIntMacro(m, MSIMODIFY_MERGE);PyModule_AddIntMacro(m, MSIMODIFY_DELETE);PyModule_AddIntMacro(m, MSIMODIFY_INSERT_TEMPORARY);PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE);PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_NEW);PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_FIELD);PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_DELETE);PyModule_AddIntMacro(m, PID_CODEPAGE);PyModule_AddIntMacro(m, PID_TITLE);PyModule_AddIntMacro(m, PID_SUBJECT);PyModule_AddIntMacro(m, PID_AUTHOR);PyModule_AddIntMacro(m, PID_KEYWORDS);PyModule_AddIntMacro(m, PID_COMMENTS);PyModule_AddIntMacro(m, PID_TEMPLATE);PyModule_AddIntMacro(m, PID_LASTAUTHOR);PyModule_AddIntMacro(m, PID_REVNUMBER);PyModule_AddIntMacro(m, PID_LASTPRINTED);PyModule_AddIntMacro(m, PID_CREATE_DTM);PyModule_AddIntMacro(m, PID_LASTSAVE_DTM);PyModule_AddIntMacro(m, PID_PAGECOUNT);PyModule_AddIntMacro(m, PID_WORDCOUNT);PyModule_AddIntMacro(m, PID_CHARCOUNT);PyModule_AddIntMacro(m, PID_APPNAME);PyModule_AddIntMacro(m, PID_SECURITY);MSIError = PyErr_NewException ("_msi.MSIError", NULL, NULL);if (!MSIError)return NULL;PyModule_AddObject(m, "MSIError", MSIError);return m;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。