blob: 000d81f139f3541364043cbce19f9931adb602a6 [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;
Zachary Ware0a29e892015-05-18 00:47:15 -0500246
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:27 +0000253 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:04 +0000257 }
258
259 if (!FCIFlushCabinet(hfci, FALSE, cb_getnextcabinet, cb_status))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 goto err;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000261
262 if (!FCIDestroy(hfci))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 goto err;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000264
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200265 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000266err:
Zachary Ware0a29e892015-05-18 00:47:15 -0500267 if(erf.fError)
268 PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */
269 else
270 PyErr_SetString(PyExc_ValueError, "FCI general error");
271
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000272 FCIDestroy(hfci);
273 return NULL;
274}
275
276typedef struct msiobj{
277 PyObject_HEAD
278 MSIHANDLE h;
279}msiobj;
280
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281static void
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000282msiobj_dealloc(msiobj* msidb)
283{
284 MsiCloseHandle(msidb->h);
285 msidb->h = 0;
Zackery Spytzcb04f752017-11-07 03:03:09 -0700286 PyObject_Del(msidb);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000287}
288
289static PyObject*
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000290msierror(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;
Berker Peksag4864a612017-11-24 12:53:58 +0300318 case ERROR_OPEN_FAILED:
319 PyErr_SetString(MSIError, "open failed");
320 return NULL;
321 case ERROR_CREATE_FAILED:
322 PyErr_SetString(MSIError, "create failed");
323 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000324 default:
325 PyErr_Format(MSIError, "unknown error %x", status);
326 return NULL;
327 }
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000328 }
329
330 code = MsiRecordGetInteger(err, 1); /* XXX code */
331 if (MsiFormatRecord(0, err, res, &size) == ERROR_MORE_DATA) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 res = malloc(size+1);
333 MsiFormatRecord(0, err, res, &size);
334 res[size]='\0';
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000335 }
336 MsiCloseHandle(err);
337 PyErr_SetString(MSIError, res);
338 if (res != buf)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339 free(res);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000340 return NULL;
341}
342
Berker Peksaga9356542017-11-07 15:58:53 +0300343static PyObject*
344msidb_close(msiobj* msidb, PyObject *args)
345{
346 int status;
347 if ((status = MsiCloseHandle(msidb->h)) != ERROR_SUCCESS) {
348 return msierror(status);
349 }
350 msidb->h = 0;
351 Py_RETURN_NONE;
352}
353
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000354/*************************** Record objects **********************/
355
356static PyObject*
357record_getfieldcount(msiobj* record, PyObject* args)
358{
Christian Heimes217cfd12007-12-02 14:31:20 +0000359 return PyLong_FromLong(MsiRecordGetFieldCount(record->h));
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000360}
361
362static PyObject*
Martin v. Löwise95593e2008-06-02 10:08:54 +0000363record_getinteger(msiobj* record, PyObject* args)
364{
365 unsigned int field;
366 int status;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000367
Martin v. Löwise95593e2008-06-02 10:08:54 +0000368 if (!PyArg_ParseTuple(args, "I:GetInteger", &field))
369 return NULL;
370 status = MsiRecordGetInteger(record->h, field);
371 if (status == MSI_NULL_INTEGER){
372 PyErr_SetString(MSIError, "could not convert record field to integer");
373 return NULL;
374 }
Martin v. Löwis704d8b12008-06-02 11:32:23 +0000375 return PyLong_FromLong((long) status);
Martin v. Löwise95593e2008-06-02 10:08:54 +0000376}
377
378static PyObject*
379record_getstring(msiobj* record, PyObject* args)
380{
381 unsigned int field;
382 unsigned int status;
Martin v. Löwis371bb502008-08-16 13:02:57 +0000383 WCHAR buf[2000];
384 WCHAR *res = buf;
Martin v. Löwise95593e2008-06-02 10:08:54 +0000385 DWORD size = sizeof(buf);
386 PyObject* string;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387
Martin v. Löwise95593e2008-06-02 10:08:54 +0000388 if (!PyArg_ParseTuple(args, "I:GetString", &field))
389 return NULL;
Martin v. Löwis371bb502008-08-16 13:02:57 +0000390 status = MsiRecordGetStringW(record->h, field, res, &size);
Martin v. Löwise95593e2008-06-02 10:08:54 +0000391 if (status == ERROR_MORE_DATA) {
Martin v. Löwis371bb502008-08-16 13:02:57 +0000392 res = (WCHAR*) malloc((size + 1)*sizeof(WCHAR));
Martin v. Löwise95593e2008-06-02 10:08:54 +0000393 if (res == NULL)
394 return PyErr_NoMemory();
Martin v. Löwis371bb502008-08-16 13:02:57 +0000395 status = MsiRecordGetStringW(record->h, field, res, &size);
Martin v. Löwise95593e2008-06-02 10:08:54 +0000396 }
397 if (status != ERROR_SUCCESS)
398 return msierror((int) status);
Victor Stinner9d3b93b2011-11-22 02:27:30 +0100399 string = PyUnicode_FromWideChar(res, size);
Martin v. Löwise95593e2008-06-02 10:08:54 +0000400 if (buf != res)
401 free(res);
402 return string;
403}
404
405static PyObject*
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000406record_cleardata(msiobj* record, PyObject *args)
407{
408 int status = MsiRecordClearData(record->h);
409 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000411
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200412 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000413}
414
415static PyObject*
416record_setstring(msiobj* record, PyObject *args)
417{
418 int status;
419 int field;
Victor Stinner9d3b93b2011-11-22 02:27:30 +0100420 wchar_t *data;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000421
Martin v. Löwis371bb502008-08-16 13:02:57 +0000422 if (!PyArg_ParseTuple(args, "iu:SetString", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000424
Martin v. Löwis371bb502008-08-16 13:02:57 +0000425 if ((status = MsiRecordSetStringW(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000426 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000427
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200428 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000429}
430
431static PyObject*
432record_setstream(msiobj* record, PyObject *args)
433{
434 int status;
435 int field;
Victor Stinner9d3b93b2011-11-22 02:27:30 +0100436 wchar_t *data;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000437
Martin v. Löwis371bb502008-08-16 13:02:57 +0000438 if (!PyArg_ParseTuple(args, "iu:SetStream", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000439 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000440
Martin v. Löwis371bb502008-08-16 13:02:57 +0000441 if ((status = MsiRecordSetStreamW(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000442 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000443
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200444 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000445}
446
447static PyObject*
448record_setinteger(msiobj* record, PyObject *args)
449{
450 int status;
451 int field;
452 int data;
453
454 if (!PyArg_ParseTuple(args, "ii:SetInteger", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000456
457 if ((status = MsiRecordSetInteger(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000458 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000459
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200460 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000461}
462
463
464
465static PyMethodDef record_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 { "GetFieldCount", (PyCFunction)record_getfieldcount, METH_NOARGS,
467 PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")},
Martin v. Löwise95593e2008-06-02 10:08:54 +0000468 { "GetInteger", (PyCFunction)record_getinteger, METH_VARARGS,
469 PyDoc_STR("GetInteger(field) -> int\nWraps MsiRecordGetInteger")},
470 { "GetString", (PyCFunction)record_getstring, METH_VARARGS,
471 PyDoc_STR("GetString(field) -> string\nWraps MsiRecordGetString")},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 { "SetString", (PyCFunction)record_setstring, METH_VARARGS,
473 PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")},
474 { "SetStream", (PyCFunction)record_setstream, METH_VARARGS,
475 PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")},
476 { "SetInteger", (PyCFunction)record_setinteger, METH_VARARGS,
477 PyDoc_STR("SetInteger(field,int) -> None\nWraps MsiRecordSetInteger")},
478 { "ClearData", (PyCFunction)record_cleardata, METH_NOARGS,
479 PyDoc_STR("ClearData() -> int\nWraps MsiRecordGClearData")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000480 { NULL, NULL }
481};
482
483static PyTypeObject record_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 PyVarObject_HEAD_INIT(NULL, 0)
485 "_msi.Record", /*tp_name*/
486 sizeof(msiobj), /*tp_basicsize*/
487 0, /*tp_itemsize*/
488 /* methods */
489 (destructor)msiobj_dealloc, /*tp_dealloc*/
490 0, /*tp_print*/
491 0, /*tp_getattr*/
492 0, /*tp_setattr*/
493 0, /*tp_reserved*/
494 0, /*tp_repr*/
495 0, /*tp_as_number*/
496 0, /*tp_as_sequence*/
497 0, /*tp_as_mapping*/
498 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000499 0, /*tp_call*/
500 0, /*tp_str*/
501 PyObject_GenericGetAttr,/*tp_getattro*/
502 PyObject_GenericSetAttr,/*tp_setattro*/
503 0, /*tp_as_buffer*/
504 Py_TPFLAGS_DEFAULT, /*tp_flags*/
505 0, /*tp_doc*/
506 0, /*tp_traverse*/
507 0, /*tp_clear*/
508 0, /*tp_richcompare*/
509 0, /*tp_weaklistoffset*/
510 0, /*tp_iter*/
511 0, /*tp_iternext*/
512 record_methods, /*tp_methods*/
513 0, /*tp_members*/
514 0, /*tp_getset*/
515 0, /*tp_base*/
516 0, /*tp_dict*/
517 0, /*tp_descr_get*/
518 0, /*tp_descr_set*/
519 0, /*tp_dictoffset*/
520 0, /*tp_init*/
521 0, /*tp_alloc*/
522 0, /*tp_new*/
523 0, /*tp_free*/
524 0, /*tp_is_gc*/
525};
526
527static PyObject*
528record_new(MSIHANDLE h)
529{
530 msiobj *result = PyObject_NEW(struct msiobj, &record_Type);
531
532 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 MsiCloseHandle(h);
534 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000535 }
536
537 result->h = h;
538 return (PyObject*)result;
539}
540
541/*************************** SummaryInformation objects **************/
542
543static PyObject*
544summary_getproperty(msiobj* si, PyObject *args)
545{
546 int status;
547 int field;
548 PyObject *result;
549 UINT type;
550 INT ival;
551 FILETIME fval;
552 char sbuf[1000];
553 char *sval = sbuf;
554 DWORD ssize = sizeof(sval);
555
556 if (!PyArg_ParseTuple(args, "i:GetProperty", &field))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,
560 &fval, sval, &ssize);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000561 if (status == ERROR_MORE_DATA) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 sval = malloc(ssize);
563 status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,
564 &fval, sval, &ssize);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000565 }
566
567 switch(type) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 case VT_I2: case VT_I4:
569 return PyLong_FromLong(ival);
570 case VT_FILETIME:
571 PyErr_SetString(PyExc_NotImplementedError, "FILETIME result");
572 return NULL;
573 case VT_LPSTR:
574 result = PyBytes_FromStringAndSize(sval, ssize);
575 if (sval != sbuf)
576 free(sval);
577 return result;
Berker Peksag19fb1342017-11-24 18:11:18 +0300578 case VT_EMPTY:
579 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000580 }
581 PyErr_Format(PyExc_NotImplementedError, "result of type %d", type);
582 return NULL;
583}
584
585static PyObject*
586summary_getpropertycount(msiobj* si, PyObject *args)
587{
588 int status;
589 UINT result;
590
591 status = MsiSummaryInfoGetPropertyCount(si->h, &result);
592 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000594
Christian Heimes217cfd12007-12-02 14:31:20 +0000595 return PyLong_FromLong(result);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000596}
597
598static PyObject*
599summary_setproperty(msiobj* si, PyObject *args)
600{
601 int status;
602 int field;
603 PyObject* data;
604
605 if (!PyArg_ParseTuple(args, "iO:SetProperty", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000607
Martin v. Löwis371bb502008-08-16 13:02:57 +0000608 if (PyUnicode_Check(data)) {
Serhiy Storchakaccdc09e2017-06-28 09:55:22 +0300609 const WCHAR *value = _PyUnicode_AsUnicode(data);
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300610 if (value == NULL) {
611 return NULL;
612 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 status = MsiSummaryInfoSetPropertyW(si->h, field, VT_LPSTR,
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300614 0, NULL, value);
Martin v. Löwisd1a1d1e2007-12-04 22:10:37 +0000615 } else if (PyLong_CheckExact(data)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 long value = PyLong_AsLong(data);
617 if (value == -1 && PyErr_Occurred()) {
618 return NULL;
619 }
620 status = MsiSummaryInfoSetProperty(si->h, field, VT_I4,
621 value, NULL, NULL);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000622 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 PyErr_SetString(PyExc_TypeError, "unsupported type");
624 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000625 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000626
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000627 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000629
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200630 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000631}
632
633
634static PyObject*
635summary_persist(msiobj* si, PyObject *args)
636{
637 int status;
638
639 status = MsiSummaryInfoPersist(si->h);
640 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 return msierror(status);
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200642 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000643}
644
645static PyMethodDef summary_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 { "GetProperty", (PyCFunction)summary_getproperty, METH_VARARGS,
647 PyDoc_STR("GetProperty(propid) -> value\nWraps MsiSummaryInfoGetProperty")},
648 { "GetPropertyCount", (PyCFunction)summary_getpropertycount, METH_NOARGS,
649 PyDoc_STR("GetProperty() -> int\nWraps MsiSummaryInfoGetPropertyCount")},
650 { "SetProperty", (PyCFunction)summary_setproperty, METH_VARARGS,
651 PyDoc_STR("SetProperty(value) -> None\nWraps MsiSummaryInfoProperty")},
652 { "Persist", (PyCFunction)summary_persist, METH_NOARGS,
653 PyDoc_STR("Persist() -> None\nWraps MsiSummaryInfoPersist")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000654 { NULL, NULL }
655};
656
657static PyTypeObject summary_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 PyVarObject_HEAD_INIT(NULL, 0)
659 "_msi.SummaryInformation", /*tp_name*/
660 sizeof(msiobj), /*tp_basicsize*/
661 0, /*tp_itemsize*/
662 /* methods */
663 (destructor)msiobj_dealloc, /*tp_dealloc*/
664 0, /*tp_print*/
665 0, /*tp_getattr*/
666 0, /*tp_setattr*/
667 0, /*tp_reserved*/
668 0, /*tp_repr*/
669 0, /*tp_as_number*/
670 0, /*tp_as_sequence*/
671 0, /*tp_as_mapping*/
672 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000673 0, /*tp_call*/
674 0, /*tp_str*/
675 PyObject_GenericGetAttr,/*tp_getattro*/
676 PyObject_GenericSetAttr,/*tp_setattro*/
677 0, /*tp_as_buffer*/
678 Py_TPFLAGS_DEFAULT, /*tp_flags*/
679 0, /*tp_doc*/
680 0, /*tp_traverse*/
681 0, /*tp_clear*/
682 0, /*tp_richcompare*/
683 0, /*tp_weaklistoffset*/
684 0, /*tp_iter*/
685 0, /*tp_iternext*/
686 summary_methods, /*tp_methods*/
687 0, /*tp_members*/
688 0, /*tp_getset*/
689 0, /*tp_base*/
690 0, /*tp_dict*/
691 0, /*tp_descr_get*/
692 0, /*tp_descr_set*/
693 0, /*tp_dictoffset*/
694 0, /*tp_init*/
695 0, /*tp_alloc*/
696 0, /*tp_new*/
697 0, /*tp_free*/
698 0, /*tp_is_gc*/
699};
700
701/*************************** View objects **************/
702
703static PyObject*
704view_execute(msiobj *view, PyObject*args)
705{
706 int status;
707 MSIHANDLE params = 0;
708 PyObject *oparams = Py_None;
709
710 if (!PyArg_ParseTuple(args, "O:Execute", &oparams))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000712
713 if (oparams != Py_None) {
714 if (oparams->ob_type != &record_Type) {
715 PyErr_SetString(PyExc_TypeError, "Execute argument must be a record");
716 return NULL;
717 }
718 params = ((msiobj*)oparams)->h;
719 }
720
721 status = MsiViewExecute(view->h, params);
722 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000724
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200725 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000726}
727
728static PyObject*
729view_fetch(msiobj *view, PyObject*args)
730{
731 int status;
732 MSIHANDLE result;
733
Berker Peksagbdb83152017-11-23 15:47:30 +0300734 status = MsiViewFetch(view->h, &result);
735 if (status == ERROR_NO_MORE_ITEMS) {
736 Py_RETURN_NONE;
737 } else if (status != ERROR_SUCCESS) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738 return msierror(status);
Berker Peksagbdb83152017-11-23 15:47:30 +0300739 }
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000740
741 return record_new(result);
742}
743
744static PyObject*
745view_getcolumninfo(msiobj *view, PyObject *args)
746{
747 int status;
748 int kind;
749 MSIHANDLE result;
750
751 if (!PyArg_ParseTuple(args, "i:GetColumnInfo", &kind))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000753
754 if ((status = MsiViewGetColumnInfo(view->h, kind, &result)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000755 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000756
757 return record_new(result);
758}
759
760static PyObject*
761view_modify(msiobj *view, PyObject *args)
762{
763 int kind;
764 PyObject *data;
765 int status;
766
767 if (!PyArg_ParseTuple(args, "iO:Modify", &kind, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000768 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000769
770 if (data->ob_type != &record_Type) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000771 PyErr_SetString(PyExc_TypeError, "Modify expects a record object");
772 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000773 }
774
775 if ((status = MsiViewModify(view->h, kind, ((msiobj*)data)->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000776 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000777
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200778 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000779}
780
781static PyObject*
782view_close(msiobj *view, PyObject*args)
783{
784 int status;
785
786 if ((status = MsiViewClose(view->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000787 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000788
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200789 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000790}
791
792static PyMethodDef view_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000793 { "Execute", (PyCFunction)view_execute, METH_VARARGS,
794 PyDoc_STR("Execute(params=None) -> None\nWraps MsiViewExecute")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000795 { "GetColumnInfo", (PyCFunction)view_getcolumninfo, METH_VARARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000796 PyDoc_STR("GetColumnInfo() -> result\nWraps MsiGetColumnInfo")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000797 { "Fetch", (PyCFunction)view_fetch, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 PyDoc_STR("Fetch() -> result\nWraps MsiViewFetch")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000799 { "Modify", (PyCFunction)view_modify, METH_VARARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000800 PyDoc_STR("Modify(mode,record) -> None\nWraps MsiViewModify")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000801 { "Close", (PyCFunction)view_close, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000802 PyDoc_STR("Close() -> result\nWraps MsiViewClose")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000803 { NULL, NULL }
804};
805
806static PyTypeObject msiview_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000807 PyVarObject_HEAD_INIT(NULL, 0)
808 "_msi.View", /*tp_name*/
809 sizeof(msiobj), /*tp_basicsize*/
810 0, /*tp_itemsize*/
811 /* methods */
812 (destructor)msiobj_dealloc, /*tp_dealloc*/
813 0, /*tp_print*/
814 0, /*tp_getattr*/
815 0, /*tp_setattr*/
816 0, /*tp_reserved*/
817 0, /*tp_repr*/
818 0, /*tp_as_number*/
819 0, /*tp_as_sequence*/
820 0, /*tp_as_mapping*/
821 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000822 0, /*tp_call*/
823 0, /*tp_str*/
824 PyObject_GenericGetAttr,/*tp_getattro*/
825 PyObject_GenericSetAttr,/*tp_setattro*/
826 0, /*tp_as_buffer*/
827 Py_TPFLAGS_DEFAULT, /*tp_flags*/
828 0, /*tp_doc*/
829 0, /*tp_traverse*/
830 0, /*tp_clear*/
831 0, /*tp_richcompare*/
832 0, /*tp_weaklistoffset*/
833 0, /*tp_iter*/
834 0, /*tp_iternext*/
835 view_methods, /*tp_methods*/
836 0, /*tp_members*/
837 0, /*tp_getset*/
838 0, /*tp_base*/
839 0, /*tp_dict*/
840 0, /*tp_descr_get*/
841 0, /*tp_descr_set*/
842 0, /*tp_dictoffset*/
843 0, /*tp_init*/
844 0, /*tp_alloc*/
845 0, /*tp_new*/
846 0, /*tp_free*/
847 0, /*tp_is_gc*/
848};
849
850/*************************** Database objects **************/
851
852static PyObject*
853msidb_openview(msiobj *msidb, PyObject *args)
854{
855 int status;
856 char *sql;
857 MSIHANDLE hView;
858 msiobj *result;
859
860 if (!PyArg_ParseTuple(args, "s:OpenView", &sql))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000861 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000862
863 if ((status = MsiDatabaseOpenView(msidb->h, sql, &hView)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000864 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000865
866 result = PyObject_NEW(struct msiobj, &msiview_Type);
867 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 MsiCloseHandle(hView);
869 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000870 }
871
872 result->h = hView;
873 return (PyObject*)result;
874}
875
876static PyObject*
877msidb_commit(msiobj *msidb, PyObject *args)
878{
879 int status;
880
881 if ((status = MsiDatabaseCommit(msidb->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000882 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000883
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200884 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000885}
886
887static PyObject*
888msidb_getsummaryinformation(msiobj *db, PyObject *args)
889{
890 int status;
891 int count;
892 MSIHANDLE result;
893 msiobj *oresult;
894
895 if (!PyArg_ParseTuple(args, "i:GetSummaryInformation", &count))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000896 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000897
898 status = MsiGetSummaryInformation(db->h, NULL, count, &result);
899 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000900 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000901
902 oresult = PyObject_NEW(struct msiobj, &summary_Type);
903 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000904 MsiCloseHandle(result);
905 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000906 }
907
908 oresult->h = result;
909 return (PyObject*)oresult;
910}
911
912static PyMethodDef db_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000913 { "OpenView", (PyCFunction)msidb_openview, METH_VARARGS,
914 PyDoc_STR("OpenView(sql) -> viewobj\nWraps MsiDatabaseOpenView")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000915 { "Commit", (PyCFunction)msidb_commit, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000916 PyDoc_STR("Commit() -> None\nWraps MsiDatabaseCommit")},
917 { "GetSummaryInformation", (PyCFunction)msidb_getsummaryinformation, METH_VARARGS,
918 PyDoc_STR("GetSummaryInformation(updateCount) -> viewobj\nWraps MsiGetSummaryInformation")},
Berker Peksaga9356542017-11-07 15:58:53 +0300919 { "Close", (PyCFunction)msidb_close, METH_NOARGS,
920 PyDoc_STR("Close() -> None\nWraps MsiCloseHandle")},
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000921 { NULL, NULL }
922};
923
924static PyTypeObject msidb_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000925 PyVarObject_HEAD_INIT(NULL, 0)
926 "_msi.Database", /*tp_name*/
927 sizeof(msiobj), /*tp_basicsize*/
928 0, /*tp_itemsize*/
929 /* methods */
930 (destructor)msiobj_dealloc, /*tp_dealloc*/
931 0, /*tp_print*/
932 0, /*tp_getattr*/
933 0, /*tp_setattr*/
934 0, /*tp_reserved*/
935 0, /*tp_repr*/
936 0, /*tp_as_number*/
937 0, /*tp_as_sequence*/
938 0, /*tp_as_mapping*/
939 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000940 0, /*tp_call*/
941 0, /*tp_str*/
942 PyObject_GenericGetAttr,/*tp_getattro*/
943 PyObject_GenericSetAttr,/*tp_setattro*/
944 0, /*tp_as_buffer*/
945 Py_TPFLAGS_DEFAULT, /*tp_flags*/
946 0, /*tp_doc*/
947 0, /*tp_traverse*/
948 0, /*tp_clear*/
949 0, /*tp_richcompare*/
950 0, /*tp_weaklistoffset*/
951 0, /*tp_iter*/
952 0, /*tp_iternext*/
953 db_methods, /*tp_methods*/
954 0, /*tp_members*/
955 0, /*tp_getset*/
956 0, /*tp_base*/
957 0, /*tp_dict*/
958 0, /*tp_descr_get*/
959 0, /*tp_descr_set*/
960 0, /*tp_dictoffset*/
961 0, /*tp_init*/
962 0, /*tp_alloc*/
963 0, /*tp_new*/
964 0, /*tp_free*/
965 0, /*tp_is_gc*/
966};
967
Steve Dower6ceda632016-09-09 11:56:34 -0700968#define Py_NOT_PERSIST(x, flag) \
Segev Finer679b5662017-07-27 01:17:57 +0300969 (x != (SIZE_T)(flag) && \
970 x != ((SIZE_T)(flag) | MSIDBOPEN_PATCHFILE))
Steve Dower6ceda632016-09-09 11:56:34 -0700971
972#define Py_INVALID_PERSIST(x) \
973 (Py_NOT_PERSIST(x, MSIDBOPEN_READONLY) && \
974 Py_NOT_PERSIST(x, MSIDBOPEN_TRANSACT) && \
975 Py_NOT_PERSIST(x, MSIDBOPEN_DIRECT) && \
976 Py_NOT_PERSIST(x, MSIDBOPEN_CREATE) && \
977 Py_NOT_PERSIST(x, MSIDBOPEN_CREATEDIRECT))
978
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000979static PyObject* msiopendb(PyObject *obj, PyObject *args)
980{
981 int status;
982 char *path;
983 int persist;
984 MSIHANDLE h;
985 msiobj *result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000986 if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist))
987 return NULL;
Steve Dower6ceda632016-09-09 11:56:34 -0700988 /* We need to validate that persist is a valid MSIDBOPEN_* value. Otherwise,
989 MsiOpenDatabase may treat the value as a pointer, leading to unexpected
990 behavior. */
991 if (Py_INVALID_PERSIST(persist))
992 return msierror(ERROR_INVALID_PARAMETER);
Segev Finer679b5662017-07-27 01:17:57 +0300993 status = MsiOpenDatabase(path, (LPCSTR)(SIZE_T)persist, &h);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000994 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000995 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +0000996
997 result = PyObject_NEW(struct msiobj, &msidb_Type);
998 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000999 MsiCloseHandle(h);
1000 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001001 }
1002 result->h = h;
1003 return (PyObject*)result;
1004}
1005
1006static PyObject*
1007createrecord(PyObject *o, PyObject *args)
1008{
1009 int count;
1010 MSIHANDLE h;
1011
1012 if (!PyArg_ParseTuple(args, "i:CreateRecord", &count))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001013 return NULL;
1014
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001015 h = MsiCreateRecord(count);
1016 if (h == 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001017 return msierror(0);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001018
1019 return record_new(h);
1020}
1021
1022
1023static PyMethodDef msi_methods[] = {
1024 {"UuidCreate", (PyCFunction)uuidcreate, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001025 PyDoc_STR("UuidCreate() -> string")},
1026 {"FCICreate", (PyCFunction)fcicreate, METH_VARARGS,
1027 PyDoc_STR("fcicreate(cabname,files) -> None")},
1028 {"OpenDatabase", (PyCFunction)msiopendb, METH_VARARGS,
1029 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiOpenDatabase")},
1030 {"CreateRecord", (PyCFunction)createrecord, METH_VARARGS,
1031 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiCreateRecord")},
1032 {NULL, NULL} /* sentinel */
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001033};
1034
1035static char msi_doc[] = "Documentation";
1036
Martin v. Löwis1a214512008-06-11 05:26:20 +00001037
1038static struct PyModuleDef _msimodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001039 PyModuleDef_HEAD_INIT,
1040 "_msi",
1041 msi_doc,
1042 -1,
1043 msi_methods,
1044 NULL,
1045 NULL,
1046 NULL,
1047 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001048};
1049
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001050PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001051PyInit__msi(void)
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001052{
1053 PyObject *m;
1054
Martin v. Löwis1a214512008-06-11 05:26:20 +00001055 m = PyModule_Create(&_msimodule);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001056 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001057 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001058
Segev Finer679b5662017-07-27 01:17:57 +03001059 PyModule_AddIntConstant(m, "MSIDBOPEN_CREATEDIRECT", (long)(SIZE_T)MSIDBOPEN_CREATEDIRECT);
1060 PyModule_AddIntConstant(m, "MSIDBOPEN_CREATE", (long)(SIZE_T)MSIDBOPEN_CREATE);
1061 PyModule_AddIntConstant(m, "MSIDBOPEN_DIRECT", (long)(SIZE_T)MSIDBOPEN_DIRECT);
1062 PyModule_AddIntConstant(m, "MSIDBOPEN_READONLY", (long)(SIZE_T)MSIDBOPEN_READONLY);
1063 PyModule_AddIntConstant(m, "MSIDBOPEN_TRANSACT", (long)(SIZE_T)MSIDBOPEN_TRANSACT);
1064 PyModule_AddIntConstant(m, "MSIDBOPEN_PATCHFILE", (long)(SIZE_T)MSIDBOPEN_PATCHFILE);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001065
Charles-Francois Natali74ca8862013-05-20 19:13:19 +02001066 PyModule_AddIntMacro(m, MSICOLINFO_NAMES);
1067 PyModule_AddIntMacro(m, MSICOLINFO_TYPES);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001068
Charles-Francois Natali74ca8862013-05-20 19:13:19 +02001069 PyModule_AddIntMacro(m, MSIMODIFY_SEEK);
1070 PyModule_AddIntMacro(m, MSIMODIFY_REFRESH);
1071 PyModule_AddIntMacro(m, MSIMODIFY_INSERT);
1072 PyModule_AddIntMacro(m, MSIMODIFY_UPDATE);
1073 PyModule_AddIntMacro(m, MSIMODIFY_ASSIGN);
1074 PyModule_AddIntMacro(m, MSIMODIFY_REPLACE);
1075 PyModule_AddIntMacro(m, MSIMODIFY_MERGE);
1076 PyModule_AddIntMacro(m, MSIMODIFY_DELETE);
1077 PyModule_AddIntMacro(m, MSIMODIFY_INSERT_TEMPORARY);
1078 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE);
1079 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_NEW);
1080 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_FIELD);
1081 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_DELETE);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001082
Charles-Francois Natali74ca8862013-05-20 19:13:19 +02001083 PyModule_AddIntMacro(m, PID_CODEPAGE);
1084 PyModule_AddIntMacro(m, PID_TITLE);
1085 PyModule_AddIntMacro(m, PID_SUBJECT);
1086 PyModule_AddIntMacro(m, PID_AUTHOR);
1087 PyModule_AddIntMacro(m, PID_KEYWORDS);
1088 PyModule_AddIntMacro(m, PID_COMMENTS);
1089 PyModule_AddIntMacro(m, PID_TEMPLATE);
1090 PyModule_AddIntMacro(m, PID_LASTAUTHOR);
1091 PyModule_AddIntMacro(m, PID_REVNUMBER);
1092 PyModule_AddIntMacro(m, PID_LASTPRINTED);
1093 PyModule_AddIntMacro(m, PID_CREATE_DTM);
1094 PyModule_AddIntMacro(m, PID_LASTSAVE_DTM);
1095 PyModule_AddIntMacro(m, PID_PAGECOUNT);
1096 PyModule_AddIntMacro(m, PID_WORDCOUNT);
1097 PyModule_AddIntMacro(m, PID_CHARCOUNT);
1098 PyModule_AddIntMacro(m, PID_APPNAME);
1099 PyModule_AddIntMacro(m, PID_SECURITY);
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001100
1101 MSIError = PyErr_NewException ("_msi.MSIError", NULL, NULL);
1102 if (!MSIError)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001103 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001104 PyModule_AddObject(m, "MSIError", MSIError);
Amaury Forgeot d'Arcbf9e9662008-06-17 21:39:46 +00001105 return m;
Martin v. Löwisfbab90e2006-03-05 13:36:04 +00001106}