python-msilib 0.1.1__cp314-cp314t-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of python-msilib might be problematic. Click here for more details.

msilib/_msi.c ADDED
@@ -0,0 +1,1314 @@
1
+ /* Helper library for MSI creation with Python.
2
+ * Copyright (C) 2005 Martin v. Löwis
3
+ * Licensed to PSF under a contributor agreement.
4
+ */
5
+
6
+ #include "include/pythoncapi_compat.h"
7
+
8
+ #include <Python.h>
9
+ #include <fci.h>
10
+ #include <fcntl.h>
11
+ #include <windows.h>
12
+ #include <msi.h>
13
+ #include <msiquery.h>
14
+ #include <msidefs.h>
15
+ #include <rpc.h>
16
+
17
+ /*[clinic input]
18
+ module _msi
19
+ class _msi.Record "msiobj *" "&record_Type"
20
+ class _msi.SummaryInformation "msiobj *" "&summary_Type"
21
+ class _msi.View "msiobj *" "&msiview_Type"
22
+ class _msi.Database "msiobj *" "&msidb_Type"
23
+ [clinic start generated code]*/
24
+ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=89a3605762cf4bdc]*/
25
+
26
+ static PyObject *MSIError;
27
+
28
+ /*[clinic input]
29
+ _msi.UuidCreate
30
+
31
+ Return the string representation of a new unique identifier.
32
+ [clinic start generated code]*/
33
+
34
+ static PyObject *
35
+ _msi_UuidCreate_impl(PyObject *module)
36
+ /*[clinic end generated code: output=534ecf36f10af98e input=168024ab4b3e832b]*/
37
+ {
38
+ UUID result;
39
+ wchar_t *cresult;
40
+ PyObject *oresult;
41
+
42
+ /* May return ok, local only, and no address.
43
+ For local only, the documentation says we still get a uuid.
44
+ For RPC_S_UUID_NO_ADDRESS, it's not clear whether we can
45
+ use the result. */
46
+ if (UuidCreate(&result) == RPC_S_UUID_NO_ADDRESS) {
47
+ PyErr_SetString(PyExc_NotImplementedError, "processing 'no address' result");
48
+ return NULL;
49
+ }
50
+
51
+ if (UuidToStringW(&result, &cresult) == RPC_S_OUT_OF_MEMORY) {
52
+ PyErr_SetString(PyExc_MemoryError, "out of memory in uuidgen");
53
+ return NULL;
54
+ }
55
+
56
+ oresult = PyUnicode_FromWideChar(cresult, wcslen(cresult));
57
+ RpcStringFreeW(&cresult);
58
+ return oresult;
59
+
60
+ }
61
+
62
+ /* Helper for converting file names from UTF-8 to wchat_t*. */
63
+ static wchar_t *
64
+ utf8_to_wchar(const char *s, int *err)
65
+ {
66
+ PyObject *obj = PyUnicode_FromString(s);
67
+ if (obj == NULL) {
68
+ if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
69
+ *err = ENOMEM;
70
+ }
71
+ else {
72
+ *err = EINVAL;
73
+ }
74
+ PyErr_Clear();
75
+ return NULL;
76
+ }
77
+ wchar_t *ws = PyUnicode_AsWideCharString(obj, NULL);
78
+ if (ws == NULL) {
79
+ *err = ENOMEM;
80
+ PyErr_Clear();
81
+ }
82
+ Py_DECREF(obj);
83
+ return ws;
84
+ }
85
+
86
+ /* FCI callback functions */
87
+
88
+ static FNFCIALLOC(cb_alloc)
89
+ {
90
+ return PyMem_RawMalloc(cb);
91
+ }
92
+
93
+ static FNFCIFREE(cb_free)
94
+ {
95
+ PyMem_RawFree(memory);
96
+ }
97
+
98
+ static FNFCIOPEN(cb_open)
99
+ {
100
+ wchar_t *ws = utf8_to_wchar(pszFile, err);
101
+ if (ws == NULL) {
102
+ return -1;
103
+ }
104
+ int result = _wopen(ws, oflag | O_NOINHERIT, pmode);
105
+ PyMem_Free(ws);
106
+ if (result == -1)
107
+ *err = errno;
108
+ return result;
109
+ }
110
+
111
+ static FNFCIREAD(cb_read)
112
+ {
113
+ UINT result = (UINT)_read((int)hf, memory, cb);
114
+ if (result != cb)
115
+ *err = errno;
116
+ return result;
117
+ }
118
+
119
+ static FNFCIWRITE(cb_write)
120
+ {
121
+ UINT result = (UINT)_write((int)hf, memory, cb);
122
+ if (result != cb)
123
+ *err = errno;
124
+ return result;
125
+ }
126
+
127
+ static FNFCICLOSE(cb_close)
128
+ {
129
+ int result = _close((int)hf);
130
+ if (result != 0)
131
+ *err = errno;
132
+ return result;
133
+ }
134
+
135
+ static FNFCISEEK(cb_seek)
136
+ {
137
+ long result = (long)_lseek((int)hf, dist, seektype);
138
+ if (result == -1)
139
+ *err = errno;
140
+ return result;
141
+ }
142
+
143
+ static FNFCIDELETE(cb_delete)
144
+ {
145
+ wchar_t *ws = utf8_to_wchar(pszFile, err);
146
+ if (ws == NULL) {
147
+ return -1;
148
+ }
149
+ int result = _wremove(ws);
150
+ PyMem_Free(ws);
151
+ if (result != 0)
152
+ *err = errno;
153
+ return result;
154
+ }
155
+
156
+ static FNFCIFILEPLACED(cb_fileplaced)
157
+ {
158
+ return 0;
159
+ }
160
+
161
+ static FNFCIGETTEMPFILE(cb_gettempfile)
162
+ {
163
+ char *name = _tempnam("", "tmp");
164
+ if ((name != NULL) && ((int)strlen(name) < cbTempName)) {
165
+ strcpy(pszTempName, name);
166
+ free(name);
167
+ return TRUE;
168
+ }
169
+
170
+ if (name) free(name);
171
+ return FALSE;
172
+ }
173
+
174
+ static FNFCISTATUS(cb_status)
175
+ {
176
+ if (pv) {
177
+ PyObject *result = PyObject_CallMethod(pv, "status", "iii", typeStatus, cb1, cb2);
178
+ if (result == NULL)
179
+ return -1;
180
+ Py_DECREF(result);
181
+ }
182
+ return 0;
183
+ }
184
+
185
+ static FNFCIGETNEXTCABINET(cb_getnextcabinet)
186
+ {
187
+ if (pv) {
188
+ PyObject *result = PyObject_CallMethod(pv, "getnextcabinet", "i", pccab->iCab);
189
+ if (result == NULL)
190
+ return -1;
191
+ if (!PyBytes_Check(result)) {
192
+ PyErr_Format(PyExc_TypeError,
193
+ "Incorrect return type %s from getnextcabinet",
194
+ Py_TYPE(result)->tp_name);
195
+ Py_DECREF(result);
196
+ return FALSE;
197
+ }
198
+ strncpy(pccab->szCab, PyBytes_AsString(result), sizeof(pccab->szCab));
199
+ return TRUE;
200
+ }
201
+ return FALSE;
202
+ }
203
+
204
+ static FNFCIGETOPENINFO(cb_getopeninfo)
205
+ {
206
+ BY_HANDLE_FILE_INFORMATION bhfi;
207
+ FILETIME filetime;
208
+ HANDLE handle;
209
+
210
+ wchar_t *ws = utf8_to_wchar(pszName, err);
211
+ if (ws == NULL) {
212
+ return -1;
213
+ }
214
+
215
+ /* Need Win32 handle to get time stamps */
216
+ handle = CreateFileW(ws, GENERIC_READ, FILE_SHARE_READ, NULL,
217
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
218
+ if (handle == INVALID_HANDLE_VALUE) {
219
+ PyMem_Free(ws);
220
+ return -1;
221
+ }
222
+
223
+ if (GetFileInformationByHandle(handle, &bhfi) == FALSE) {
224
+ CloseHandle(handle);
225
+ PyMem_Free(ws);
226
+ return -1;
227
+ }
228
+
229
+ FileTimeToLocalFileTime(&bhfi.ftLastWriteTime, &filetime);
230
+ FileTimeToDosDateTime(&filetime, pdate, ptime);
231
+
232
+ *pattribs = (int)(bhfi.dwFileAttributes &
233
+ (_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH));
234
+
235
+ CloseHandle(handle);
236
+
237
+ int result = _wopen(ws, _O_RDONLY | _O_BINARY | O_NOINHERIT);
238
+ PyMem_Free(ws);
239
+ return result;
240
+ }
241
+
242
+ /*[clinic input]
243
+ _msi.FCICreate
244
+ cabname: str
245
+ the name of the CAB file
246
+ files: object
247
+ a list of tuples, each containing the name of the file on disk,
248
+ and the name of the file inside the CAB file
249
+ /
250
+
251
+ Create a new CAB file.
252
+ [clinic start generated code]*/
253
+
254
+ static PyObject *
255
+ _msi_FCICreate_impl(PyObject *module, const char *cabname, PyObject *files)
256
+ /*[clinic end generated code: output=55dc05728361b799 input=1d2d75fdc8b44b71]*/
257
+ {
258
+ const char *p;
259
+ CCAB ccab;
260
+ HFCI hfci;
261
+ ERF erf;
262
+ Py_ssize_t i;
263
+
264
+ if (!PyList_Check(files)) {
265
+ PyErr_SetString(PyExc_TypeError, "FCICreate expects a list");
266
+ return NULL;
267
+ }
268
+
269
+ ccab.cb = INT_MAX; /* no need to split CAB into multiple media */
270
+ ccab.cbFolderThresh = 1000000; /* flush directory after this many bytes */
271
+ ccab.cbReserveCFData = 0;
272
+ ccab.cbReserveCFFolder = 0;
273
+ ccab.cbReserveCFHeader = 0;
274
+
275
+ ccab.iCab = 1;
276
+ ccab.iDisk = 1;
277
+
278
+ ccab.setID = 0;
279
+ ccab.szDisk[0] = '\0';
280
+
281
+ for (i = 0, p = cabname; *p; p++)
282
+ if (*p == '\\' || *p == '/')
283
+ i = p - cabname + 1;
284
+
285
+ if (i >= sizeof(ccab.szCabPath) ||
286
+ strlen(cabname+i) >= sizeof(ccab.szCab)) {
287
+ PyErr_SetString(PyExc_ValueError, "path name too long");
288
+ return 0;
289
+ }
290
+
291
+ if (i > 0) {
292
+ memcpy(ccab.szCabPath, cabname, i);
293
+ ccab.szCabPath[i] = '\0';
294
+ strcpy(ccab.szCab, cabname+i);
295
+ } else {
296
+ strcpy(ccab.szCabPath, ".\\");
297
+ strcpy(ccab.szCab, cabname);
298
+ }
299
+
300
+ hfci = FCICreate(&erf, cb_fileplaced, cb_alloc, cb_free,
301
+ cb_open, cb_read, cb_write, cb_close, cb_seek, cb_delete,
302
+ cb_gettempfile, &ccab, NULL);
303
+
304
+ if (hfci == NULL) {
305
+ PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper);
306
+ return NULL;
307
+ }
308
+
309
+ for (i=0; i < PyList_GET_SIZE(files); i++) {
310
+ PyObject *item = PyList_GET_ITEM(files, i);
311
+ char *filename, *cabname;
312
+
313
+ if (!PyArg_ParseTuple(item, "ss", &filename, &cabname)) {
314
+ PyErr_SetString(PyExc_TypeError, "FCICreate expects a list of tuples containing two strings");
315
+ FCIDestroy(hfci);
316
+ return NULL;
317
+ }
318
+
319
+ if (!FCIAddFile(hfci, filename, cabname, FALSE,
320
+ cb_getnextcabinet, cb_status, cb_getopeninfo,
321
+ tcompTYPE_MSZIP))
322
+ goto err;
323
+ }
324
+
325
+ if (!FCIFlushCabinet(hfci, FALSE, cb_getnextcabinet, cb_status))
326
+ goto err;
327
+
328
+ if (!FCIDestroy(hfci))
329
+ goto err;
330
+
331
+ Py_RETURN_NONE;
332
+ err:
333
+ if(erf.fError)
334
+ PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */
335
+ else
336
+ PyErr_SetString(PyExc_ValueError, "FCI general error");
337
+
338
+ FCIDestroy(hfci);
339
+ return NULL;
340
+ }
341
+
342
+ typedef struct msiobj{
343
+ PyObject_HEAD
344
+ MSIHANDLE h;
345
+ }msiobj;
346
+
347
+ static void
348
+ msiobj_dealloc(msiobj* msidb)
349
+ {
350
+ MsiCloseHandle(msidb->h);
351
+ msidb->h = 0;
352
+ PyObject_Free(msidb);
353
+ }
354
+
355
+ static PyObject*
356
+ msierror(int status)
357
+ {
358
+ int code;
359
+ char buf[2000];
360
+ char *res = buf;
361
+ DWORD size = Py_ARRAY_LENGTH(buf);
362
+ MSIHANDLE err = MsiGetLastErrorRecord();
363
+
364
+ if (err == 0) {
365
+ switch(status) {
366
+ case ERROR_ACCESS_DENIED:
367
+ PyErr_SetString(MSIError, "access denied");
368
+ return NULL;
369
+ case ERROR_FUNCTION_FAILED:
370
+ PyErr_SetString(MSIError, "function failed");
371
+ return NULL;
372
+ case ERROR_INVALID_DATA:
373
+ PyErr_SetString(MSIError, "invalid data");
374
+ return NULL;
375
+ case ERROR_INVALID_HANDLE:
376
+ PyErr_SetString(MSIError, "invalid handle");
377
+ return NULL;
378
+ case ERROR_INVALID_STATE:
379
+ PyErr_SetString(MSIError, "invalid state");
380
+ return NULL;
381
+ case ERROR_INVALID_PARAMETER:
382
+ PyErr_SetString(MSIError, "invalid parameter");
383
+ return NULL;
384
+ case ERROR_OPEN_FAILED:
385
+ PyErr_SetString(MSIError, "open failed");
386
+ return NULL;
387
+ case ERROR_CREATE_FAILED:
388
+ PyErr_SetString(MSIError, "create failed");
389
+ return NULL;
390
+ default:
391
+ PyErr_Format(MSIError, "unknown error %x", status);
392
+ return NULL;
393
+ }
394
+ }
395
+
396
+ code = MsiRecordGetInteger(err, 1); /* XXX code */
397
+ if (MsiFormatRecord(0, err, res, &size) == ERROR_MORE_DATA) {
398
+ res = malloc(size+1);
399
+ if (res == NULL) {
400
+ MsiCloseHandle(err);
401
+ return PyErr_NoMemory();
402
+ }
403
+ MsiFormatRecord(0, err, res, &size);
404
+ res[size]='\0';
405
+ }
406
+ MsiCloseHandle(err);
407
+ PyErr_SetString(MSIError, res);
408
+ if (res != buf)
409
+ free(res);
410
+ return NULL;
411
+ }
412
+
413
+ #include "include/_msi.h"
414
+
415
+ /*[clinic input]
416
+ _msi.Database.Close
417
+
418
+ Close the database object.
419
+ [clinic start generated code]*/
420
+
421
+ static PyObject *
422
+ _msi_Database_Close_impl(msiobj *self)
423
+ /*[clinic end generated code: output=ddf2d7712ea804f1 input=104330ce4a486187]*/
424
+ {
425
+ int status;
426
+ if ((status = MsiCloseHandle(self->h)) != ERROR_SUCCESS) {
427
+ return msierror(status);
428
+ }
429
+ self->h = 0;
430
+ Py_RETURN_NONE;
431
+ }
432
+
433
+ /*************************** Record objects **********************/
434
+
435
+ /*[clinic input]
436
+ _msi.Record.GetFieldCount
437
+
438
+ Return the number of fields of the record.
439
+ [clinic start generated code]*/
440
+
441
+ static PyObject *
442
+ _msi_Record_GetFieldCount_impl(msiobj *self)
443
+ /*[clinic end generated code: output=112795079c904398 input=5fb9d4071b28897b]*/
444
+ {
445
+ return PyLong_FromLong(MsiRecordGetFieldCount(self->h));
446
+ }
447
+
448
+ /*[clinic input]
449
+ _msi.Record.GetInteger
450
+ field: unsigned_int(bitwise=True)
451
+ /
452
+
453
+ Return the value of field as an integer where possible.
454
+ [clinic start generated code]*/
455
+
456
+ static PyObject *
457
+ _msi_Record_GetInteger_impl(msiobj *self, unsigned int field)
458
+ /*[clinic end generated code: output=7174ebb6e8ed1c79 input=d19209947e2bfe61]*/
459
+ {
460
+ int status;
461
+
462
+ status = MsiRecordGetInteger(self->h, field);
463
+ if (status == MSI_NULL_INTEGER){
464
+ PyErr_SetString(MSIError, "could not convert record field to integer");
465
+ return NULL;
466
+ }
467
+ return PyLong_FromLong((long) status);
468
+ }
469
+
470
+ /*[clinic input]
471
+ _msi.Record.GetString
472
+ field: unsigned_int(bitwise=True)
473
+ /
474
+
475
+ Return the value of field as a string where possible.
476
+ [clinic start generated code]*/
477
+
478
+ static PyObject *
479
+ _msi_Record_GetString_impl(msiobj *self, unsigned int field)
480
+ /*[clinic end generated code: output=f670d1b484cfa47c input=ffa11f21450b77d8]*/
481
+ {
482
+ unsigned int status;
483
+ WCHAR buf[2000];
484
+ WCHAR *res = buf;
485
+ DWORD size = Py_ARRAY_LENGTH(buf);
486
+ PyObject* string;
487
+
488
+ status = MsiRecordGetStringW(self->h, field, res, &size);
489
+ if (status == ERROR_MORE_DATA) {
490
+ res = (WCHAR*) malloc((size + 1)*sizeof(WCHAR));
491
+ if (res == NULL)
492
+ return PyErr_NoMemory();
493
+ status = MsiRecordGetStringW(self->h, field, res, &size);
494
+ }
495
+ if (status != ERROR_SUCCESS)
496
+ return msierror((int) status);
497
+ string = PyUnicode_FromWideChar(res, size);
498
+ if (buf != res)
499
+ free(res);
500
+ return string;
501
+ }
502
+
503
+ /*[clinic input]
504
+ _msi.Record.ClearData
505
+
506
+ Set all fields of the record to 0.
507
+ [clinic start generated code]*/
508
+
509
+ static PyObject *
510
+ _msi_Record_ClearData_impl(msiobj *self)
511
+ /*[clinic end generated code: output=1891467214b977f4 input=2a911c95aaded102]*/
512
+ {
513
+ int status = MsiRecordClearData(self->h);
514
+ if (status != ERROR_SUCCESS)
515
+ return msierror(status);
516
+
517
+ Py_RETURN_NONE;
518
+ }
519
+
520
+ /*[clinic input]
521
+ _msi.Record.SetString
522
+ field: int
523
+ value: wchar_t
524
+ /
525
+
526
+ Set field to a string value.
527
+ [clinic start generated code]*/
528
+
529
+ static PyObject *
530
+ _msi_Record_SetString_impl(msiobj *self, int field, const wchar_t *value)
531
+ /*[clinic end generated code: output=2e37505b0f11f985 input=fb8ec70a2a6148e0]*/
532
+ {
533
+ int status;
534
+
535
+ if ((status = MsiRecordSetStringW(self->h, field, value)) != ERROR_SUCCESS)
536
+ return msierror(status);
537
+
538
+ Py_RETURN_NONE;
539
+ }
540
+
541
+ /*[clinic input]
542
+ _msi.Record.SetStream
543
+ field: int
544
+ value: wchar_t
545
+ /
546
+
547
+ Set field to the contents of the file named value.
548
+ [clinic start generated code]*/
549
+
550
+ static PyObject *
551
+ _msi_Record_SetStream_impl(msiobj *self, int field, const wchar_t *value)
552
+ /*[clinic end generated code: output=442facac16913b48 input=a07aa19b865e8292]*/
553
+ {
554
+ int status;
555
+
556
+ if ((status = MsiRecordSetStreamW(self->h, field, value)) != ERROR_SUCCESS)
557
+ return msierror(status);
558
+
559
+ Py_RETURN_NONE;
560
+ }
561
+
562
+ /*[clinic input]
563
+ _msi.Record.SetInteger
564
+ field: int
565
+ value: int
566
+ /
567
+
568
+ Set field to an integer value.
569
+ [clinic start generated code]*/
570
+
571
+ static PyObject *
572
+ _msi_Record_SetInteger_impl(msiobj *self, int field, int value)
573
+ /*[clinic end generated code: output=669e8647775d0ce7 input=c571aa775e7e451b]*/
574
+ {
575
+ int status;
576
+
577
+ if ((status = MsiRecordSetInteger(self->h, field, value)) != ERROR_SUCCESS)
578
+ return msierror(status);
579
+
580
+ Py_RETURN_NONE;
581
+ }
582
+
583
+
584
+
585
+ static PyMethodDef record_methods[] = {
586
+ _MSI_RECORD_GETFIELDCOUNT_METHODDEF
587
+ _MSI_RECORD_GETINTEGER_METHODDEF
588
+ _MSI_RECORD_GETSTRING_METHODDEF
589
+ _MSI_RECORD_SETSTRING_METHODDEF
590
+ _MSI_RECORD_SETSTREAM_METHODDEF
591
+ _MSI_RECORD_SETINTEGER_METHODDEF
592
+ _MSI_RECORD_CLEARDATA_METHODDEF
593
+ { NULL, NULL }
594
+ };
595
+
596
+ static PyTypeObject record_Type = {
597
+ PyVarObject_HEAD_INIT(NULL, 0)
598
+ "_msi.Record", /*tp_name*/
599
+ sizeof(msiobj), /*tp_basicsize*/
600
+ 0, /*tp_itemsize*/
601
+ /* methods */
602
+ (destructor)msiobj_dealloc, /*tp_dealloc*/
603
+ 0, /*tp_vectorcall_offset*/
604
+ 0, /*tp_getattr*/
605
+ 0, /*tp_setattr*/
606
+ 0, /*tp_as_async*/
607
+ 0, /*tp_repr*/
608
+ 0, /*tp_as_number*/
609
+ 0, /*tp_as_sequence*/
610
+ 0, /*tp_as_mapping*/
611
+ 0, /*tp_hash*/
612
+ 0, /*tp_call*/
613
+ 0, /*tp_str*/
614
+ PyObject_GenericGetAttr,/*tp_getattro*/
615
+ PyObject_GenericSetAttr,/*tp_setattro*/
616
+ 0, /*tp_as_buffer*/
617
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
618
+ 0, /*tp_doc*/
619
+ 0, /*tp_traverse*/
620
+ 0, /*tp_clear*/
621
+ 0, /*tp_richcompare*/
622
+ 0, /*tp_weaklistoffset*/
623
+ 0, /*tp_iter*/
624
+ 0, /*tp_iternext*/
625
+ record_methods, /*tp_methods*/
626
+ 0, /*tp_members*/
627
+ 0, /*tp_getset*/
628
+ 0, /*tp_base*/
629
+ 0, /*tp_dict*/
630
+ 0, /*tp_descr_get*/
631
+ 0, /*tp_descr_set*/
632
+ 0, /*tp_dictoffset*/
633
+ 0, /*tp_init*/
634
+ 0, /*tp_alloc*/
635
+ 0, /*tp_new*/
636
+ 0, /*tp_free*/
637
+ 0, /*tp_is_gc*/
638
+ };
639
+
640
+ static PyObject*
641
+ record_new(MSIHANDLE h)
642
+ {
643
+ msiobj *result = PyObject_New(struct msiobj, &record_Type);
644
+
645
+ if (!result) {
646
+ MsiCloseHandle(h);
647
+ return NULL;
648
+ }
649
+
650
+ result->h = h;
651
+ return (PyObject*)result;
652
+ }
653
+
654
+ /*************************** SummaryInformation objects **************/
655
+
656
+ /*[clinic input]
657
+ _msi.SummaryInformation.GetProperty
658
+ field: int
659
+ the name of the property, one of the PID_* constants
660
+ /
661
+
662
+ Return a property of the summary.
663
+ [clinic start generated code]*/
664
+
665
+ static PyObject *
666
+ _msi_SummaryInformation_GetProperty_impl(msiobj *self, int field)
667
+ /*[clinic end generated code: output=f8946a33ee14f6ef input=f8dfe2c890d6cb8b]*/
668
+ {
669
+ int status;
670
+ PyObject *result;
671
+ UINT type;
672
+ INT ival;
673
+ FILETIME fval;
674
+ char sbuf[1000];
675
+ char *sval = sbuf;
676
+ DWORD ssize = sizeof(sbuf);
677
+
678
+ status = MsiSummaryInfoGetProperty(self->h, field, &type, &ival,
679
+ &fval, sval, &ssize);
680
+ if (status == ERROR_MORE_DATA) {
681
+ ssize++;
682
+ sval = malloc(ssize);
683
+ if (sval == NULL) {
684
+ return PyErr_NoMemory();
685
+ }
686
+ status = MsiSummaryInfoGetProperty(self->h, field, &type, &ival,
687
+ &fval, sval, &ssize);
688
+ }
689
+ if (status != ERROR_SUCCESS) {
690
+ return msierror(status);
691
+ }
692
+
693
+ switch(type) {
694
+ case VT_I2:
695
+ case VT_I4:
696
+ result = PyLong_FromLong(ival);
697
+ break;
698
+ case VT_FILETIME:
699
+ PyErr_SetString(PyExc_NotImplementedError, "FILETIME result");
700
+ result = NULL;
701
+ break;
702
+ case VT_LPSTR:
703
+ result = PyBytes_FromStringAndSize(sval, ssize);
704
+ break;
705
+ case VT_EMPTY:
706
+ result = Py_NewRef(Py_None);
707
+ break;
708
+ default:
709
+ PyErr_Format(PyExc_NotImplementedError, "result of type %d", type);
710
+ result = NULL;
711
+ break;
712
+ }
713
+ if (sval != sbuf)
714
+ free(sval);
715
+ return result;
716
+ }
717
+
718
+ /*[clinic input]
719
+ _msi.SummaryInformation.GetPropertyCount
720
+
721
+ Return the number of summary properties.
722
+ [clinic start generated code]*/
723
+
724
+ static PyObject *
725
+ _msi_SummaryInformation_GetPropertyCount_impl(msiobj *self)
726
+ /*[clinic end generated code: output=68e94b2aeee92b3d input=2e71e985586d82dc]*/
727
+ {
728
+ int status;
729
+ UINT result;
730
+
731
+ status = MsiSummaryInfoGetPropertyCount(self->h, &result);
732
+ if (status != ERROR_SUCCESS)
733
+ return msierror(status);
734
+
735
+ return PyLong_FromLong(result);
736
+ }
737
+
738
+ /*[clinic input]
739
+ _msi.SummaryInformation.SetProperty
740
+ field: int
741
+ the name of the property, one of the PID_* constants
742
+ value as data: object
743
+ the new value of the property (integer or string)
744
+ /
745
+
746
+ Set a property.
747
+ [clinic start generated code]*/
748
+
749
+ static PyObject *
750
+ _msi_SummaryInformation_SetProperty_impl(msiobj *self, int field,
751
+ PyObject *data)
752
+ /*[clinic end generated code: output=3d4692c8984bb675 input=f2a7811b905abbed]*/
753
+ {
754
+ int status;
755
+
756
+ if (PyUnicode_Check(data)) {
757
+ WCHAR *value = PyUnicode_AsWideCharString(data, NULL);
758
+ if (value == NULL) {
759
+ return NULL;
760
+ }
761
+ status = MsiSummaryInfoSetPropertyW(self->h, field, VT_LPSTR,
762
+ 0, NULL, value);
763
+ PyMem_Free(value);
764
+ } else if (PyLong_CheckExact(data)) {
765
+ long value = PyLong_AsLong(data);
766
+ if (value == -1 && PyErr_Occurred()) {
767
+ return NULL;
768
+ }
769
+ status = MsiSummaryInfoSetProperty(self->h, field, VT_I4,
770
+ value, NULL, NULL);
771
+ } else {
772
+ PyErr_SetString(PyExc_TypeError, "unsupported type");
773
+ return NULL;
774
+ }
775
+
776
+ if (status != ERROR_SUCCESS)
777
+ return msierror(status);
778
+
779
+ Py_RETURN_NONE;
780
+ }
781
+
782
+
783
+ /*[clinic input]
784
+ _msi.SummaryInformation.Persist
785
+
786
+ Write the modified properties to the summary information stream.
787
+ [clinic start generated code]*/
788
+
789
+ static PyObject *
790
+ _msi_SummaryInformation_Persist_impl(msiobj *self)
791
+ /*[clinic end generated code: output=c564bd17f5e122c9 input=e3dda9d530095ef7]*/
792
+ {
793
+ int status;
794
+
795
+ status = MsiSummaryInfoPersist(self->h);
796
+ if (status != ERROR_SUCCESS)
797
+ return msierror(status);
798
+ Py_RETURN_NONE;
799
+ }
800
+
801
+ static PyMethodDef summary_methods[] = {
802
+ _MSI_SUMMARYINFORMATION_GETPROPERTY_METHODDEF
803
+ _MSI_SUMMARYINFORMATION_GETPROPERTYCOUNT_METHODDEF
804
+ _MSI_SUMMARYINFORMATION_SETPROPERTY_METHODDEF
805
+ _MSI_SUMMARYINFORMATION_PERSIST_METHODDEF
806
+ { NULL, NULL }
807
+ };
808
+
809
+ static PyTypeObject summary_Type = {
810
+ PyVarObject_HEAD_INIT(NULL, 0)
811
+ "_msi.SummaryInformation", /*tp_name*/
812
+ sizeof(msiobj), /*tp_basicsize*/
813
+ 0, /*tp_itemsize*/
814
+ /* methods */
815
+ (destructor)msiobj_dealloc, /*tp_dealloc*/
816
+ 0, /*tp_vectorcall_offset*/
817
+ 0, /*tp_getattr*/
818
+ 0, /*tp_setattr*/
819
+ 0, /*tp_as_async*/
820
+ 0, /*tp_repr*/
821
+ 0, /*tp_as_number*/
822
+ 0, /*tp_as_sequence*/
823
+ 0, /*tp_as_mapping*/
824
+ 0, /*tp_hash*/
825
+ 0, /*tp_call*/
826
+ 0, /*tp_str*/
827
+ PyObject_GenericGetAttr,/*tp_getattro*/
828
+ PyObject_GenericSetAttr,/*tp_setattro*/
829
+ 0, /*tp_as_buffer*/
830
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
831
+ 0, /*tp_doc*/
832
+ 0, /*tp_traverse*/
833
+ 0, /*tp_clear*/
834
+ 0, /*tp_richcompare*/
835
+ 0, /*tp_weaklistoffset*/
836
+ 0, /*tp_iter*/
837
+ 0, /*tp_iternext*/
838
+ summary_methods, /*tp_methods*/
839
+ 0, /*tp_members*/
840
+ 0, /*tp_getset*/
841
+ 0, /*tp_base*/
842
+ 0, /*tp_dict*/
843
+ 0, /*tp_descr_get*/
844
+ 0, /*tp_descr_set*/
845
+ 0, /*tp_dictoffset*/
846
+ 0, /*tp_init*/
847
+ 0, /*tp_alloc*/
848
+ 0, /*tp_new*/
849
+ 0, /*tp_free*/
850
+ 0, /*tp_is_gc*/
851
+ };
852
+
853
+ /*************************** View objects **************/
854
+
855
+ /*[clinic input]
856
+ _msi.View.Execute
857
+ params as oparams: object
858
+ a record describing actual values of the parameter tokens
859
+ in the query or None
860
+ /
861
+
862
+ Execute the SQL query of the view.
863
+ [clinic start generated code]*/
864
+
865
+ static PyObject *
866
+ _msi_View_Execute(msiobj *self, PyObject *oparams)
867
+ /*[clinic end generated code: output=f0f65fd2900bcb4e input=cb163a15d453348e]*/
868
+ {
869
+ int status;
870
+ MSIHANDLE params = 0;
871
+
872
+ if (!Py_IsNone(oparams)) {
873
+ if (!Py_IS_TYPE(oparams, &record_Type)) {
874
+ PyErr_SetString(PyExc_TypeError, "Execute argument must be a record");
875
+ return NULL;
876
+ }
877
+ params = ((msiobj*)oparams)->h;
878
+ }
879
+
880
+ status = MsiViewExecute(self->h, params);
881
+ if (status != ERROR_SUCCESS)
882
+ return msierror(status);
883
+
884
+ Py_RETURN_NONE;
885
+ }
886
+
887
+ /*[clinic input]
888
+ _msi.View.Fetch
889
+
890
+ Return a result record of the query.
891
+ [clinic start generated code]*/
892
+
893
+ static PyObject *
894
+ _msi_View_Fetch_impl(msiobj *self)
895
+ /*[clinic end generated code: output=ba154a3794537d4e input=7f3e3d06c449001c]*/
896
+ {
897
+ int status;
898
+ MSIHANDLE result;
899
+
900
+ status = MsiViewFetch(self->h, &result);
901
+ if (status == ERROR_NO_MORE_ITEMS) {
902
+ Py_RETURN_NONE;
903
+ } else if (status != ERROR_SUCCESS) {
904
+ return msierror(status);
905
+ }
906
+
907
+ return record_new(result);
908
+ }
909
+
910
+ /*[clinic input]
911
+ _msi.View.GetColumnInfo
912
+ kind: int
913
+ MSICOLINFO_NAMES or MSICOLINFO_TYPES
914
+ /
915
+
916
+ Return a record describing the columns of the view.
917
+ [clinic start generated code]*/
918
+
919
+ static PyObject *
920
+ _msi_View_GetColumnInfo_impl(msiobj *self, int kind)
921
+ /*[clinic end generated code: output=e7c1697db9403660 input=afedb892bf564a3b]*/
922
+ {
923
+ int status;
924
+ MSIHANDLE result;
925
+
926
+ if ((status = MsiViewGetColumnInfo(self->h, kind, &result)) != ERROR_SUCCESS)
927
+ return msierror(status);
928
+
929
+ return record_new(result);
930
+ }
931
+
932
+ /*[clinic input]
933
+ _msi.View.Modify
934
+ kind: int
935
+ one of the MSIMODIFY_* constants
936
+ data: object
937
+ a record describing the new data
938
+ /
939
+
940
+ Modify the view.
941
+ [clinic start generated code]*/
942
+
943
+ static PyObject *
944
+ _msi_View_Modify_impl(msiobj *self, int kind, PyObject *data)
945
+ /*[clinic end generated code: output=69aaf3ce8ddac0ba input=2828de22de0d47b4]*/
946
+ {
947
+ int status;
948
+
949
+ if (!Py_IS_TYPE(data, &record_Type)) {
950
+ PyErr_SetString(PyExc_TypeError, "Modify expects a record object");
951
+ return NULL;
952
+ }
953
+
954
+ if ((status = MsiViewModify(self->h, kind, ((msiobj*)data)->h)) != ERROR_SUCCESS)
955
+ return msierror(status);
956
+
957
+ Py_RETURN_NONE;
958
+ }
959
+
960
+ /*[clinic input]
961
+ _msi.View.Close
962
+
963
+ Close the view.
964
+ [clinic start generated code]*/
965
+
966
+ static PyObject *
967
+ _msi_View_Close_impl(msiobj *self)
968
+ /*[clinic end generated code: output=488f7b8645ca104a input=de6927d1308c401c]*/
969
+ {
970
+ int status;
971
+
972
+ if ((status = MsiViewClose(self->h)) != ERROR_SUCCESS)
973
+ return msierror(status);
974
+
975
+ Py_RETURN_NONE;
976
+ }
977
+
978
+ static PyMethodDef view_methods[] = {
979
+ _MSI_VIEW_EXECUTE_METHODDEF
980
+ _MSI_VIEW_GETCOLUMNINFO_METHODDEF
981
+ _MSI_VIEW_FETCH_METHODDEF
982
+ _MSI_VIEW_MODIFY_METHODDEF
983
+ _MSI_VIEW_CLOSE_METHODDEF
984
+ { NULL, NULL }
985
+ };
986
+
987
+ static PyTypeObject msiview_Type = {
988
+ PyVarObject_HEAD_INIT(NULL, 0)
989
+ "_msi.View", /*tp_name*/
990
+ sizeof(msiobj), /*tp_basicsize*/
991
+ 0, /*tp_itemsize*/
992
+ /* methods */
993
+ (destructor)msiobj_dealloc, /*tp_dealloc*/
994
+ 0, /*tp_vectorcall_offset*/
995
+ 0, /*tp_getattr*/
996
+ 0, /*tp_setattr*/
997
+ 0, /*tp_as_async*/
998
+ 0, /*tp_repr*/
999
+ 0, /*tp_as_number*/
1000
+ 0, /*tp_as_sequence*/
1001
+ 0, /*tp_as_mapping*/
1002
+ 0, /*tp_hash*/
1003
+ 0, /*tp_call*/
1004
+ 0, /*tp_str*/
1005
+ PyObject_GenericGetAttr,/*tp_getattro*/
1006
+ PyObject_GenericSetAttr,/*tp_setattro*/
1007
+ 0, /*tp_as_buffer*/
1008
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
1009
+ 0, /*tp_doc*/
1010
+ 0, /*tp_traverse*/
1011
+ 0, /*tp_clear*/
1012
+ 0, /*tp_richcompare*/
1013
+ 0, /*tp_weaklistoffset*/
1014
+ 0, /*tp_iter*/
1015
+ 0, /*tp_iternext*/
1016
+ view_methods, /*tp_methods*/
1017
+ 0, /*tp_members*/
1018
+ 0, /*tp_getset*/
1019
+ 0, /*tp_base*/
1020
+ 0, /*tp_dict*/
1021
+ 0, /*tp_descr_get*/
1022
+ 0, /*tp_descr_set*/
1023
+ 0, /*tp_dictoffset*/
1024
+ 0, /*tp_init*/
1025
+ 0, /*tp_alloc*/
1026
+ 0, /*tp_new*/
1027
+ 0, /*tp_free*/
1028
+ 0, /*tp_is_gc*/
1029
+ };
1030
+
1031
+ /*************************** Database objects **************/
1032
+
1033
+ /*[clinic input]
1034
+ _msi.Database.OpenView
1035
+ sql: wchar_t
1036
+ the SQL statement to execute
1037
+ /
1038
+
1039
+ Return a view object.
1040
+ [clinic start generated code]*/
1041
+
1042
+ static PyObject *
1043
+ _msi_Database_OpenView_impl(msiobj *self, const wchar_t *sql)
1044
+ /*[clinic end generated code: output=e712e6a11229abfd input=50f1771f37e500df]*/
1045
+ {
1046
+ int status;
1047
+ MSIHANDLE hView;
1048
+ msiobj *result;
1049
+
1050
+ if ((status = MsiDatabaseOpenViewW(self->h, sql, &hView)) != ERROR_SUCCESS)
1051
+ return msierror(status);
1052
+
1053
+ result = PyObject_New(struct msiobj, &msiview_Type);
1054
+ if (!result) {
1055
+ MsiCloseHandle(hView);
1056
+ return NULL;
1057
+ }
1058
+
1059
+ result->h = hView;
1060
+ return (PyObject*)result;
1061
+ }
1062
+
1063
+ /*[clinic input]
1064
+ _msi.Database.Commit
1065
+
1066
+ Commit the changes pending in the current transaction.
1067
+ [clinic start generated code]*/
1068
+
1069
+ static PyObject *
1070
+ _msi_Database_Commit_impl(msiobj *self)
1071
+ /*[clinic end generated code: output=f33021feb8b0cdd8 input=375bb120d402266d]*/
1072
+ {
1073
+ int status;
1074
+
1075
+ if ((status = MsiDatabaseCommit(self->h)) != ERROR_SUCCESS)
1076
+ return msierror(status);
1077
+
1078
+ Py_RETURN_NONE;
1079
+ }
1080
+
1081
+ /*[clinic input]
1082
+ _msi.Database.GetSummaryInformation
1083
+ count: int
1084
+ the maximum number of updated values
1085
+ /
1086
+
1087
+ Return a new summary information object.
1088
+ [clinic start generated code]*/
1089
+
1090
+ static PyObject *
1091
+ _msi_Database_GetSummaryInformation_impl(msiobj *self, int count)
1092
+ /*[clinic end generated code: output=781e51a4ea4da847 input=18a899ead6521735]*/
1093
+ {
1094
+ int status;
1095
+ MSIHANDLE result;
1096
+ msiobj *oresult;
1097
+
1098
+ status = MsiGetSummaryInformation(self->h, NULL, count, &result);
1099
+ if (status != ERROR_SUCCESS)
1100
+ return msierror(status);
1101
+
1102
+ oresult = PyObject_New(struct msiobj, &summary_Type);
1103
+ if (!oresult) {
1104
+ MsiCloseHandle(result);
1105
+ return NULL;
1106
+ }
1107
+
1108
+ oresult->h = result;
1109
+ return (PyObject*)oresult;
1110
+ }
1111
+
1112
+ static PyMethodDef db_methods[] = {
1113
+ _MSI_DATABASE_OPENVIEW_METHODDEF
1114
+ _MSI_DATABASE_COMMIT_METHODDEF
1115
+ _MSI_DATABASE_GETSUMMARYINFORMATION_METHODDEF
1116
+ _MSI_DATABASE_CLOSE_METHODDEF
1117
+ { NULL, NULL }
1118
+ };
1119
+
1120
+ static PyTypeObject msidb_Type = {
1121
+ PyVarObject_HEAD_INIT(NULL, 0)
1122
+ "_msi.Database", /*tp_name*/
1123
+ sizeof(msiobj), /*tp_basicsize*/
1124
+ 0, /*tp_itemsize*/
1125
+ /* methods */
1126
+ (destructor)msiobj_dealloc, /*tp_dealloc*/
1127
+ 0, /*tp_vectorcall_offset*/
1128
+ 0, /*tp_getattr*/
1129
+ 0, /*tp_setattr*/
1130
+ 0, /*tp_as_async*/
1131
+ 0, /*tp_repr*/
1132
+ 0, /*tp_as_number*/
1133
+ 0, /*tp_as_sequence*/
1134
+ 0, /*tp_as_mapping*/
1135
+ 0, /*tp_hash*/
1136
+ 0, /*tp_call*/
1137
+ 0, /*tp_str*/
1138
+ PyObject_GenericGetAttr,/*tp_getattro*/
1139
+ PyObject_GenericSetAttr,/*tp_setattro*/
1140
+ 0, /*tp_as_buffer*/
1141
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
1142
+ 0, /*tp_doc*/
1143
+ 0, /*tp_traverse*/
1144
+ 0, /*tp_clear*/
1145
+ 0, /*tp_richcompare*/
1146
+ 0, /*tp_weaklistoffset*/
1147
+ 0, /*tp_iter*/
1148
+ 0, /*tp_iternext*/
1149
+ db_methods, /*tp_methods*/
1150
+ 0, /*tp_members*/
1151
+ 0, /*tp_getset*/
1152
+ 0, /*tp_base*/
1153
+ 0, /*tp_dict*/
1154
+ 0, /*tp_descr_get*/
1155
+ 0, /*tp_descr_set*/
1156
+ 0, /*tp_dictoffset*/
1157
+ 0, /*tp_init*/
1158
+ 0, /*tp_alloc*/
1159
+ 0, /*tp_new*/
1160
+ 0, /*tp_free*/
1161
+ 0, /*tp_is_gc*/
1162
+ };
1163
+
1164
+ #define Py_NOT_PERSIST(x, flag) \
1165
+ (x != (SIZE_T)(flag) && \
1166
+ x != ((SIZE_T)(flag) | MSIDBOPEN_PATCHFILE))
1167
+
1168
+ #define Py_INVALID_PERSIST(x) \
1169
+ (Py_NOT_PERSIST(x, MSIDBOPEN_READONLY) && \
1170
+ Py_NOT_PERSIST(x, MSIDBOPEN_TRANSACT) && \
1171
+ Py_NOT_PERSIST(x, MSIDBOPEN_DIRECT) && \
1172
+ Py_NOT_PERSIST(x, MSIDBOPEN_CREATE) && \
1173
+ Py_NOT_PERSIST(x, MSIDBOPEN_CREATEDIRECT))
1174
+
1175
+ /*[clinic input]
1176
+ _msi.OpenDatabase
1177
+ path: wchar_t
1178
+ the file name of the MSI file
1179
+ persist: int
1180
+ the persistence mode
1181
+ /
1182
+
1183
+ Return a new database object.
1184
+ [clinic start generated code]*/
1185
+
1186
+ static PyObject *
1187
+ _msi_OpenDatabase_impl(PyObject *module, const wchar_t *path, int persist)
1188
+ /*[clinic end generated code: output=d34b7202b745de05 input=1300f3b97659559b]*/
1189
+ {
1190
+ int status;
1191
+ MSIHANDLE h;
1192
+ msiobj *result;
1193
+
1194
+ /* We need to validate that persist is a valid MSIDBOPEN_* value. Otherwise,
1195
+ MsiOpenDatabase may treat the value as a pointer, leading to unexpected
1196
+ behavior. */
1197
+ if (Py_INVALID_PERSIST(persist))
1198
+ return msierror(ERROR_INVALID_PARAMETER);
1199
+ status = MsiOpenDatabaseW(path, (LPCWSTR)(SIZE_T)persist, &h);
1200
+ if (status != ERROR_SUCCESS)
1201
+ return msierror(status);
1202
+
1203
+ result = PyObject_New(struct msiobj, &msidb_Type);
1204
+ if (!result) {
1205
+ MsiCloseHandle(h);
1206
+ return NULL;
1207
+ }
1208
+ result->h = h;
1209
+ return (PyObject*)result;
1210
+ }
1211
+
1212
+ /*[clinic input]
1213
+ _msi.CreateRecord
1214
+ count: int
1215
+ the number of fields of the record
1216
+ /
1217
+
1218
+ Return a new record object.
1219
+ [clinic start generated code]*/
1220
+
1221
+ static PyObject *
1222
+ _msi_CreateRecord_impl(PyObject *module, int count)
1223
+ /*[clinic end generated code: output=0ba0a00beea3e99e input=53f17d5b5d9b077d]*/
1224
+ {
1225
+ MSIHANDLE h;
1226
+
1227
+ h = MsiCreateRecord(count);
1228
+ if (h == 0)
1229
+ return msierror(0);
1230
+
1231
+ return record_new(h);
1232
+ }
1233
+
1234
+
1235
+ static PyMethodDef msi_methods[] = {
1236
+ _MSI_UUIDCREATE_METHODDEF
1237
+ _MSI_FCICREATE_METHODDEF
1238
+ _MSI_OPENDATABASE_METHODDEF
1239
+ _MSI_CREATERECORD_METHODDEF
1240
+ {NULL, NULL} /* sentinel */
1241
+ };
1242
+
1243
+ static char msi_doc[] = "Documentation";
1244
+
1245
+
1246
+ static struct PyModuleDef _msimodule = {
1247
+ PyModuleDef_HEAD_INIT,
1248
+ "_msi",
1249
+ msi_doc,
1250
+ -1,
1251
+ msi_methods,
1252
+ NULL,
1253
+ NULL,
1254
+ NULL,
1255
+ NULL
1256
+ };
1257
+
1258
+ PyMODINIT_FUNC
1259
+ PyInit__msi(void)
1260
+ {
1261
+ PyObject *m;
1262
+
1263
+ m = PyModule_Create(&_msimodule);
1264
+ if (m == NULL)
1265
+ return NULL;
1266
+
1267
+ PyModule_AddIntConstant(m, "MSIDBOPEN_CREATEDIRECT", (long)(SIZE_T)MSIDBOPEN_CREATEDIRECT);
1268
+ PyModule_AddIntConstant(m, "MSIDBOPEN_CREATE", (long)(SIZE_T)MSIDBOPEN_CREATE);
1269
+ PyModule_AddIntConstant(m, "MSIDBOPEN_DIRECT", (long)(SIZE_T)MSIDBOPEN_DIRECT);
1270
+ PyModule_AddIntConstant(m, "MSIDBOPEN_READONLY", (long)(SIZE_T)MSIDBOPEN_READONLY);
1271
+ PyModule_AddIntConstant(m, "MSIDBOPEN_TRANSACT", (long)(SIZE_T)MSIDBOPEN_TRANSACT);
1272
+ PyModule_AddIntConstant(m, "MSIDBOPEN_PATCHFILE", (long)(SIZE_T)MSIDBOPEN_PATCHFILE);
1273
+
1274
+ PyModule_AddIntMacro(m, MSICOLINFO_NAMES);
1275
+ PyModule_AddIntMacro(m, MSICOLINFO_TYPES);
1276
+
1277
+ PyModule_AddIntMacro(m, MSIMODIFY_SEEK);
1278
+ PyModule_AddIntMacro(m, MSIMODIFY_REFRESH);
1279
+ PyModule_AddIntMacro(m, MSIMODIFY_INSERT);
1280
+ PyModule_AddIntMacro(m, MSIMODIFY_UPDATE);
1281
+ PyModule_AddIntMacro(m, MSIMODIFY_ASSIGN);
1282
+ PyModule_AddIntMacro(m, MSIMODIFY_REPLACE);
1283
+ PyModule_AddIntMacro(m, MSIMODIFY_MERGE);
1284
+ PyModule_AddIntMacro(m, MSIMODIFY_DELETE);
1285
+ PyModule_AddIntMacro(m, MSIMODIFY_INSERT_TEMPORARY);
1286
+ PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE);
1287
+ PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_NEW);
1288
+ PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_FIELD);
1289
+ PyModule_AddIntMacro(m, MSIMODIFY_VALIDATE_DELETE);
1290
+
1291
+ PyModule_AddIntMacro(m, PID_CODEPAGE);
1292
+ PyModule_AddIntMacro(m, PID_TITLE);
1293
+ PyModule_AddIntMacro(m, PID_SUBJECT);
1294
+ PyModule_AddIntMacro(m, PID_AUTHOR);
1295
+ PyModule_AddIntMacro(m, PID_KEYWORDS);
1296
+ PyModule_AddIntMacro(m, PID_COMMENTS);
1297
+ PyModule_AddIntMacro(m, PID_TEMPLATE);
1298
+ PyModule_AddIntMacro(m, PID_LASTAUTHOR);
1299
+ PyModule_AddIntMacro(m, PID_REVNUMBER);
1300
+ PyModule_AddIntMacro(m, PID_LASTPRINTED);
1301
+ PyModule_AddIntMacro(m, PID_CREATE_DTM);
1302
+ PyModule_AddIntMacro(m, PID_LASTSAVE_DTM);
1303
+ PyModule_AddIntMacro(m, PID_PAGECOUNT);
1304
+ PyModule_AddIntMacro(m, PID_WORDCOUNT);
1305
+ PyModule_AddIntMacro(m, PID_CHARCOUNT);
1306
+ PyModule_AddIntMacro(m, PID_APPNAME);
1307
+ PyModule_AddIntMacro(m, PID_SECURITY);
1308
+
1309
+ MSIError = PyErr_NewException ("_msi.MSIError", NULL, NULL);
1310
+ if (!MSIError)
1311
+ return NULL;
1312
+ PyModule_AddObject(m, "MSIError", MSIError);
1313
+ return m;
1314
+ }