diff -r 37c3df559270 Lib/msilib/__init__.py --- a/Lib/msilib/__init__.py Sun Aug 10 14:16:45 2008 +0200 +++ b/Lib/msilib/__init__.py Mon Aug 11 17:25:15 2008 +0200 @@ -101,6 +101,8 @@ field = value[i] if isinstance(field, int): r.SetInteger(i+1,field) + elif isinstance(field, bytes): + r.SetBytes(i+1,field) elif isinstance(field, str): r.SetString(i+1,field) elif field is None: @@ -133,6 +135,17 @@ except OSError: pass ProductCode = ProductCode.upper() + # XXX According to + # http://blogs.msdn.com/heaths/archive/2005/10/05/msi-databases-and-code-pages.aspx + # we should be able to use the 65001 codepage to select utf-8 encoding + # of summary information (using si.SetProperty(PID_CODEPAGE, 65001)), + # but the generated MSI files aren't recognized by Windows. This means + # non-ASCII data will get garbled on output. However, we think it is + # better to allow generating MSI with such imperfect output rather than + # disallow it altogether. + ProductName = ProductName.encode("utf8") + ProductVersion = ProductVersion.encode("utf8") + Manufacturer = Manufacturer.encode("utf8") # Create the database db = OpenDatabase(name, MSIDBOPEN_CREATE) # Create the tables @@ -142,17 +155,17 @@ add_data(db, "_Validation", schema._Validation_records) # Initialize the summary information, allowing atmost 20 properties si = db.GetSummaryInformation(20) - si.SetProperty(PID_TITLE, "Installation Database") + si.SetProperty(PID_TITLE, b"Installation Database") si.SetProperty(PID_SUBJECT, ProductName) si.SetProperty(PID_AUTHOR, Manufacturer) if Win64: - si.SetProperty(PID_TEMPLATE, "Intel64;1033") + si.SetProperty(PID_TEMPLATE, b"Intel64;1033") else: - si.SetProperty(PID_TEMPLATE, "Intel;1033") + si.SetProperty(PID_TEMPLATE, b"Intel;1033") si.SetProperty(PID_REVNUMBER, gen_uuid()) si.SetProperty(PID_WORDCOUNT, 2) # long file names, compressed, original media si.SetProperty(PID_PAGECOUNT, 200) - si.SetProperty(PID_APPNAME, "Python MSI Library") + si.SetProperty(PID_APPNAME, b"Python MSI Library") # XXX more properties si.Persist() add_data(db, "Property", [ @@ -160,7 +173,7 @@ ("ProductCode", ProductCode), ("ProductVersion", ProductVersion), ("Manufacturer", Manufacturer), - ("ProductLanguage", "1033")]) + ("ProductLanguage", b"1033")]) db.Commit() return db @@ -178,7 +191,7 @@ return str def gen_uuid(): - return "{"+UuidCreate().upper()+"}" + return b"{" + UuidCreate().upper() + b"}" class CAB: def __init__(self, name): diff -r 37c3df559270 PC/_msi.c --- a/PC/_msi.c Sun Aug 10 14:16:45 2008 +0200 +++ b/PC/_msi.c Mon Aug 11 17:25:15 2008 +0200 @@ -399,7 +399,26 @@ int field; char *data; + /* XXX This is wrong, it will use the default encoding + (utf-8) which is probably not what is awaited by MSI */ if (!PyArg_ParseTuple(args, "is:SetString", &field, &data)) + return NULL; + + if ((status = MsiRecordSetString(record->h, field, data)) != ERROR_SUCCESS) + return msierror(status); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +record_setbytes(msiobj* record, PyObject *args) +{ + int status; + int field; + char *data; + + if (!PyArg_ParseTuple(args, "iy:SetBytes", &field, &data)) return NULL; if ((status = MsiRecordSetString(record->h, field, data)) != ERROR_SUCCESS) @@ -454,6 +473,8 @@ PyDoc_STR("GetString(field) -> string\nWraps MsiRecordGetString")}, { "SetString", (PyCFunction)record_setstring, METH_VARARGS, PyDoc_STR("SetString(field,str) -> None\nWraps MsiRecordSetString")}, + { "SetBytes", (PyCFunction)record_setbytes, METH_VARARGS, + PyDoc_STR("SetBytes(field,bytes) -> None\nWraps MsiRecordSetString")}, { "SetStream", (PyCFunction)record_setstream, METH_VARARGS, PyDoc_STR("SetStream(field,filename) -> None\nWraps MsiRecordSetInteger")}, { "SetInteger", (PyCFunction)record_setinteger, METH_VARARGS,