~jacksonc/python-packager/devel

« back to all changes in this revision

Viewing changes to Build-Server/pyinstaller/windows-2.6/source/windows/dllmain.c

  • Committer: Jackson Cooper
  • Date: 2010-04-13 03:14:06 UTC
  • Revision ID: jackson@jacksonc.com-20100413031406-415e68ruamsfc5se
Added pyinstaller for Windows

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Bootloader for a DLL COM server.
 
3
 * Copyright (C) 2005, Giovanni Bajo
 
4
 * Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc.
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version.
 
10
 *
 
11
 * In addition to the permissions in the GNU General Public License, the
 
12
 * authors give you unlimited permission to link or embed the compiled
 
13
 * version of this file into combinations with other programs, and to
 
14
 * distribute those combinations without any restriction coming from the
 
15
 * use of this file. (The General Public License restrictions do apply in
 
16
 * other respects; for example, they cover modification of the file, and
 
17
 * distribution when not linked into a combine executable.)
 
18
 *
 
19
 * This program is distributed in the hope that it will be useful,
 
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
 * GNU General Public License for more details.
 
23
 *
 
24
 * You should have received a copy of the GNU General Public License
 
25
 * along with this program; if not, write to the Free Software
 
26
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
27
 */
 
28
#include "launch.h"
 
29
#include <windows.h>
 
30
#include <olectl.h>
 
31
 
 
32
typedef int (__stdcall *__PROC__DllCanUnloadNow) (void);
 
33
__PROC__DllCanUnloadNow Pyc_DllCanUnloadNow = NULL;
 
34
typedef HRESULT (__stdcall *__PROC__DllGetClassObject) (REFCLSID, REFIID, LPVOID *);
 
35
__PROC__DllGetClassObject Pyc_DllGetClassObject = NULL;
 
36
typedef int (__cdecl *__PROC__DllRegisterServerEx) (const char *);
 
37
__PROC__DllRegisterServerEx Pyc_DllRegisterServerEx = NULL;
 
38
typedef int (__cdecl *__PROC__DllUnregisterServerEx) (const char *);
 
39
__PROC__DllUnregisterServerEx Pyc_DllUnregisterServerEx = NULL;
 
40
typedef void (__cdecl *__PROC__PyCom_CoUninitialize) (void);
 
41
__PROC__PyCom_CoUninitialize PyCom_CoUninitialize = NULL;
 
42
 
 
43
HINSTANCE gPythoncom = 0;
 
44
char here[_MAX_PATH + 1];
 
45
int LoadPythonCom(void);
 
46
void releasePythonCom(void);
 
47
HINSTANCE gInstance;
 
48
PyThreadState *thisthread = NULL;
 
49
 
 
50
int launch(char const * archivePath, char  const * archiveName)
 
51
{
 
52
        PyObject *obHandle;
 
53
        int loadedNew = 0;
 
54
        char pathnm[_MAX_PATH];
 
55
 
 
56
    VS("START");
 
57
        strcpy(pathnm, archivePath);
 
58
        strcat(pathnm, archiveName);
 
59
    /* Set up paths */
 
60
    if (setPaths(archivePath, archiveName))
 
61
        return -1;
 
62
        VS("Got Paths");
 
63
    /* Open the archive */
 
64
    if (openArchive())
 
65
        return -1;
 
66
        VS("Opened Archive");
 
67
    /* Load Python DLL */
 
68
    if (attachPython(&loadedNew))
 
69
        return -1;
 
70
 
 
71
        if (loadedNew) {
 
72
                /* Start Python with silly command line */
 
73
                PI_PyEval_InitThreads();
 
74
                if (startPython(1, (char**)&pathnm))
 
75
                        return -1;
 
76
                VS("Started new Python");
 
77
                thisthread = PI_PyThreadState_Swap(NULL);
 
78
                PI_PyThreadState_Swap(thisthread);
 
79
        }
 
80
        else {
 
81
                VS("Attached to existing Python");
 
82
 
 
83
                /* start a mew interp */
 
84
                thisthread = PI_PyThreadState_Swap(NULL);
 
85
                PI_PyThreadState_Swap(thisthread);
 
86
                if (thisthread == NULL) {
 
87
                        thisthread = PI_Py_NewInterpreter();
 
88
                        VS("created thisthread");
 
89
                }
 
90
                else
 
91
                        VS("grabbed thisthread");
 
92
                PI_PyRun_SimpleString("import sys;sys.argv=[]");
 
93
        }
 
94
 
 
95
        /* a signal to scripts */
 
96
        PI_PyRun_SimpleString("import sys;sys.frozen='dll'\n");
 
97
        VS("set sys.frozen");
 
98
        /* Create a 'frozendllhandle' as a counterpart to
 
99
           sys.dllhandle (which is the Pythonxx.dll handle)
 
100
        */
 
101
        obHandle = PI_Py_BuildValue("i", gInstance);
 
102
        PI_PySys_SetObject("frozendllhandle", obHandle);
 
103
        Py_XDECREF(obHandle);
 
104
    /* Import modules from archive - this is to bootstrap */
 
105
    if (importModules())
 
106
        return -1;
 
107
        VS("Imported Modules");
 
108
    /* Install zlibs - now import hooks are in place */
 
109
    if (installZlibs())
 
110
        return -1;
 
111
        VS("Installed Zlibs");
 
112
    /* Run scripts */
 
113
    if (runScripts())
 
114
        return -1;
 
115
        VS("All scripts run");
 
116
    if (PI_PyErr_Occurred()) {
 
117
                // PI_PyErr_Print();
 
118
                //PI_PyErr_Clear();
 
119
                VS("Some error occurred");
 
120
    }
 
121
        VS("PGL released");
 
122
        // Abandon our thread state.
 
123
        PI_PyEval_ReleaseThread(thisthread);
 
124
    VS("OK.");
 
125
    return 0;
 
126
}
 
