1
//-----------------------------------------------------------------------------
3
// Shared library for use by cx_Freeze.
4
//-----------------------------------------------------------------------------
15
BYTE bWidth; // Width, in pixels, of the image
16
BYTE bHeight; // Height, in pixels, of the image
17
BYTE bColorCount; // Number of colors in image
18
BYTE bReserved; // Reserved ( must be 0)
19
WORD wPlanes; // Color Planes
20
WORD wBitCount; // Bits per pixel
21
DWORD dwBytesInRes; // How many bytes in this resource?
22
DWORD dwImageOffset; // Where in the file is this image?
26
WORD idReserved; // Reserved (must be 0)
27
WORD idType; // Resource Type (1 for icons)
28
WORD idCount; // How many images?
29
ICONDIRENTRY idEntries[0]; // An entry for each image
33
BYTE bWidth; // Width, in pixels, of the image
34
BYTE bHeight; // Height, in pixels, of the image
35
BYTE bColorCount; // Number of colors in image
36
BYTE bReserved; // Reserved ( must be 0)
37
WORD wPlanes; // Color Planes
38
WORD wBitCount; // Bits per pixel
39
DWORD dwBytesInRes; // How many bytes in this resource?
40
WORD nID; // resource ID
44
WORD idReserved; // Reserved (must be 0)
45
WORD idType; // Resource Type (1 for icons)
46
WORD idCount; // How many images?
47
GRPICONDIRENTRY idEntries[0]; // An entry for each image
51
//-----------------------------------------------------------------------------
53
//-----------------------------------------------------------------------------
55
static PyObject *g_BindErrorException = NULL;
56
static PyObject *g_ImageNames = NULL;
61
//-----------------------------------------------------------------------------
62
// BindStatusRoutine()
63
// Called by BindImageEx() at various points. This is used to determine the
64
// dependency tree which is later examined by cx_Freeze.
65
//-----------------------------------------------------------------------------
66
static BOOL __stdcall BindStatusRoutine(
67
IMAGEHLP_STATUS_REASON reason, // reason called
68
PSTR imageName, // name of image being examined
69
PSTR dllName, // name of DLL
70
ULONG virtualAddress, // computed virtual address
71
ULONG parameter) // parameter (value depends on reason)
73
char fileName[MAX_PATH + 1];
76
case BindImportModule:
77
if (!SearchPath(NULL, dllName, NULL, sizeof(fileName), fileName,
81
if (PyDict_SetItemString(g_ImageNames, fileName, Py_None) < 0)
91
//-----------------------------------------------------------------------------
93
// Return the data for the given file.
94
//-----------------------------------------------------------------------------
95
static int GetFileData(
96
const char *fileName, // name of file to read
97
char **data) // pointer to data (OUT)
99
DWORD numberOfBytesRead, dataSize;
102
file = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
103
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
104
if (file == INVALID_HANDLE_VALUE)
106
dataSize = GetFileSize(file, NULL);
107
if (dataSize == INVALID_FILE_SIZE) {
111
*data = PyMem_Malloc(dataSize);
116
if (!ReadFile(file, *data, dataSize, &numberOfBytesRead, NULL)) {
125
//-----------------------------------------------------------------------------
126
// CreateGroupIconResource()
127
// Return the group icon resource given the icon file data.
128
//-----------------------------------------------------------------------------
129
static GRPICONDIR *CreateGroupIconResource(
130
ICONDIR *iconDir, // icon information
131
DWORD *resourceSize) // size of resource (OUT)
133
GRPICONDIR *groupIconDir;
136
*resourceSize = sizeof(GRPICONDIR) +
137
sizeof(GRPICONDIRENTRY) * iconDir->idCount;
138
groupIconDir = PyMem_Malloc(*resourceSize);
141
groupIconDir->idReserved = iconDir->idReserved;
142
groupIconDir->idType = iconDir->idType;
143
groupIconDir->idCount = iconDir->idCount;
144
for (i = 0; i < iconDir->idCount; i++) {
145
groupIconDir->idEntries[i].bWidth = iconDir->idEntries[i].bWidth;
146
groupIconDir->idEntries[i].bHeight = iconDir->idEntries[i].bHeight;
147
groupIconDir->idEntries[i].bColorCount =
148
iconDir->idEntries[i].bColorCount;
149
groupIconDir->idEntries[i].bReserved = iconDir->idEntries[i].bReserved;
150
groupIconDir->idEntries[i].wPlanes = iconDir->idEntries[i].wPlanes;
151
groupIconDir->idEntries[i].wBitCount = iconDir->idEntries[i].wBitCount;
152
groupIconDir->idEntries[i].dwBytesInRes =
153
iconDir->idEntries[i].dwBytesInRes;
154
groupIconDir->idEntries[i].nID = i + 1;
161
//-----------------------------------------------------------------------------
163
// Add the icon as a resource to the specified file.
164
//-----------------------------------------------------------------------------
165
static PyObject *ExtAddIcon(
166
PyObject *self, // passthrough argument
167
PyObject *args) // arguments
169
char *executableName, *iconName, *data, *iconData;
170
GRPICONDIR *groupIconDir;
177
if (!PyArg_ParseTuple(args, "ss", &executableName, &iconName))
180
// begin updating the executable
181
handle = BeginUpdateResource(executableName, FALSE);
183
PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,
184
GetLastError(), executableName);
188
// first attempt to get the data from the icon file
192
if (GetFileData(iconName, &data) < 0)
194
iconDir = (ICONDIR*) data;
196
// next, attempt to add a group icon resource
198
groupIconDir = CreateGroupIconResource(iconDir, &resourceSize);
200
succeeded = UpdateResource(handle, RT_GROUP_ICON,
202
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
203
groupIconDir, resourceSize);
204
else succeeded = FALSE;
207
// next, add each icon as a resource
209
for (i = 0; i < iconDir->idCount; i++) {
210
iconData = &data[iconDir->idEntries[i].dwImageOffset];
211
resourceSize = iconDir->idEntries[i].dwBytesInRes;
212
succeeded = UpdateResource(handle, RT_ICON, MAKEINTRESOURCE(i + 1),
213
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), iconData,
220
// finish writing the resource (or discarding the changes upon an error)
221
if (!EndUpdateResource(handle, !succeeded)) {
224
PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,
225
GetLastError(), executableName);
231
PyMem_Free(groupIconDir);
242
//-----------------------------------------------------------------------------
243
// ExtBeginUpdateResource()
244
// Wrapper for BeginUpdateResource().
245
//-----------------------------------------------------------------------------
246
static PyObject *ExtBeginUpdateResource(
247
PyObject *self, // passthrough argument
248
PyObject *args) // arguments
250
BOOL deleteExistingResources;
254
deleteExistingResources = TRUE;
255
if (!PyArg_ParseTuple(args, "s|i", &fileName, &deleteExistingResources))
257
handle = BeginUpdateResource(fileName, deleteExistingResources);
259
PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,
260
GetLastError(), fileName);
263
return PyInt_FromLong((long) handle);
267
//-----------------------------------------------------------------------------
268
// ExtUpdateResource()
269
// Wrapper for UpdateResource().
270
//-----------------------------------------------------------------------------
271
static PyObject *ExtUpdateResource(
272
PyObject *self, // passthrough argument
273
PyObject *args) // arguments
275
int resourceType, resourceId, resourceDataSize;
279
if (!PyArg_ParseTuple(args, "iiis#", &handle, &resourceType, &resourceId,
280
&resourceData, &resourceDataSize))
282
if (!UpdateResource(handle, MAKEINTRESOURCE(resourceType),
283
MAKEINTRESOURCE(resourceId),
284
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), resourceData,
286
PyErr_SetExcFromWindowsErr(PyExc_WindowsError, GetLastError());
295
//-----------------------------------------------------------------------------
296
// ExtEndUpdateResource()
297
// Wrapper for EndUpdateResource().
298
//-----------------------------------------------------------------------------
299
static PyObject *ExtEndUpdateResource(
300
PyObject *self, // passthrough argument
301
PyObject *args) // arguments
306
discardChanges = FALSE;
307
if (!PyArg_ParseTuple(args, "i|i", &handle, &discardChanges))
309
if (!EndUpdateResource(handle, discardChanges)) {
310
PyErr_SetExcFromWindowsErr(PyExc_WindowsError, GetLastError());
319
//-----------------------------------------------------------------------------
320
// ExtGetDependentFiles()
321
// Return a list of files that this file depends on.
322
//-----------------------------------------------------------------------------
323
static PyObject *ExtGetDependentFiles(
324
PyObject *self, // passthrough argument
325
PyObject *args) // arguments
330
if (!PyArg_ParseTuple(args, "s", &imageName))
332
g_ImageNames = PyDict_New();
335
if (!BindImageEx(BIND_NO_BOUND_IMPORTS | BIND_NO_UPDATE | BIND_ALL_IMAGES,
336
imageName, NULL, NULL, BindStatusRoutine)) {
337
Py_DECREF(g_ImageNames);
338
PyErr_SetExcFromWindowsErrWithFilename(g_BindErrorException,
339
GetLastError(), imageName);
342
results = PyDict_Keys(g_ImageNames);
343
Py_DECREF(g_ImageNames);
348
//-----------------------------------------------------------------------------
350
// Return the Windows directory (C:\Windows for example).
351
//-----------------------------------------------------------------------------
352
static PyObject *ExtGetSystemDir(
353
PyObject *self, // passthrough argument
354
PyObject *args) // arguments (ignored)
356
char dir[MAX_PATH + 1];
358
if (GetSystemDirectory(dir, sizeof(dir)))
359
return PyString_FromString(dir);
360
PyErr_SetExcFromWindowsErr(PyExc_RuntimeError, GetLastError());
366
//-----------------------------------------------------------------------------
367
// ExtSetOptimizeFlag()
368
// Set the optimize flag as needed.
369
//-----------------------------------------------------------------------------
370
static PyObject *ExtSetOptimizeFlag(
371
PyObject *self, // passthrough argument
372
PyObject *args) // arguments
374
if (!PyArg_ParseTuple(args, "i", &Py_OptimizeFlag))
381
//-----------------------------------------------------------------------------
383
//-----------------------------------------------------------------------------
384
static PyMethodDef g_ModuleMethods[] = {
385
{ "SetOptimizeFlag", ExtSetOptimizeFlag, METH_VARARGS },
387
{ "BeginUpdateResource", ExtBeginUpdateResource, METH_VARARGS },
388
{ "UpdateResource", ExtUpdateResource, METH_VARARGS },
389
{ "EndUpdateResource", ExtEndUpdateResource, METH_VARARGS },
390
{ "AddIcon", ExtAddIcon, METH_VARARGS },
391
{ "GetDependentFiles", ExtGetDependentFiles, METH_VARARGS },
392
{ "GetSystemDir", ExtGetSystemDir, METH_NOARGS },
398
//-----------------------------------------------------------------------------
400
// Initialization routine for the shared libary.
401
//-----------------------------------------------------------------------------
406
module = Py_InitModule("cx_Freeze.util", g_ModuleMethods);
410
g_BindErrorException = PyErr_NewException("cx_Freeze.util.BindError",
412
if (!g_BindErrorException)
414
if (PyModule_AddObject(module, "BindError", g_BindErrorException) < 0)