blob: 0487743b59aaacd2980b64ab455279bbd3f77c8f [file] [log] [blame]
Martin v. Löwisfbab90e2006-03-05 13:36:041/* Helper library for MSI creation with Python.
Florent Xiclunac934f322010-09-03 23:47:322 * Copyright (C) 2005 Martin v. Löwis
Martin v. Löwisdd860ca2006-03-05 13:39:103 * Licensed to PSF under a contributor agreement.
Martin v. Löwisfbab90e2006-03-05 13:36:044 */
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
15static PyObject *MSIError;
16
17static PyObject*
18uuidcreate(PyObject* obj, PyObject*args)
19{
20 UUID result;
Victor Stinner9d3b93b2011-11-22 01:27:3021 wchar_t *cresult;
Martin v. Löwisfbab90e2006-03-05 13:36:0422 PyObject *oresult;
Antoine Pitrouf95a1b32010-05-09 15:52:2723
Martin v. Löwisfbab90e2006-03-05 13:36:0424 /* 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 Pitrouf95a1b32010-05-09 15:52:2729 PyErr_SetString(PyExc_NotImplementedError, "processing 'no address' result");
30 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:0431 }
32
Martin v. Löwis371bb502008-08-16 13:02:5733 if (UuidToStringW(&result, &cresult) == RPC_S_OUT_OF_MEMORY) {
Antoine Pitrouf95a1b32010-05-09 15:52:2734 PyErr_SetString(PyExc_MemoryError, "out of memory in uuidgen");
35 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:0436 }
37
Victor Stinner9d3b93b2011-11-22 01:27:3038 oresult = PyUnicode_FromWideChar(cresult, wcslen(cresult));
Martin v. Löwis371bb502008-08-16 13:02:5739 RpcStringFreeW(&cresult);
Martin v. Löwisfbab90e2006-03-05 13:36:0440 return oresult;
41
42}
43
44/* FCI callback functions */
45
46static FNFCIALLOC(cb_alloc)
47{
48 return malloc(cb);
49}
50
51static FNFCIFREE(cb_free)
52{
53 free(memory);
54}
55
56static FNFCIOPEN(cb_open)
57{
Victor Stinnerdaf45552013-08-27 22:53:5958 int result = _open(pszFile, oflag | O_NOINHERIT, pmode);
Martin v. Löwisfbab90e2006-03-05 13:36:0459 if (result == -1)
Antoine Pitrouf95a1b32010-05-09 15:52:2760 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:0461 return result;
62}
63
64static FNFCIREAD(cb_read)
65{
Victor Stinner67158282013-11-19 23:14:4966 UINT result = (UINT)_read((int)hf, memory, cb);
Martin v. Löwisfbab90e2006-03-05 13:36:0467 if (result != cb)
Antoine Pitrouf95a1b32010-05-09 15:52:2768 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:0469 return result;
70}
71
72static FNFCIWRITE(cb_write)
73{
Victor Stinner67158282013-11-19 23:14:4974 UINT result = (UINT)_write((int)hf, memory, cb);
Martin v. Löwisfbab90e2006-03-05 13:36:0475 if (result != cb)
Antoine Pitrouf95a1b32010-05-09 15:52:2776 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:0477 return result;
78}
79
80static FNFCICLOSE(cb_close)
81{
Victor Stinner67158282013-11-19 23:14:4982 int result = _close((int)hf);
Martin v. Löwisfbab90e2006-03-05 13:36:0483 if (result != 0)
Antoine Pitrouf95a1b32010-05-09 15:52:2784 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:0485 return result;
86}
87
88static FNFCISEEK(cb_seek)
89{
Victor Stinner67158282013-11-19 23:14:4990 long result = (long)_lseek((int)hf, dist, seektype);
Martin v. Löwisfbab90e2006-03-05 13:36:0491 if (result == -1)
Antoine Pitrouf95a1b32010-05-09 15:52:2792 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:0493 return result;
94}
95
96static FNFCIDELETE(cb_delete)
97{
98 int result = remove(pszFile);
99 if (result != 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27100 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:04101 return result;
102}
103
104static FNFCIFILEPLACED(cb_fileplaced)
105{
106 return 0;
107}
108
109static FNFCIGETTEMPFILE(cb_gettempfile)
110{
111 char *name = _tempnam("", "tmp");
112 if ((name != NULL) && ((int)strlen(name) < cbTempName)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27113 strcpy(pszTempName, name);
114 free(name);
115 return TRUE;
Martin v. Löwisfbab90e2006-03-05 13:36:04116 }
117
118 if (name) free(name);
119 return FALSE;
120}
121
122static FNFCISTATUS(cb_status)
123{
124 if (pv) {
Martin v. Löwisbd928fe2011-10-14 08:20:37125 _Py_IDENTIFIER(status);
Martin v. Löwisafe55bb2011-10-09 08:38:36126
127 PyObject *result = _PyObject_CallMethodId(pv, &PyId_status, "iii", typeStatus, cb1, cb2);
Antoine Pitrouf95a1b32010-05-09 15:52:27128 if (result == NULL)
129 return -1;
130 Py_DECREF(result);
Martin v. Löwisfbab90e2006-03-05 13:36:04131 }
132 return 0;
133}
134
135static FNFCIGETNEXTCABINET(cb_getnextcabinet)
136{
137 if (pv) {
Martin v. Löwisbd928fe2011-10-14 08:20:37138 _Py_IDENTIFIER(getnextcabinet);
Martin v. Löwisafe55bb2011-10-09 08:38:36139
140 PyObject *result = _PyObject_CallMethodId(pv, &PyId_getnextcabinet, "i", pccab->iCab);
Antoine Pitrouf95a1b32010-05-09 15:52:27141 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öwisfbab90e2006-03-05 13:36:04152 }
153 return FALSE;
154}
155
156static 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 Pitrouf95a1b32010-05-09 15:52:27164 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
Martin v. Löwisfbab90e2006-03-05 13:36:04165 if (handle == INVALID_HANDLE_VALUE)
Antoine Pitrouf95a1b32010-05-09 15:52:27166 return -1;
Martin v. Löwisfbab90e2006-03-05 13:36:04167
168 if (GetFileInformationByHandle(handle, &bhfi) == FALSE)
169 {
Antoine Pitrouf95a1b32010-05-09 15:52:27170 CloseHandle(handle);
171 return -1;
Martin v. Löwisfbab90e2006-03-05 13:36:04172 }
173
174 FileTimeToLocalFileTime(&bhfi.ftLastWriteTime, &filetime);
175 FileTimeToDosDateTime(&filetime, pdate, ptime);
176
Antoine Pitrouf95a1b32010-05-09 15:52:27177 *pattribs = (int)(bhfi.dwFileAttributes &
178 (_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH));
Martin v. Löwisfbab90e2006-03-05 13:36:04179
180 CloseHandle(handle);
181
Victor Stinnerdaf45552013-08-27 22:53:59182 return _open(pszName, _O_RDONLY | _O_BINARY | O_NOINHERIT);
Martin v. Löwisfbab90e2006-03-05 13:36:04183}
184
185static PyObject* fcicreate(PyObject* obj, PyObject* args)
186{
Christian Heimes0bd4e112008-02-12 22:59:25187 char *cabname, *p;
Martin v. Löwisfbab90e2006-03-05 13:36:04188 PyObject *files;
189 CCAB ccab;
190 HFCI hfci;
191 ERF erf;
Christian Heimes0bd4e112008-02-12 22:59:25192 Py_ssize_t i;
Martin v. Löwisfbab90e2006-03-05 13:36:04193
194
195 if (!PyArg_ParseTuple(args, "sO:FCICreate", &cabname, &files))
Antoine Pitrouf95a1b32010-05-09 15:52:27196 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04197
198 if (!PyList_Check(files)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27199 PyErr_SetString(PyExc_TypeError, "FCICreate expects a list");
200 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04201 }
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 Heimes0bd4e112008-02-12 22:59:25215 for (i = 0, p = cabname; *p; p = CharNext(p))
Antoine Pitrouf95a1b32010-05-09 15:52:27216 if (*p == '\\' || *p == '/')
217 i = p - cabname + 1;
Martin v. Löwisfbab90e2006-03-05 13:36:04218
Christian Heimes0bd4e112008-02-12 22:59:25219 if (i >= sizeof(ccab.szCabPath) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27220 strlen(cabname+i) >= sizeof(ccab.szCab)) {
221 PyErr_SetString(PyExc_ValueError, "path name too long");
222 return 0;
Martin v. Löwisfbab90e2006-03-05 13:36:04223 }
224
Christian Heimes0bd4e112008-02-12 22:59:25225 if (i > 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27226 memcpy(ccab.szCabPath, cabname, i);
227 ccab.szCabPath[i] = '\0';
228 strcpy(ccab.szCab, cabname+i);
Martin v. Löwisfbab90e2006-03-05 13:36:04229 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27230 strcpy(ccab.szCabPath, ".\\");
231 strcpy(ccab.szCab, cabname);
Martin v. Löwisfbab90e2006-03-05 13:36:04232 }
233
234 hfci = FCICreate(&erf, cb_fileplaced, cb_alloc, cb_free,
Antoine Pitrouf95a1b32010-05-09 15:52:27235 cb_open, cb_read, cb_write, cb_close, cb_seek, cb_delete,
236 cb_gettempfile, &ccab, NULL);
Martin v. Löwisfbab90e2006-03-05 13:36:04237
238 if (hfci == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27239 PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper);
240 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04241 }
242
243 for (i=0; i < PyList_GET_SIZE(files); i++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27244 PyObject *item = PyList_GET_ITEM(files, i);
245 char *filename, *cabname;
Zachary Ware0a29e892015-05-18 05:47:15246
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 Pitrouf95a1b32010-05-09 15:52:27253 if (!FCIAddFile(hfci, filename, cabname, FALSE,
254 cb_getnextcabinet, cb_status, cb_getopeninfo,
255 tcompTYPE_MSZIP))
256 goto err;
Martin v. Löwisfbab90e2006-03-05 13:36:04257 }
258
259 if (!FCIFlushCabinet(hfci, FALSE, cb_getnextcabinet, cb_status))
Antoine Pitrouf95a1b32010-05-09 15:52:27260 goto err;
Martin v. Löwisfbab90e2006-03-05 13:36:04261
262 if (!FCIDestroy(hfci))
Antoine Pitrouf95a1b32010-05-09 15:52:27263 goto err;
Martin v. Löwisfbab90e2006-03-05 13:36:04264
265 Py_INCREF(Py_None);
266 return Py_None;
267err:
Zachary Ware0a29e892015-05-18 05:47:15268 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öwisfbab90e2006-03-05 13:36:04273 FCIDestroy(hfci);
274 return NULL;
275}
276
277typedef struct msiobj{
278 PyObject_HEAD
279 MSIHANDLE h;
280}msiobj;
281
Antoine Pitrouf95a1b32010-05-09 15:52:27282static void
Martin v. Löwisfbab90e2006-03-05 13:36:04283msiobj_dealloc(msiobj* msidb)
284{
285 MsiCloseHandle(msidb->h);
286 msidb->h = 0;
Miss Islington (bot)ef6f2242017-11-07 10:50:41287 PyObject_Del(msidb);
Martin v. Löwisfbab90e2006-03-05 13:36:04288}
289
290static PyObject*
291msiobj_close(msiobj* msidb, PyObject *args)
292{
293 MsiCloseHandle(msidb->h);
294 msidb->h = 0;
295 Py_INCREF(Py_None);
296 return Py_None;
297}
298
299static PyObject*
300msierror(int status)
301{
302 int code;
303 char buf[2000];
304 char *res = buf;
305 DWORD size = sizeof(buf);
306 MSIHANDLE err = MsiGetLastErrorRecord();
307
308 if (err == 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27309 switch(status) {
310 case ERROR_ACCESS_DENIED:
311 PyErr_SetString(MSIError, "access denied");
312 return NULL;
313 case ERROR_FUNCTION_FAILED:
314 PyErr_SetString(MSIError, "function failed");
315 return NULL;
316 case ERROR_INVALID_DATA:
317 PyErr_SetString(MSIError, "invalid data");
318 return NULL;
319 case ERROR_INVALID_HANDLE:
320 PyErr_SetString(MSIError, "invalid handle");
321 return NULL;
322 case ERROR_INVALID_STATE:
323 PyErr_SetString(MSIError, "invalid state");
324 return NULL;
325 case ERROR_INVALID_PARAMETER:
326 PyErr_SetString(MSIError, "invalid parameter");
327 return NULL;
Miss Islington (bot)bfa89b22017-11-24 10:31:21328 case ERROR_OPEN_FAILED:
329 PyErr_SetString(MSIError, "open failed");
330 return NULL;
331 case ERROR_CREATE_FAILED:
332 PyErr_SetString(MSIError, "create failed");
333 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27334 default:
335 PyErr_Format(MSIError, "unknown error %x", status);
336 return NULL;
337 }
Martin v. Löwisfbab90e2006-03-05 13:36:04338 }
339
340 code = MsiRecordGetInteger(err, 1); /* XXX code */
341 if (MsiFormatRecord(0, err, res, &size) == ERROR_MORE_DATA) {
Antoine Pitrouf95a1b32010-05-09 15:52:27342 res = malloc(size+1);
Miss Islington (bot)8a0c2542018-09-10 16:41:31343 if (res == NULL) {
344 MsiCloseHandle(err);
345 return PyErr_NoMemory();
346 }
Antoine Pitrouf95a1b32010-05-09 15:52:27347 MsiFormatRecord(0, err, res, &size);
348 res[size]='\0';
Martin v. Löwisfbab90e2006-03-05 13:36:04349 }
350 MsiCloseHandle(err);
351 PyErr_SetString(MSIError, res);
352 if (res != buf)
Antoine Pitrouf95a1b32010-05-09 15:52:27353 free(res);
Martin v. Löwisfbab90e2006-03-05 13:36:04354 return NULL;
355}
356
357/*************************** Record objects **********************/
358
359static PyObject*
360record_getfieldcount(msiobj* record, PyObject* args)
361{
Christian Heimes217cfd12007-12-02 14:31:20362 return PyLong_FromLong(MsiRecordGetFieldCount(record->h));
Martin v. Löwisfbab90e2006-03-05 13:36:04363}
364
365static PyObject*
Martin v. Löwise95593e2008-06-02 10:08:54366record_getinteger(msiobj* record, PyObject* args)
367{
368 unsigned int field;
369 int status;
Antoine Pitrouf95a1b32010-05-09 15:52:27370
Martin v. Löwise95593e2008-06-02 10:08:54371 if (!PyArg_ParseTuple(args, "I:GetInteger", &field))
372 return NULL;
373 status = MsiRecordGetInteger(record->h, field);
374 if (status == MSI_NULL_INTEGER){
375 PyErr_SetString(MSIError, "could not convert record field to integer");
376 return NULL;
377 }
Martin v. Löwis704d8b12008-06-02 11:32:23378 return PyLong_FromLong((long) status);
Martin v. Löwise95593e2008-06-02 10:08:54379}
380
381static PyObject*
382record_getstring(msiobj* record, PyObject* args)
383{
384 unsigned int field;
385 unsigned int status;
Martin v. Löwis371bb502008-08-16 13:02:57386 WCHAR buf[2000];
387 WCHAR *res = buf;
Martin v. Löwise95593e2008-06-02 10:08:54388 DWORD size = sizeof(buf);
389 PyObject* string;
Antoine Pitrouf95a1b32010-05-09 15:52:27390
Martin v. Löwise95593e2008-06-02 10:08:54391 if (!PyArg_ParseTuple(args, "I:GetString", &field))
392 return NULL;
Martin v. Löwis371bb502008-08-16 13:02:57393 status = MsiRecordGetStringW(record->h, field, res, &size);
Martin v. Löwise95593e2008-06-02 10:08:54394 if (status == ERROR_MORE_DATA) {
Martin v. Löwis371bb502008-08-16 13:02:57395 res = (WCHAR*) malloc((size + 1)*sizeof(WCHAR));
Martin v. Löwise95593e2008-06-02 10:08:54396 if (res == NULL)
397 return PyErr_NoMemory();
Martin v. Löwis371bb502008-08-16 13:02:57398 status = MsiRecordGetStringW(record->h, field, res, &size);
Martin v. Löwise95593e2008-06-02 10:08:54399 }
400 if (status != ERROR_SUCCESS)
401 return msierror((int) status);
Victor Stinner9d3b93b2011-11-22 01:27:30402 string = PyUnicode_FromWideChar(res, size);
Martin v. Löwise95593e2008-06-02 10:08:54403 if (buf != res)
404 free(res);
405 return string;
406}
407
408static PyObject*
Martin v. Löwisfbab90e2006-03-05 13:36:04409record_cleardata(msiobj* record, PyObject *args)
410{
411 int status = MsiRecordClearData(record->h);
412 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27413 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04414
415 Py_INCREF(Py_None);
416 return Py_None;
417}
418
419static PyObject*
420record_setstring(msiobj* record, PyObject *args)
421{
422 int status;
423 int field;
Victor Stinner9d3b93b2011-11-22 01:27:30424 wchar_t *data;
Martin v. Löwisfbab90e2006-03-05 13:36:04425
Martin v. Löwis371bb502008-08-16 13:02:57426 if (!PyArg_ParseTuple(args, "iu:SetString", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27427 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04428
Martin v. Löwis371bb502008-08-16 13:02:57429 if ((status = MsiRecordSetStringW(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27430 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04431
432 Py_INCREF(Py_None);
433 return Py_None;
434}
435
436static PyObject*
437record_setstream(msiobj* record, PyObject *args)
438{
439 int status;
440 int field;
Victor Stinner9d3b93b2011-11-22 01:27:30441 wchar_t *data;
Martin v. Löwisfbab90e2006-03-05 13:36:04442
Martin v. Löwis371bb502008-08-16 13:02:57443 if (!PyArg_ParseTuple(args, "iu:SetStream", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27444 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04445
Martin v. Löwis371bb502008-08-16 13:02:57446 if ((status = MsiRecordSetStreamW(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27447 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04448
449 Py_INCREF(Py_None);
450 return Py_None;
451}
452
453static PyObject*
454record_setinteger(msiobj* record, PyObject *args)
455{
456 int status;
457 int field;
458 int data;
459
460 if (!PyArg_ParseTuple(args, "ii:SetInteger", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27461 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04462
463 if ((status = MsiRecordSetInteger(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27464 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04465
466 Py_INCREF(Py_None);
467 return Py_None;
468}
469
470
471
472static PyMethodDef record_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27473 { "GetFieldCount", (PyCFunction)record_getfieldcount, METH_NOARGS,
474 PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")},
Martin v. Löwise95593e2008-06-02 10:08:54475 { "GetInteger", (PyCFunction)record_getinteger, METH_VARARGS,
476 PyDoc_STR("GetInteger(field) -> int\nWraps MsiRecordGetInteger")},
477 { "GetString", (PyCFunction)record_getstring, METH_VARARGS,
478 PyDoc_STR("GetString(field) -> string\nWraps MsiRecordGetString")},
Antoine Pitrouf95a1b32010-05-09 15:52:27479 { "SetString", (PyCFunction)record_setstring, METH_VARARGS,
480 PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")},
481 { "SetStream", (PyCFunction)record_setstream, METH_VARARGS,
482 PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")},
483 { "SetInteger", (PyCFunction)record_setinteger, METH_VARARGS,
484 PyDoc_STR("SetInteger(field,int) -> None\nWraps MsiRecordSetInteger")},
485 { "ClearData", (PyCFunction)record_cleardata, METH_NOARGS,
486 PyDoc_STR("ClearData() -> int\nWraps MsiRecordGClearData")},
Martin v. Löwisfbab90e2006-03-05 13:36:04487 { NULL, NULL }
488};
489
490static PyTypeObject record_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27491 PyVarObject_HEAD_INIT(NULL, 0)
492 "_msi.Record", /*tp_name*/
493 sizeof(msiobj), /*tp_basicsize*/
494 0, /*tp_itemsize*/
495 /* methods */
496 (destructor)msiobj_dealloc, /*tp_dealloc*/
497 0, /*tp_print*/
498 0, /*tp_getattr*/
499 0, /*tp_setattr*/
500 0, /*tp_reserved*/
501 0, /*tp_repr*/
502 0, /*tp_as_number*/
503 0, /*tp_as_sequence*/
504 0, /*tp_as_mapping*/
505 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04506 0, /*tp_call*/
507 0, /*tp_str*/
508 PyObject_GenericGetAttr,/*tp_getattro*/
509 PyObject_GenericSetAttr,/*tp_setattro*/
510 0, /*tp_as_buffer*/
511 Py_TPFLAGS_DEFAULT, /*tp_flags*/
512 0, /*tp_doc*/
513 0, /*tp_traverse*/
514 0, /*tp_clear*/
515 0, /*tp_richcompare*/
516 0, /*tp_weaklistoffset*/
517 0, /*tp_iter*/
518 0, /*tp_iternext*/
519 record_methods, /*tp_methods*/
520 0, /*tp_members*/
521 0, /*tp_getset*/
522 0, /*tp_base*/
523 0, /*tp_dict*/
524 0, /*tp_descr_get*/
525 0, /*tp_descr_set*/
526 0, /*tp_dictoffset*/
527 0, /*tp_init*/
528 0, /*tp_alloc*/
529 0, /*tp_new*/
530 0, /*tp_free*/
531 0, /*tp_is_gc*/
532};
533
534static PyObject*
535record_new(MSIHANDLE h)
536{
537 msiobj *result = PyObject_NEW(struct msiobj, &record_Type);
538
539 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27540 MsiCloseHandle(h);
541 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04542 }
543
544 result->h = h;
545 return (PyObject*)result;
546}
547
548/*************************** SummaryInformation objects **************/
549
550static PyObject*
551summary_getproperty(msiobj* si, PyObject *args)
552{
553 int status;
554 int field;
555 PyObject *result;
556 UINT type;
557 INT ival;
558 FILETIME fval;
559 char sbuf[1000];
560 char *sval = sbuf;
561 DWORD ssize = sizeof(sval);
562
563 if (!PyArg_ParseTuple(args, "i:GetProperty", &field))
Antoine Pitrouf95a1b32010-05-09 15:52:27564 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04565
Antoine Pitrouf95a1b32010-05-09 15:52:27566 status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,
567 &fval, sval, &ssize);
Thomas Wouters89f507f2006-12-13 04:49:30568 if (status == ERROR_MORE_DATA) {
Antoine Pitrouf95a1b32010-05-09 15:52:27569 sval = malloc(ssize);
Miss Islington (bot)8a0c2542018-09-10 16:41:31570 if (sval == NULL) {
571 return PyErr_NoMemory();
572 }
Antoine Pitrouf95a1b32010-05-09 15:52:27573 status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,
574 &fval, sval, &ssize);
Martin v. Löwisfbab90e2006-03-05 13:36:04575 }
576
577 switch(type) {
Antoine Pitrouf95a1b32010-05-09 15:52:27578 case VT_I2: case VT_I4:
579 return PyLong_FromLong(ival);
580 case VT_FILETIME:
581 PyErr_SetString(PyExc_NotImplementedError, "FILETIME result");
582 return NULL;
583 case VT_LPSTR:
584 result = PyBytes_FromStringAndSize(sval, ssize);
585 if (sval != sbuf)
586 free(sval);
587 return result;
Berker Peksag412f00b2017-11-24 16:04:40588 case VT_EMPTY:
589 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04590 }
591 PyErr_Format(PyExc_NotImplementedError, "result of type %d", type);
592 return NULL;
593}
594
595static PyObject*
596summary_getpropertycount(msiobj* si, PyObject *args)
597{
598 int status;
599 UINT result;
600
601 status = MsiSummaryInfoGetPropertyCount(si->h, &result);
602 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27603 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04604
Christian Heimes217cfd12007-12-02 14:31:20605 return PyLong_FromLong(result);
Martin v. Löwisfbab90e2006-03-05 13:36:04606}
607
608static PyObject*
609summary_setproperty(msiobj* si, PyObject *args)
610{
611 int status;
612 int field;
613 PyObject* data;
614
615 if (!PyArg_ParseTuple(args, "iO:SetProperty", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27616 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04617
Martin v. Löwis371bb502008-08-16 13:02:57618 if (PyUnicode_Check(data)) {
Serhiy Storchaka08349052017-06-28 06:27:35619 const WCHAR *value = _PyUnicode_AsUnicode(data);
620 if (value == NULL) {
621 return NULL;
622 }
Antoine Pitrouf95a1b32010-05-09 15:52:27623 status = MsiSummaryInfoSetPropertyW(si->h, field, VT_LPSTR,
Serhiy Storchaka08349052017-06-28 06:27:35624 0, NULL, value);
Martin v. Löwisd1a1d1e2007-12-04 22:10:37625 } else if (PyLong_CheckExact(data)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27626 long value = PyLong_AsLong(data);
627 if (value == -1 && PyErr_Occurred()) {
628 return NULL;
629 }
630 status = MsiSummaryInfoSetProperty(si->h, field, VT_I4,
631 value, NULL, NULL);
Martin v. Löwisfbab90e2006-03-05 13:36:04632 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27633 PyErr_SetString(PyExc_TypeError, "unsupported type");
634 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04635 }
Antoine Pitrouf95a1b32010-05-09 15:52:27636
Martin v. Löwisfbab90e2006-03-05 13:36:04637 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27638 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04639
640 Py_INCREF(Py_None);
641 return Py_None;
642}
643
644
645static PyObject*
646summary_persist(msiobj* si, PyObject *args)
647{
648 int status;
649
650 status = MsiSummaryInfoPersist(si->h);
651 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27652 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04653 Py_INCREF(Py_None);
654 return Py_None;
655}
656
657static PyMethodDef summary_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27658 { "GetProperty", (PyCFunction)summary_getproperty, METH_VARARGS,
659 PyDoc_STR("GetProperty(propid) -> value\nWraps MsiSummaryInfoGetProperty")},
660 { "GetPropertyCount", (PyCFunction)summary_getpropertycount, METH_NOARGS,
661 PyDoc_STR("GetProperty() -> int\nWraps MsiSummaryInfoGetPropertyCount")},
662 { "SetProperty", (PyCFunction)summary_setproperty, METH_VARARGS,
663 PyDoc_STR("SetProperty(value) -> None\nWraps MsiSummaryInfoProperty")},
664 { "Persist", (PyCFunction)summary_persist, METH_NOARGS,
665 PyDoc_STR("Persist() -> None\nWraps MsiSummaryInfoPersist")},
Martin v. Löwisfbab90e2006-03-05 13:36:04666 { NULL, NULL }
667};
668
669static PyTypeObject summary_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27670 PyVarObject_HEAD_INIT(NULL, 0)
671 "_msi.SummaryInformation", /*tp_name*/
672 sizeof(msiobj), /*tp_basicsize*/
673 0, /*tp_itemsize*/
674 /* methods */
675 (destructor)msiobj_dealloc, /*tp_dealloc*/
676 0, /*tp_print*/
677 0, /*tp_getattr*/
678 0, /*tp_setattr*/
679 0, /*tp_reserved*/
680 0, /*tp_repr*/
681 0, /*tp_as_number*/
682 0, /*tp_as_sequence*/
683 0, /*tp_as_mapping*/
684 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04685 0, /*tp_call*/
686 0, /*tp_str*/
687 PyObject_GenericGetAttr,/*tp_getattro*/
688 PyObject_GenericSetAttr,/*tp_setattro*/
689 0, /*tp_as_buffer*/
690 Py_TPFLAGS_DEFAULT, /*tp_flags*/
691 0, /*tp_doc*/
692 0, /*tp_traverse*/
693 0, /*tp_clear*/
694 0, /*tp_richcompare*/
695 0, /*tp_weaklistoffset*/
696 0, /*tp_iter*/
697 0, /*tp_iternext*/
698 summary_methods, /*tp_methods*/
699 0, /*tp_members*/
700 0, /*tp_getset*/
701 0, /*tp_base*/
702 0, /*tp_dict*/
703 0, /*tp_descr_get*/
704 0, /*tp_descr_set*/
705 0, /*tp_dictoffset*/
706 0, /*tp_init*/
707 0, /*tp_alloc*/
708 0, /*tp_new*/
709 0, /*tp_free*/
710 0, /*tp_is_gc*/
711};
712
713/*************************** View objects **************/
714
715static PyObject*
716view_execute(msiobj *view, PyObject*args)
717{
718 int status;
719 MSIHANDLE params = 0;
720 PyObject *oparams = Py_None;
721
722 if (!PyArg_ParseTuple(args, "O:Execute", &oparams))
Antoine Pitrouf95a1b32010-05-09 15:52:27723 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04724
725 if (oparams != Py_None) {
726 if (oparams->ob_type != &record_Type) {
727 PyErr_SetString(PyExc_TypeError, "Execute argument must be a record");
728 return NULL;
729 }
730 params = ((msiobj*)oparams)->h;
731 }
732
733 status = MsiViewExecute(view->h, params);
734 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27735 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04736
737 Py_INCREF(Py_None);
738 return Py_None;
739}
740
741static PyObject*
742view_fetch(msiobj *view, PyObject*args)
743{
744 int status;
745 MSIHANDLE result;
746
Berker Peksag4b304292017-11-23 14:33:12747 status = MsiViewFetch(view->h, &result);
748 if (status == ERROR_NO_MORE_ITEMS) {
749 Py_RETURN_NONE;
750 } else if (status != ERROR_SUCCESS) {
Antoine Pitrouf95a1b32010-05-09 15:52:27751 return msierror(status);
Berker Peksag4b304292017-11-23 14:33:12752 }
Martin v. Löwisfbab90e2006-03-05 13:36:04753
754 return record_new(result);
755}
756
757static PyObject*
758view_getcolumninfo(msiobj *view, PyObject *args)
759{
760 int status;
761 int kind;
762 MSIHANDLE result;
763
764 if (!PyArg_ParseTuple(args, "i:GetColumnInfo", &kind))
Antoine Pitrouf95a1b32010-05-09 15:52:27765 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04766
767 if ((status = MsiViewGetColumnInfo(view->h, kind, &result)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27768 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04769
770 return record_new(result);
771}
772
773static PyObject*
774view_modify(msiobj *view, PyObject *args)
775{
776 int kind;
777 PyObject *data;
778 int status;
779
780 if (!PyArg_ParseTuple(args, "iO:Modify", &kind, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27781 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04782
783 if (data->ob_type != &record_Type) {
Antoine Pitrouf95a1b32010-05-09 15:52:27784 PyErr_SetString(PyExc_TypeError, "Modify expects a record object");
785 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04786 }
787
788 if ((status = MsiViewModify(view->h, kind, ((msiobj*)data)->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27789 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04790
791 Py_INCREF(Py_None);
792 return Py_None;
793}
794
795static PyObject*
796view_close(msiobj *view, PyObject*args)
797{
798 int status;
799
800 if ((status = MsiViewClose(view->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27801 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04802
803 Py_INCREF(Py_None);
804 return Py_None;
805}
806
807static PyMethodDef view_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27808 { "Execute", (PyCFunction)view_execute, METH_VARARGS,
809 PyDoc_STR("Execute(params=None) -> None\nWraps MsiViewExecute")},
Martin v. Löwisfbab90e2006-03-05 13:36:04810 { "GetColumnInfo", (PyCFunction)view_getcolumninfo, METH_VARARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27811 PyDoc_STR("GetColumnInfo() -> result\nWraps MsiGetColumnInfo")},
Martin v. Löwisfbab90e2006-03-05 13:36:04812 { "Fetch", (PyCFunction)view_fetch, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27813 PyDoc_STR("Fetch() -> result\nWraps MsiViewFetch")},
Martin v. Löwisfbab90e2006-03-05 13:36:04814 { "Modify", (PyCFunction)view_modify, METH_VARARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27815 PyDoc_STR("Modify(mode,record) -> None\nWraps MsiViewModify")},
Martin v. Löwisfbab90e2006-03-05 13:36:04816 { "Close", (PyCFunction)view_close, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27817 PyDoc_STR("Close() -> result\nWraps MsiViewClose")},
Martin v. Löwisfbab90e2006-03-05 13:36:04818 { NULL, NULL }
819};
820
821static PyTypeObject msiview_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27822 PyVarObject_HEAD_INIT(NULL, 0)
823 "_msi.View", /*tp_name*/
824 sizeof(msiobj), /*tp_basicsize*/
825 0, /*tp_itemsize*/
826 /* methods */
827 (destructor)msiobj_dealloc, /*tp_dealloc*/
828 0, /*tp_print*/
829 0, /*tp_getattr*/
830 0, /*tp_setattr*/
831 0, /*tp_reserved*/
832 0, /*tp_repr*/
833 0, /*tp_as_number*/
834 0, /*tp_as_sequence*/
835 0, /*tp_as_mapping*/
836 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04837 0, /*tp_call*/
838 0, /*tp_str*/
839 PyObject_GenericGetAttr,/*tp_getattro*/
840 PyObject_GenericSetAttr,/*tp_setattro*/
841 0, /*tp_as_buffer*/
842 Py_TPFLAGS_DEFAULT, /*tp_flags*/
843 0, /*tp_doc*/
844 0, /*tp_traverse*/
845 0, /*tp_clear*/
846 0, /*tp_richcompare*/
847 0, /*tp_weaklistoffset*/
848 0, /*tp_iter*/
849 0, /*tp_iternext*/
850 view_methods, /*tp_methods*/
851 0, /*tp_members*/
852 0, /*tp_getset*/
853 0, /*tp_base*/
854 0, /*tp_dict*/
855 0, /*tp_descr_get*/
856 0, /*tp_descr_set*/
857 0, /*tp_dictoffset*/
858 0, /*tp_init*/
859 0, /*tp_alloc*/
860 0, /*tp_new*/
861 0, /*tp_free*/
862 0, /*tp_is_gc*/
863};
864
865/*************************** Database objects **************/
866
867static PyObject*
868msidb_openview(msiobj *msidb, PyObject *args)
869{
870 int status;
871 char *sql;
872 MSIHANDLE hView;
873 msiobj *result;
874
875 if (!PyArg_ParseTuple(args, "s:OpenView", &sql))
Antoine Pitrouf95a1b32010-05-09 15:52:27876 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04877
878 if ((status = MsiDatabaseOpenView(msidb->h, sql, &hView)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27879 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04880
881 result = PyObject_NEW(struct msiobj, &msiview_Type);
882 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27883 MsiCloseHandle(hView);
884 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04885 }
886
887 result->h = hView;
888 return (PyObject*)result;
889}
890
891static PyObject*
892msidb_commit(msiobj *msidb, PyObject *args)
893{
894 int status;
895
896 if ((status = MsiDatabaseCommit(msidb->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27897 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04898
899 Py_INCREF(Py_None);
900 return Py_None;
901}
902
903static PyObject*
904msidb_getsummaryinformation(msiobj *db, PyObject *args)
905{
906 int status;
907 int count;
908 MSIHANDLE result;
909 msiobj *oresult;
910
911 if (!PyArg_ParseTuple(args, "i:GetSummaryInformation", &count))
Antoine Pitrouf95a1b32010-05-09 15:52:27912 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04913
914 status = MsiGetSummaryInformation(db->h, NULL, count, &result);
915 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27916 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04917
918 oresult = PyObject_NEW(struct msiobj, &summary_Type);
919 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27920 MsiCloseHandle(result);
921 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04922 }
923
924 oresult->h = result;
925 return (PyObject*)oresult;
926}
927
928static PyMethodDef db_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27929 { "OpenView", (PyCFunction)msidb_openview, METH_VARARGS,
930 PyDoc_STR("OpenView(sql) -> viewobj\nWraps MsiDatabaseOpenView")},
Martin v. Löwisfbab90e2006-03-05 13:36:04931 { "Commit", (PyCFunction)msidb_commit, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27932 PyDoc_STR("Commit() -> None\nWraps MsiDatabaseCommit")},
933 { "GetSummaryInformation", (PyCFunction)msidb_getsummaryinformation, METH_VARARGS,
934 PyDoc_STR("GetSummaryInformation(updateCount) -> viewobj\nWraps MsiGetSummaryInformation")},
Martin v. Löwisfbab90e2006-03-05 13:36:04935 { NULL, NULL }
936};
937
938static PyTypeObject msidb_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27939 PyVarObject_HEAD_INIT(NULL, 0)
940 "_msi.Database", /*tp_name*/
941 sizeof(msiobj), /*tp_basicsize*/
942 0, /*tp_itemsize*/
943 /* methods */
944 (destructor)msiobj_dealloc, /*tp_dealloc*/
945 0, /*tp_print*/
946 0, /*tp_getattr*/
947 0, /*tp_setattr*/
948 0, /*tp_reserved*/
949 0, /*tp_repr*/
950 0, /*tp_as_number*/
951 0, /*tp_as_sequence*/
952 0, /*tp_as_mapping*/
953 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04954 0, /*tp_call*/
955 0, /*tp_str*/
956 PyObject_GenericGetAttr,/*tp_getattro*/
957 PyObject_GenericSetAttr,/*tp_setattro*/
958 0, /*tp_as_buffer*/
959 Py_TPFLAGS_DEFAULT, /*tp_flags*/
960 0, /*tp_doc*/
961 0, /*tp_traverse*/
962 0, /*tp_clear*/
963 0, /*tp_richcompare*/
964 0, /*tp_weaklistoffset*/
965 0, /*tp_iter*/
966 0, /*tp_iternext*/
967 db_methods, /*tp_methods*/
968 0, /*tp_members*/
969 0, /*tp_getset*/
970 0, /*tp_base*/
971 0, /*tp_dict*/
972 0, /*tp_descr_get*/
973 0, /*tp_descr_set*/
974 0, /*tp_dictoffset*/
975 0, /*tp_init*/
976 0, /*tp_alloc*/
977 0, /*tp_new*/
978 0, /*tp_free*/
979 0, /*tp_is_gc*/
980};
981
Steve Dower6ceda632016-09-09 18:56:34982#define Py_NOT_PERSIST(x, flag) \
983 (x != (int)(flag) && \
984 x != ((int)(flag) | MSIDBOPEN_PATCHFILE))
985
986#define Py_INVALID_PERSIST(x) \
987 (Py_NOT_PERSIST(x, MSIDBOPEN_READONLY) && \
988 Py_NOT_PERSIST(x, MSIDBOPEN_TRANSACT) && \
989 Py_NOT_PERSIST(x, MSIDBOPEN_DIRECT) && \
990 Py_NOT_PERSIST(x, MSIDBOPEN_CREATE) && \
991 Py_NOT_PERSIST(x, MSIDBOPEN_CREATEDIRECT))
992
Martin v. Löwisfbab90e2006-03-05 13:36:04993static PyObject* msiopendb(PyObject *obj, PyObject *args)
994{
995 int status;
996 char *path;
997 int persist;
998 MSIHANDLE h;
999 msiobj *result;
Antoine Pitrouf95a1b32010-05-09 15:52:271000 if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist))
1001 return NULL;
Steve Dower6ceda632016-09-09 18:56:341002 /* We need to validate that persist is a valid MSIDBOPEN_* value. Otherwise,
1003 MsiOpenDatabase may treat the value as a pointer, leading to unexpected
1004 behavior. */
1005 if (Py_INVALID_PERSIST(persist))
1006 return msierror(ERROR_INVALID_PARAMETER);
1007 status = MsiOpenDatabase(path, (LPCSTR)persist, &h);
Martin v. Löwisfbab90e2006-03-05 13:36:041008 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:271009 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:041010
1011 result = PyObject_NEW(struct msiobj, &msidb_Type);
1012 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:271013 MsiCloseHandle(h);
1014 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:041015 }
1016 result->h = h;
1017 return (PyObject*)result;
1018}
1019
1020static PyObject*
1021createrecord(PyObject *o, PyObject *args)
1022{
1023 int count;
1024 MSIHANDLE h;
1025
1026 if (!PyArg_ParseTuple(args, "i:CreateRecord", &count))
Antoine Pitrouf95a1b32010-05-09 15:52:271027 return NULL;
1028
Martin v. Löwisfbab90e2006-03-05 13:36:041029 h = MsiCreateRecord(count);
1030 if (h == 0)
Antoine Pitrouf95a1b32010-05-09 15:52:271031 return msierror(0);
Martin v. Löwisfbab90e2006-03-05 13:36:041032
1033 return record_new(h);
1034}
1035
1036
1037static PyMethodDef msi_methods[] = {
1038 {"UuidCreate", (PyCFunction)uuidcreate, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:271039 PyDoc_STR("UuidCreate() -> string")},
1040 {"FCICreate", (PyCFunction)fcicreate, METH_VARARGS,
1041 PyDoc_STR("fcicreate(cabname,files) -> None")},
1042 {"OpenDatabase", (PyCFunction)msiopendb, METH_VARARGS,
1043 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiOpenDatabase")},
1044 {"CreateRecord", (PyCFunction)createrecord, METH_VARARGS,
1045 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiCreateRecord")},
1046 {NULL, NULL} /* sentinel */
Martin v. Löwisfbab90e2006-03-05 13:36:041047};
1048
1049static char msi_doc[] = "Documentation";
1050
Martin v. Löwis1a214512008-06-11 05:26:201051
1052static struct PyModuleDef _msimodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:271053 PyModuleDef_HEAD_INIT,
1054 "_msi",
1055 msi_doc,
1056 -1,
1057 msi_methods,
1058 NULL,
1059 NULL,
1060 NULL,
1061 NULL
Martin v. Löwis1a214512008-06-11 05:26:201062};
1063
Martin v. Löwisfbab90e2006-03-05 13:36:041064PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:201065PyInit__msi(void)
Martin v. Löwisfbab90e2006-03-05 13:36:041066{
1067 PyObject *m;
1068
Martin v. Löwis1a214512008-06-11 05:26:201069 m = PyModule_Create(&_msimodule);
Martin v. Löwisfbab90e2006-03-05 13:36:041070 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:271071 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:041072
Victor Stinnere9857262016-03-23 10:37:411073 PyModule_AddIntConstant(m, "MSIDBOPEN_CREATEDIRECT", (long)MSIDBOPEN_CREATEDIRECT);
1074 PyModule_AddIntConstant(m, "MSIDBOPEN_CREATE", (long)MSIDBOPEN_CREATE);
1075 PyModule_AddIntConstant(m, "MSIDBOPEN_DIRECT", (long)MSIDBOPEN_DIRECT);
1076 PyModule_AddIntConstant(m, "MSIDBOPEN_READONLY", (long)MSIDBOPEN_READONLY);
1077 PyModule_AddIntConstant(m, "MSIDBOPEN_TRANSACT", (long)MSIDBOPEN_TRANSACT);
1078 PyModule_AddIntConstant(m, "MSIDBOPEN_PATCHFILE", (long)MSIDBOPEN_PATCHFILE);
Martin v. Löwisfbab90e2006-03-05 13:36:041079
Charles-Francois Natali74ca8862013-05-20 17:13:191080 PyModule_AddIntMacro(m, MSICOLINFO_NAMES);
1081 PyModule_AddIntMacro(m, MSICOLINFO_TYPES);
Martin v. Löwisfbab90e2006-03-05 13:36:041082
Charles-Francois Natali74ca8862013-05-20 17:13:191083 PyModule_AddIntMacro(m, MSIMODIFY_SEEK);
1084 PyModule_AddIntMacro(m, MSIMODIFY_REFRESH);
1085 PyModule_AddIntMacro(m, MSIMODIFY_INSERT);
1086 PyModule_AddIntMacro(m, MSIMODIFY_UPDATE);
1087 PyModule_AddIntMacro(m, MSIMODIFY_ASSIGN);
1088 PyModule_AddIntMacro(m, MSIMODIFY_REPLACE);
1089 PyModule_AddIntMacro(m, MSIMODIFY_MERGE);
1090 PyModule_AddIntMacro(m, MSIMODIFY_DELETE);
1091 PyModule_AddIntMacro(m, MSIMODIFY_INSERT_TEMPORARY);
1092 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE);
1093 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_NEW);
1094 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_FIELD);
1095 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_DELETE);
Martin v. Löwisfbab90e2006-03-05 13:36:041096
Charles-Francois Natali74ca8862013-05-20 17:13:191097 PyModule_AddIntMacro(m, PID_CODEPAGE);
1098 PyModule_AddIntMacro(m, PID_TITLE);
1099 PyModule_AddIntMacro(m, PID_SUBJECT);
1100 PyModule_AddIntMacro(m, PID_AUTHOR);
1101 PyModule_AddIntMacro(m, PID_KEYWORDS);
1102 PyModule_AddIntMacro(m, PID_COMMENTS);
1103 PyModule_AddIntMacro(m, PID_TEMPLATE);
1104 PyModule_AddIntMacro(m, PID_LASTAUTHOR);
1105 PyModule_AddIntMacro(m, PID_REVNUMBER);
1106 PyModule_AddIntMacro(m, PID_LASTPRINTED);
1107 PyModule_AddIntMacro(m, PID_CREATE_DTM);
1108 PyModule_AddIntMacro(m, PID_LASTSAVE_DTM);
1109 PyModule_AddIntMacro(m, PID_PAGECOUNT);
1110 PyModule_AddIntMacro(m, PID_WORDCOUNT);
1111 PyModule_AddIntMacro(m, PID_CHARCOUNT);
1112 PyModule_AddIntMacro(m, PID_APPNAME);
1113 PyModule_AddIntMacro(m, PID_SECURITY);
Martin v. Löwisfbab90e2006-03-05 13:36:041114
1115 MSIError = PyErr_NewException ("_msi.MSIError", NULL, NULL);
1116 if (!MSIError)
Antoine Pitrouf95a1b32010-05-09 15:52:271117 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:041118 PyModule_AddObject(m, "MSIError", MSIError);
Amaury Forgeot d'Arcbf9e9662008-06-17 21:39:461119 return m;
Martin v. Löwisfbab90e2006-03-05 13:36:041120}