127
void startUp()
 
128
{
 
129
        char thisfile[_MAX_PATH + 1];
 
130
        char *p;
 
131
        int len;
 
132
 
 
133
        if (!GetModuleFileNameA(gInstance, thisfile, _MAX_PATH)) {
 
134
                FATALERROR("System error - unable to load!");
 
135
                return;
 
136
        }
 
137
        // fill in here (directory of thisfile)
 
138
        //GetModuleFileName returns an absolute path
 
139
        strcpy(here, thisfile);
 
140
        for (p=here+strlen(here); *p != '\\' && p >= here+2; --p);
 
141
        *++p = '\0';
 
142
        len = p - here;
 
143
        //VS(here);
 
144
        //VS(&thisfile[len]);
 
145
        launch(here, &thisfile[len]);
 
146
        LoadPythonCom();
 
147
        // Now Python is up and running (any scripts have run)
 
148
}
 
149
 
 
150
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
 
151
{
 
152
        if ( dwReason == DLL_PROCESS_ATTACH) {
 
153
                VS("Attach from thread %x", GetCurrentThreadId());
 
154
                gInstance = hInstance;
 
155
        }
 
156
        else if ( dwReason == DLL_PROCESS_DETACH ) {
 
157
                VS("Process Detach");
 
158
                //if (gPythoncom)
 
159
                //      releasePythonCom();
 
160
                //finalizePython();
 
161
        }
 
162
 
 
163
        return TRUE; 
 
164
}
 
165
 
 
166
int LoadPythonCom()
 
167
{
 
168
        char dllpath[_MAX_PATH+1];
 
169
        VS("Loading Pythoncom");
 
170
        // see if pythoncom is already loaded
 
171
        sprintf(dllpath, "pythoncom%02d.dll", getPyVersion());
 
172
        gPythoncom = GetModuleHandleA(dllpath);
 
173
        if (gPythoncom == NULL) {
 
174
                sprintf(dllpath, "%spythoncom%02d.dll", here, getPyVersion());
 
175
                //VS(dllpath);
 
176
                gPythoncom = LoadLibraryExA( dllpath, // points to name of executable module 
 
177
                                           NULL, // HANDLE hFile, // reserved, must be NULL 
 
178
                                           LOAD_WITH_ALTERED_SEARCH_PATH // DWORD dwFlags // entry-point execution flag 
 
179
                                          ); 
 
180
        }
 
181
        if (!gPythoncom) {
 
182
                VS("Pythoncom failed to load");
 
183
                return -1;
 
184
        }
 
185
        // debugging
 
186
        GetModuleFileNameA(gPythoncom, dllpath, _MAX_PATH);
 
187
        VS(dllpath);
 
188
 
 
189
        Pyc_DllCanUnloadNow = (__PROC__DllCanUnloadNow)GetProcAddress(gPythoncom, "DllCanUnloadNow");
 
190
        Pyc_DllGetClassObject = (__PROC__DllGetClassObject)GetProcAddress(gPythoncom, "DllGetClassObject");
 
191
        // DllRegisterServerEx etc are mainly used for "scripts", so that regsvr32.exe can be run on
 
192
        // a .py file, for example.  They aren't really relevant here.
 
193
        Pyc_DllRegisterServerEx = (__PROC__DllRegisterServerEx)GetProcAddress(gPythoncom, "DllRegisterServerEx");
 
194
        Pyc_DllUnregisterServerEx = (__PROC__DllUnregisterServerEx)GetProcAddress(gPythoncom, "DllUnregisterServerEx");
 
195
        PyCom_CoUninitialize = (__PROC__PyCom_CoUninitialize)GetProcAddress(gPythoncom, "PyCom_CoUninitialize");
 
196
        if (Pyc_DllGetClassObject == NULL) {
 
197
                VS("Couldn't get DllGetClassObject from pythoncom!");
 
198
                return -1;
 
199
        }
 
200
        if (PyCom_CoUninitialize == NULL) {
 
201
                VS("Couldn't get PyCom_CoUninitialize from pythoncom!");
 
202
                return -1;
 
203
        }
 
204
        return 0;
 
205
}
 
