~ubuntu-branches/ubuntu/jaunty/calibre/jaunty-backports

« back to all changes in this revision

Viewing changes to installer/cx_Freeze/source/util.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-01-20 17:14:02 UTC
  • Revision ID: james.westby@ubuntu.com-20090120171402-8y3znf6nokwqe80k
Tags: upstream-0.4.125+dfsg
ImportĀ upstreamĀ versionĀ 0.4.125+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//-----------------------------------------------------------------------------
 
2
// util.c
 
3
//   Shared library for use by cx_Freeze.
 
4
//-----------------------------------------------------------------------------
 
5
 
 
6
#include <Python.h>
 
7
 
 
8
#ifdef WIN32
 
9
#include <windows.h>
 
10
#include <imagehlp.h>
 
11
 
 
12
#pragma pack(2)
 
13
 
 
14
typedef struct {
 
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?
 
23
} ICONDIRENTRY;
 
24
 
 
25
typedef struct {
 
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
 
30
} ICONDIR;
 
31
 
 
32
typedef struct {
 
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
 
41
} GRPICONDIRENTRY;
 
42
 
 
43
typedef struct {
 
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
 
48
} GRPICONDIR;
 
49
#endif
 
50
 
 
51
//-----------------------------------------------------------------------------
 
52
// Globals
 
53
//-----------------------------------------------------------------------------
 
54
#ifdef WIN32
 
55
static PyObject *g_BindErrorException = NULL;
 
56
static PyObject *g_ImageNames = NULL;
 
57
#endif
 
58
 
 
59
 
 
60
#ifdef WIN32
 
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)
 
72
{
 
73
    char fileName[MAX_PATH + 1];
 
74
 
 
75
    switch (reason) {
 
76
        case BindImportModule:
 
77
            if (!SearchPath(NULL, dllName, NULL, sizeof(fileName), fileName,
 
78
                    NULL))
 
79
                return FALSE;
 
80
            Py_INCREF(Py_None);
 
81
            if (PyDict_SetItemString(g_ImageNames, fileName, Py_None) < 0)
 
82
                return FALSE;
 
83
            break;
 
84
        default:
 
85
            break;
 
86
    }
 
87
    return TRUE;
 
88
}
 
89
 
 
90
 
 
91
//-----------------------------------------------------------------------------
 
92
// GetFileData()
 
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)
 
98
{
 
99
    DWORD numberOfBytesRead, dataSize;
 
100
    HANDLE file;
 
101
 
 
102
    file = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
 
103
            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 
104
    if (file == INVALID_HANDLE_VALUE)
 
105
        return -1;
 
106
    dataSize = GetFileSize(file, NULL);
 
107
    if (dataSize == INVALID_FILE_SIZE) {
 
108
        CloseHandle(file);
 
109
        return -1;
 
110
    }
 
111
    *data = PyMem_Malloc(dataSize);
 
112
    if (!*data) {
 
113
        CloseHandle(file);
 
114
        return -1;
 
115
    }
 
116
    if (!ReadFile(file, *data, dataSize, &numberOfBytesRead, NULL)) {
 
117
        CloseHandle(file);
 
118
        return -1;
 
119
    }
 
120
    CloseHandle(file);
 
121
    return 0;
 
122
}
 
123
 
 
124
 
 
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)
 
132
{
 
133
    GRPICONDIR *groupIconDir;
 
134
    int i;
 
135
 
 
136
    *resourceSize = sizeof(GRPICONDIR) +
 
137
            sizeof(GRPICONDIRENTRY) * iconDir->idCount;
 
138
    groupIconDir = PyMem_Malloc(*resourceSize);
 
139
    if (!groupIconDir)
 
140
        return NULL;
 
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;
 
155
    }
 
156
 
 
157
    return groupIconDir;
 
158
}
 
159
 
 
160
 
 
161
//-----------------------------------------------------------------------------
 
162
// ExtAddIcon()
 
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
 
168
{
 
169
    char *executableName, *iconName, *data, *iconData;
 
170
    GRPICONDIR *groupIconDir;
 
171
    DWORD resourceSize;
 
172
    ICONDIR *iconDir;
 
173
    BOOL succeeded;
 
174
    HANDLE handle;
 
175
    int i;
 
176
 
 
177
    if (!PyArg_ParseTuple(args, "ss", &executableName, &iconName))
 
178
        return NULL;
 
179
 
 
180
    // begin updating the executable
 
181
    handle = BeginUpdateResource(executableName, FALSE);
 
182
    if (!handle) {
 
183
        PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,
 
184
                GetLastError(), executableName);
 
185
        return NULL;
 
186
    }
 
