blob: 6a99b40cda8dc0ad3dcd46f3b542135bfcdd5781 [file] [log] [blame]
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001/* Helper library for MSI creation with Python.
Florent Xiclunac934f322010-09-03 23:47:32 +00002 * Copyright (C) 2005 Martin v. Löwis
Martin v. Löwisdd860ca2006-03-05 13:39:10 +00003 * Licensed to PSF under a contributor agreement.
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00004 */
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 02:27:30 +010021 wchar_t *cresult;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000022 PyObject *oresult;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000023
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000024 /* 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:27 +000029 PyErr_SetString(PyExc_NotImplementedError, "processing 'no address' result");
30 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000031 }
32
Martin v. Löwis371bb502008-08-16 13:02:57 +000033 if (UuidToStringW(&result, &cresult) == RPC_S_OUT_OF_MEMORY) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000034 PyErr_SetString(PyExc_MemoryError, "out of memory in uuidgen");
35 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000036 }
37
Victor Stinner9d3b93b2011-11-22 02:27:30 +010038 oresult = PyUnicode_FromWideChar(cresult, wcslen(cresult));
Martin v. Löwis371bb502008-08-16 13:02:57 +000039 RpcStringFreeW(&cresult);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000040 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-28 00:53:59 +020058 int result = _open(pszFile, oflag | O_NOINHERIT, pmode);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000059 if (result == -1)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000061 return result;
62}
63
64static FNFCIREAD(cb_read)
65{
Victor Stinner67158282013-11-20 00:14:49 +010066 UINT result = (UINT)_read((int)hf, memory, cb);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000067 if (result != cb)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000069 return result;
70}
71
72static FNFCIWRITE(cb_write)
73{
Victor Stinner67158282013-11-20 00:14:49 +010074 UINT result = (UINT)_write((int)hf, memory, cb);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000075 if (result != cb)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000076 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000077 return result;
78}
79
80static FNFCICLOSE(cb_close)
81{
Victor Stinner67158282013-11-20 00:14:49 +010082 int result = _close((int)hf);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000083 if (result != 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000084 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000085 return result;
86}
87
88static FNFCISEEK(cb_seek)
89{
Victor Stinner67158282013-11-20 00:14:49 +010090 long result = (long)_lseek((int)hf, dist, seektype);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000091 if (result == -1)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000092 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +000093 return result;
94}
95
96static FNFCIDELETE(cb_delete)
97{
98 int result = remove(pszFile);
99 if (result != 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000100 *err = errno;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000101 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:27 +0000113 strcpy(pszTempName, name);
114 free(name);
115 return TRUE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000116 }
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 10:20:37 +0200125 _Py_IDENTIFIER(status);
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200126
127 PyObject *result = _PyObject_CallMethodId(pv, &PyId_status, "iii", typeStatus, cb1, cb2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000128 if (result == NULL)
129 return -1;
130 Py_DECREF(result);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000131 }
132 return 0;
133}
134
135static FNFCIGETNEXTCABINET(cb_getnextcabinet)
136{
137 if (pv) {
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200138 _Py_IDENTIFIER(getnextcabinet);
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200139
140 PyObject *result = _PyObject_CallMethodId(pv, &PyId_getnextcabinet, "i", pccab->iCab);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 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:04 +0000152 }
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:27 +0000164 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000165 if (handle == INVALID_HANDLE_VALUE)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166 return -1;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000167
168 if (GetFileInformationByHandle(handle, &bhfi) == FALSE)
169 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170 CloseHandle(handle);
171 return -1;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000172 }
173
174 FileTimeToLocalFileTime(&bhfi.ftLastWriteTime, &filetime);
175 FileTimeToDosDateTime(&filetime, pdate, ptime);
176
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 *pattribs = (int)(bhfi.dwFileAttributes &
178 (_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH));
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000179
180 CloseHandle(handle);
181
Victor Stinnerdaf45552013-08-28 00:53:59 +0200182 return _open(pszName, _O_RDONLY | _O_BINARY | O_NOINHERIT);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000183}
184
185static PyObject* fcicreate(PyObject* obj, PyObject* args)
186{
Christian Heimes0bd4e112008-02-12 22:59:25 +0000187 char *cabname, *p;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000188 PyObject *files;
189 CCAB ccab;
190 HFCI hfci;
191 ERF erf;
Christian Heimes0bd4e112008-02-12 22:59:25 +0000192 Py_ssize_t i;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000193
194
195 if (!PyArg_ParseTuple(args, "sO:FCICreate", &cabname, &files))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000196 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000197
198 if (!PyList_Check(files)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 PyErr_SetString(PyExc_TypeError, "FCICreate expects a list");
200 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000201 }
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:25 +0000215 for (i = 0, p = cabname; *p; p = CharNext(p))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000216 if (*p == '\\' || *p == '/')
217 i = p - cabname + 1;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000218
Christian Heimes0bd4e112008-02-12 22:59:25 +0000219 if (i >= sizeof(ccab.szCabPath) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000220 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:04 +0000223 }
224
Christian Heimes0bd4e112008-02-12 22:59:25 +0000225 if (i > 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 memcpy(ccab.szCabPath, cabname, i);
227 ccab.szCabPath[i] = '\0';
228 strcpy(ccab.szCab, cabname+i);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000229 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000230 strcpy(ccab.szCabPath, ".\\");
231 strcpy(ccab.szCab, cabname);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000232 }
233
234 hfci = FCICreate(&erf, cb_fileplaced, cb_alloc, cb_free,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000235 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:04 +0000237
238 if (hfci == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000239 PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper);
240 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000241 }
242
243 for (i=0; i < PyList_GET_SIZE(files); i++) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000244 PyObject *item = PyList_GET_ITEM(files, i);
245 char *filename, *cabname;
246 if (!PyArg_ParseTuple(item, "ss", &filename, &cabname))
247 goto err;
248 if (!FCIAddFile(hfci, filename, cabname, FALSE,
249 cb_getnextcabinet, cb_status, cb_getopeninfo,
250 tcompTYPE_MSZIP))
251 goto err;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000252 }
253
254 if (!FCIFlushCabinet(hfci, FALSE, cb_getnextcabinet, cb_status))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000255 goto err;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000256
257 if (!FCIDestroy(hfci))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000258 goto err;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000259
260 Py_INCREF(Py_None);
261 return Py_None;
262err:
263 PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */
264 FCIDestroy(hfci);
265 return NULL;
266}
267
268typedef struct msiobj{
269 PyObject_HEAD
270 MSIHANDLE h;
271}msiobj;
272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273static void
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000274msiobj_dealloc(msiobj* msidb)
275{
276 MsiCloseHandle(msidb->h);
277 msidb->h = 0;
278}
279
280static PyObject*
281msiobj_close(msiobj* msidb, PyObject *args)
282{
283 MsiCloseHandle(msidb->h);
284 msidb->h = 0;
285 Py_INCREF(Py_None);
286 return Py_None;
287}
288
289static PyObject*
290msierror(int status)
291{
292 int code;
293 char buf[2000];
294 char *res = buf;
295 DWORD size = sizeof(buf);
296 MSIHANDLE err = MsiGetLastErrorRecord();
297
298 if (err == 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299 switch(status) {
300 case ERROR_ACCESS_DENIED:
301 PyErr_SetString(MSIError, "access denied");
302 return NULL;
303 case ERROR_FUNCTION_FAILED:
304 PyErr_SetString(MSIError, "function failed");
305 return NULL;
306 case ERROR_INVALID_DATA:
307 PyErr_SetString(MSIError, "invalid data");
308 return NULL;
309 case ERROR_INVALID_HANDLE:
310 PyErr_SetString(MSIError, "invalid handle");
311 return NULL;
312 case ERROR_INVALID_STATE:
313 PyErr_SetString(MSIError, "invalid state");
314 return NULL;
315 case ERROR_INVALID_PARAMETER:
316 PyErr_SetString(MSIError, "invalid parameter");
317 return NULL;
318 default:
319 PyErr_Format(MSIError, "unknown error %x", status);
320 return NULL;
321 }
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000322 }
323
324 code = MsiRecordGetInteger(err, 1); /* XXX code */
325 if (MsiFormatRecord(0, err, res, &size) == ERROR_MORE_DATA) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326 res = malloc(size+1);
327 MsiFormatRecord(0, err, res, &size);
328 res[size]='\0';
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000329 }
330 MsiCloseHandle(err);
331 PyErr_SetString(MSIError, res);
332 if (res != buf)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000333 free(res);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000334 return NULL;
335}
336
337/*************************** Record objects **********************/
338
339static PyObject*
340record_getfieldcount(msiobj* record, PyObject* args)
341{
Christian Heimes217cfd12007-12-02 14:31:20 +0000342 return PyLong_FromLong(MsiRecordGetFieldCount(record->h));
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000343}
344
345static PyObject*
Martin v. Löwise95593e2008-06-02 10:08:54 +0000346record_getinteger(msiobj* record, PyObject* args)
347{
348 unsigned int field;
349 int status;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000350
Martin v. Löwise95593e2008-06-02 10:08:54 +0000351 if (!PyArg_ParseTuple(args, "I:GetInteger", &field))
352 return NULL;
353 status = MsiRecordGetInteger(record->h, field);
354 if (status == MSI_NULL_INTEGER){
355 PyErr_SetString(MSIError, "could not convert record field to integer");
356 return NULL;
357 }
Martin v. Löwis704d8b12008-06-02 11:32:23 +0000358 return PyLong_FromLong((long) status);
Martin v. Löwise95593e2008-06-02 10:08:54 +0000359}
360
361static PyObject*
362record_getstring(msiobj* record, PyObject* args)
363{
364 unsigned int field;
365 unsigned int status;
Martin v. Löwis371bb502008-08-16 13:02:57 +0000366 WCHAR buf[2000];
367 WCHAR *res = buf;
Martin v. Löwise95593e2008-06-02 10:08:54 +0000368 DWORD size = sizeof(buf);
369 PyObject* string;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370
Martin v. Löwise95593e2008-06-02 10:08:54 +0000371 if (!PyArg_ParseTuple(args, "I:GetString", &field))
372 return NULL;
Martin v. Löwis371bb502008-08-16 13:02:57 +0000373 status = MsiRecordGetStringW(record->h, field, res, &size);
Martin v. Löwise95593e2008-06-02 10:08:54 +0000374 if (status == ERROR_MORE_DATA) {
Martin v. Löwis371bb502008-08-16 13:02:57 +0000375 res = (WCHAR*) malloc((size + 1)*sizeof(WCHAR));
Martin v. Löwise95593e2008-06-02 10:08:54 +0000376 if (res == NULL)
377 return PyErr_NoMemory();
Martin v. Löwis371bb502008-08-16 13:02:57 +0000378 status = MsiRecordGetStringW(record->h, field, res, &size);
Martin v. Löwise95593e2008-06-02 10:08:54 +0000379 }
380 if (status != ERROR_SUCCESS)
381 return msierror((int) status);
Victor Stinner9d3b93b2011-11-22 02:27:30 +0100382 string = PyUnicode_FromWideChar(res, size);
Martin v. Löwise95593e2008-06-02 10:08:54 +0000383 if (buf != res)
384 free(res);
385 return string;
386}
387
388static PyObject*
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000389record_cleardata(msiobj* record, PyObject *args)
390{
391 int status = MsiRecordClearData(record->h);
392 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000394
395 Py_INCREF(Py_None);
396 return Py_None;
397}
398
399static PyObject*
400record_setstring(msiobj* record, PyObject *args)
401{
402 int status;
403 int field;
Victor Stinner9d3b93b2011-11-22 02:27:30 +0100404 wchar_t *data;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000405
Martin v. Löwis371bb502008-08-16 13:02:57 +0000406 if (!PyArg_ParseTuple(args, "iu:SetString", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000407 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000408
Martin v. Löwis371bb502008-08-16 13:02:57 +0000409 if ((status = MsiRecordSetStringW(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000411
412 Py_INCREF(Py_None);
413 return Py_None;
414}
415
416static PyObject*
417record_setstream(msiobj* record, PyObject *args)
418{
419 int status;
420 int field;
Victor Stinner9d3b93b2011-11-22 02:27:30 +0100421 wchar_t *data;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000422
Martin v. Löwis371bb502008-08-16 13:02:57 +0000423 if (!PyArg_ParseTuple(args, "iu:SetStream", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000424 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000425
Martin v. Löwis371bb502008-08-16 13:02:57 +0000426 if ((status = MsiRecordSetStreamW(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000427 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000428
429 Py_INCREF(Py_None);
430 return Py_None;
431}
432
433static PyObject*
434record_setinteger(msiobj* record, PyObject *args)
435{
436 int status;
437 int field;
438 int data;
439
440 if (!PyArg_ParseTuple(args, "ii:SetInteger", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000442
443 if ((status = MsiRecordSetInteger(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000445
446 Py_INCREF(Py_None);
447 return Py_None;
448}
449
450
451
452static PyMethodDef record_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000453 { "GetFieldCount", (PyCFunction)record_getfieldcount, METH_NOARGS,
454 PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")},
Martin v. Löwise95593e2008-06-02 10:08:54 +0000455 { "GetInteger", (PyCFunction)record_getinteger, METH_VARARGS,
456 PyDoc_STR("GetInteger(field) -> int\nWraps MsiRecordGetInteger")},
457 { "GetString", (PyCFunction)record_getstring, METH_VARARGS,
458 PyDoc_STR("GetString(field) -> string\nWraps MsiRecordGetString")},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000459 { "SetString", (PyCFunction)record_setstring, METH_VARARGS,
460 PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")},
461 { "SetStream", (PyCFunction)record_setstream, METH_VARARGS,
462 PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")},
463 { "SetInteger", (PyCFunction)record_setinteger, METH_VARARGS,
464 PyDoc_STR("SetInteger(field,int) -> None\nWraps MsiRecordSetInteger")},
465 { "ClearData", (PyCFunction)record_cleardata, METH_NOARGS,
466 PyDoc_STR("ClearData() -> int\nWraps MsiRecordGClearData")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000467 { NULL, NULL }
468};
469
470static PyTypeObject record_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000471 PyVarObject_HEAD_INIT(NULL, 0)
472 "_msi.Record", /*tp_name*/
473 sizeof(msiobj), /*tp_basicsize*/
474 0, /*tp_itemsize*/
475 /* methods */
476 (destructor)msiobj_dealloc, /*tp_dealloc*/
477 0, /*tp_print*/
478 0, /*tp_getattr*/
479 0, /*tp_setattr*/
480 0, /*tp_reserved*/
481 0, /*tp_repr*/
482 0, /*tp_as_number*/
483 0, /*tp_as_sequence*/
484 0, /*tp_as_mapping*/
485 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000486 0, /*tp_call*/
487 0, /*tp_str*/
488 PyObject_GenericGetAttr,/*tp_getattro*/
489 PyObject_GenericSetAttr,/*tp_setattro*/
490 0, /*tp_as_buffer*/
491 Py_TPFLAGS_DEFAULT, /*tp_flags*/
492 0, /*tp_doc*/
493 0, /*tp_traverse*/
494 0, /*tp_clear*/
495 0, /*tp_richcompare*/
496 0, /*tp_weaklistoffset*/
497 0, /*tp_iter*/
498 0, /*tp_iternext*/
499 record_methods, /*tp_methods*/
500 0, /*tp_members*/
501 0, /*tp_getset*/
502 0, /*tp_base*/
503 0, /*tp_dict*/
504 0, /*tp_descr_get*/
505 0, /*tp_descr_set*/
506 0, /*tp_dictoffset*/
507 0, /*tp_init*/
508 0, /*tp_alloc*/
509 0, /*tp_new*/
510 0, /*tp_free*/
511 0, /*tp_is_gc*/
512};
513
514static PyObject*
515record_new(MSIHANDLE h)
516{
517 msiobj *result = PyObject_NEW(struct msiobj, &record_Type);
518
519 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 MsiCloseHandle(h);
521 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000522 }
523
524 result->h = h;
525 return (PyObject*)result;
526}
527
528/*************************** SummaryInformation objects **************/
529
530static PyObject*
531summary_getproperty(msiobj* si, PyObject *args)
532{
533 int status;
534 int field;
535 PyObject *result;
536 UINT type;
537 INT ival;
538 FILETIME fval;
539 char sbuf[1000];
540 char *sval = sbuf;
541 DWORD ssize = sizeof(sval);
542
543 if (!PyArg_ParseTuple(args, "i:GetProperty", &field))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000546 status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,
547 &fval, sval, &ssize);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000548 if (status == ERROR_MORE_DATA) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 sval = malloc(ssize);
550 status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,
551 &fval, sval, &ssize);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000552 }
553
554 switch(type) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555 case VT_I2: case VT_I4:
556 return PyLong_FromLong(ival);
557 case VT_FILETIME:
558 PyErr_SetString(PyExc_NotImplementedError, "FILETIME result");
559 return NULL;
560 case VT_LPSTR:
561 result = PyBytes_FromStringAndSize(sval, ssize);
562 if (sval != sbuf)
563 free(sval);
564 return result;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000565 }
566 PyErr_Format(PyExc_NotImplementedError, "result of type %d", type);
567 return NULL;
568}
569
570static PyObject*
571summary_getpropertycount(msiobj* si, PyObject *args)
572{
573 int status;
574 UINT result;
575
576 status = MsiSummaryInfoGetPropertyCount(si->h, &result);
577 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000579
Christian Heimes217cfd12007-12-02 14:31:20 +0000580 return PyLong_FromLong(result);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000581}
582
583static PyObject*
584summary_setproperty(msiobj* si, PyObject *args)
585{
586 int status;
587 int field;
588 PyObject* data;
589
590 if (!PyArg_ParseTuple(args, "iO:SetProperty", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000592
Martin v. Löwis371bb502008-08-16 13:02:57 +0000593 if (PyUnicode_Check(data)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000594 status = MsiSummaryInfoSetPropertyW(si->h, field, VT_LPSTR,
595 0, NULL, PyUnicode_AsUnicode(data));
Martin v. Löwisd1a1d1e2007-12-04 22:10:37 +0000596 } else if (PyLong_CheckExact(data)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 long value = PyLong_AsLong(data);
598 if (value == -1 && PyErr_Occurred()) {
599 return NULL;
600 }
601 status = MsiSummaryInfoSetProperty(si->h, field, VT_I4,
602 value, NULL, NULL);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000603 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000604 PyErr_SetString(PyExc_TypeError, "unsupported type");
605 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000606 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000608 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000610
611 Py_INCREF(Py_None);
612 return Py_None;
613}
614
615
616static PyObject*
617summary_persist(msiobj* si, PyObject *args)
618{
619 int status;
620
621 status = MsiSummaryInfoPersist(si->h);
622 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000624 Py_INCREF(Py_None);
625 return Py_None;
626}
627
628static PyMethodDef summary_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 { "GetProperty", (PyCFunction)summary_getproperty, METH_VARARGS,
630 PyDoc_STR("GetProperty(propid) -> value\nWraps MsiSummaryInfoGetProperty")},
631 { "GetPropertyCount", (PyCFunction)summary_getpropertycount, METH_NOARGS,
632 PyDoc_STR("GetProperty() -> int\nWraps MsiSummaryInfoGetPropertyCount")},
633 { "SetProperty", (PyCFunction)summary_setproperty, METH_VARARGS,
634 PyDoc_STR("SetProperty(value) -> None\nWraps MsiSummaryInfoProperty")},
635 { "Persist", (PyCFunction)summary_persist, METH_NOARGS,
636 PyDoc_STR("Persist() -> None\nWraps MsiSummaryInfoPersist")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000637 { NULL, NULL }
638};
639
640static PyTypeObject summary_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 PyVarObject_HEAD_INIT(NULL, 0)
642 "_msi.SummaryInformation", /*tp_name*/
643 sizeof(msiobj), /*tp_basicsize*/
644 0, /*tp_itemsize*/
645 /* methods */
646 (destructor)msiobj_dealloc, /*tp_dealloc*/
647 0, /*tp_print*/
648 0, /*tp_getattr*/
649 0, /*tp_setattr*/
650 0, /*tp_reserved*/
651 0, /*tp_repr*/
652 0, /*tp_as_number*/
653 0, /*tp_as_sequence*/
654 0, /*tp_as_mapping*/
655 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000656 0, /*tp_call*/
657 0, /*tp_str*/
658 PyObject_GenericGetAttr,/*tp_getattro*/
659 PyObject_GenericSetAttr,/*tp_setattro*/
660 0, /*tp_as_buffer*/
661 Py_TPFLAGS_DEFAULT, /*tp_flags*/
662 0, /*tp_doc*/
663 0, /*tp_traverse*/
664 0, /*tp_clear*/
665 0, /*tp_richcompare*/
666 0, /*tp_weaklistoffset*/
667 0, /*tp_iter*/
668 0, /*tp_iternext*/
669 summary_methods, /*tp_methods*/
670 0, /*tp_members*/
671 0, /*tp_getset*/
672 0, /*tp_base*/
673 0, /*tp_dict*/
674 0, /*tp_descr_get*/
675 0, /*tp_descr_set*/
676 0, /*tp_dictoffset*/
677 0, /*tp_init*/
678 0, /*tp_alloc*/
679 0, /*tp_new*/
680 0, /*tp_free*/
681 0, /*tp_is_gc*/
682};
683
684/*************************** View objects **************/
685
686static PyObject*
687view_execute(msiobj *view, PyObject*args)
688{
689 int status;
690 MSIHANDLE params = 0;
691 PyObject *oparams = Py_None;
692
693 if (!PyArg_ParseTuple(args, "O:Execute", &oparams))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000695
696 if (oparams != Py_None) {
697 if (oparams->ob_type != &record_Type) {
698 PyErr_SetString(PyExc_TypeError, "Execute argument must be a record");
699 return NULL;
700 }
701 params = ((msiobj*)oparams)->h;
702 }
703
704 status = MsiViewExecute(view->h, params);
705 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000707
708 Py_INCREF(Py_None);
709 return Py_None;
710}
711
712static PyObject*
713view_fetch(msiobj *view, PyObject*args)
714{
715 int status;
716 MSIHANDLE result;
717
718 if ((status = MsiViewFetch(view->h, &result)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000720
721 return record_new(result);
722}
723
724static PyObject*
725view_getcolumninfo(msiobj *view, PyObject *args)
726{
727 int status;
728 int kind;
729 MSIHANDLE result;
730
731 if (!PyArg_ParseTuple(args, "i:GetColumnInfo", &kind))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000733
734 if ((status = MsiViewGetColumnInfo(view->h, kind, &result)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000736
737 return record_new(result);
738}
739
740static PyObject*
741view_modify(msiobj *view, PyObject *args)
742{
743 int kind;
744 PyObject *data;
745 int status;
746
747 if (!PyArg_ParseTuple(args, "iO:Modify", &kind, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000749
750 if (data->ob_type != &record_Type) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000751 PyErr_SetString(PyExc_TypeError, "Modify expects a record object");
752 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000753 }
754
755 if ((status = MsiViewModify(view->h, kind, ((msiobj*)data)->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000757
758 Py_INCREF(Py_None);
759 return Py_None;
760}
761
762static PyObject*
763view_close(msiobj *view, PyObject*args)
764{
765 int status;
766
767 if ((status = MsiViewClose(view->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000768 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000769
770 Py_INCREF(Py_None);
771 return Py_None;
772}
773
774static PyMethodDef view_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 { "Execute", (PyCFunction)view_execute, METH_VARARGS,
776 PyDoc_STR("Execute(params=None) -> None\nWraps MsiViewExecute")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000777 { "GetColumnInfo", (PyCFunction)view_getcolumninfo, METH_VARARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000778 PyDoc_STR("GetColumnInfo() -> result\nWraps MsiGetColumnInfo")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000779 { "Fetch", (PyCFunction)view_fetch, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000780 PyDoc_STR("Fetch() -> result\nWraps MsiViewFetch")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000781 { "Modify", (PyCFunction)view_modify, METH_VARARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782 PyDoc_STR("Modify(mode,record) -> None\nWraps MsiViewModify")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000783 { "Close", (PyCFunction)view_close, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000784 PyDoc_STR("Close() -> result\nWraps MsiViewClose")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000785 { NULL, NULL }
786};
787
788static PyTypeObject msiview_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 PyVarObject_HEAD_INIT(NULL, 0)
790 "_msi.View", /*tp_name*/
791 sizeof(msiobj), /*tp_basicsize*/
792 0, /*tp_itemsize*/
793 /* methods */
794 (destructor)msiobj_dealloc, /*tp_dealloc*/
795 0, /*tp_print*/
796 0, /*tp_getattr*/
797 0, /*tp_setattr*/
798 0, /*tp_reserved*/
799 0, /*tp_repr*/
800 0, /*tp_as_number*/
801 0, /*tp_as_sequence*/
802 0, /*tp_as_mapping*/
803 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000804 0, /*tp_call*/
805 0, /*tp_str*/
806 PyObject_GenericGetAttr,/*tp_getattro*/
807 PyObject_GenericSetAttr,/*tp_setattro*/
808 0, /*tp_as_buffer*/
809 Py_TPFLAGS_DEFAULT, /*tp_flags*/
810 0, /*tp_doc*/
811 0, /*tp_traverse*/
812 0, /*tp_clear*/
813 0, /*tp_richcompare*/
814 0, /*tp_weaklistoffset*/
815 0, /*tp_iter*/
816 0, /*tp_iternext*/
817 view_methods, /*tp_methods*/
818 0, /*tp_members*/
819 0, /*tp_getset*/
820 0, /*tp_base*/
821 0, /*tp_dict*/
822 0, /*tp_descr_get*/
823 0, /*tp_descr_set*/
824 0, /*tp_dictoffset*/
825 0, /*tp_init*/
826 0, /*tp_alloc*/
827 0, /*tp_new*/
828 0, /*tp_free*/
829 0, /*tp_is_gc*/
830};
831
832/*************************** Database objects **************/
833
834static PyObject*
835msidb_openview(msiobj *msidb, PyObject *args)
836{
837 int status;
838 char *sql;
839 MSIHANDLE hView;
840 msiobj *result;
841
842 if (!PyArg_ParseTuple(args, "s:OpenView", &sql))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000843 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000844
845 if ((status = MsiDatabaseOpenView(msidb->h, sql, &hView)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000846 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000847
848 result = PyObject_NEW(struct msiobj, &msiview_Type);
849 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000850 MsiCloseHandle(hView);
851 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000852 }
853
854 result->h = hView;
855 return (PyObject*)result;
856}
857
858static PyObject*
859msidb_commit(msiobj *msidb, PyObject *args)
860{
861 int status;
862
863 if ((status = MsiDatabaseCommit(msidb->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000864 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000865
866 Py_INCREF(Py_None);
867 return Py_None;
868}
869
870static PyObject*
871msidb_getsummaryinformation(msiobj *db, PyObject *args)
872{
873 int status;
874 int count;
875 MSIHANDLE result;
876 msiobj *oresult;
877
878 if (!PyArg_ParseTuple(args, "i:GetSummaryInformation", &count))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000879 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000880
881 status = MsiGetSummaryInformation(db->h, NULL, count, &result);
882 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000883 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000884
885 oresult = PyObject_NEW(struct msiobj, &summary_Type);
886 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 MsiCloseHandle(result);
888 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000889 }
890
891 oresult->h = result;
892 return (PyObject*)oresult;
893}
894
895static PyMethodDef db_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000896 { "OpenView", (PyCFunction)msidb_openview, METH_VARARGS,
897 PyDoc_STR("OpenView(sql) -> viewobj\nWraps MsiDatabaseOpenView")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000898 { "Commit", (PyCFunction)msidb_commit, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000899 PyDoc_STR("Commit() -> None\nWraps MsiDatabaseCommit")},
900 { "GetSummaryInformation", (PyCFunction)msidb_getsummaryinformation, METH_VARARGS,
901 PyDoc_STR("GetSummaryInformation(updateCount) -> viewobj\nWraps MsiGetSummaryInformation")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000902 { NULL, NULL }
903};
904
905static PyTypeObject msidb_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000906 PyVarObject_HEAD_INIT(NULL, 0)
907 "_msi.Database", /*tp_name*/
908 sizeof(msiobj), /*tp_basicsize*/
909 0, /*tp_itemsize*/
910 /* methods */
911 (destructor)msiobj_dealloc, /*tp_dealloc*/
912 0, /*tp_print*/
913 0, /*tp_getattr*/
914 0, /*tp_setattr*/
915 0, /*tp_reserved*/
916 0, /*tp_repr*/
917 0, /*tp_as_number*/
918 0, /*tp_as_sequence*/
919 0, /*tp_as_mapping*/
920 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000921 0, /*tp_call*/
922 0, /*tp_str*/
923 PyObject_GenericGetAttr,/*tp_getattro*/
924 PyObject_GenericSetAttr,/*tp_setattro*/
925 0, /*tp_as_buffer*/
926 Py_TPFLAGS_DEFAULT, /*tp_flags*/
927 0, /*tp_doc*/
928 0, /*tp_traverse*/
929 0, /*tp_clear*/
930 0, /*tp_richcompare*/
931 0, /*tp_weaklistoffset*/
932 0, /*tp_iter*/
933 0, /*tp_iternext*/
934 db_methods, /*tp_methods*/
935 0, /*tp_members*/
936 0, /*tp_getset*/
937 0, /*tp_base*/
938 0, /*tp_dict*/
939 0, /*tp_descr_get*/
940 0, /*tp_descr_set*/
941 0, /*tp_dictoffset*/
942 0, /*tp_init*/
943 0, /*tp_alloc*/
944 0, /*tp_new*/
945 0, /*tp_free*/
946 0, /*tp_is_gc*/
947};
948
949static PyObject* msiopendb(PyObject *obj, PyObject *args)
950{
951 int status;
952 char *path;
953 int persist;
954 MSIHANDLE h;
955 msiobj *result;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000956
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000957 if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist))
958 return NULL;
959
960 status = MsiOpenDatabase(path, (LPCSTR)persist, &h);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000961 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000963
964 result = PyObject_NEW(struct msiobj, &msidb_Type);
965 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000966 MsiCloseHandle(h);
967 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000968 }
969 result->h = h;
970 return (PyObject*)result;
971}
972
973static PyObject*
974createrecord(PyObject *o, PyObject *args)
975{
976 int count;
977 MSIHANDLE h;
978
979 if (!PyArg_ParseTuple(args, "i:CreateRecord", &count))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000980 return NULL;
981
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000982 h = MsiCreateRecord(count);
983 if (h == 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984 return msierror(0);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000985
986 return record_new(h);
987}
988
989
990static PyMethodDef msi_methods[] = {
991 {"UuidCreate", (PyCFunction)uuidcreate, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000992 PyDoc_STR("UuidCreate() -> string")},
993 {"FCICreate", (PyCFunction)fcicreate, METH_VARARGS,
994 PyDoc_STR("fcicreate(cabname,files) -> None")},
995 {"OpenDatabase", (PyCFunction)msiopendb, METH_VARARGS,
996 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiOpenDatabase")},
997 {"CreateRecord", (PyCFunction)createrecord, METH_VARARGS,
998 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiCreateRecord")},
999 {NULL, NULL} /* sentinel */
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001000};
1001
1002static char msi_doc[] = "Documentation";
1003
Martin v. Löwis1a214512008-06-11 05:26:20 +00001004
1005static struct PyModuleDef _msimodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001006 PyModuleDef_HEAD_INIT,
1007 "_msi",
1008 msi_doc,
1009 -1,
1010 msi_methods,
1011 NULL,
1012 NULL,
1013 NULL,
1014 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001015};
1016
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001017PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001018PyInit__msi(void)
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001019{
1020 PyObject *m;
1021
Martin v. Löwis1a214512008-06-11 05:26:20 +00001022 m = PyModule_Create(&_msimodule);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001023 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001024 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001025
1026 PyModule_AddIntConstant(m, "MSIDBOPEN_CREATEDIRECT", (int)MSIDBOPEN_CREATEDIRECT);
1027 PyModule_AddIntConstant(m, "MSIDBOPEN_CREATE", (int)MSIDBOPEN_CREATE);
1028 PyModule_AddIntConstant(m, "MSIDBOPEN_DIRECT", (int)MSIDBOPEN_DIRECT);
1029 PyModule_AddIntConstant(m, "MSIDBOPEN_READONLY", (int)MSIDBOPEN_READONLY);
1030 PyModule_AddIntConstant(m, "MSIDBOPEN_TRANSACT", (int)MSIDBOPEN_TRANSACT);
1031 PyModule_AddIntConstant(m, "MSIDBOPEN_PATCHFILE", (int)MSIDBOPEN_PATCHFILE);
1032
Charles-Francois Natali74ca8862013-05-20 19:13:19 +02001033 PyModule_AddIntMacro(m, MSICOLINFO_NAMES);
1034 PyModule_AddIntMacro(m, MSICOLINFO_TYPES);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001035
Charles-Francois Natali74ca8862013-05-20 19:13:19 +02001036 PyModule_AddIntMacro(m, MSIMODIFY_SEEK);
1037 PyModule_AddIntMacro(m, MSIMODIFY_REFRESH);
1038 PyModule_AddIntMacro(m, MSIMODIFY_INSERT);
1039 PyModule_AddIntMacro(m, MSIMODIFY_UPDATE);
1040 PyModule_AddIntMacro(m, MSIMODIFY_ASSIGN);
1041 PyModule_AddIntMacro(m, MSIMODIFY_REPLACE);
1042 PyModule_AddIntMacro(m, MSIMODIFY_MERGE);
1043 PyModule_AddIntMacro(m, MSIMODIFY_DELETE);
1044 PyModule_AddIntMacro(m, MSIMODIFY_INSERT_TEMPORARY);
1045 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE);
1046 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_NEW);
1047 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_FIELD);
1048 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_DELETE);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001049
Charles-Francois Natali74ca8862013-05-20 19:13:19 +02001050 PyModule_AddIntMacro(m, PID_CODEPAGE);
1051 PyModule_AddIntMacro(m, PID_TITLE);
1052 PyModule_AddIntMacro(m, PID_SUBJECT);
1053 PyModule_AddIntMacro(m, PID_AUTHOR);
1054 PyModule_AddIntMacro(m, PID_KEYWORDS);
1055 PyModule_AddIntMacro(m, PID_COMMENTS);
1056 PyModule_AddIntMacro(m, PID_TEMPLATE);
1057 PyModule_AddIntMacro(m, PID_LASTAUTHOR);
1058 PyModule_AddIntMacro(m, PID_REVNUMBER);
1059 PyModule_AddIntMacro(m, PID_LASTPRINTED);
1060 PyModule_AddIntMacro(m, PID_CREATE_DTM);
1061 PyModule_AddIntMacro(m, PID_LASTSAVE_DTM);
1062 PyModule_AddIntMacro(m, PID_PAGECOUNT);
1063 PyModule_AddIntMacro(m, PID_WORDCOUNT);
1064 PyModule_AddIntMacro(m, PID_CHARCOUNT);
1065 PyModule_AddIntMacro(m, PID_APPNAME);
1066 PyModule_AddIntMacro(m, PID_SECURITY);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001067
1068 MSIError = PyErr_NewException ("_msi.MSIError", NULL, NULL);
1069 if (!MSIError)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001070 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001071 PyModule_AddObject(m, "MSIError", MSIError);
Amaury Forgeot d'Arcbf9e9662008-06-17 21:39:46 +00001072 return m;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001073}