symbian-qemu-0.9.1-12/python-2.6.1/PC/_msi.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 <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 
       
    15 static PyObject *MSIError;
       
    16 
       
    17 static PyObject*
       
    18 uuidcreate(PyObject* obj, PyObject*args)
       
    19 {
       
    20     UUID result;
       
    21     char *cresult;
       
    22     PyObject *oresult;
       
    23     
       
    24     /* 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) {
       
    29 	PyErr_SetString(PyExc_NotImplementedError, "processing 'no address' result");
       
    30 	return NULL;
       
    31     }
       
    32 
       
    33     if (UuidToString(&result, &cresult) == RPC_S_OUT_OF_MEMORY) {
       
    34 	PyErr_SetString(PyExc_MemoryError, "out of memory in uuidgen");
       
    35 	return NULL;
       
    36     }
       
    37 
       
    38     oresult = PyString_FromString(cresult);
       
    39     RpcStringFree(&cresult);
       
    40     return oresult;
       
    41 
       
    42 }
       
    43 
       
    44 /* FCI callback functions */
       
    45 
       
    46 static FNFCIALLOC(cb_alloc)
       
    47 {
       
    48     return malloc(cb);
       
    49 }
       
    50 
       
    51 static FNFCIFREE(cb_free)
       
    52 {
       
    53     free(memory);
       
    54 }
       
    55 
       
    56 static FNFCIOPEN(cb_open)
       
    57 {
       
    58     int result = _open(pszFile, oflag, pmode);
       
    59     if (result == -1)
       
    60 	*err = errno;
       
    61     return result;
       
    62 }
       
    63 
       
    64 static FNFCIREAD(cb_read)
       
    65 {
       
    66     UINT result = (UINT)_read(hf, memory, cb);
       
    67     if (result != cb)
       
    68 	*err = errno;
       
    69     return result;
       
    70 }
       
    71 
       
    72 static FNFCIWRITE(cb_write)
       
    73 {
       
    74     UINT result = (UINT)_write(hf, memory, cb);
       
    75     if (result != cb)
       
    76 	*err = errno;
       
    77     return result;
       
    78 }
       
    79 
       
    80 static FNFCICLOSE(cb_close)
       
    81 {
       
    82     int result = _close(hf);
       
    83     if (result != 0)
       
    84 	*err = errno;
       
    85     return result;
       
    86 }
       
    87 
       
    88 static FNFCISEEK(cb_seek)
       
    89 {
       
    90     long result = (long)_lseek(hf, dist, seektype);
       
    91     if (result == -1)
       
    92 	*err = errno;
       
    93     return result;
       
    94 }
       
    95 
       
    96 static FNFCIDELETE(cb_delete)
       
    97 {
       
    98     int result = remove(pszFile);
       
    99     if (result != 0)
       
   100 	*err = errno;
       
   101     return result;
       
   102 }
       
   103 
       
   104 static FNFCIFILEPLACED(cb_fileplaced)
       
   105 {
       
   106     return 0;
       
   107 }
       
   108 
       
   109 static FNFCIGETTEMPFILE(cb_gettempfile)
       
   110 {
       
   111     char *name = _tempnam("", "tmp");
       
   112     if ((name != NULL) && ((int)strlen(name) < cbTempName)) {
       
   113 	strcpy(pszTempName, name);
       
   114 	free(name);
       
   115 	return TRUE;
       
   116     }
       
   117 
       
   118     if (name) free(name);
       
   119     return FALSE;
       
   120 }
       
   121 
       
   122 static FNFCISTATUS(cb_status)
       
   123 {
       
   124     if (pv) {
       
   125 	PyObject *result = PyObject_CallMethod(pv, "status", "iii", typeStatus, cb1, cb2);
       
   126 	if (result == NULL)
       
   127 	    return -1;
       
   128 	Py_DECREF(result);
       
   129     }
       
   130     return 0;
       
   131 }
       
   132 
       
   133 static FNFCIGETNEXTCABINET(cb_getnextcabinet)
       
   134 {
       
   135     if (pv) {
       
   136 	PyObject *result = PyObject_CallMethod(pv, "getnextcabinet", "i", pccab->iCab);
       
   137 	if (result == NULL)
       
   138 	    return -1;
       
   139 	if (!PyString_Check(result)) {
       
   140 	    PyErr_Format(PyExc_TypeError, 
       
   141 		"Incorrect return type %s from getnextcabinet",
       
   142 		result->ob_type->tp_name);
       
   143 	    Py_DECREF(result);
       
   144 	    return FALSE;
       
   145 	}
       
   146 	strncpy(pccab->szCab, PyString_AsString(result), sizeof(pccab->szCab));
       
   147 	return TRUE;
       
   148     }
       
   149     return FALSE;
       
   150 }
       
   151 
       
   152 static FNFCIGETOPENINFO(cb_getopeninfo)
       
   153 {
       
   154     BY_HANDLE_FILE_INFORMATION bhfi;
       
   155     FILETIME filetime;
       
   156     HANDLE handle;
       
   157 
       
   158     /* Need Win32 handle to get time stamps */
       
   159     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
       
   160 	OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
       
   161     if (handle == INVALID_HANDLE_VALUE)
       
   162 	return -1;
       
   163 
       
   164     if (GetFileInformationByHandle(handle, &bhfi) == FALSE)
       
   165     {
       
   166 	CloseHandle(handle);
       
   167 	return -1;
       
   168     }
       
   169 
       
   170     FileTimeToLocalFileTime(&bhfi.ftLastWriteTime, &filetime);
       
   171     FileTimeToDosDateTime(&filetime, pdate, ptime);
       
   172 
       
   173     *pattribs = (int)(bhfi.dwFileAttributes & 
       
   174 	(_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH));
       
   175 
       
   176     CloseHandle(handle);
       
   177 
       
   178     return _open(pszName, _O_RDONLY | _O_BINARY);
       
   179 }
       
   180 
       
   181 static PyObject* fcicreate(PyObject* obj, PyObject* args)
       
   182 {
       
   183     char *cabname, *p;
       
   184     PyObject *files;
       
   185     CCAB ccab;
       
   186     HFCI hfci;
       
   187     ERF erf;
       
   188     Py_ssize_t i;
       
   189 
       
   190 
       
   191     if (!PyArg_ParseTuple(args, "sO:FCICreate", &cabname, &files))
       
   192 	return NULL;
       
   193 
       
   194     if (!PyList_Check(files)) {
       
   195 	PyErr_SetString(PyExc_TypeError, "FCICreate expects a list");
       
   196 	return NULL;
       
   197     }
       
   198 
       
   199     ccab.cb = INT_MAX; /* no need to split CAB into multiple media */
       
   200     ccab.cbFolderThresh = 1000000; /* flush directory after this many bytes */
       
   201     ccab.cbReserveCFData = 0;
       
   202     ccab.cbReserveCFFolder = 0;
       
   203     ccab.cbReserveCFHeader = 0;
       
   204 
       
   205     ccab.iCab = 1;
       
   206     ccab.iDisk = 1;
       
   207 
       
   208     ccab.setID = 0;
       
   209     ccab.szDisk[0] = '\0';
       
   210 
       
   211     for (i = 0, p = cabname; *p; p = CharNext(p))
       
   212 	if (*p == '\\' || *p == '/')
       
   213 	    i = p - cabname + 1;
       
   214 
       
   215     if (i >= sizeof(ccab.szCabPath) ||
       
   216 	strlen(cabname+i) >= sizeof(ccab.szCab)) {
       
   217 	PyErr_SetString(PyExc_ValueError, "path name too long");
       
   218 	return 0;
       
   219     }
       
   220 
       
   221     if (i > 0) {
       
   222 	memcpy(ccab.szCabPath, cabname, i);
       
   223 	ccab.szCabPath[i] = '\0';
       
   224 	strcpy(ccab.szCab, cabname+i);
       
   225     } else {
       
   226 	strcpy(ccab.szCabPath, ".\\");
       
   227 	strcpy(ccab.szCab, cabname);
       
   228     }
       
   229 
       
   230     hfci = FCICreate(&erf, cb_fileplaced, cb_alloc, cb_free,
       
   231 	cb_open, cb_read, cb_write, cb_close, cb_seek, cb_delete,
       
   232 	cb_gettempfile, &ccab, NULL);
       
   233 
       
   234     if (hfci == NULL) {
       
   235 	PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper);
       
   236 	return NULL;
       
   237     }
       
   238 
       
   239     for (i=0; i < PyList_GET_SIZE(files); i++) {
       
   240 	PyObject *item = PyList_GET_ITEM(files, i);
       
   241 	char *filename, *cabname;
       
   242 	if (!PyArg_ParseTuple(item, "ss", &filename, &cabname))
       
   243 	    goto err;
       
   244 	if (!FCIAddFile(hfci, filename, cabname, FALSE, 
       
   245 	    cb_getnextcabinet, cb_status, cb_getopeninfo,
       
   246 	    tcompTYPE_MSZIP))
       
   247 	    goto err;
       
   248     }
       
   249 
       
   250     if (!FCIFlushCabinet(hfci, FALSE, cb_getnextcabinet, cb_status))
       
   251 	goto err;
       
   252 
       
   253     if (!FCIDestroy(hfci))
       
   254 	goto err;
       
   255 
       
   256     Py_INCREF(Py_None);
       
   257     return Py_None;
       
   258 err:
       
   259     PyErr_Format(PyExc_ValueError, "FCI error %d", erf.erfOper); /* XXX better error type */
       
   260     FCIDestroy(hfci);
       
   261     return NULL;
       
   262 }
       
   263 
       
   264 typedef struct msiobj{
       
   265     PyObject_HEAD
       
   266     MSIHANDLE h;
       
   267 }msiobj;
       
   268 
       
   269 static void 
       
   270 msiobj_dealloc(msiobj* msidb)
       
   271 {
       
   272     MsiCloseHandle(msidb->h);
       
   273     msidb->h = 0;
       
   274 }
       
   275 
       
   276 static PyObject*
       
   277 msiobj_close(msiobj* msidb, PyObject *args)
       
   278 {
       
   279     MsiCloseHandle(msidb->h);
       
   280     msidb->h = 0;
       
   281     Py_INCREF(Py_None);
       
   282     return Py_None;
       
   283 }
       
   284 
       
   285 static PyObject*
       
   286 msierror(int status)
       
   287 {
       
   288     int code;
       
   289     char buf[2000];
       
   290     char *res = buf;
       
   291     DWORD size = sizeof(buf);
       
   292     MSIHANDLE err = MsiGetLastErrorRecord();
       
   293 
       
   294     if (err == 0) {
       
   295 	switch(status) {
       
   296 	case ERROR_ACCESS_DENIED:
       
   297 	    PyErr_SetString(MSIError, "access denied");
       
   298 	    return NULL;
       
   299 	case ERROR_FUNCTION_FAILED:
       
   300 	    PyErr_SetString(MSIError, "function failed");
       
   301 	    return NULL;
       
   302 	case ERROR_INVALID_DATA:
       
   303 	    PyErr_SetString(MSIError, "invalid data");
       
   304 	    return NULL;
       
   305 	case ERROR_INVALID_HANDLE:
       
   306 	    PyErr_SetString(MSIError, "invalid handle");
       
   307 	    return NULL;
       
   308 	case ERROR_INVALID_STATE:
       
   309 	    PyErr_SetString(MSIError, "invalid state");
       
   310 	    return NULL;
       
   311 	case ERROR_INVALID_PARAMETER:
       
   312 	    PyErr_SetString(MSIError, "invalid parameter");
       
   313 	    return NULL;
       
   314 	default:
       
   315 	    PyErr_Format(MSIError, "unknown error %x", status);
       
   316 	    return NULL;
       
   317 	}
       
   318     }
       
   319 
       
   320     code = MsiRecordGetInteger(err, 1); /* XXX code */
       
   321     if (MsiFormatRecord(0, err, res, &size) == ERROR_MORE_DATA) {
       
   322 	res = malloc(size+1);
       
   323 	MsiFormatRecord(0, err, res, &size);
       
   324 	res[size]='\0';
       
   325     }
       
   326     MsiCloseHandle(err);
       
   327     PyErr_SetString(MSIError, res);
       
   328     if (res != buf)
       
   329 	free(res);
       
   330     return NULL;
       
   331 }
       
   332 
       
   333 /*************************** Record objects **********************/
       
   334 
       
   335 static PyObject*
       
   336 record_getfieldcount(msiobj* record, PyObject* args)
       
   337 {
       
   338     return PyInt_FromLong(MsiRecordGetFieldCount(record->h));
       
   339 }
       
   340 
       
   341 static PyObject*
       
   342 record_getinteger(msiobj* record, PyObject* args)
       
   343 {
       
   344     unsigned int field;
       
   345     int status;
       
   346     
       
   347     if (!PyArg_ParseTuple(args, "I:GetInteger", &field))
       
   348         return NULL;
       
   349     status = MsiRecordGetInteger(record->h, field);
       
   350     if (status == MSI_NULL_INTEGER){
       
   351         PyErr_SetString(MSIError, "could not convert record field to integer");
       
   352         return NULL;
       
   353     }
       
   354     return PyInt_FromLong((long) status);
       
   355 }
       
   356 
       
   357 static PyObject*
       
   358 record_getstring(msiobj* record, PyObject* args)
       
   359 {
       
   360     unsigned int field;
       
   361     unsigned int status;
       
   362     char buf[2000];
       
   363     char *res = buf;
       
   364     DWORD size = sizeof(buf);
       
   365     PyObject* string;
       
   366     
       
   367     if (!PyArg_ParseTuple(args, "I:GetString", &field))
       
   368         return NULL;
       
   369     status = MsiRecordGetString(record->h, field, res, &size);
       
   370     if (status == ERROR_MORE_DATA) {
       
   371         res = (char*) malloc(size + 1);
       
   372         if (res == NULL)
       
   373             return PyErr_NoMemory();
       
   374         status = MsiRecordGetString(record->h, field, res, &size);
       
   375     }
       
   376     if (status != ERROR_SUCCESS)
       
   377         return msierror((int) status);
       
   378     string = PyString_FromString(res);
       
   379     if (buf != res)
       
   380         free(res);
       
   381     return string;
       
   382 }
       
   383 
       
   384 static PyObject*
       
   385 record_cleardata(msiobj* record, PyObject *args)
       
   386 {
       
   387     int status = MsiRecordClearData(record->h);
       
   388     if (status != ERROR_SUCCESS)
       
   389 	return msierror(status);
       
   390 
       
   391     Py_INCREF(Py_None);
       
   392     return Py_None;
       
   393 }
       
   394 
       
   395 static PyObject*
       
   396 record_setstring(msiobj* record, PyObject *args)
       
   397 {
       
   398     int status;
       
   399     int field;
       
   400     char *data;
       
   401 
       
   402     if (!PyArg_ParseTuple(args, "is:SetString", &field, &data))
       
   403 	return NULL;
       
   404 
       
   405     if ((status = MsiRecordSetString(record->h, field, data)) != ERROR_SUCCESS)
       
   406 	return msierror(status);
       
   407 
       
   408     Py_INCREF(Py_None);
       
   409     return Py_None;
       
   410 }
       
   411 
       
   412 static PyObject*
       
   413 record_setstream(msiobj* record, PyObject *args)
       
   414 {
       
   415     int status;
       
   416     int field;
       
   417     char *data;
       
   418 
       
   419     if (!PyArg_ParseTuple(args, "is:SetStream", &field, &data))
       
   420 	return NULL;
       
   421 
       
   422     if ((status = MsiRecordSetStream(record->h, field, data)) != ERROR_SUCCESS)
       
   423 	return msierror(status);
       
   424 
       
   425     Py_INCREF(Py_None);
       
   426     return Py_None;
       
   427 }
       
   428 
       
   429 static PyObject*
       
   430 record_setinteger(msiobj* record, PyObject *args)
       
   431 {
       
   432     int status;
       
   433     int field;
       
   434     int data;
       
   435 
       
   436     if (!PyArg_ParseTuple(args, "ii:SetInteger", &field, &data))
       
   437 	return NULL;
       
   438 
       
   439     if ((status = MsiRecordSetInteger(record->h, field, data)) != ERROR_SUCCESS)
       
   440 	return msierror(status);
       
   441 
       
   442     Py_INCREF(Py_None);
       
   443     return Py_None;
       
   444 }
       
   445 
       
   446 
       
   447 
       
   448 static PyMethodDef record_methods[] = {
       
   449     { "GetFieldCount", (PyCFunction)record_getfieldcount, METH_NOARGS, 
       
   450 	PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")},
       
   451     { "GetInteger", (PyCFunction)record_getinteger, METH_VARARGS,
       
   452     PyDoc_STR("GetInteger(field) -> int\nWraps MsiRecordGetInteger")},
       
   453     { "GetString", (PyCFunction)record_getstring, METH_VARARGS,
       
   454     PyDoc_STR("GetString(field) -> string\nWraps MsiRecordGetString")},
       
   455     { "SetString", (PyCFunction)record_setstring, METH_VARARGS, 
       
   456 	PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")},
       
   457     { "SetStream", (PyCFunction)record_setstream, METH_VARARGS, 
       
   458 	PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")},
       
   459     { "SetInteger", (PyCFunction)record_setinteger, METH_VARARGS, 
       
   460 	PyDoc_STR("SetInteger(field,int) -> None\nWraps MsiRecordSetInteger")},
       
   461     { "ClearData", (PyCFunction)record_cleardata, METH_NOARGS, 
       
   462 	PyDoc_STR("ClearData() -> int\nWraps MsiRecordGClearData")},
       
   463     { NULL, NULL }
       
   464 };
       
   465 
       
   466 static PyTypeObject record_Type = {
       
   467 	PyVarObject_HEAD_INIT(NULL, 0)
       
   468 	"_msi.Record",		/*tp_name*/
       
   469 	sizeof(msiobj),	/*tp_basicsize*/
       
   470 	0,			/*tp_itemsize*/
       
   471 	/* methods */
       
   472 	(destructor)msiobj_dealloc, /*tp_dealloc*/
       
   473 	0,			/*tp_print*/
       
   474 	0,			/*tp_getattr*/
       
   475 	0,			/*tp_setattr*/
       
   476 	0,			/*tp_compare*/
       
   477 	0,			/*tp_repr*/
       
   478 	0,			/*tp_as_number*/
       
   479 	0,			/*tp_as_sequence*/
       
   480 	0,			/*tp_as_mapping*/
       
   481 	0,			/*tp_hash*/
       
   482         0,                      /*tp_call*/
       
   483         0,                      /*tp_str*/
       
   484         PyObject_GenericGetAttr,/*tp_getattro*/
       
   485         PyObject_GenericSetAttr,/*tp_setattro*/
       
   486         0,                      /*tp_as_buffer*/
       
   487         Py_TPFLAGS_DEFAULT,     /*tp_flags*/
       
   488         0,                      /*tp_doc*/
       
   489         0,                      /*tp_traverse*/
       
   490         0,                      /*tp_clear*/
       
   491         0,                      /*tp_richcompare*/
       
   492         0,                      /*tp_weaklistoffset*/
       
   493         0,                      /*tp_iter*/
       
   494         0,                      /*tp_iternext*/
       
   495         record_methods,           /*tp_methods*/
       
   496         0,                      /*tp_members*/
       
   497         0,                      /*tp_getset*/
       
   498         0,                      /*tp_base*/
       
   499         0,                      /*tp_dict*/
       
   500         0,                      /*tp_descr_get*/
       
   501         0,                      /*tp_descr_set*/
       
   502         0,                      /*tp_dictoffset*/
       
   503         0,                      /*tp_init*/
       
   504         0,                      /*tp_alloc*/
       
   505         0,                      /*tp_new*/
       
   506         0,                      /*tp_free*/
       
   507         0,                      /*tp_is_gc*/
       
   508 };
       
   509 
       
   510 static PyObject*
       
   511 record_new(MSIHANDLE h)
       
   512 {
       
   513     msiobj *result = PyObject_NEW(struct msiobj, &record_Type);
       
   514 
       
   515     if (!result) {
       
   516 	MsiCloseHandle(h);
       
   517 	return NULL;
       
   518     }
       
   519 
       
   520     result->h = h;
       
   521     return (PyObject*)result;
       
   522 }
       
   523 
       
   524 /*************************** SummaryInformation objects **************/
       
   525 
       
   526 static PyObject*
       
   527 summary_getproperty(msiobj* si, PyObject *args)
       
   528 {
       
   529     int status;
       
   530     int field;
       
   531     PyObject *result;
       
   532     UINT type;
       
   533     INT ival;
       
   534     FILETIME fval;
       
   535     char sbuf[1000];
       
   536     char *sval = sbuf;
       
   537     DWORD ssize = sizeof(sval);
       
   538 
       
   539     if (!PyArg_ParseTuple(args, "i:GetProperty", &field))
       
   540 	return NULL;
       
   541 
       
   542     status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival, 
       
   543 	&fval, sval, &ssize);
       
   544     if (status == ERROR_MORE_DATA) {
       
   545 	sval = malloc(ssize);
       
   546         status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival, 
       
   547     	    &fval, sval, &ssize);
       
   548     }
       
   549 
       
   550     switch(type) {
       
   551 	case VT_I2: case VT_I4:
       
   552 	    return PyInt_FromLong(ival);
       
   553 	case VT_FILETIME:
       
   554 	    PyErr_SetString(PyExc_NotImplementedError, "FILETIME result");
       
   555 	    return NULL;
       
   556 	case VT_LPSTR:
       
   557 	    result = PyString_FromStringAndSize(sval, ssize);
       
   558 	    if (sval != sbuf)
       
   559 		free(sval);
       
   560 	    return result;
       
   561     }
       
   562     PyErr_Format(PyExc_NotImplementedError, "result of type %d", type);
       
   563     return NULL;
       
   564 }
       
   565 
       
   566 static PyObject*
       
   567 summary_getpropertycount(msiobj* si, PyObject *args)
       
   568 {
       
   569     int status;
       
   570     UINT result;
       
   571 
       
   572     status = MsiSummaryInfoGetPropertyCount(si->h, &result);
       
   573     if (status != ERROR_SUCCESS)
       
   574 	return msierror(status);
       
   575 
       
   576     return PyInt_FromLong(result);
       
   577 }
       
   578 
       
   579 static PyObject*
       
   580 summary_setproperty(msiobj* si, PyObject *args)
       
   581 {
       
   582     int status;
       
   583     int field;
       
   584     PyObject* data;
       
   585 
       
   586     if (!PyArg_ParseTuple(args, "iO:SetProperty", &field, &data))
       
   587 	return NULL;
       
   588 
       
   589     if (PyString_Check(data)) {
       
   590 	status = MsiSummaryInfoSetProperty(si->h, field, VT_LPSTR,
       
   591 	    0, NULL, PyString_AsString(data));
       
   592     } else if (PyInt_Check(data)) {
       
   593 	status = MsiSummaryInfoSetProperty(si->h, field, VT_I4,
       
   594 	    PyInt_AsLong(data), NULL, NULL);
       
   595     } else {
       
   596 	PyErr_SetString(PyExc_TypeError, "unsupported type");
       
   597 	return NULL;
       
   598     }
       
   599     
       
   600     if (status != ERROR_SUCCESS)
       
   601 	return msierror(status);
       
   602 
       
   603     Py_INCREF(Py_None);
       
   604     return Py_None;
       
   605 }
       
   606 
       
   607 
       
   608 static PyObject*
       
   609 summary_persist(msiobj* si, PyObject *args)
       
   610 {
       
   611     int status;
       
   612 
       
   613     status = MsiSummaryInfoPersist(si->h);
       
   614     if (status != ERROR_SUCCESS)
       
   615 	return msierror(status);
       
   616     Py_INCREF(Py_None);
       
   617     return Py_None;
       
   618 }
       
   619 
       
   620 static PyMethodDef summary_methods[] = {
       
   621     { "GetProperty", (PyCFunction)summary_getproperty, METH_VARARGS, 
       
   622 	PyDoc_STR("GetProperty(propid) -> value\nWraps MsiSummaryInfoGetProperty")},
       
   623     { "GetPropertyCount", (PyCFunction)summary_getpropertycount, METH_NOARGS, 
       
   624 	PyDoc_STR("GetProperty() -> int\nWraps MsiSummaryInfoGetPropertyCount")},
       
   625     { "SetProperty", (PyCFunction)summary_setproperty, METH_VARARGS, 
       
   626 	PyDoc_STR("SetProperty(value) -> None\nWraps MsiSummaryInfoProperty")},
       
   627     { "Persist", (PyCFunction)summary_persist, METH_NOARGS, 
       
   628 	PyDoc_STR("Persist() -> None\nWraps MsiSummaryInfoPersist")},
       
   629     { NULL, NULL }
       
   630 };
       
   631 
       
   632 static PyTypeObject summary_Type = {
       
   633 	PyVarObject_HEAD_INIT(NULL, 0)
       
   634 	"_msi.SummaryInformation",		/*tp_name*/
       
   635 	sizeof(msiobj),	/*tp_basicsize*/
       
   636 	0,			/*tp_itemsize*/
       
   637 	/* methods */
       
   638 	(destructor)msiobj_dealloc, /*tp_dealloc*/
       
   639 	0,			/*tp_print*/
       
   640 	0,			/*tp_getattr*/
       
   641 	0,			/*tp_setattr*/
       
   642 	0,			/*tp_compare*/
       
   643 	0,			/*tp_repr*/
       
   644 	0,			/*tp_as_number*/
       
   645 	0,			/*tp_as_sequence*/
       
   646 	0,			/*tp_as_mapping*/
       
   647 	0,			/*tp_hash*/
       
   648         0,                      /*tp_call*/
       
   649         0,                      /*tp_str*/
       
   650         PyObject_GenericGetAttr,/*tp_getattro*/
       
   651         PyObject_GenericSetAttr,/*tp_setattro*/
       
   652         0,                      /*tp_as_buffer*/
       
   653         Py_TPFLAGS_DEFAULT,     /*tp_flags*/
       
   654         0,                      /*tp_doc*/
       
   655         0,                      /*tp_traverse*/
       
   656         0,                      /*tp_clear*/
       
   657         0,                      /*tp_richcompare*/
       
   658         0,                      /*tp_weaklistoffset*/
       
   659         0,                      /*tp_iter*/
       
   660         0,                      /*tp_iternext*/
       
   661         summary_methods,        /*tp_methods*/
       
   662         0,                      /*tp_members*/
       
   663         0,                      /*tp_getset*/
       
   664         0,                      /*tp_base*/
       
   665         0,                      /*tp_dict*/
       
   666         0,                      /*tp_descr_get*/
       
   667         0,                      /*tp_descr_set*/
       
   668         0,                      /*tp_dictoffset*/
       
   669         0,                      /*tp_init*/
       
   670         0,                      /*tp_alloc*/
       
   671         0,                      /*tp_new*/
       
   672         0,                      /*tp_free*/
       
   673         0,                      /*tp_is_gc*/
       
   674 };
       
   675 
       
   676 /*************************** View objects **************/
       
   677 
       
   678 static PyObject*
       
   679 view_execute(msiobj *view, PyObject*args)
       
   680 {
       
   681     int status;
       
   682     MSIHANDLE params = 0;
       
   683     PyObject *oparams = Py_None;
       
   684 
       
   685     if (!PyArg_ParseTuple(args, "O:Execute", &oparams))
       
   686 	return NULL;
       
   687 
       
   688     if (oparams != Py_None) {
       
   689         if (oparams->ob_type != &record_Type) {
       
   690             PyErr_SetString(PyExc_TypeError, "Execute argument must be a record");
       
   691             return NULL;
       
   692         }
       
   693         params = ((msiobj*)oparams)->h;
       
   694     }
       
   695 
       
   696     status = MsiViewExecute(view->h, params);
       
   697     if (status != ERROR_SUCCESS)
       
   698 	return msierror(status);
       
   699 
       
   700     Py_INCREF(Py_None);
       
   701     return Py_None;
       
   702 }
       
   703 
       
   704 static PyObject*
       
   705 view_fetch(msiobj *view, PyObject*args)
       
   706 {
       
   707     int status;
       
   708     MSIHANDLE result;
       
   709 
       
   710     if ((status = MsiViewFetch(view->h, &result)) != ERROR_SUCCESS)
       
   711 	return msierror(status);
       
   712 
       
   713     return record_new(result);
       
   714 }
       
   715 
       
   716 static PyObject*
       
   717 view_getcolumninfo(msiobj *view, PyObject *args)
       
   718 {
       
   719     int status;
       
   720     int kind;
       
   721     MSIHANDLE result;
       
   722 
       
   723     if (!PyArg_ParseTuple(args, "i:GetColumnInfo", &kind))
       
   724 	return NULL;
       
   725 
       
   726     if ((status = MsiViewGetColumnInfo(view->h, kind, &result)) != ERROR_SUCCESS)
       
   727 	return msierror(status);
       
   728 
       
   729     return record_new(result);
       
   730 }
       
   731 
       
   732 static PyObject*
       
   733 view_modify(msiobj *view, PyObject *args)
       
   734 {
       
   735     int kind;
       
   736     PyObject *data;
       
   737     int status;
       
   738 
       
   739     if (!PyArg_ParseTuple(args, "iO:Modify", &kind, &data))
       
   740 	return NULL;
       
   741 
       
   742     if (data->ob_type != &record_Type) {
       
   743 	PyErr_SetString(PyExc_TypeError, "Modify expects a record object");
       
   744 	return NULL;
       
   745     }
       
   746 
       
   747     if ((status = MsiViewModify(view->h, kind, ((msiobj*)data)->h)) != ERROR_SUCCESS)
       
   748 	return msierror(status);
       
   749 
       
   750     Py_INCREF(Py_None);
       
   751     return Py_None;
       
   752 }
       
   753 
       
   754 static PyObject*
       
   755 view_close(msiobj *view, PyObject*args)
       
   756 {
       
   757     int status;
       
   758 
       
   759     if ((status = MsiViewClose(view->h)) != ERROR_SUCCESS)
       
   760 	return msierror(status);
       
   761 
       
   762     Py_INCREF(Py_None);
       
   763     return Py_None;
       
   764 }
       
   765 
       
   766 static PyMethodDef view_methods[] = {
       
   767     { "Execute", (PyCFunction)view_execute, METH_VARARGS, 
       
   768 	PyDoc_STR("Execute(params=None) -> None\nWraps MsiViewExecute")},
       
   769     { "GetColumnInfo", (PyCFunction)view_getcolumninfo, METH_VARARGS,
       
   770 	PyDoc_STR("GetColumnInfo() -> result\nWraps MsiGetColumnInfo")},
       
   771     { "Fetch", (PyCFunction)view_fetch, METH_NOARGS,
       
   772 	PyDoc_STR("Fetch() -> result\nWraps MsiViewFetch")},
       
   773     { "Modify", (PyCFunction)view_modify, METH_VARARGS,
       
   774 	PyDoc_STR("Modify(mode,record) -> None\nWraps MsiViewModify")},
       
   775     { "Close", (PyCFunction)view_close, METH_NOARGS,
       
   776 	PyDoc_STR("Close() -> result\nWraps MsiViewClose")},
       
   777     { NULL, NULL }
       
   778 };
       
   779 
       
   780 static PyTypeObject msiview_Type = {
       
   781 	PyVarObject_HEAD_INIT(NULL, 0)
       
   782 	"_msi.View",		/*tp_name*/
       
   783 	sizeof(msiobj),	/*tp_basicsize*/
       
   784 	0,			/*tp_itemsize*/
       
   785 	/* methods */
       
   786 	(destructor)msiobj_dealloc, /*tp_dealloc*/
       
   787 	0,			/*tp_print*/
       
   788 	0,			/*tp_getattr*/
       
   789 	0,			/*tp_setattr*/
       
   790 	0,			/*tp_compare*/
       
   791 	0,			/*tp_repr*/
       
   792 	0,			/*tp_as_number*/
       
   793 	0,			/*tp_as_sequence*/
       
   794 	0,			/*tp_as_mapping*/
       
   795 	0,			/*tp_hash*/
       
   796         0,                      /*tp_call*/
       
   797         0,                      /*tp_str*/
       
   798         PyObject_GenericGetAttr,/*tp_getattro*/
       
   799         PyObject_GenericSetAttr,/*tp_setattro*/
       
   800         0,                      /*tp_as_buffer*/
       
   801         Py_TPFLAGS_DEFAULT,     /*tp_flags*/
       
   802         0,                      /*tp_doc*/
       
   803         0,                      /*tp_traverse*/
       
   804         0,                      /*tp_clear*/
       
   805         0,                      /*tp_richcompare*/
       
   806         0,                      /*tp_weaklistoffset*/
       
   807         0,                      /*tp_iter*/
       
   808         0,                      /*tp_iternext*/
       
   809         view_methods,           /*tp_methods*/
       
   810         0,                      /*tp_members*/
       
   811         0,                      /*tp_getset*/
       
   812         0,                      /*tp_base*/
       
   813         0,                      /*tp_dict*/
       
   814         0,                      /*tp_descr_get*/
       
   815         0,                      /*tp_descr_set*/
       
   816         0,                      /*tp_dictoffset*/
       
   817         0,                      /*tp_init*/
       
   818         0,                      /*tp_alloc*/
       
   819         0,                      /*tp_new*/
       
   820         0,                      /*tp_free*/
       
   821         0,                      /*tp_is_gc*/
       
   822 };
       
   823 
       
   824 /*************************** Database objects **************/
       
   825 
       
   826 static PyObject*
       
   827 msidb_openview(msiobj *msidb, PyObject *args)
       
   828 {
       
   829     int status;
       
   830     char *sql;
       
   831     MSIHANDLE hView;
       
   832     msiobj *result;
       
   833 
       
   834     if (!PyArg_ParseTuple(args, "s:OpenView", &sql))
       
   835 	return NULL;
       
   836 
       
   837     if ((status = MsiDatabaseOpenView(msidb->h, sql, &hView)) != ERROR_SUCCESS)
       
   838 	return msierror(status);
       
   839 
       
   840     result = PyObject_NEW(struct msiobj, &msiview_Type);
       
   841     if (!result) {
       
   842 	MsiCloseHandle(hView);
       
   843 	return NULL;
       
   844     }
       
   845 
       
   846     result->h = hView;
       
   847     return (PyObject*)result;
       
   848 }
       
   849 
       
   850 static PyObject*
       
   851 msidb_commit(msiobj *msidb, PyObject *args)
       
   852 {
       
   853     int status;
       
   854 
       
   855     if ((status = MsiDatabaseCommit(msidb->h)) != ERROR_SUCCESS)
       
   856 	return msierror(status);
       
   857 
       
   858     Py_INCREF(Py_None);
       
   859     return Py_None;
       
   860 }
       
   861 
       
   862 static PyObject*
       
   863 msidb_getsummaryinformation(msiobj *db, PyObject *args)
       
   864 {
       
   865     int status;
       
   866     int count;
       
   867     MSIHANDLE result;
       
   868     msiobj *oresult;
       
   869 
       
   870     if (!PyArg_ParseTuple(args, "i:GetSummaryInformation", &count))
       
   871 	return NULL;
       
   872 
       
   873     status = MsiGetSummaryInformation(db->h, NULL, count, &result);
       
   874     if (status != ERROR_SUCCESS)
       
   875 	return msierror(status);
       
   876 
       
   877     oresult = PyObject_NEW(struct msiobj, &summary_Type);
       
   878     if (!result) {
       
   879 	MsiCloseHandle(result);
       
   880 	return NULL;
       
   881     }
       
   882 
       
   883     oresult->h = result;
       
   884     return (PyObject*)oresult;
       
   885 }
       
   886 
       
   887 static PyMethodDef db_methods[] = {
       
   888     { "OpenView", (PyCFunction)msidb_openview, METH_VARARGS, 
       
   889 	PyDoc_STR("OpenView(sql) -> viewobj\nWraps MsiDatabaseOpenView")},
       
   890     { "Commit", (PyCFunction)msidb_commit, METH_NOARGS,
       
   891 	PyDoc_STR("Commit() -> None\nWraps MsiDatabaseCommit")},
       
   892     { "GetSummaryInformation", (PyCFunction)msidb_getsummaryinformation, METH_VARARGS, 
       
   893 	PyDoc_STR("GetSummaryInformation(updateCount) -> viewobj\nWraps MsiGetSummaryInformation")},
       
   894     { NULL, NULL }
       
   895 };
       
   896 
       
   897 static PyTypeObject msidb_Type = {
       
   898 	PyVarObject_HEAD_INIT(NULL, 0)
       
   899 	"_msi.Database",		/*tp_name*/
       
   900 	sizeof(msiobj),	/*tp_basicsize*/
       
   901 	0,			/*tp_itemsize*/
       
   902 	/* methods */
       
   903 	(destructor)msiobj_dealloc, /*tp_dealloc*/
       
   904 	0,			/*tp_print*/
       
   905 	0,			/*tp_getattr*/
       
   906 	0,			/*tp_setattr*/
       
   907 	0,			/*tp_compare*/
       
   908 	0,			/*tp_repr*/
       
   909 	0,			/*tp_as_number*/
       
   910 	0,			/*tp_as_sequence*/
       
   911 	0,			/*tp_as_mapping*/
       
   912 	0,			/*tp_hash*/
       
   913         0,                      /*tp_call*/
       
   914         0,                      /*tp_str*/
       
   915         PyObject_GenericGetAttr,/*tp_getattro*/
       
   916         PyObject_GenericSetAttr,/*tp_setattro*/
       
   917         0,                      /*tp_as_buffer*/
       
   918         Py_TPFLAGS_DEFAULT,     /*tp_flags*/
       
   919         0,                      /*tp_doc*/
       
   920         0,                      /*tp_traverse*/
       
   921         0,                      /*tp_clear*/
       
   922         0,                      /*tp_richcompare*/
       
   923         0,                      /*tp_weaklistoffset*/
       
   924         0,                      /*tp_iter*/
       
   925         0,                      /*tp_iternext*/
       
   926         db_methods,             /*tp_methods*/
       
   927         0,                      /*tp_members*/
       
   928         0,                      /*tp_getset*/
       
   929         0,                      /*tp_base*/
       
   930         0,                      /*tp_dict*/
       
   931         0,                      /*tp_descr_get*/
       
   932         0,                      /*tp_descr_set*/
       
   933         0,                      /*tp_dictoffset*/
       
   934         0,                      /*tp_init*/
       
   935         0,                      /*tp_alloc*/
       
   936         0,                      /*tp_new*/
       
   937         0,                      /*tp_free*/
       
   938         0,                      /*tp_is_gc*/
       
   939 };
       
   940 
       
   941 static PyObject* msiopendb(PyObject *obj, PyObject *args)
       
   942 {
       
   943     int status;
       
   944     char *path;
       
   945     int persist;
       
   946     MSIHANDLE h;
       
   947     msiobj *result;
       
   948     
       
   949     if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist))
       
   950 	return NULL;
       
   951 
       
   952 	status = MsiOpenDatabase(path, (LPCSTR)persist, &h);
       
   953     if (status != ERROR_SUCCESS)
       
   954 	return msierror(status);
       
   955 
       
   956     result = PyObject_NEW(struct msiobj, &msidb_Type);
       
   957     if (!result) {
       
   958 	MsiCloseHandle(h);
       
   959 	return NULL;
       
   960     }
       
   961     result->h = h;
       
   962     return (PyObject*)result;
       
   963 }
       
   964 
       
   965 static PyObject*
       
   966 createrecord(PyObject *o, PyObject *args)
       
   967 {
       
   968     int count;
       
   969     MSIHANDLE h;
       
   970 
       
   971     if (!PyArg_ParseTuple(args, "i:CreateRecord", &count))
       
   972 	return NULL;
       
   973     
       
   974     h = MsiCreateRecord(count);
       
   975     if (h == 0)
       
   976 	return msierror(0);
       
   977 
       
   978     return record_new(h);
       
   979 }
       
   980 
       
   981 
       
   982 static PyMethodDef msi_methods[] = {
       
   983         {"UuidCreate", (PyCFunction)uuidcreate, METH_NOARGS,
       
   984 		PyDoc_STR("UuidCreate() -> string")},
       
   985 	{"FCICreate",	(PyCFunction)fcicreate,	METH_VARARGS,
       
   986 		PyDoc_STR("fcicreate(cabname,files) -> None")},
       
   987 	{"OpenDatabase", (PyCFunction)msiopendb, METH_VARARGS,
       
   988 	PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiOpenDatabase")},
       
   989 	{"CreateRecord", (PyCFunction)createrecord, METH_VARARGS,
       
   990 	PyDoc_STR("OpenDatabase(name, flags) -> dbobj\nWraps MsiCreateRecord")},
       
   991 	{NULL,		NULL}		/* sentinel */
       
   992 };
       
   993 
       
   994 static char msi_doc[] = "Documentation";
       
   995 
       
   996 PyMODINIT_FUNC
       
   997 init_msi(void)
       
   998 {
       
   999     PyObject *m;
       
  1000 
       
  1001     m = Py_InitModule3("_msi", msi_methods, msi_doc);
       
  1002     if (m == NULL)
       
  1003 	return;
       
  1004 
       
  1005     PyModule_AddIntConstant(m, "MSIDBOPEN_CREATEDIRECT", (int)MSIDBOPEN_CREATEDIRECT);
       
  1006     PyModule_AddIntConstant(m, "MSIDBOPEN_CREATE", (int)MSIDBOPEN_CREATE);
       
  1007     PyModule_AddIntConstant(m, "MSIDBOPEN_DIRECT", (int)MSIDBOPEN_DIRECT);
       
  1008     PyModule_AddIntConstant(m, "MSIDBOPEN_READONLY", (int)MSIDBOPEN_READONLY);
       
  1009     PyModule_AddIntConstant(m, "MSIDBOPEN_TRANSACT", (int)MSIDBOPEN_TRANSACT);
       
  1010     PyModule_AddIntConstant(m, "MSIDBOPEN_PATCHFILE", (int)MSIDBOPEN_PATCHFILE);
       
  1011 
       
  1012     PyModule_AddIntConstant(m, "MSICOLINFO_NAMES", MSICOLINFO_NAMES);
       
  1013     PyModule_AddIntConstant(m, "MSICOLINFO_TYPES", MSICOLINFO_TYPES);
       
  1014 
       
  1015     PyModule_AddIntConstant(m, "MSIMODIFY_SEEK", MSIMODIFY_SEEK);
       
  1016     PyModule_AddIntConstant(m, "MSIMODIFY_REFRESH", MSIMODIFY_REFRESH);
       
  1017     PyModule_AddIntConstant(m, "MSIMODIFY_INSERT", MSIMODIFY_INSERT);
       
  1018     PyModule_AddIntConstant(m, "MSIMODIFY_UPDATE", MSIMODIFY_UPDATE);
       
  1019     PyModule_AddIntConstant(m, "MSIMODIFY_ASSIGN", MSIMODIFY_ASSIGN);
       
  1020     PyModule_AddIntConstant(m, "MSIMODIFY_REPLACE", MSIMODIFY_REPLACE);
       
  1021     PyModule_AddIntConstant(m, "MSIMODIFY_MERGE", MSIMODIFY_MERGE);
       
  1022     PyModule_AddIntConstant(m, "MSIMODIFY_DELETE", MSIMODIFY_DELETE);
       
  1023     PyModule_AddIntConstant(m, "MSIMODIFY_INSERT_TEMPORARY", MSIMODIFY_INSERT_TEMPORARY);
       
  1024     PyModule_AddIntConstant(m, "MSIMODIFY_VALIDATE", MSIMODIFY_VALIDATE);
       
  1025     PyModule_AddIntConstant(m, "MSIMODIFY_VALIDATE_NEW", MSIMODIFY_VALIDATE_NEW);
       
  1026     PyModule_AddIntConstant(m, "MSIMODIFY_VALIDATE_FIELD", MSIMODIFY_VALIDATE_FIELD);
       
  1027     PyModule_AddIntConstant(m, "MSIMODIFY_VALIDATE_DELETE", MSIMODIFY_VALIDATE_DELETE);
       
  1028 
       
  1029     PyModule_AddIntConstant(m, "PID_CODEPAGE", PID_CODEPAGE);
       
  1030     PyModule_AddIntConstant(m, "PID_TITLE", PID_TITLE);
       
  1031     PyModule_AddIntConstant(m, "PID_SUBJECT", PID_SUBJECT);
       
  1032     PyModule_AddIntConstant(m, "PID_AUTHOR", PID_AUTHOR);
       
  1033     PyModule_AddIntConstant(m, "PID_KEYWORDS", PID_KEYWORDS);
       
  1034     PyModule_AddIntConstant(m, "PID_COMMENTS", PID_COMMENTS);
       
  1035     PyModule_AddIntConstant(m, "PID_TEMPLATE", PID_TEMPLATE);
       
  1036     PyModule_AddIntConstant(m, "PID_LASTAUTHOR", PID_LASTAUTHOR);
       
  1037     PyModule_AddIntConstant(m, "PID_REVNUMBER", PID_REVNUMBER);
       
  1038     PyModule_AddIntConstant(m, "PID_LASTPRINTED", PID_LASTPRINTED);
       
  1039     PyModule_AddIntConstant(m, "PID_CREATE_DTM", PID_CREATE_DTM);
       
  1040     PyModule_AddIntConstant(m, "PID_LASTSAVE_DTM", PID_LASTSAVE_DTM);
       
  1041     PyModule_AddIntConstant(m, "PID_PAGECOUNT", PID_PAGECOUNT);
       
  1042     PyModule_AddIntConstant(m, "PID_WORDCOUNT", PID_WORDCOUNT);
       
  1043     PyModule_AddIntConstant(m, "PID_CHARCOUNT", PID_CHARCOUNT);
       
  1044     PyModule_AddIntConstant(m, "PID_APPNAME", PID_APPNAME);
       
  1045     PyModule_AddIntConstant(m, "PID_SECURITY", PID_SECURITY);
       
  1046 
       
  1047     MSIError = PyErr_NewException ("_msi.MSIError", NULL, NULL);
       
  1048     if (!MSIError)
       
  1049 	return;
       
  1050     PyModule_AddObject(m, "MSIError", MSIError);
       
  1051 }