187
 
 
188
    // first attempt to get the data from the icon file
 
189
    data = NULL;
 
190
    succeeded = TRUE;
 
191
    groupIconDir = NULL;
 
192
    if (GetFileData(iconName, &data) < 0)
 
193
        succeeded = FALSE;
 
194
    iconDir = (ICONDIR*) data;
 
195
 
 
196
    // next, attempt to add a group icon resource
 
197
    if (succeeded) {
 
198
        groupIconDir = CreateGroupIconResource(iconDir, &resourceSize);
 
199
        if (groupIconDir)
 
200
            succeeded = UpdateResource(handle, RT_GROUP_ICON,
 
201
                    MAKEINTRESOURCE(1),
 
202
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
 
203
                    groupIconDir, resourceSize);
 
204
        else succeeded = FALSE;
 
205
    }
 
206
 
 
207
    // next, add each icon as a resource
 
208
    if (succeeded) {
 
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,
 
214
                    resourceSize);
 
215
            if (!succeeded)
 
216
                break;
 
217
        }
 
218
    }
 
219
 
 
220
    // finish writing the resource (or discarding the changes upon an error)
 
221
    if (!EndUpdateResource(handle, !succeeded)) {
 
222
        if (succeeded) {
 
223
            succeeded = FALSE;
 
224
            PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,
 
225
                    GetLastError(), executableName);
 
226
        }
 
227
    }
 
228
 
 
229
    // clean up
 
230
    if (groupIconDir)
 
231
        PyMem_Free(groupIconDir);
 
232
    if (data)
 
233
        PyMem_Free(data);
 
234
    if (!succeeded)
 
235
        return NULL;
 
236
 
 
237
    Py_INCREF(Py_None);
 
238
    return Py_None;
 
239
}
 
240
 
 
241
 
 
242
//-----------------------------------------------------------------------------
 
243
// ExtBeginUpdateResource()
 
244
//   Wrapper for BeginUpdateResource().
 
245
//-----------------------------------------------------------------------------
 
246
static PyObject *ExtBeginUpdateResource(
 
247
    PyObject *self,                     // passthrough argument
 
248
    PyObject *args)                     // arguments
 
249
{
 
250
    BOOL deleteExistingResources;
 
251
    char *fileName;
 
252
    HANDLE handle;
 
253
 
 
254
    deleteExistingResources = TRUE;
 
255
    if (!PyArg_ParseTuple(args, "s|i", &fileName, &deleteExistingResources))
 
256
        return NULL;
 
257
    handle = BeginUpdateResource(fileName, deleteExistingResources);
 
258
    if (!handle) {
 
259
        PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,
 
260
                GetLastError(), fileName);
 
261
        return NULL;
 
262
    }
 
263
    return PyInt_FromLong((long) handle);
 
264
}
 
265
 
 
266
 
 
267
//-----------------------------------------------------------------------------
 
268
// ExtUpdateResource()
 
269
//   Wrapper for UpdateResource().
 
270
//-----------------------------------------------------------------------------
 
271
static PyObject *ExtUpdateResource(
 
272
    PyObject *self,                     // passthrough argument
 
273
    PyObject *args)                     // arguments
 
274
{
 
275
    int resourceType, resourceId, resourceDataSize;
 
276
    char *resourceData;
 
277
    HANDLE handle;
 
278
 
 
279
    if (!PyArg_ParseTuple(args, "iiis#", &handle, &resourceType, &resourceId,
 
280
            &resourceData, &resourceDataSize))
 
281
        return NULL;
 
282
    if (!UpdateResource(handle, MAKEINTRESOURCE(resourceType),
 
283
            MAKEINTRESOURCE(resourceId),
 
284
            MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), resourceData,
 
285
            resourceDataSize)) {
 
286
        PyErr_SetExcFromWindowsErr(PyExc_WindowsError, GetLastError());
 
287
        return NULL;
 
288
    }
 
289
 
 
290
    Py_INCREF(Py_None);
 
