blob: 0b92712233c9b56fce80e16d55e19c677b889b83 [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
Serhiy Storchaka228b12e2017-01-23 07:47:21265 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04266err:
Zachary Ware0a29e892015-05-18 05:47:15267 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:04272 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:27281static void
Martin v. Löwisfbab90e2006-03-05 13:36:04282msiobj_dealloc(msiobj* msidb)
283{
284 MsiCloseHandle(msidb->h);
285 msidb->h = 0;
Zackery Spytzcb04f752017-11-07 10:03:09286 PyObject_Del(msidb);
Martin v. Löwisfbab90e2006-03-05 13:36:04287}
288
289static PyObject*
Martin v. Löwisfbab90e2006-03-05 13:36:04290msierror(int status)
291{
292 int code;
293 char buf[2000];
294 char *res = buf;
Miss Islington (bot)12c72d62022-10-04 18:07:09295 DWORD size = Py_ARRAY_LENGTH(buf);
Martin v. Löwisfbab90e2006-03-05 13:36:04296 MSIHANDLE err = MsiGetLastErrorRecord();
297
298 if (err == 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27299 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 09:53:58318 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:27324 default:
325 PyErr_Format(MSIError, "unknown error %x", status);
326 return NULL;
327 }
Martin v. Löwisfbab90e2006-03-05 13:36:04328 }
329
330 code = MsiRecordGetInteger(err, 1); /* XXX code */
331 if (MsiFormatRecord(0, err, res, &size) == ERROR_MORE_DATA) {
Antoine Pitrouf95a1b32010-05-09 15:52:27332 res = malloc(size+1);
Zackery Spytz4e519372018-09-07 22:02:56333 if (res == NULL) {
334 MsiCloseHandle(err);
335 return PyErr_NoMemory();
336 }
Antoine Pitrouf95a1b32010-05-09 15:52:27337 MsiFormatRecord(0, err, res, &size);
338 res[size]='\0';
Martin v. Löwisfbab90e2006-03-05 13:36:04339 }
340 MsiCloseHandle(err);
341 PyErr_SetString(MSIError, res);
342 if (res != buf)
Antoine Pitrouf95a1b32010-05-09 15:52:27343 free(res);
Martin v. Löwisfbab90e2006-03-05 13:36:04344 return NULL;
345}
346
Berker Peksaga9356542017-11-07 12:58:53347static PyObject*
348msidb_close(msiobj* msidb, PyObject *args)
349{
350 int status;
351 if ((status = MsiCloseHandle(msidb->h)) != ERROR_SUCCESS) {
352 return msierror(status);
353 }
354 msidb->h = 0;
355 Py_RETURN_NONE;
356}
357
Martin v. Löwisfbab90e2006-03-05 13:36:04358/*************************** Record objects **********************/
359
360static PyObject*
361record_getfieldcount(msiobj* record, PyObject* args)
362{
Christian Heimes217cfd12007-12-02 14:31:20363 return PyLong_FromLong(MsiRecordGetFieldCount(record->h));
Martin v. Löwisfbab90e2006-03-05 13:36:04364}
365
366static PyObject*
Martin v. Löwise95593e2008-06-02 10:08:54367record_getinteger(msiobj* record, PyObject* args)
368{
369 unsigned int field;
370 int status;
Antoine Pitrouf95a1b32010-05-09 15:52:27371
Martin v. Löwise95593e2008-06-02 10:08:54372 if (!PyArg_ParseTuple(args, "I:GetInteger", &field))
373 return NULL;
374 status = MsiRecordGetInteger(record->h, field);
375 if (status == MSI_NULL_INTEGER){
376 PyErr_SetString(MSIError, "could not convert record field to integer");
377 return NULL;
378 }
Martin v. Löwis704d8b12008-06-02 11:32:23379 return PyLong_FromLong((long) status);
Martin v. Löwise95593e2008-06-02 10:08:54380}
381
382static PyObject*
383record_getstring(msiobj* record, PyObject* args)
384{
385 unsigned int field;
386 unsigned int status;
Martin v. Löwis371bb502008-08-16 13:02:57387 WCHAR buf[2000];
388 WCHAR *res = buf;
Miss Islington (bot)12c72d62022-10-04 18:07:09389 DWORD size = Py_ARRAY_LENGTH(buf);
Martin v. Löwise95593e2008-06-02 10:08:54390 PyObject* string;
Antoine Pitrouf95a1b32010-05-09 15:52:27391
Martin v. Löwise95593e2008-06-02 10:08:54392 if (!PyArg_ParseTuple(args, "I:GetString", &field))
393 return NULL;
Martin v. Löwis371bb502008-08-16 13:02:57394 status = MsiRecordGetStringW(record->h, field, res, &size);
Martin v. Löwise95593e2008-06-02 10:08:54395 if (status == ERROR_MORE_DATA) {
Martin v. Löwis371bb502008-08-16 13:02:57396 res = (WCHAR*) malloc((size + 1)*sizeof(WCHAR));
Martin v. Löwise95593e2008-06-02 10:08:54397 if (res == NULL)
398 return PyErr_NoMemory();
Martin v. Löwis371bb502008-08-16 13:02:57399 status = MsiRecordGetStringW(record->h, field, res, &size);
Martin v. Löwise95593e2008-06-02 10:08:54400 }
401 if (status != ERROR_SUCCESS)
402 return msierror((int) status);
Victor Stinner9d3b93b2011-11-22 01:27:30403 string = PyUnicode_FromWideChar(res, size);
Martin v. Löwise95593e2008-06-02 10:08:54404 if (buf != res)
405 free(res);
406 return string;
407}
408
409static PyObject*
Martin v. Löwisfbab90e2006-03-05 13:36:04410record_cleardata(msiobj* record, PyObject *args)
411{
412 int status = MsiRecordClearData(record->h);
413 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27414 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04415
Serhiy Storchaka228b12e2017-01-23 07:47:21416 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04417}
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
Serhiy Storchaka228b12e2017-01-23 07:47:21432 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04433}
434
435static PyObject*
436record_setstream(msiobj* record, PyObject *args)
437{
438 int status;
439 int field;
Victor Stinner9d3b93b2011-11-22 01:27:30440 wchar_t *data;
Martin v. Löwisfbab90e2006-03-05 13:36:04441
Martin v. Löwis371bb502008-08-16 13:02:57442 if (!PyArg_ParseTuple(args, "iu:SetStream", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27443 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04444
Martin v. Löwis371bb502008-08-16 13:02:57445 if ((status = MsiRecordSetStreamW(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27446 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04447
Serhiy Storchaka228b12e2017-01-23 07:47:21448 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04449}
450
451static PyObject*
452record_setinteger(msiobj* record, PyObject *args)
453{
454 int status;
455 int field;
456 int data;
457
458 if (!PyArg_ParseTuple(args, "ii:SetInteger", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27459 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04460
461 if ((status = MsiRecordSetInteger(record->h, field, data)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27462 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04463
Serhiy Storchaka228b12e2017-01-23 07:47:21464 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04465}
466
467
468
469static PyMethodDef record_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27470 { "GetFieldCount", (PyCFunction)record_getfieldcount, METH_NOARGS,
471 PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")},
Martin v. Löwise95593e2008-06-02 10:08:54472 { "GetInteger", (PyCFunction)record_getinteger, METH_VARARGS,
473 PyDoc_STR("GetInteger(field) -> int\nWraps MsiRecordGetInteger")},
474 { "GetString", (PyCFunction)record_getstring, METH_VARARGS,
475 PyDoc_STR("GetString(field) -> string\nWraps MsiRecordGetString")},
Antoine Pitrouf95a1b32010-05-09 15:52:27476 { "SetString", (PyCFunction)record_setstring, METH_VARARGS,
477 PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")},
478 { "SetStream", (PyCFunction)record_setstream, METH_VARARGS,
479 PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")},
480 { "SetInteger", (PyCFunction)record_setinteger, METH_VARARGS,
481 PyDoc_STR("SetInteger(field,int) -> None\nWraps MsiRecordSetInteger")},
482 { "ClearData", (PyCFunction)record_cleardata, METH_NOARGS,
483 PyDoc_STR("ClearData() -> int\nWraps MsiRecordGClearData")},
Martin v. Löwisfbab90e2006-03-05 13:36:04484 { NULL, NULL }
485};
486
487static PyTypeObject record_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27488 PyVarObject_HEAD_INIT(NULL, 0)
489 "_msi.Record", /*tp_name*/
490 sizeof(msiobj), /*tp_basicsize*/
491 0, /*tp_itemsize*/
492 /* methods */
493 (destructor)msiobj_dealloc, /*tp_dealloc*/
Jeroen Demeyer530f5062019-05-31 02:13:39494 0, /*tp_vectorcall_offset*/
Antoine Pitrouf95a1b32010-05-09 15:52:27495 0, /*tp_getattr*/
496 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 02:13:39497 0, /*tp_as_async*/
Antoine Pitrouf95a1b32010-05-09 15:52:27498 0, /*tp_repr*/
499 0, /*tp_as_number*/
500 0, /*tp_as_sequence*/
501 0, /*tp_as_mapping*/
502 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04503 0, /*tp_call*/
504 0, /*tp_str*/
505 PyObject_GenericGetAttr,/*tp_getattro*/
506 PyObject_GenericSetAttr,/*tp_setattro*/
507 0, /*tp_as_buffer*/
508 Py_TPFLAGS_DEFAULT, /*tp_flags*/
509 0, /*tp_doc*/
510 0, /*tp_traverse*/
511 0, /*tp_clear*/
512 0, /*tp_richcompare*/
513 0, /*tp_weaklistoffset*/
514 0, /*tp_iter*/
515 0, /*tp_iternext*/
516 record_methods, /*tp_methods*/
517 0, /*tp_members*/
518 0, /*tp_getset*/
519 0, /*tp_base*/
520 0, /*tp_dict*/
521 0, /*tp_descr_get*/
522 0, /*tp_descr_set*/
523 0, /*tp_dictoffset*/
524 0, /*tp_init*/
525 0, /*tp_alloc*/
526 0, /*tp_new*/
527 0, /*tp_free*/
528 0, /*tp_is_gc*/
529};
530
531static PyObject*
532record_new(MSIHANDLE h)
533{
534 msiobj *result = PyObject_NEW(struct msiobj, &record_Type);
535
536 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27537 MsiCloseHandle(h);
538 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04539 }
540
541 result->h = h;
542 return (PyObject*)result;
543}
544
545/*************************** SummaryInformation objects **************/
546
547static PyObject*
548summary_getproperty(msiobj* si, PyObject *args)
549{
550 int status;
551 int field;
552 PyObject *result;
553 UINT type;
554 INT ival;
555 FILETIME fval;
556 char sbuf[1000];
557 char *sval = sbuf;
Tzu-ping Chung2de576e2019-02-02 17:13:23558 DWORD ssize = sizeof(sbuf);
Martin v. Löwisfbab90e2006-03-05 13:36:04559
560 if (!PyArg_ParseTuple(args, "i:GetProperty", &field))
Antoine Pitrouf95a1b32010-05-09 15:52:27561 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04562
Antoine Pitrouf95a1b32010-05-09 15:52:27563 status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,
564 &fval, sval, &ssize);
Thomas Wouters89f507f2006-12-13 04:49:30565 if (status == ERROR_MORE_DATA) {
Tzu-ping Chung2de576e2019-02-02 17:13:23566 ssize++;
Antoine Pitrouf95a1b32010-05-09 15:52:27567 sval = malloc(ssize);
Zackery Spytz4e519372018-09-07 22:02:56568 if (sval == NULL) {
569 return PyErr_NoMemory();
570 }
Antoine Pitrouf95a1b32010-05-09 15:52:27571 status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival,
572 &fval, sval, &ssize);
Martin v. Löwisfbab90e2006-03-05 13:36:04573 }
Zackery Spytz549e55a2019-06-01 00:16:20574 if (status != ERROR_SUCCESS) {
575 return msierror(status);
576 }
Martin v. Löwisfbab90e2006-03-05 13:36:04577
578 switch(type) {
Tzu-ping Chung2de576e2019-02-02 17:13:23579 case VT_I2:
580 case VT_I4:
581 result = PyLong_FromLong(ival);
582 break;
Antoine Pitrouf95a1b32010-05-09 15:52:27583 case VT_FILETIME:
584 PyErr_SetString(PyExc_NotImplementedError, "FILETIME result");
Tzu-ping Chung2de576e2019-02-02 17:13:23585 result = NULL;
586 break;
Antoine Pitrouf95a1b32010-05-09 15:52:27587 case VT_LPSTR:
588 result = PyBytes_FromStringAndSize(sval, ssize);
Tzu-ping Chung2de576e2019-02-02 17:13:23589 break;
Berker Peksag19fb1342017-11-24 15:11:18590 case VT_EMPTY:
Tzu-ping Chung2de576e2019-02-02 17:13:23591 Py_INCREF(Py_None);
592 result = Py_None;
593 break;
594 default:
595 PyErr_Format(PyExc_NotImplementedError, "result of type %d", type);
596 result = NULL;
597 break;
Martin v. Löwisfbab90e2006-03-05 13:36:04598 }
Tzu-ping Chung2de576e2019-02-02 17:13:23599 if (sval != sbuf)
600 free(sval);
601 return result;
Martin v. Löwisfbab90e2006-03-05 13:36:04602}
603
604static PyObject*
605summary_getpropertycount(msiobj* si, PyObject *args)
606{
607 int status;
608 UINT result;
609
610 status = MsiSummaryInfoGetPropertyCount(si->h, &result);
611 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27612 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04613
Christian Heimes217cfd12007-12-02 14:31:20614 return PyLong_FromLong(result);
Martin v. Löwisfbab90e2006-03-05 13:36:04615}
616
617static PyObject*
618summary_setproperty(msiobj* si, PyObject *args)
619{
620 int status;
621 int field;
622 PyObject* data;
623
624 if (!PyArg_ParseTuple(args, "iO:SetProperty", &field, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27625 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04626
Martin v. Löwis371bb502008-08-16 13:02:57627 if (PyUnicode_Check(data)) {
Serhiy Storchakaccdc09e2017-06-28 06:55:22628 const WCHAR *value = _PyUnicode_AsUnicode(data);
Serhiy Storchakaf7eae0a2017-06-28 05:30:06629 if (value == NULL) {
630 return NULL;
631 }
Antoine Pitrouf95a1b32010-05-09 15:52:27632 status = MsiSummaryInfoSetPropertyW(si->h, field, VT_LPSTR,
Serhiy Storchakaf7eae0a2017-06-28 05:30:06633 0, NULL, value);
Martin v. Löwisd1a1d1e2007-12-04 22:10:37634 } else if (PyLong_CheckExact(data)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27635 long value = PyLong_AsLong(data);
636 if (value == -1 && PyErr_Occurred()) {
637 return NULL;
638 }
639 status = MsiSummaryInfoSetProperty(si->h, field, VT_I4,
640 value, NULL, NULL);
Martin v. Löwisfbab90e2006-03-05 13:36:04641 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27642 PyErr_SetString(PyExc_TypeError, "unsupported type");
643 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04644 }
Antoine Pitrouf95a1b32010-05-09 15:52:27645
Martin v. Löwisfbab90e2006-03-05 13:36:04646 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27647 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04648
Serhiy Storchaka228b12e2017-01-23 07:47:21649 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04650}
651
652
653static PyObject*
654summary_persist(msiobj* si, PyObject *args)
655{
656 int status;
657
658 status = MsiSummaryInfoPersist(si->h);
659 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27660 return msierror(status);
Serhiy Storchaka228b12e2017-01-23 07:47:21661 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04662}
663
664static PyMethodDef summary_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27665 { "GetProperty", (PyCFunction)summary_getproperty, METH_VARARGS,
666 PyDoc_STR("GetProperty(propid) -> value\nWraps MsiSummaryInfoGetProperty")},
667 { "GetPropertyCount", (PyCFunction)summary_getpropertycount, METH_NOARGS,
668 PyDoc_STR("GetProperty() -> int\nWraps MsiSummaryInfoGetPropertyCount")},
669 { "SetProperty", (PyCFunction)summary_setproperty, METH_VARARGS,
670 PyDoc_STR("SetProperty(value) -> None\nWraps MsiSummaryInfoProperty")},
671 { "Persist", (PyCFunction)summary_persist, METH_NOARGS,
672 PyDoc_STR("Persist() -> None\nWraps MsiSummaryInfoPersist")},
Martin v. Löwisfbab90e2006-03-05 13:36:04673 { NULL, NULL }
674};
675
676static PyTypeObject summary_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27677 PyVarObject_HEAD_INIT(NULL, 0)
678 "_msi.SummaryInformation", /*tp_name*/
679 sizeof(msiobj), /*tp_basicsize*/
680 0, /*tp_itemsize*/
681 /* methods */
682 (destructor)msiobj_dealloc, /*tp_dealloc*/
Jeroen Demeyer530f5062019-05-31 02:13:39683 0, /*tp_vectorcall_offset*/
Antoine Pitrouf95a1b32010-05-09 15:52:27684 0, /*tp_getattr*/
685 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 02:13:39686 0, /*tp_as_async*/
Antoine Pitrouf95a1b32010-05-09 15:52:27687 0, /*tp_repr*/
688 0, /*tp_as_number*/
689 0, /*tp_as_sequence*/
690 0, /*tp_as_mapping*/
691 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04692 0, /*tp_call*/
693 0, /*tp_str*/
694 PyObject_GenericGetAttr,/*tp_getattro*/
695 PyObject_GenericSetAttr,/*tp_setattro*/
696 0, /*tp_as_buffer*/
697 Py_TPFLAGS_DEFAULT, /*tp_flags*/
698 0, /*tp_doc*/
699 0, /*tp_traverse*/
700 0, /*tp_clear*/
701 0, /*tp_richcompare*/
702 0, /*tp_weaklistoffset*/
703 0, /*tp_iter*/
704 0, /*tp_iternext*/
705 summary_methods, /*tp_methods*/
706 0, /*tp_members*/
707 0, /*tp_getset*/
708 0, /*tp_base*/
709 0, /*tp_dict*/
710 0, /*tp_descr_get*/
711 0, /*tp_descr_set*/
712 0, /*tp_dictoffset*/
713 0, /*tp_init*/
714 0, /*tp_alloc*/
715 0, /*tp_new*/
716 0, /*tp_free*/
717 0, /*tp_is_gc*/
718};
719
720/*************************** View objects **************/
721
722static PyObject*
723view_execute(msiobj *view, PyObject*args)
724{
725 int status;
726 MSIHANDLE params = 0;
727 PyObject *oparams = Py_None;
728
729 if (!PyArg_ParseTuple(args, "O:Execute", &oparams))
Antoine Pitrouf95a1b32010-05-09 15:52:27730 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04731
732 if (oparams != Py_None) {
733 if (oparams->ob_type != &record_Type) {
734 PyErr_SetString(PyExc_TypeError, "Execute argument must be a record");
735 return NULL;
736 }
737 params = ((msiobj*)oparams)->h;
738 }
739
740 status = MsiViewExecute(view->h, params);
741 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27742 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04743
Serhiy Storchaka228b12e2017-01-23 07:47:21744 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04745}
746
747static PyObject*
748view_fetch(msiobj *view, PyObject*args)
749{
750 int status;
751 MSIHANDLE result;
752
Berker Peksagbdb83152017-11-23 12:47:30753 status = MsiViewFetch(view->h, &result);
754 if (status == ERROR_NO_MORE_ITEMS) {
755 Py_RETURN_NONE;
756 } else if (status != ERROR_SUCCESS) {
Antoine Pitrouf95a1b32010-05-09 15:52:27757 return msierror(status);
Berker Peksagbdb83152017-11-23 12:47:30758 }
Martin v. Löwisfbab90e2006-03-05 13:36:04759
760 return record_new(result);
761}
762
763static PyObject*
764view_getcolumninfo(msiobj *view, PyObject *args)
765{
766 int status;
767 int kind;
768 MSIHANDLE result;
769
770 if (!PyArg_ParseTuple(args, "i:GetColumnInfo", &kind))
Antoine Pitrouf95a1b32010-05-09 15:52:27771 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04772
773 if ((status = MsiViewGetColumnInfo(view->h, kind, &result)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27774 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04775
776 return record_new(result);
777}
778
779static PyObject*
780view_modify(msiobj *view, PyObject *args)
781{
782 int kind;
783 PyObject *data;
784 int status;
785
786 if (!PyArg_ParseTuple(args, "iO:Modify", &kind, &data))
Antoine Pitrouf95a1b32010-05-09 15:52:27787 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04788
789 if (data->ob_type != &record_Type) {
Antoine Pitrouf95a1b32010-05-09 15:52:27790 PyErr_SetString(PyExc_TypeError, "Modify expects a record object");
791 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04792 }
793
794 if ((status = MsiViewModify(view->h, kind, ((msiobj*)data)->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27795 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04796
Serhiy Storchaka228b12e2017-01-23 07:47:21797 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04798}
799
800static PyObject*
801view_close(msiobj *view, PyObject*args)
802{
803 int status;
804
805 if ((status = MsiViewClose(view->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27806 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04807
Serhiy Storchaka228b12e2017-01-23 07:47:21808 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04809}
810
811static PyMethodDef view_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27812 { "Execute", (PyCFunction)view_execute, METH_VARARGS,
813 PyDoc_STR("Execute(params=None) -> None\nWraps MsiViewExecute")},
Martin v. Löwisfbab90e2006-03-05 13:36:04814 { "GetColumnInfo", (PyCFunction)view_getcolumninfo, METH_VARARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27815 PyDoc_STR("GetColumnInfo() -> result\nWraps MsiGetColumnInfo")},
Martin v. Löwisfbab90e2006-03-05 13:36:04816 { "Fetch", (PyCFunction)view_fetch, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27817 PyDoc_STR("Fetch() -> result\nWraps MsiViewFetch")},
Martin v. Löwisfbab90e2006-03-05 13:36:04818 { "Modify", (PyCFunction)view_modify, METH_VARARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27819 PyDoc_STR("Modify(mode,record) -> None\nWraps MsiViewModify")},
Martin v. Löwisfbab90e2006-03-05 13:36:04820 { "Close", (PyCFunction)view_close, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27821 PyDoc_STR("Close() -> result\nWraps MsiViewClose")},
Martin v. Löwisfbab90e2006-03-05 13:36:04822 { NULL, NULL }
823};
824
825static PyTypeObject msiview_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27826 PyVarObject_HEAD_INIT(NULL, 0)
827 "_msi.View", /*tp_name*/
828 sizeof(msiobj), /*tp_basicsize*/
829 0, /*tp_itemsize*/
830 /* methods */
831 (destructor)msiobj_dealloc, /*tp_dealloc*/
Jeroen Demeyer530f5062019-05-31 02:13:39832 0, /*tp_vectorcall_offset*/
Antoine Pitrouf95a1b32010-05-09 15:52:27833 0, /*tp_getattr*/
834 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 02:13:39835 0, /*tp_as_async*/
Antoine Pitrouf95a1b32010-05-09 15:52:27836 0, /*tp_repr*/
837 0, /*tp_as_number*/
838 0, /*tp_as_sequence*/
839 0, /*tp_as_mapping*/
840 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04841 0, /*tp_call*/
842 0, /*tp_str*/
843 PyObject_GenericGetAttr,/*tp_getattro*/
844 PyObject_GenericSetAttr,/*tp_setattro*/
845 0, /*tp_as_buffer*/
846 Py_TPFLAGS_DEFAULT, /*tp_flags*/
847 0, /*tp_doc*/
848 0, /*tp_traverse*/
849 0, /*tp_clear*/
850 0, /*tp_richcompare*/
851 0, /*tp_weaklistoffset*/
852 0, /*tp_iter*/
853 0, /*tp_iternext*/
854 view_methods, /*tp_methods*/
855 0, /*tp_members*/
856 0, /*tp_getset*/
857 0, /*tp_base*/
858 0, /*tp_dict*/
859 0, /*tp_descr_get*/
860 0, /*tp_descr_set*/
861 0, /*tp_dictoffset*/
862 0, /*tp_init*/
863 0, /*tp_alloc*/
864 0, /*tp_new*/
865 0, /*tp_free*/
866 0, /*tp_is_gc*/
867};
868
869/*************************** Database objects **************/
870
871static PyObject*
872msidb_openview(msiobj *msidb, PyObject *args)
873{
874 int status;
Miss Islington (bot)3f4de442020-06-25 09:12:41875 const wchar_t *sql;
Martin v. Löwisfbab90e2006-03-05 13:36:04876 MSIHANDLE hView;
877 msiobj *result;
878
Miss Islington (bot)3f4de442020-06-25 09:12:41879 if (!PyArg_ParseTuple(args, "u:OpenView", &sql))
Antoine Pitrouf95a1b32010-05-09 15:52:27880 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04881
Miss Islington (bot)3f4de442020-06-25 09:12:41882 if ((status = MsiDatabaseOpenViewW(msidb->h, sql, &hView)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27883 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04884
885 result = PyObject_NEW(struct msiobj, &msiview_Type);
886 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:27887 MsiCloseHandle(hView);
888 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04889 }
890
891 result->h = hView;
892 return (PyObject*)result;
893}
894
895static PyObject*
896msidb_commit(msiobj *msidb, PyObject *args)
897{
898 int status;
899
900 if ((status = MsiDatabaseCommit(msidb->h)) != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27901 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04902
Serhiy Storchaka228b12e2017-01-23 07:47:21903 Py_RETURN_NONE;
Martin v. Löwisfbab90e2006-03-05 13:36:04904}
905
906static PyObject*
907msidb_getsummaryinformation(msiobj *db, PyObject *args)
908{
909 int status;
910 int count;
911 MSIHANDLE result;
912 msiobj *oresult;
913
914 if (!PyArg_ParseTuple(args, "i:GetSummaryInformation", &count))
Antoine Pitrouf95a1b32010-05-09 15:52:27915 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04916
917 status = MsiGetSummaryInformation(db->h, NULL, count, &result);
918 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:27919 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:04920
921 oresult = PyObject_NEW(struct msiobj, &summary_Type);
Zackery Spytzbf94cc72019-03-07 18:20:13922 if (!oresult) {
Antoine Pitrouf95a1b32010-05-09 15:52:27923 MsiCloseHandle(result);
924 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:04925 }
926
927 oresult->h = result;
928 return (PyObject*)oresult;
929}
930
931static PyMethodDef db_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27932 { "OpenView", (PyCFunction)msidb_openview, METH_VARARGS,
933 PyDoc_STR("OpenView(sql) -> viewobj\nWraps MsiDatabaseOpenView")},
Martin v. Löwisfbab90e2006-03-05 13:36:04934 { "Commit", (PyCFunction)msidb_commit, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:27935 PyDoc_STR("Commit() -> None\nWraps MsiDatabaseCommit")},
936 { "GetSummaryInformation", (PyCFunction)msidb_getsummaryinformation, METH_VARARGS,
937 PyDoc_STR("GetSummaryInformation(updateCount) -> viewobj\nWraps MsiGetSummaryInformation")},
Berker Peksaga9356542017-11-07 12:58:53938 { "Close", (PyCFunction)msidb_close, METH_NOARGS,
939 PyDoc_STR("Close() -> None\nWraps MsiCloseHandle")},
Martin v. Löwisfbab90e2006-03-05 13:36:04940 { NULL, NULL }
941};
942
943static PyTypeObject msidb_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27944 PyVarObject_HEAD_INIT(NULL, 0)
945 "_msi.Database", /*tp_name*/
946 sizeof(msiobj), /*tp_basicsize*/
947 0, /*tp_itemsize*/
948 /* methods */
949 (destructor)msiobj_dealloc, /*tp_dealloc*/
Jeroen Demeyer530f5062019-05-31 02:13:39950 0, /*tp_vectorcall_offset*/
Antoine Pitrouf95a1b32010-05-09 15:52:27951 0, /*tp_getattr*/
952 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 02:13:39953 0, /*tp_as_async*/
Antoine Pitrouf95a1b32010-05-09 15:52:27954 0, /*tp_repr*/
955 0, /*tp_as_number*/
956 0, /*tp_as_sequence*/
957 0, /*tp_as_mapping*/
958 0, /*tp_hash*/
Martin v. Löwisfbab90e2006-03-05 13:36:04959 0, /*tp_call*/
960 0, /*tp_str*/
961 PyObject_GenericGetAttr,/*tp_getattro*/
962 PyObject_GenericSetAttr,/*tp_setattro*/
963 0, /*tp_as_buffer*/
964 Py_TPFLAGS_DEFAULT, /*tp_flags*/
965 0, /*tp_doc*/
966 0, /*tp_traverse*/
967 0, /*tp_clear*/
968 0, /*tp_richcompare*/
969 0, /*tp_weaklistoffset*/
970 0, /*tp_iter*/
971 0, /*tp_iternext*/
972 db_methods, /*tp_methods*/
973 0, /*tp_members*/
974 0, /*tp_getset*/
975 0, /*tp_base*/
976 0, /*tp_dict*/
977 0, /*tp_descr_get*/
978 0, /*tp_descr_set*/
979 0, /*tp_dictoffset*/
980 0, /*tp_init*/
981 0, /*tp_alloc*/
982 0, /*tp_new*/
983 0, /*tp_free*/
984 0, /*tp_is_gc*/
985};
986
Steve Dower6ceda632016-09-09 18:56:34987#define Py_NOT_PERSIST(x, flag) \
Segev Finer679b5662017-07-26 22:17:57988 (x != (SIZE_T)(flag) && \
989 x != ((SIZE_T)(flag) | MSIDBOPEN_PATCHFILE))
Steve Dower6ceda632016-09-09 18:56:34990
991#define Py_INVALID_PERSIST(x) \
992 (Py_NOT_PERSIST(x, MSIDBOPEN_READONLY) && \
993 Py_NOT_PERSIST(x, MSIDBOPEN_TRANSACT) && \
994 Py_NOT_PERSIST(x, MSIDBOPEN_DIRECT) && \
995 Py_NOT_PERSIST(x, MSIDBOPEN_CREATE) && \
996 Py_NOT_PERSIST(x, MSIDBOPEN_CREATEDIRECT))
997
Martin v. Löwisfbab90e2006-03-05 13:36:04998static PyObject* msiopendb(PyObject *obj, PyObject *args)
999{
1000 int status;
Miss Islington (bot)3f4de442020-06-25 09:12:411001 const wchar_t *path;
Martin v. Löwisfbab90e2006-03-05 13:36:041002 int persist;
1003 MSIHANDLE h;
1004 msiobj *result;
Miss Islington (bot)3f4de442020-06-25 09:12:411005 if (!PyArg_ParseTuple(args, "ui:MSIOpenDatabase", &path, &persist))
Antoine Pitrouf95a1b32010-05-09 15:52:271006 return NULL;
Steve Dower6ceda632016-09-09 18:56:341007 /* We need to validate that persist is a valid MSIDBOPEN_* value. Otherwise,
1008 MsiOpenDatabase may treat the value as a pointer, leading to unexpected
1009 behavior. */
1010 if (Py_INVALID_PERSIST(persist))
1011 return msierror(ERROR_INVALID_PARAMETER);
Miss Islington (bot)3f4de442020-06-25 09:12:411012 status = MsiOpenDatabaseW(path, (LPCWSTR)(SIZE_T)persist, &h);
Martin v. Löwisfbab90e2006-03-05 13:36:041013 if (status != ERROR_SUCCESS)
Antoine Pitrouf95a1b32010-05-09 15:52:271014 return msierror(status);
Martin v. Löwisfbab90e2006-03-05 13:36:041015
1016 result = PyObject_NEW(struct msiobj, &msidb_Type);
1017 if (!result) {
Antoine Pitrouf95a1b32010-05-09 15:52:271018 MsiCloseHandle(h);
1019 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:041020 }
1021 result->h = h;
1022 return (PyObject*)result;
1023}
1024
1025static PyObject*
1026createrecord(PyObject *o, PyObject *args)
1027{
1028 int count;
1029 MSIHANDLE h;
1030
1031 if (!PyArg_ParseTuple(args, "i:CreateRecord", &count))
Antoine Pitrouf95a1b32010-05-09 15:52:271032 return NULL;
1033
Martin v. Löwisfbab90e2006-03-05 13:36:041034 h = MsiCreateRecord(count);
1035 if (h == 0)
Antoine Pitrouf95a1b32010-05-09 15:52:271036 return msierror(0);
Martin v. Löwisfbab90e2006-03-05 13:36:041037
1038 return record_new(h);
1039}
1040
1041
1042static PyMethodDef msi_methods[] = {
1043 {"UuidCreate", (PyCFunction)uuidcreate, METH_NOARGS,
Antoine Pitrouf95a1b32010-05-09 15:52:271044 PyDoc_STR("UuidCreate() -> string")},
1045 {"FCICreate", (PyCFunction)fcicreate, METH_VARARGS,
1046 PyDoc_STR("fcicreate(cabname,files) -> None")},
1047 {"OpenDatabase", (PyCFunction)msiopendb, METH_VARARGS,
1048 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiOpenDatabase")},
1049 {"CreateRecord", (PyCFunction)createrecord, METH_VARARGS,
1050 PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiCreateRecord")},
1051 {NULL, NULL} /* sentinel */
Martin v. Löwisfbab90e2006-03-05 13:36:041052};
1053
1054static char msi_doc[] = "Documentation";
1055
Martin v. Löwis1a214512008-06-11 05:26:201056
1057static struct PyModuleDef _msimodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:271058 PyModuleDef_HEAD_INIT,
1059 "_msi",
1060 msi_doc,
1061 -1,
1062 msi_methods,
1063 NULL,
1064 NULL,
1065 NULL,
1066 NULL
Martin v. Löwis1a214512008-06-11 05:26:201067};
1068
Martin v. Löwisfbab90e2006-03-05 13:36:041069PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:201070PyInit__msi(void)
Martin v. Löwisfbab90e2006-03-05 13:36:041071{
1072 PyObject *m;
1073
Martin v. Löwis1a214512008-06-11 05:26:201074 m = PyModule_Create(&_msimodule);
Martin v. Löwisfbab90e2006-03-05 13:36:041075 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:271076 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:041077
Segev Finer679b5662017-07-26 22:17:571078 PyModule_AddIntConstant(m, "MSIDBOPEN_CREATEDIRECT", (long)(SIZE_T)MSIDBOPEN_CREATEDIRECT);
1079 PyModule_AddIntConstant(m, "MSIDBOPEN_CREATE", (long)(SIZE_T)MSIDBOPEN_CREATE);
1080 PyModule_AddIntConstant(m, "MSIDBOPEN_DIRECT", (long)(SIZE_T)MSIDBOPEN_DIRECT);
1081 PyModule_AddIntConstant(m, "MSIDBOPEN_READONLY", (long)(SIZE_T)MSIDBOPEN_READONLY);
1082 PyModule_AddIntConstant(m, "MSIDBOPEN_TRANSACT", (long)(SIZE_T)MSIDBOPEN_TRANSACT);
1083 PyModule_AddIntConstant(m, "MSIDBOPEN_PATCHFILE", (long)(SIZE_T)MSIDBOPEN_PATCHFILE);
Martin v. Löwisfbab90e2006-03-05 13:36:041084
Charles-Francois Natali74ca8862013-05-20 17:13:191085 PyModule_AddIntMacro(m, MSICOLINFO_NAMES);
1086 PyModule_AddIntMacro(m, MSICOLINFO_TYPES);
Martin v. Löwisfbab90e2006-03-05 13:36:041087
Charles-Francois Natali74ca8862013-05-20 17:13:191088 PyModule_AddIntMacro(m, MSIMODIFY_SEEK);
1089 PyModule_AddIntMacro(m, MSIMODIFY_REFRESH);
1090 PyModule_AddIntMacro(m, MSIMODIFY_INSERT);
1091 PyModule_AddIntMacro(m, MSIMODIFY_UPDATE);
1092 PyModule_AddIntMacro(m, MSIMODIFY_ASSIGN);
1093 PyModule_AddIntMacro(m, MSIMODIFY_REPLACE);
1094 PyModule_AddIntMacro(m, MSIMODIFY_MERGE);
1095 PyModule_AddIntMacro(m, MSIMODIFY_DELETE);
1096 PyModule_AddIntMacro(m, MSIMODIFY_INSERT_TEMPORARY);
1097 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE);
1098 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_NEW);
1099 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_FIELD);
1100 PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_DELETE);
Martin v. Löwisfbab90e2006-03-05 13:36:041101
Charles-Francois Natali74ca8862013-05-20 17:13:191102 PyModule_AddIntMacro(m, PID_CODEPAGE);
1103 PyModule_AddIntMacro(m, PID_TITLE);
1104 PyModule_AddIntMacro(m, PID_SUBJECT);
1105 PyModule_AddIntMacro(m, PID_AUTHOR);
1106 PyModule_AddIntMacro(m, PID_KEYWORDS);
1107 PyModule_AddIntMacro(m, PID_COMMENTS);
1108 PyModule_AddIntMacro(m, PID_TEMPLATE);
1109 PyModule_AddIntMacro(m, PID_LASTAUTHOR);
1110 PyModule_AddIntMacro(m, PID_REVNUMBER);
1111 PyModule_AddIntMacro(m, PID_LASTPRINTED);
1112 PyModule_AddIntMacro(m, PID_CREATE_DTM);
1113 PyModule_AddIntMacro(m, PID_LASTSAVE_DTM);
1114 PyModule_AddIntMacro(m, PID_PAGECOUNT);
1115 PyModule_AddIntMacro(m, PID_WORDCOUNT);
1116 PyModule_AddIntMacro(m, PID_CHARCOUNT);
1117 PyModule_AddIntMacro(m, PID_APPNAME);
1118 PyModule_AddIntMacro(m, PID_SECURITY);
Martin v. Löwisfbab90e2006-03-05 13:36:041119
1120 MSIError = PyErr_NewException ("_msi.MSIError", NULL, NULL);
1121 if (!MSIError)
Antoine Pitrouf95a1b32010-05-09 15:52:271122 return NULL;
Martin v. Löwisfbab90e2006-03-05 13:36:041123 PyModule_AddObject(m, "MSIError", MSIError);
Amaury Forgeot d'Arcbf9e9662008-06-17 21:39:461124 return m;
Martin v. Löwisfbab90e2006-03-05 13:36:041125}