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