291
    return Py_None;
 
292
}
 
293
 
 
294
 
 
295
//-----------------------------------------------------------------------------
 
296
// ExtEndUpdateResource()
 
297
//   Wrapper for EndUpdateResource().
 
298
//-----------------------------------------------------------------------------
 
299
static PyObject *ExtEndUpdateResource(
 
300
    PyObject *self,                     // passthrough argument
 
301
    PyObject *args)                     // arguments
 
302
{
 
303
    BOOL discardChanges;
 
304
    HANDLE handle;
 
305
 
 
306
    discardChanges = FALSE;
 
307
    if (!PyArg_ParseTuple(args, "i|i", &handle, &discardChanges))
 
308
        return NULL;
 
309
    if (!EndUpdateResource(handle, discardChanges)) {
 
310
        PyErr_SetExcFromWindowsErr(PyExc_WindowsError, GetLastError());
 
311
        return NULL;
 
312
    }
 
313
 
 
314
    Py_INCREF(Py_None);
 
315
    return Py_None;
 
316
}
 
317
 
 
318
 
 
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
 
326
{
 
327
    PyObject *results;
 
328
    char *imageName;
 
329
 
 
330
    if (!PyArg_ParseTuple(args, "s", &imageName))
 
331
        return NULL;
 
332
    g_ImageNames = PyDict_New();
 
333
    if (!g_ImageNames)
 
334
        return NULL;
 
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);
 
340
        return NULL;
 
341
    }
 
342
    results = PyDict_Keys(g_ImageNames);
 
343
    Py_DECREF(g_ImageNames);
 
344
    return results;
 
345
}
 
346
 
 
347
 
 
348
//-----------------------------------------------------------------------------
 
349
// ExtGetSystemDir()
 
350
//   Return the Windows directory (C:\Windows for example).
 
351
//-----------------------------------------------------------------------------
 
352
static PyObject *ExtGetSystemDir(
 
353
    PyObject *self,                     // passthrough argument
 
354
    PyObject *args)                     // arguments (ignored)
 
355
{
 
356
    char dir[MAX_PATH + 1];
 
357
 
 
358
    if (GetSystemDirectory(dir, sizeof(dir)))
 
359
        return PyString_FromString(dir);
 
360
    PyErr_SetExcFromWindowsErr(PyExc_RuntimeError, GetLastError());
 
361
    return NULL;
 
362
}
 
363
#endif
 
364
 
 
365
 
 
366
//-----------------------------------------------------------------------------
 
367
// ExtSetOptimizeFlag()
 
368
//   Set the optimize flag as needed.
 
369
//-----------------------------------------------------------------------------
 
370
static PyObject *ExtSetOptimizeFlag(
 
371
    PyObject *self,                     // passthrough argument
 
372
    PyObject *args)                     // arguments
 
373
{
 
374
    if (!PyArg_ParseTuple(args, "i", &Py_OptimizeFlag))
 
375
        return NULL;
 
376
    Py_INCREF(Py_None);
 
377
    return Py_None;
 
378
}
 
379
 
 
380
 
 
381
//-----------------------------------------------------------------------------
 
382
// Methods
 
383
//-----------------------------------------------------------------------------
 
384
static PyMethodDef g_ModuleMethods[] = {
 
385
    { "SetOptimizeFlag", ExtSetOptimizeFlag, METH_VARARGS },
 
386
#ifdef WIN32
 
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 },
 
393
#endif
 
394
    { NULL }
 
395
};
 
396
 
 
397
 
 
398
//-----------------------------------------------------------------------------
 
399
// initutil()
 
400
//   Initialization routine for the shared libary.
 
401
//-----------------------------------------------------------------------------
 
402
void initutil(void)
 
403
{
 
404
    PyObject *module;
 
405
 
 
406
    module = Py_InitModule("cx_Freeze.util", g_ModuleMethods);
 
407
    if (!module)
 
408
        return;
 
409
#ifdef WIN32
 
410
    g_BindErrorException = PyErr_NewException("cx_Freeze.util.BindError",
 
411
            NULL, NULL);
 
412
    if (!g_BindErrorException)
 
413
        return;
 
414
    if (PyModule_AddObject(module, "BindError", g_BindErrorException) < 0)
 
415
        return;
 
416
#endif
 
417
}
 
418