| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1 | /* Helper library for MSI creation with Python. | 
| Florent Xicluna | c934f32 | 2010-09-03 23:47:32 +0000 | [diff] [blame] | 2 | * Copyright (C) 2005 Martin v. Löwis | 
| Martin v. Löwis | dd860ca | 2006-03-05 13:39:10 +0000 | [diff] [blame] | 3 | * Licensed to PSF under a contributor agreement. | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 4 | */ | 
|  | 5 |  | 
|  | 6 | #include <Python.h> | 
|  | 7 | #include <fci.h> | 
|  | 8 | #include <fcntl.h> | 
|  | 9 | #include <windows.h> | 
|  | 10 | #include <msi.h> | 
|  | 11 | #include <msiquery.h> | 
|  | 12 | #include <msidefs.h> | 
|  | 13 | #include <rpc.h> | 
|  | 14 |  | 
|  | 15 | static PyObject *MSIError; | 
|  | 16 |  | 
|  | 17 | static PyObject* | 
|  | 18 | uuidcreate(PyObject* obj, PyObject*args) | 
|  | 19 | { | 
|  | 20 | UUID result; | 
| Victor Stinner | 9d3b93b | 2011-11-22 02:27:30 +0100 | [diff] [blame] | 21 | wchar_t *cresult; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 22 | PyObject *oresult; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 23 |  | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 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 | 
|  | 27 | use the result. */ | 
|  | 28 | if (UuidCreate(&result) == RPC_S_UUID_NO_ADDRESS) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 29 | PyErr_SetString(PyExc_NotImplementedError, "processing 'no address' result"); | 
|  | 30 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 31 | } | 
|  | 32 |  | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 33 | if (UuidToStringW(&result, &cresult) == RPC_S_OUT_OF_MEMORY) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 34 | PyErr_SetString(PyExc_MemoryError, "out of memory in uuidgen"); | 
|  | 35 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 36 | } | 
|  | 37 |  | 
| Victor Stinner | 9d3b93b | 2011-11-22 02:27:30 +0100 | [diff] [blame] | 38 | oresult = PyUnicode_FromWideChar(cresult, wcslen(cresult)); | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 39 | RpcStringFreeW(&cresult); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 40 | return oresult; | 
|  | 41 |  | 
|  | 42 | } | 
|  | 43 |  | 
|  | 44 | /* FCI callback functions */ | 
|  | 45 |  | 
|  | 46 | static FNFCIALLOC(cb_alloc) | 
|  | 47 | { | 
|  | 48 | return malloc(cb); | 
|  | 49 | } | 
|  | 50 |  | 
|  | 51 | static FNFCIFREE(cb_free) | 
|  | 52 | { | 
|  | 53 | free(memory); | 
|  | 54 | } | 
|  | 55 |  | 
|  | 56 | static FNFCIOPEN(cb_open) | 
|  | 57 | { | 
| Victor Stinner | daf4555 | 2013-08-28 00:53:59 +0200 | [diff] [blame] | 58 | int result = _open(pszFile, oflag | O_NOINHERIT, pmode); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 59 | if (result == -1) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 60 | *err = errno; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 61 | return result; | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | static FNFCIREAD(cb_read) | 
|  | 65 | { | 
| Victor Stinner | 6715828 | 2013-11-20 00:14:49 +0100 | [diff] [blame] | 66 | UINT result = (UINT)_read((int)hf, memory, cb); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 67 | if (result != cb) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 68 | *err = errno; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 69 | return result; | 
|  | 70 | } | 
|  | 71 |  | 
|  | 72 | static FNFCIWRITE(cb_write) | 
|  | 73 | { | 
| Victor Stinner | 6715828 | 2013-11-20 00:14:49 +0100 | [diff] [blame] | 74 | UINT result = (UINT)_write((int)hf, memory, cb); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 75 | if (result != cb) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 76 | *err = errno; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 77 | return result; | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | static FNFCICLOSE(cb_close) | 
|  | 81 | { | 
| Victor Stinner | 6715828 | 2013-11-20 00:14:49 +0100 | [diff] [blame] | 82 | int result = _close((int)hf); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 83 | if (result != 0) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 84 | *err = errno; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 85 | return result; | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | static FNFCISEEK(cb_seek) | 
|  | 89 | { | 
| Victor Stinner | 6715828 | 2013-11-20 00:14:49 +0100 | [diff] [blame] | 90 | long result = (long)_lseek((int)hf, dist, seektype); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 91 | if (result == -1) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 92 | *err = errno; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 93 | return result; | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | static FNFCIDELETE(cb_delete) | 
|  | 97 | { | 
|  | 98 | int result = remove(pszFile); | 
|  | 99 | if (result != 0) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 100 | *err = errno; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 101 | return result; | 
|  | 102 | } | 
|  | 103 |  | 
|  | 104 | static FNFCIFILEPLACED(cb_fileplaced) | 
|  | 105 | { | 
|  | 106 | return 0; | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | static FNFCIGETTEMPFILE(cb_gettempfile) | 
|  | 110 | { | 
|  | 111 | char *name = _tempnam("", "tmp"); | 
|  | 112 | if ((name != NULL) && ((int)strlen(name) < cbTempName)) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 113 | strcpy(pszTempName, name); | 
|  | 114 | free(name); | 
|  | 115 | return TRUE; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 116 | } | 
|  | 117 |  | 
|  | 118 | if (name) free(name); | 
|  | 119 | return FALSE; | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | static FNFCISTATUS(cb_status) | 
|  | 123 | { | 
|  | 124 | if (pv) { | 
| Martin v. Löwis | bd928fe | 2011-10-14 10:20:37 +0200 | [diff] [blame] | 125 | _Py_IDENTIFIER(status); | 
| Martin v. Löwis | afe55bb | 2011-10-09 10:38:36 +0200 | [diff] [blame] | 126 |  | 
|  | 127 | PyObject *result = _PyObject_CallMethodId(pv, &PyId_status, "iii", typeStatus, cb1, cb2); | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 128 | if (result == NULL) | 
|  | 129 | return -1; | 
|  | 130 | Py_DECREF(result); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 131 | } | 
|  | 132 | return 0; | 
|  | 133 | } | 
|  | 134 |  | 
|  | 135 | static FNFCIGETNEXTCABINET(cb_getnextcabinet) | 
|  | 136 | { | 
|  | 137 | if (pv) { | 
| Martin v. Löwis | bd928fe | 2011-10-14 10:20:37 +0200 | [diff] [blame] | 138 | _Py_IDENTIFIER(getnextcabinet); | 
| Martin v. Löwis | afe55bb | 2011-10-09 10:38:36 +0200 | [diff] [blame] | 139 |  | 
|  | 140 | PyObject *result = _PyObject_CallMethodId(pv, &PyId_getnextcabinet, "i", pccab->iCab); | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 141 | if (result == NULL) | 
|  | 142 | return -1; | 
|  | 143 | if (!PyBytes_Check(result)) { | 
|  | 144 | PyErr_Format(PyExc_TypeError, | 
|  | 145 | "Incorrect return type %s from getnextcabinet", | 
|  | 146 | result->ob_type->tp_name); | 
|  | 147 | Py_DECREF(result); | 
|  | 148 | return FALSE; | 
|  | 149 | } | 
|  | 150 | strncpy(pccab->szCab, PyBytes_AsString(result), sizeof(pccab->szCab)); | 
|  | 151 | return TRUE; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 152 | } | 
|  | 153 | return FALSE; | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | static FNFCIGETOPENINFO(cb_getopeninfo) | 
|  | 157 | { | 
|  | 158 | BY_HANDLE_FILE_INFORMATION bhfi; | 
|  | 159 | FILETIME filetime; | 
|  | 160 | HANDLE handle; | 
|  | 161 |  | 
|  | 162 | /* Need Win32 handle to get time stamps */ | 
|  | 163 | handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 164 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 165 | if (handle == INVALID_HANDLE_VALUE) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 166 | return -1; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 167 |  | 
|  | 168 | if (GetFileInformationByHandle(handle, &bhfi) == FALSE) | 
|  | 169 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 170 | CloseHandle(handle); | 
|  | 171 | return -1; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 172 | } | 
|  | 173 |  | 
|  | 174 | FileTimeToLocalFileTime(&bhfi.ftLastWriteTime, &filetime); | 
|  | 175 | FileTimeToDosDateTime(&filetime, pdate, ptime); | 
|  | 176 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 177 | *pattribs = (int)(bhfi.dwFileAttributes & | 
|  | 178 | (_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH)); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 179 |  | 
|  | 180 | CloseHandle(handle); | 
|  | 181 |  | 
| Victor Stinner | daf4555 | 2013-08-28 00:53:59 +0200 | [diff] [blame] | 182 | return _open(pszName, _O_RDONLY | _O_BINARY | O_NOINHERIT); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 183 | } | 
|  | 184 |  | 
|  | 185 | static PyObject* fcicreate(PyObject* obj, PyObject* args) | 
|  | 186 | { | 
| Christian Heimes | 0bd4e11 | 2008-02-12 22:59:25 +0000 | [diff] [blame] | 187 | char *cabname, *p; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 188 | PyObject *files; | 
|  | 189 | CCAB ccab; | 
|  | 190 | HFCI hfci; | 
|  | 191 | ERF erf; | 
| Christian Heimes | 0bd4e11 | 2008-02-12 22:59:25 +0000 | [diff] [blame] | 192 | Py_ssize_t i; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 193 |  | 
|  | 194 |  | 
|  | 195 | if (!PyArg_ParseTuple(args, "sO:FCICreate", &cabname, &files)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 196 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 197 |  | 
|  | 198 | if (!PyList_Check(files)) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 199 | PyErr_SetString(PyExc_TypeError, "FCICreate expects a list"); | 
|  | 200 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 201 | } | 
|  | 202 |  | 
|  | 203 | ccab.cb = INT_MAX; /* no need to split CAB into multiple media */ | 
|  | 204 | ccab.cbFolderThresh = 1000000; /* flush directory after this many bytes */ | 
|  | 205 | ccab.cbReserveCFData = 0; | 
|  | 206 | ccab.cbReserveCFFolder = 0; | 
|  | 207 | ccab.cbReserveCFHeader = 0; | 
|  | 208 |  | 
|  | 209 | ccab.iCab = 1; | 
|  | 210 | ccab.iDisk = 1; | 
|  | 211 |  | 
|  | 212 | ccab.setID = 0; | 
|  | 213 | ccab.szDisk[0] = '\0'; | 
|  | 214 |  | 
| Christian Heimes | 0bd4e11 | 2008-02-12 22:59:25 +0000 | [diff] [blame] | 215 | for (i = 0, p = cabname; *p; p = CharNext(p)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 216 | if (*p == '\\' || *p == '/') | 
|  | 217 | i = p - cabname + 1; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 218 |  | 
| Christian Heimes | 0bd4e11 | 2008-02-12 22:59:25 +0000 | [diff] [blame] | 219 | if (i >= sizeof(ccab.szCabPath) || | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 220 | strlen(cabname+i) >= sizeof(ccab.szCab)) { | 
|  | 221 | PyErr_SetString(PyExc_ValueError, "path name too long"); | 
|  | 222 | return 0; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 223 | } | 
|  | 224 |  | 
| Christian Heimes | 0bd4e11 | 2008-02-12 22:59:25 +0000 | [diff] [blame] | 225 | if (i > 0) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 226 | memcpy(ccab.szCabPath, cabname, i); | 
|  | 227 | ccab.szCabPath[i] = '\0'; | 
|  | 228 | strcpy(ccab.szCab, cabname+i); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 229 | } else { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 230 | strcpy(ccab.szCabPath, ".\\"); | 
|  | 231 | strcpy(ccab.szCab, cabname); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 232 | } | 
|  | 233 |  | 
|  | 234 | hfci = FCICreate(&erf, cb_fileplaced, cb_alloc, cb_free, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 235 | cb_open, cb_read, cb_write, cb_close, cb_seek, cb_delete, | 
|  | 236 | cb_gettempfile, &ccab, NULL); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 237 |  | 
|  | 238 | if (hfci == NULL) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 239 | PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); | 
|  | 240 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 241 | } | 
|  | 242 |  | 
|  | 243 | for (i=0; i < PyList_GET_SIZE(files); i++) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 244 | PyObject *item = PyList_GET_ITEM(files, i); | 
|  | 245 | char *filename, *cabname; | 
| Zachary Ware | 0a29e89 | 2015-05-18 00:47:15 -0500 | [diff] [blame] | 246 |  | 
|  | 247 | if (!PyArg_ParseTuple(item, "ss", &filename, &cabname)) { | 
|  | 248 | PyErr_SetString(PyExc_TypeError, "FCICreate expects a list of tuples containing two strings"); | 
|  | 249 | FCIDestroy(hfci); | 
|  | 250 | return NULL; | 
|  | 251 | } | 
|  | 252 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 253 | if (!FCIAddFile(hfci, filename, cabname, FALSE, | 
|  | 254 | cb_getnextcabinet, cb_status, cb_getopeninfo, | 
|  | 255 | tcompTYPE_MSZIP)) | 
|  | 256 | goto err; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 257 | } | 
|  | 258 |  | 
|  | 259 | if (!FCIFlushCabinet(hfci, FALSE, cb_getnextcabinet, cb_status)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 260 | goto err; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 261 |  | 
|  | 262 | if (!FCIDestroy(hfci)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 263 | goto err; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 264 |  | 
|  | 265 | Py_INCREF(Py_None); | 
|  | 266 | return Py_None; | 
|  | 267 | err: | 
| Zachary Ware | 0a29e89 | 2015-05-18 00:47:15 -0500 | [diff] [blame] | 268 | if(erf.fError) | 
|  | 269 | PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */ | 
|  | 270 | else | 
|  | 271 | PyErr_SetString(PyExc_ValueError, "FCI general error"); | 
|  | 272 |  | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 273 | FCIDestroy(hfci); | 
|  | 274 | return NULL; | 
|  | 275 | } | 
|  | 276 |  | 
|  | 277 | typedef struct msiobj{ | 
|  | 278 | PyObject_HEAD | 
|  | 279 | MSIHANDLE h; | 
|  | 280 | }msiobj; | 
|  | 281 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 282 | static void | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 283 | msiobj_dealloc(msiobj* msidb) | 
|  | 284 | { | 
|  | 285 | MsiCloseHandle(msidb->h); | 
|  | 286 | msidb->h = 0; | 
|  | 287 | } | 
|  | 288 |  | 
|  | 289 | static PyObject* | 
|  | 290 | msiobj_close(msiobj* msidb, PyObject *args) | 
|  | 291 | { | 
|  | 292 | MsiCloseHandle(msidb->h); | 
|  | 293 | msidb->h = 0; | 
|  | 294 | Py_INCREF(Py_None); | 
|  | 295 | return Py_None; | 
|  | 296 | } | 
|  | 297 |  | 
|  | 298 | static PyObject* | 
|  | 299 | msierror(int status) | 
|  | 300 | { | 
|  | 301 | int code; | 
|  | 302 | char buf[2000]; | 
|  | 303 | char *res = buf; | 
|  | 304 | DWORD size = sizeof(buf); | 
|  | 305 | MSIHANDLE err = MsiGetLastErrorRecord(); | 
|  | 306 |  | 
|  | 307 | if (err == 0) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 308 | switch(status) { | 
|  | 309 | case ERROR_ACCESS_DENIED: | 
|  | 310 | PyErr_SetString(MSIError, "access denied"); | 
|  | 311 | return NULL; | 
|  | 312 | case ERROR_FUNCTION_FAILED: | 
|  | 313 | PyErr_SetString(MSIError, "function failed"); | 
|  | 314 | return NULL; | 
|  | 315 | case ERROR_INVALID_DATA: | 
|  | 316 | PyErr_SetString(MSIError, "invalid data"); | 
|  | 317 | return NULL; | 
|  | 318 | case ERROR_INVALID_HANDLE: | 
|  | 319 | PyErr_SetString(MSIError, "invalid handle"); | 
|  | 320 | return NULL; | 
|  | 321 | case ERROR_INVALID_STATE: | 
|  | 322 | PyErr_SetString(MSIError, "invalid state"); | 
|  | 323 | return NULL; | 
|  | 324 | case ERROR_INVALID_PARAMETER: | 
|  | 325 | PyErr_SetString(MSIError, "invalid parameter"); | 
|  | 326 | return NULL; | 
|  | 327 | default: | 
|  | 328 | PyErr_Format(MSIError, "unknown error %x", status); | 
|  | 329 | return NULL; | 
|  | 330 | } | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 331 | } | 
|  | 332 |  | 
|  | 333 | code = MsiRecordGetInteger(err, 1); /* XXX code */ | 
|  | 334 | if (MsiFormatRecord(0, err, res, &size) == ERROR_MORE_DATA) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 335 | res = malloc(size+1); | 
|  | 336 | MsiFormatRecord(0, err, res, &size); | 
|  | 337 | res[size]='\0'; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 338 | } | 
|  | 339 | MsiCloseHandle(err); | 
|  | 340 | PyErr_SetString(MSIError, res); | 
|  | 341 | if (res != buf) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 342 | free(res); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 343 | return NULL; | 
|  | 344 | } | 
|  | 345 |  | 
|  | 346 | /*************************** Record objects **********************/ | 
|  | 347 |  | 
|  | 348 | static PyObject* | 
|  | 349 | record_getfieldcount(msiobj* record, PyObject* args) | 
|  | 350 | { | 
| Christian Heimes | 217cfd1 | 2007-12-02 14:31:20 +0000 | [diff] [blame] | 351 | return PyLong_FromLong(MsiRecordGetFieldCount(record->h)); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 352 | } | 
|  | 353 |  | 
|  | 354 | static PyObject* | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 355 | record_getinteger(msiobj* record, PyObject* args) | 
|  | 356 | { | 
|  | 357 | unsigned int field; | 
|  | 358 | int status; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 359 |  | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 360 | if (!PyArg_ParseTuple(args, "I:GetInteger", &field)) | 
|  | 361 | return NULL; | 
|  | 362 | status = MsiRecordGetInteger(record->h, field); | 
|  | 363 | if (status == MSI_NULL_INTEGER){ | 
|  | 364 | PyErr_SetString(MSIError, "could not convert record field to integer"); | 
|  | 365 | return NULL; | 
|  | 366 | } | 
| Martin v. Löwis | 704d8b1 | 2008-06-02 11:32:23 +0000 | [diff] [blame] | 367 | return PyLong_FromLong((long) status); | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 368 | } | 
|  | 369 |  | 
|  | 370 | static PyObject* | 
|  | 371 | record_getstring(msiobj* record, PyObject* args) | 
|  | 372 | { | 
|  | 373 | unsigned int field; | 
|  | 374 | unsigned int status; | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 375 | WCHAR buf[2000]; | 
|  | 376 | WCHAR *res = buf; | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 377 | DWORD size = sizeof(buf); | 
|  | 378 | PyObject* string; | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 379 |  | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 380 | if (!PyArg_ParseTuple(args, "I:GetString", &field)) | 
|  | 381 | return NULL; | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 382 | status = MsiRecordGetStringW(record->h, field, res, &size); | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 383 | if (status == ERROR_MORE_DATA) { | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 384 | res = (WCHAR*) malloc((size + 1)*sizeof(WCHAR)); | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 385 | if (res == NULL) | 
|  | 386 | return PyErr_NoMemory(); | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 387 | status = MsiRecordGetStringW(record->h, field, res, &size); | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 388 | } | 
|  | 389 | if (status != ERROR_SUCCESS) | 
|  | 390 | return msierror((int) status); | 
| Victor Stinner | 9d3b93b | 2011-11-22 02:27:30 +0100 | [diff] [blame] | 391 | string = PyUnicode_FromWideChar(res, size); | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 392 | if (buf != res) | 
|  | 393 | free(res); | 
|  | 394 | return string; | 
|  | 395 | } | 
|  | 396 |  | 
|  | 397 | static PyObject* | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 398 | record_cleardata(msiobj* record, PyObject *args) | 
|  | 399 | { | 
|  | 400 | int status = MsiRecordClearData(record->h); | 
|  | 401 | if (status != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 402 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 403 |  | 
|  | 404 | Py_INCREF(Py_None); | 
|  | 405 | return Py_None; | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | static PyObject* | 
|  | 409 | record_setstring(msiobj* record, PyObject *args) | 
|  | 410 | { | 
|  | 411 | int status; | 
|  | 412 | int field; | 
| Victor Stinner | 9d3b93b | 2011-11-22 02:27:30 +0100 | [diff] [blame] | 413 | wchar_t *data; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 414 |  | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 415 | if (!PyArg_ParseTuple(args, "iu:SetString", &field, &data)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 416 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 417 |  | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 418 | if ((status = MsiRecordSetStringW(record->h, field, data)) != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 419 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 420 |  | 
|  | 421 | Py_INCREF(Py_None); | 
|  | 422 | return Py_None; | 
|  | 423 | } | 
|  | 424 |  | 
|  | 425 | static PyObject* | 
|  | 426 | record_setstream(msiobj* record, PyObject *args) | 
|  | 427 | { | 
|  | 428 | int status; | 
|  | 429 | int field; | 
| Victor Stinner | 9d3b93b | 2011-11-22 02:27:30 +0100 | [diff] [blame] | 430 | wchar_t *data; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 431 |  | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 432 | if (!PyArg_ParseTuple(args, "iu:SetStream", &field, &data)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 433 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 434 |  | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 435 | if ((status = MsiRecordSetStreamW(record->h, field, data)) != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 436 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 437 |  | 
|  | 438 | Py_INCREF(Py_None); | 
|  | 439 | return Py_None; | 
|  | 440 | } | 
|  | 441 |  | 
|  | 442 | static PyObject* | 
|  | 443 | record_setinteger(msiobj* record, PyObject *args) | 
|  | 444 | { | 
|  | 445 | int status; | 
|  | 446 | int field; | 
|  | 447 | int data; | 
|  | 448 |  | 
|  | 449 | if (!PyArg_ParseTuple(args, "ii:SetInteger", &field, &data)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 450 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 451 |  | 
|  | 452 | if ((status = MsiRecordSetInteger(record->h, field, data)) != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 453 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 454 |  | 
|  | 455 | Py_INCREF(Py_None); | 
|  | 456 | return Py_None; | 
|  | 457 | } | 
|  | 458 |  | 
|  | 459 |  | 
|  | 460 |  | 
|  | 461 | static PyMethodDef record_methods[] = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 462 | { "GetFieldCount", (PyCFunction)record_getfieldcount, METH_NOARGS, | 
|  | 463 | PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")}, | 
| Martin v. Löwis | e95593e | 2008-06-02 10:08:54 +0000 | [diff] [blame] | 464 | { "GetInteger", (PyCFunction)record_getinteger, METH_VARARGS, | 
|  | 465 | PyDoc_STR("GetInteger(field) -> int\nWraps MsiRecordGetInteger")}, | 
|  | 466 | { "GetString", (PyCFunction)record_getstring, METH_VARARGS, | 
|  | 467 | PyDoc_STR("GetString(field) -> string\nWraps MsiRecordGetString")}, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 468 | { "SetString", (PyCFunction)record_setstring, METH_VARARGS, | 
|  | 469 | PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")}, | 
|  | 470 | { "SetStream", (PyCFunction)record_setstream, METH_VARARGS, | 
|  | 471 | PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")}, | 
|  | 472 | { "SetInteger", (PyCFunction)record_setinteger, METH_VARARGS, | 
|  | 473 | PyDoc_STR("SetInteger(field,int) -> None\nWraps MsiRecordSetInteger")}, | 
|  | 474 | { "ClearData", (PyCFunction)record_cleardata, METH_NOARGS, | 
|  | 475 | PyDoc_STR("ClearData() -> int\nWraps MsiRecordGClearData")}, | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 476 | { NULL, NULL } | 
|  | 477 | }; | 
|  | 478 |  | 
|  | 479 | static PyTypeObject record_Type = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 480 | PyVarObject_HEAD_INIT(NULL, 0) | 
|  | 481 | "_msi.Record",          /*tp_name*/ | 
|  | 482 | sizeof(msiobj), /*tp_basicsize*/ | 
|  | 483 | 0,                      /*tp_itemsize*/ | 
|  | 484 | /* methods */ | 
|  | 485 | (destructor)msiobj_dealloc, /*tp_dealloc*/ | 
|  | 486 | 0,                      /*tp_print*/ | 
|  | 487 | 0,                      /*tp_getattr*/ | 
|  | 488 | 0,                      /*tp_setattr*/ | 
|  | 489 | 0,                      /*tp_reserved*/ | 
|  | 490 | 0,                      /*tp_repr*/ | 
|  | 491 | 0,                      /*tp_as_number*/ | 
|  | 492 | 0,                      /*tp_as_sequence*/ | 
|  | 493 | 0,                      /*tp_as_mapping*/ | 
|  | 494 | 0,                      /*tp_hash*/ | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 495 | 0,                      /*tp_call*/ | 
|  | 496 | 0,                      /*tp_str*/ | 
|  | 497 | PyObject_GenericGetAttr,/*tp_getattro*/ | 
|  | 498 | PyObject_GenericSetAttr,/*tp_setattro*/ | 
|  | 499 | 0,                      /*tp_as_buffer*/ | 
|  | 500 | Py_TPFLAGS_DEFAULT,     /*tp_flags*/ | 
|  | 501 | 0,                      /*tp_doc*/ | 
|  | 502 | 0,                      /*tp_traverse*/ | 
|  | 503 | 0,                      /*tp_clear*/ | 
|  | 504 | 0,                      /*tp_richcompare*/ | 
|  | 505 | 0,                      /*tp_weaklistoffset*/ | 
|  | 506 | 0,                      /*tp_iter*/ | 
|  | 507 | 0,                      /*tp_iternext*/ | 
|  | 508 | record_methods,           /*tp_methods*/ | 
|  | 509 | 0,                      /*tp_members*/ | 
|  | 510 | 0,                      /*tp_getset*/ | 
|  | 511 | 0,                      /*tp_base*/ | 
|  | 512 | 0,                      /*tp_dict*/ | 
|  | 513 | 0,                      /*tp_descr_get*/ | 
|  | 514 | 0,                      /*tp_descr_set*/ | 
|  | 515 | 0,                      /*tp_dictoffset*/ | 
|  | 516 | 0,                      /*tp_init*/ | 
|  | 517 | 0,                      /*tp_alloc*/ | 
|  | 518 | 0,                      /*tp_new*/ | 
|  | 519 | 0,                      /*tp_free*/ | 
|  | 520 | 0,                      /*tp_is_gc*/ | 
|  | 521 | }; | 
|  | 522 |  | 
|  | 523 | static PyObject* | 
|  | 524 | record_new(MSIHANDLE h) | 
|  | 525 | { | 
|  | 526 | msiobj *result = PyObject_NEW(struct msiobj, &record_Type); | 
|  | 527 |  | 
|  | 528 | if (!result) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 529 | MsiCloseHandle(h); | 
|  | 530 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 531 | } | 
|  | 532 |  | 
|  | 533 | result->h = h; | 
|  | 534 | return (PyObject*)result; | 
|  | 535 | } | 
|  | 536 |  | 
|  | 537 | /*************************** SummaryInformation objects **************/ | 
|  | 538 |  | 
|  | 539 | static PyObject* | 
|  | 540 | summary_getproperty(msiobj* si, PyObject *args) | 
|  | 541 | { | 
|  | 542 | int status; | 
|  | 543 | int field; | 
|  | 544 | PyObject *result; | 
|  | 545 | UINT type; | 
|  | 546 | INT ival; | 
|  | 547 | FILETIME fval; | 
|  | 548 | char sbuf[1000]; | 
|  | 549 | char *sval = sbuf; | 
|  | 550 | DWORD ssize = sizeof(sval); | 
|  | 551 |  | 
|  | 552 | if (!PyArg_ParseTuple(args, "i:GetProperty", &field)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 553 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 554 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 555 | status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival, | 
|  | 556 | &fval, sval, &ssize); | 
| Thomas Wouters | 89f507f | 2006-12-13 04:49:30 +0000 | [diff] [blame] | 557 | if (status == ERROR_MORE_DATA) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 558 | sval = malloc(ssize); | 
|  | 559 | status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival, | 
|  | 560 | &fval, sval, &ssize); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 561 | } | 
|  | 562 |  | 
|  | 563 | switch(type) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 564 | case VT_I2: case VT_I4: | 
|  | 565 | return PyLong_FromLong(ival); | 
|  | 566 | case VT_FILETIME: | 
|  | 567 | PyErr_SetString(PyExc_NotImplementedError, "FILETIME result"); | 
|  | 568 | return NULL; | 
|  | 569 | case VT_LPSTR: | 
|  | 570 | result = PyBytes_FromStringAndSize(sval, ssize); | 
|  | 571 | if (sval != sbuf) | 
|  | 572 | free(sval); | 
|  | 573 | return result; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 574 | } | 
|  | 575 | PyErr_Format(PyExc_NotImplementedError, "result of type %d", type); | 
|  | 576 | return NULL; | 
|  | 577 | } | 
|  | 578 |  | 
|  | 579 | static PyObject* | 
|  | 580 | summary_getpropertycount(msiobj* si, PyObject *args) | 
|  | 581 | { | 
|  | 582 | int status; | 
|  | 583 | UINT result; | 
|  | 584 |  | 
|  | 585 | status = MsiSummaryInfoGetPropertyCount(si->h, &result); | 
|  | 586 | if (status != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 587 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 588 |  | 
| Christian Heimes | 217cfd1 | 2007-12-02 14:31:20 +0000 | [diff] [blame] | 589 | return PyLong_FromLong(result); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 590 | } | 
|  | 591 |  | 
|  | 592 | static PyObject* | 
|  | 593 | summary_setproperty(msiobj* si, PyObject *args) | 
|  | 594 | { | 
|  | 595 | int status; | 
|  | 596 | int field; | 
|  | 597 | PyObject* data; | 
|  | 598 |  | 
|  | 599 | if (!PyArg_ParseTuple(args, "iO:SetProperty", &field, &data)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 600 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 601 |  | 
| Martin v. Löwis | 371bb50 | 2008-08-16 13:02:57 +0000 | [diff] [blame] | 602 | if (PyUnicode_Check(data)) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 603 | status = MsiSummaryInfoSetPropertyW(si->h, field, VT_LPSTR, | 
|  | 604 | 0, NULL, PyUnicode_AsUnicode(data)); | 
| Martin v. Löwis | d1a1d1e | 2007-12-04 22:10:37 +0000 | [diff] [blame] | 605 | } else if (PyLong_CheckExact(data)) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 606 | long value = PyLong_AsLong(data); | 
|  | 607 | if (value == -1 && PyErr_Occurred()) { | 
|  | 608 | return NULL; | 
|  | 609 | } | 
|  | 610 | status = MsiSummaryInfoSetProperty(si->h, field, VT_I4, | 
|  | 611 | value, NULL, NULL); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 612 | } else { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 613 | PyErr_SetString(PyExc_TypeError, "unsupported type"); | 
|  | 614 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 615 | } | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 616 |  | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 617 | if (status != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 618 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 619 |  | 
|  | 620 | Py_INCREF(Py_None); | 
|  | 621 | return Py_None; | 
|  | 622 | } | 
|  | 623 |  | 
|  | 624 |  | 
|  | 625 | static PyObject* | 
|  | 626 | summary_persist(msiobj* si, PyObject *args) | 
|  | 627 | { | 
|  | 628 | int status; | 
|  | 629 |  | 
|  | 630 | status = MsiSummaryInfoPersist(si->h); | 
|  | 631 | if (status != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 632 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 633 | Py_INCREF(Py_None); | 
|  | 634 | return Py_None; | 
|  | 635 | } | 
|  | 636 |  | 
|  | 637 | static PyMethodDef summary_methods[] = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 638 | { "GetProperty", (PyCFunction)summary_getproperty, METH_VARARGS, | 
|  | 639 | PyDoc_STR("GetProperty(propid) -> value\nWraps MsiSummaryInfoGetProperty")}, | 
|  | 640 | { "GetPropertyCount", (PyCFunction)summary_getpropertycount, METH_NOARGS, | 
|  | 641 | PyDoc_STR("GetProperty() -> int\nWraps MsiSummaryInfoGetPropertyCount")}, | 
|  | 642 | { "SetProperty", (PyCFunction)summary_setproperty, METH_VARARGS, | 
|  | 643 | PyDoc_STR("SetProperty(value) -> None\nWraps MsiSummaryInfoProperty")}, | 
|  | 644 | { "Persist", (PyCFunction)summary_persist, METH_NOARGS, | 
|  | 645 | PyDoc_STR("Persist() -> None\nWraps MsiSummaryInfoPersist")}, | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 646 | { NULL, NULL } | 
|  | 647 | }; | 
|  | 648 |  | 
|  | 649 | static PyTypeObject summary_Type = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 650 | PyVarObject_HEAD_INIT(NULL, 0) | 
|  | 651 | "_msi.SummaryInformation",              /*tp_name*/ | 
|  | 652 | sizeof(msiobj), /*tp_basicsize*/ | 
|  | 653 | 0,                      /*tp_itemsize*/ | 
|  | 654 | /* methods */ | 
|  | 655 | (destructor)msiobj_dealloc, /*tp_dealloc*/ | 
|  | 656 | 0,                      /*tp_print*/ | 
|  | 657 | 0,                      /*tp_getattr*/ | 
|  | 658 | 0,                      /*tp_setattr*/ | 
|  | 659 | 0,                      /*tp_reserved*/ | 
|  | 660 | 0,                      /*tp_repr*/ | 
|  | 661 | 0,                      /*tp_as_number*/ | 
|  | 662 | 0,                      /*tp_as_sequence*/ | 
|  | 663 | 0,                      /*tp_as_mapping*/ | 
|  | 664 | 0,                      /*tp_hash*/ | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 665 | 0,                      /*tp_call*/ | 
|  | 666 | 0,                      /*tp_str*/ | 
|  | 667 | PyObject_GenericGetAttr,/*tp_getattro*/ | 
|  | 668 | PyObject_GenericSetAttr,/*tp_setattro*/ | 
|  | 669 | 0,                      /*tp_as_buffer*/ | 
|  | 670 | Py_TPFLAGS_DEFAULT,     /*tp_flags*/ | 
|  | 671 | 0,                      /*tp_doc*/ | 
|  | 672 | 0,                      /*tp_traverse*/ | 
|  | 673 | 0,                      /*tp_clear*/ | 
|  | 674 | 0,                      /*tp_richcompare*/ | 
|  | 675 | 0,                      /*tp_weaklistoffset*/ | 
|  | 676 | 0,                      /*tp_iter*/ | 
|  | 677 | 0,                      /*tp_iternext*/ | 
|  | 678 | summary_methods,        /*tp_methods*/ | 
|  | 679 | 0,                      /*tp_members*/ | 
|  | 680 | 0,                      /*tp_getset*/ | 
|  | 681 | 0,                      /*tp_base*/ | 
|  | 682 | 0,                      /*tp_dict*/ | 
|  | 683 | 0,                      /*tp_descr_get*/ | 
|  | 684 | 0,                      /*tp_descr_set*/ | 
|  | 685 | 0,                      /*tp_dictoffset*/ | 
|  | 686 | 0,                      /*tp_init*/ | 
|  | 687 | 0,                      /*tp_alloc*/ | 
|  | 688 | 0,                      /*tp_new*/ | 
|  | 689 | 0,                      /*tp_free*/ | 
|  | 690 | 0,                      /*tp_is_gc*/ | 
|  | 691 | }; | 
|  | 692 |  | 
|  | 693 | /*************************** View objects **************/ | 
|  | 694 |  | 
|  | 695 | static PyObject* | 
|  | 696 | view_execute(msiobj *view, PyObject*args) | 
|  | 697 | { | 
|  | 698 | int status; | 
|  | 699 | MSIHANDLE params = 0; | 
|  | 700 | PyObject *oparams = Py_None; | 
|  | 701 |  | 
|  | 702 | if (!PyArg_ParseTuple(args, "O:Execute", &oparams)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 703 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 704 |  | 
|  | 705 | if (oparams != Py_None) { | 
|  | 706 | if (oparams->ob_type != &record_Type) { | 
|  | 707 | PyErr_SetString(PyExc_TypeError, "Execute argument must be a record"); | 
|  | 708 | return NULL; | 
|  | 709 | } | 
|  | 710 | params = ((msiobj*)oparams)->h; | 
|  | 711 | } | 
|  | 712 |  | 
|  | 713 | status = MsiViewExecute(view->h, params); | 
|  | 714 | if (status != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 715 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 716 |  | 
|  | 717 | Py_INCREF(Py_None); | 
|  | 718 | return Py_None; | 
|  | 719 | } | 
|  | 720 |  | 
|  | 721 | static PyObject* | 
|  | 722 | view_fetch(msiobj *view, PyObject*args) | 
|  | 723 | { | 
|  | 724 | int status; | 
|  | 725 | MSIHANDLE result; | 
|  | 726 |  | 
|  | 727 | if ((status = MsiViewFetch(view->h, &result)) != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 728 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 729 |  | 
|  | 730 | return record_new(result); | 
|  | 731 | } | 
|  | 732 |  | 
|  | 733 | static PyObject* | 
|  | 734 | view_getcolumninfo(msiobj *view, PyObject *args) | 
|  | 735 | { | 
|  | 736 | int status; | 
|  | 737 | int kind; | 
|  | 738 | MSIHANDLE result; | 
|  | 739 |  | 
|  | 740 | if (!PyArg_ParseTuple(args, "i:GetColumnInfo", &kind)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 741 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 742 |  | 
|  | 743 | if ((status = MsiViewGetColumnInfo(view->h, kind, &result)) != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 744 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 745 |  | 
|  | 746 | return record_new(result); | 
|  | 747 | } | 
|  | 748 |  | 
|  | 749 | static PyObject* | 
|  | 750 | view_modify(msiobj *view, PyObject *args) | 
|  | 751 | { | 
|  | 752 | int kind; | 
|  | 753 | PyObject *data; | 
|  | 754 | int status; | 
|  | 755 |  | 
|  | 756 | if (!PyArg_ParseTuple(args, "iO:Modify", &kind, &data)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 757 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 758 |  | 
|  | 759 | if (data->ob_type != &record_Type) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 760 | PyErr_SetString(PyExc_TypeError, "Modify expects a record object"); | 
|  | 761 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 762 | } | 
|  | 763 |  | 
|  | 764 | if ((status = MsiViewModify(view->h, kind, ((msiobj*)data)->h)) != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 765 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 766 |  | 
|  | 767 | Py_INCREF(Py_None); | 
|  | 768 | return Py_None; | 
|  | 769 | } | 
|  | 770 |  | 
|  | 771 | static PyObject* | 
|  | 772 | view_close(msiobj *view, PyObject*args) | 
|  | 773 | { | 
|  | 774 | int status; | 
|  | 775 |  | 
|  | 776 | if ((status = MsiViewClose(view->h)) != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 777 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 778 |  | 
|  | 779 | Py_INCREF(Py_None); | 
|  | 780 | return Py_None; | 
|  | 781 | } | 
|  | 782 |  | 
|  | 783 | static PyMethodDef view_methods[] = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 784 | { "Execute", (PyCFunction)view_execute, METH_VARARGS, | 
|  | 785 | PyDoc_STR("Execute(params=None) -> None\nWraps MsiViewExecute")}, | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 786 | { "GetColumnInfo", (PyCFunction)view_getcolumninfo, METH_VARARGS, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 787 | PyDoc_STR("GetColumnInfo() -> result\nWraps MsiGetColumnInfo")}, | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 788 | { "Fetch", (PyCFunction)view_fetch, METH_NOARGS, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 789 | PyDoc_STR("Fetch() -> result\nWraps MsiViewFetch")}, | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 790 | { "Modify", (PyCFunction)view_modify, METH_VARARGS, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 791 | PyDoc_STR("Modify(mode,record) -> None\nWraps MsiViewModify")}, | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 792 | { "Close", (PyCFunction)view_close, METH_NOARGS, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 793 | PyDoc_STR("Close() -> result\nWraps MsiViewClose")}, | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 794 | { NULL, NULL } | 
|  | 795 | }; | 
|  | 796 |  | 
|  | 797 | static PyTypeObject msiview_Type = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 798 | PyVarObject_HEAD_INIT(NULL, 0) | 
|  | 799 | "_msi.View",            /*tp_name*/ | 
|  | 800 | sizeof(msiobj), /*tp_basicsize*/ | 
|  | 801 | 0,                      /*tp_itemsize*/ | 
|  | 802 | /* methods */ | 
|  | 803 | (destructor)msiobj_dealloc, /*tp_dealloc*/ | 
|  | 804 | 0,                      /*tp_print*/ | 
|  | 805 | 0,                      /*tp_getattr*/ | 
|  | 806 | 0,                      /*tp_setattr*/ | 
|  | 807 | 0,                      /*tp_reserved*/ | 
|  | 808 | 0,                      /*tp_repr*/ | 
|  | 809 | 0,                      /*tp_as_number*/ | 
|  | 810 | 0,                      /*tp_as_sequence*/ | 
|  | 811 | 0,                      /*tp_as_mapping*/ | 
|  | 812 | 0,                      /*tp_hash*/ | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 813 | 0,                      /*tp_call*/ | 
|  | 814 | 0,                      /*tp_str*/ | 
|  | 815 | PyObject_GenericGetAttr,/*tp_getattro*/ | 
|  | 816 | PyObject_GenericSetAttr,/*tp_setattro*/ | 
|  | 817 | 0,                      /*tp_as_buffer*/ | 
|  | 818 | Py_TPFLAGS_DEFAULT,     /*tp_flags*/ | 
|  | 819 | 0,                      /*tp_doc*/ | 
|  | 820 | 0,                      /*tp_traverse*/ | 
|  | 821 | 0,                      /*tp_clear*/ | 
|  | 822 | 0,                      /*tp_richcompare*/ | 
|  | 823 | 0,                      /*tp_weaklistoffset*/ | 
|  | 824 | 0,                      /*tp_iter*/ | 
|  | 825 | 0,                      /*tp_iternext*/ | 
|  | 826 | view_methods,           /*tp_methods*/ | 
|  | 827 | 0,                      /*tp_members*/ | 
|  | 828 | 0,                      /*tp_getset*/ | 
|  | 829 | 0,                      /*tp_base*/ | 
|  | 830 | 0,                      /*tp_dict*/ | 
|  | 831 | 0,                      /*tp_descr_get*/ | 
|  | 832 | 0,                      /*tp_descr_set*/ | 
|  | 833 | 0,                      /*tp_dictoffset*/ | 
|  | 834 | 0,                      /*tp_init*/ | 
|  | 835 | 0,                      /*tp_alloc*/ | 
|  | 836 | 0,                      /*tp_new*/ | 
|  | 837 | 0,                      /*tp_free*/ | 
|  | 838 | 0,                      /*tp_is_gc*/ | 
|  | 839 | }; | 
|  | 840 |  | 
|  | 841 | /*************************** Database objects **************/ | 
|  | 842 |  | 
|  | 843 | static PyObject* | 
|  | 844 | msidb_openview(msiobj *msidb, PyObject *args) | 
|  | 845 | { | 
|  | 846 | int status; | 
|  | 847 | char *sql; | 
|  | 848 | MSIHANDLE hView; | 
|  | 849 | msiobj *result; | 
|  | 850 |  | 
|  | 851 | if (!PyArg_ParseTuple(args, "s:OpenView", &sql)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 852 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 853 |  | 
|  | 854 | if ((status = MsiDatabaseOpenView(msidb->h, sql, &hView)) != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 855 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 856 |  | 
|  | 857 | result = PyObject_NEW(struct msiobj, &msiview_Type); | 
|  | 858 | if (!result) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 859 | MsiCloseHandle(hView); | 
|  | 860 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 861 | } | 
|  | 862 |  | 
|  | 863 | result->h = hView; | 
|  | 864 | return (PyObject*)result; | 
|  | 865 | } | 
|  | 866 |  | 
|  | 867 | static PyObject* | 
|  | 868 | msidb_commit(msiobj *msidb, PyObject *args) | 
|  | 869 | { | 
|  | 870 | int status; | 
|  | 871 |  | 
|  | 872 | if ((status = MsiDatabaseCommit(msidb->h)) != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 873 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 874 |  | 
|  | 875 | Py_INCREF(Py_None); | 
|  | 876 | return Py_None; | 
|  | 877 | } | 
|  | 878 |  | 
|  | 879 | static PyObject* | 
|  | 880 | msidb_getsummaryinformation(msiobj *db, PyObject *args) | 
|  | 881 | { | 
|  | 882 | int status; | 
|  | 883 | int count; | 
|  | 884 | MSIHANDLE result; | 
|  | 885 | msiobj *oresult; | 
|  | 886 |  | 
|  | 887 | if (!PyArg_ParseTuple(args, "i:GetSummaryInformation", &count)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 888 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 889 |  | 
|  | 890 | status = MsiGetSummaryInformation(db->h, NULL, count, &result); | 
|  | 891 | if (status != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 892 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 893 |  | 
|  | 894 | oresult = PyObject_NEW(struct msiobj, &summary_Type); | 
|  | 895 | if (!result) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 896 | MsiCloseHandle(result); | 
|  | 897 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 898 | } | 
|  | 899 |  | 
|  | 900 | oresult->h = result; | 
|  | 901 | return (PyObject*)oresult; | 
|  | 902 | } | 
|  | 903 |  | 
|  | 904 | static PyMethodDef db_methods[] = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 905 | { "OpenView", (PyCFunction)msidb_openview, METH_VARARGS, | 
|  | 906 | PyDoc_STR("OpenView(sql) -> viewobj\nWraps MsiDatabaseOpenView")}, | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 907 | { "Commit", (PyCFunction)msidb_commit, METH_NOARGS, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 908 | PyDoc_STR("Commit() -> None\nWraps MsiDatabaseCommit")}, | 
|  | 909 | { "GetSummaryInformation", (PyCFunction)msidb_getsummaryinformation, METH_VARARGS, | 
|  | 910 | PyDoc_STR("GetSummaryInformation(updateCount) -> viewobj\nWraps MsiGetSummaryInformation")}, | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 911 | { NULL, NULL } | 
|  | 912 | }; | 
|  | 913 |  | 
|  | 914 | static PyTypeObject msidb_Type = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 915 | PyVarObject_HEAD_INIT(NULL, 0) | 
|  | 916 | "_msi.Database",                /*tp_name*/ | 
|  | 917 | sizeof(msiobj), /*tp_basicsize*/ | 
|  | 918 | 0,                      /*tp_itemsize*/ | 
|  | 919 | /* methods */ | 
|  | 920 | (destructor)msiobj_dealloc, /*tp_dealloc*/ | 
|  | 921 | 0,                      /*tp_print*/ | 
|  | 922 | 0,                      /*tp_getattr*/ | 
|  | 923 | 0,                      /*tp_setattr*/ | 
|  | 924 | 0,                      /*tp_reserved*/ | 
|  | 925 | 0,                      /*tp_repr*/ | 
|  | 926 | 0,                      /*tp_as_number*/ | 
|  | 927 | 0,                      /*tp_as_sequence*/ | 
|  | 928 | 0,                      /*tp_as_mapping*/ | 
|  | 929 | 0,                      /*tp_hash*/ | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 930 | 0,                      /*tp_call*/ | 
|  | 931 | 0,                      /*tp_str*/ | 
|  | 932 | PyObject_GenericGetAttr,/*tp_getattro*/ | 
|  | 933 | PyObject_GenericSetAttr,/*tp_setattro*/ | 
|  | 934 | 0,                      /*tp_as_buffer*/ | 
|  | 935 | Py_TPFLAGS_DEFAULT,     /*tp_flags*/ | 
|  | 936 | 0,                      /*tp_doc*/ | 
|  | 937 | 0,                      /*tp_traverse*/ | 
|  | 938 | 0,                      /*tp_clear*/ | 
|  | 939 | 0,                      /*tp_richcompare*/ | 
|  | 940 | 0,                      /*tp_weaklistoffset*/ | 
|  | 941 | 0,                      /*tp_iter*/ | 
|  | 942 | 0,                      /*tp_iternext*/ | 
|  | 943 | db_methods,             /*tp_methods*/ | 
|  | 944 | 0,                      /*tp_members*/ | 
|  | 945 | 0,                      /*tp_getset*/ | 
|  | 946 | 0,                      /*tp_base*/ | 
|  | 947 | 0,                      /*tp_dict*/ | 
|  | 948 | 0,                      /*tp_descr_get*/ | 
|  | 949 | 0,                      /*tp_descr_set*/ | 
|  | 950 | 0,                      /*tp_dictoffset*/ | 
|  | 951 | 0,                      /*tp_init*/ | 
|  | 952 | 0,                      /*tp_alloc*/ | 
|  | 953 | 0,                      /*tp_new*/ | 
|  | 954 | 0,                      /*tp_free*/ | 
|  | 955 | 0,                      /*tp_is_gc*/ | 
|  | 956 | }; | 
|  | 957 |  | 
|  | 958 | static PyObject* msiopendb(PyObject *obj, PyObject *args) | 
|  | 959 | { | 
|  | 960 | int status; | 
|  | 961 | char *path; | 
|  | 962 | int persist; | 
|  | 963 | MSIHANDLE h; | 
|  | 964 | msiobj *result; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 965 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 966 | if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist)) | 
|  | 967 | return NULL; | 
|  | 968 |  | 
|  | 969 | status = MsiOpenDatabase(path, (LPCSTR)persist, &h); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 970 | if (status != ERROR_SUCCESS) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 971 | return msierror(status); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 972 |  | 
|  | 973 | result = PyObject_NEW(struct msiobj, &msidb_Type); | 
|  | 974 | if (!result) { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 975 | MsiCloseHandle(h); | 
|  | 976 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 977 | } | 
|  | 978 | result->h = h; | 
|  | 979 | return (PyObject*)result; | 
|  | 980 | } | 
|  | 981 |  | 
|  | 982 | static PyObject* | 
|  | 983 | createrecord(PyObject *o, PyObject *args) | 
|  | 984 | { | 
|  | 985 | int count; | 
|  | 986 | MSIHANDLE h; | 
|  | 987 |  | 
|  | 988 | if (!PyArg_ParseTuple(args, "i:CreateRecord", &count)) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 989 | return NULL; | 
|  | 990 |  | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 991 | h = MsiCreateRecord(count); | 
|  | 992 | if (h == 0) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 993 | return msierror(0); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 994 |  | 
|  | 995 | return record_new(h); | 
|  | 996 | } | 
|  | 997 |  | 
|  | 998 |  | 
|  | 999 | static PyMethodDef msi_methods[] = { | 
|  | 1000 | {"UuidCreate", (PyCFunction)uuidcreate, METH_NOARGS, | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 1001 | PyDoc_STR("UuidCreate() -> string")}, | 
|  | 1002 | {"FCICreate",   (PyCFunction)fcicreate, METH_VARARGS, | 
|  | 1003 | PyDoc_STR("fcicreate(cabname,files) -> None")}, | 
|  | 1004 | {"OpenDatabase", (PyCFunction)msiopendb, METH_VARARGS, | 
|  | 1005 | PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiOpenDatabase")}, | 
|  | 1006 | {"CreateRecord", (PyCFunction)createrecord, METH_VARARGS, | 
|  | 1007 | PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiCreateRecord")}, | 
|  | 1008 | {NULL,          NULL}           /* sentinel */ | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1009 | }; | 
|  | 1010 |  | 
|  | 1011 | static char msi_doc[] = "Documentation"; | 
|  | 1012 |  | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 1013 |  | 
|  | 1014 | static struct PyModuleDef _msimodule = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 1015 | PyModuleDef_HEAD_INIT, | 
|  | 1016 | "_msi", | 
|  | 1017 | msi_doc, | 
|  | 1018 | -1, | 
|  | 1019 | msi_methods, | 
|  | 1020 | NULL, | 
|  | 1021 | NULL, | 
|  | 1022 | NULL, | 
|  | 1023 | NULL | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 1024 | }; | 
|  | 1025 |  | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1026 | PyMODINIT_FUNC | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 1027 | PyInit__msi(void) | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1028 | { | 
|  | 1029 | PyObject *m; | 
|  | 1030 |  | 
| Martin v. Löwis | 1a21451 | 2008-06-11 05:26:20 +0000 | [diff] [blame] | 1031 | m = PyModule_Create(&_msimodule); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1032 | if (m == NULL) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 1033 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1034 |  | 
|  | 1035 | PyModule_AddIntConstant(m, "MSIDBOPEN_CREATEDIRECT", (int)MSIDBOPEN_CREATEDIRECT); | 
|  | 1036 | PyModule_AddIntConstant(m, "MSIDBOPEN_CREATE", (int)MSIDBOPEN_CREATE); | 
|  | 1037 | PyModule_AddIntConstant(m, "MSIDBOPEN_DIRECT", (int)MSIDBOPEN_DIRECT); | 
|  | 1038 | PyModule_AddIntConstant(m, "MSIDBOPEN_READONLY", (int)MSIDBOPEN_READONLY); | 
|  | 1039 | PyModule_AddIntConstant(m, "MSIDBOPEN_TRANSACT", (int)MSIDBOPEN_TRANSACT); | 
|  | 1040 | PyModule_AddIntConstant(m, "MSIDBOPEN_PATCHFILE", (int)MSIDBOPEN_PATCHFILE); | 
|  | 1041 |  | 
| Charles-Francois Natali | 74ca886 | 2013-05-20 19:13:19 +0200 | [diff] [blame] | 1042 | PyModule_AddIntMacro(m, MSICOLINFO_NAMES); | 
|  | 1043 | PyModule_AddIntMacro(m, MSICOLINFO_TYPES); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1044 |  | 
| Charles-Francois Natali | 74ca886 | 2013-05-20 19:13:19 +0200 | [diff] [blame] | 1045 | PyModule_AddIntMacro(m, MSIMODIFY_SEEK); | 
|  | 1046 | PyModule_AddIntMacro(m, MSIMODIFY_REFRESH); | 
|  | 1047 | PyModule_AddIntMacro(m, MSIMODIFY_INSERT); | 
|  | 1048 | PyModule_AddIntMacro(m, MSIMODIFY_UPDATE); | 
|  | 1049 | PyModule_AddIntMacro(m, MSIMODIFY_ASSIGN); | 
|  | 1050 | PyModule_AddIntMacro(m, MSIMODIFY_REPLACE); | 
|  | 1051 | PyModule_AddIntMacro(m, MSIMODIFY_MERGE); | 
|  | 1052 | PyModule_AddIntMacro(m, MSIMODIFY_DELETE); | 
|  | 1053 | PyModule_AddIntMacro(m, MSIMODIFY_INSERT_TEMPORARY); | 
|  | 1054 | PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE); | 
|  | 1055 | PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_NEW); | 
|  | 1056 | PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_FIELD); | 
|  | 1057 | PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_DELETE); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1058 |  | 
| Charles-Francois Natali | 74ca886 | 2013-05-20 19:13:19 +0200 | [diff] [blame] | 1059 | PyModule_AddIntMacro(m, PID_CODEPAGE); | 
|  | 1060 | PyModule_AddIntMacro(m, PID_TITLE); | 
|  | 1061 | PyModule_AddIntMacro(m, PID_SUBJECT); | 
|  | 1062 | PyModule_AddIntMacro(m, PID_AUTHOR); | 
|  | 1063 | PyModule_AddIntMacro(m, PID_KEYWORDS); | 
|  | 1064 | PyModule_AddIntMacro(m, PID_COMMENTS); | 
|  | 1065 | PyModule_AddIntMacro(m, PID_TEMPLATE); | 
|  | 1066 | PyModule_AddIntMacro(m, PID_LASTAUTHOR); | 
|  | 1067 | PyModule_AddIntMacro(m, PID_REVNUMBER); | 
|  | 1068 | PyModule_AddIntMacro(m, PID_LASTPRINTED); | 
|  | 1069 | PyModule_AddIntMacro(m, PID_CREATE_DTM); | 
|  | 1070 | PyModule_AddIntMacro(m, PID_LASTSAVE_DTM); | 
|  | 1071 | PyModule_AddIntMacro(m, PID_PAGECOUNT); | 
|  | 1072 | PyModule_AddIntMacro(m, PID_WORDCOUNT); | 
|  | 1073 | PyModule_AddIntMacro(m, PID_CHARCOUNT); | 
|  | 1074 | PyModule_AddIntMacro(m, PID_APPNAME); | 
|  | 1075 | PyModule_AddIntMacro(m, PID_SECURITY); | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1076 |  | 
|  | 1077 | MSIError = PyErr_NewException ("_msi.MSIError", NULL, NULL); | 
|  | 1078 | if (!MSIError) | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 1079 | return NULL; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1080 | PyModule_AddObject(m, "MSIError", MSIError); | 
| Amaury Forgeot d'Arc | bf9e966 | 2008-06-17 21:39:46 +0000 | [diff] [blame] | 1081 | return m; | 
| Martin v. Löwis | fbab90e | 2006-03-05 13:36:04 +0000 | [diff] [blame] | 1082 | } |