206
void releasePythonCom(void)
 
207
{
 
208
        if (gPythoncom) {
 
209
                PyCom_CoUninitialize();
 
210
                FreeLibrary(gPythoncom);
 
211
                gPythoncom = 0;
 
212
        }
 
213
}
 
214
//__declspec(dllexport) int __stdcall DllCanUnloadNow(void)
 
215
//__declspec(dllexport)
 
216
//STDAPI
 
217
HRESULT __stdcall DllCanUnloadNow(void)
 
218
{
 
219
        HRESULT rc;
 
220
 
 
221
        VS("DllCanUnloadNow from thread %x", GetCurrentThreadId());
 
222
        if (gPythoncom == 0)
 
223
                startUp();
 
224
        rc = Pyc_DllCanUnloadNow();
 
225
        VS("DllCanUnloadNow returns %x", rc);
 
226
        //if (rc == S_OK)
 
227
        //      PyCom_CoUninitialize();
 
228
        return rc;
 
229
}
 
230
 
 
231
//__declspec(dllexport) int __stdcall DllGetClassObject(void *rclsid, void *riid, void *ppv)
 
232
HRESULT __stdcall DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
 
233
{
 
234
        HRESULT rc;
 
235
 
 
236
        VS("DllGetClassObject from thread %x", GetCurrentThreadId());
 
237
        if (gPythoncom == 0)
 
238
                startUp();
 
239
        rc = Pyc_DllGetClassObject(rclsid, riid, ppv);
 
240
        VS("DllGetClassObject set %x and returned %x", *ppv, rc);
 
241
 
 
242
        return rc;
 
243
}
 
244
 
 
245
__declspec(dllexport) int DllRegisterServerEx(LPCSTR fileName)
 
246
{
 
247
        VS("DllRegisterServerEx from thread %x", GetCurrentThreadId());
 
248
        if (gPythoncom == 0)
 
249
                startUp();
 
250
        return Pyc_DllRegisterServerEx(fileName);
 
251
}
 
252
 
 
253
__declspec(dllexport) int DllUnregisterServerEx(LPCSTR fileName)
 
254
{
 
255
        if (gPythoncom == 0)
 
256
                startUp();
 
257
        return Pyc_DllUnregisterServerEx(fileName);
 
258
}
 
259
 
 
260
STDAPI DllRegisterServer()
 
261
{
 
262
        int rc, pyrc;
 
263
        if (gPythoncom == 0)
 
264
                startUp();
 
265
        PI_PyEval_AcquireThread(thisthread);
 
266
        rc = callSimpleEntryPoint("DllRegisterServer", &pyrc);
 
267
        PI_PyEval_ReleaseThread(thisthread);
 
268
        return rc==0 ? pyrc : SELFREG_E_CLASS;
 
269
}
 
270
 
 
271
STDAPI DllUnregisterServer()
 
272
{
 
273
        int rc, pyrc;
 
274
        if (gPythoncom == 0)
 
275
                startUp();
 
276
        PI_PyEval_AcquireThread(thisthread);
 
277
        rc = callSimpleEntryPoint("DllUnregisterServer", &pyrc);
 
278
        PI_PyEval_ReleaseThread(thisthread);
 
279
        return rc==0 ? pyrc : SELFREG_E_CLASS;
 
280
}