mirror of
https://github.com/kennethreitz-archive/pyinstaller.git
synced 2026-06-05 23:50:17 +00:00
7500d720b6
https://svn.pyinstaller.python-hosting.com/branches/crypt ........ r465 | giovannibajo | 2008-05-21 15:30:21 +0200 (Wed, 21 May 2008) | 2 lines Ignore ".sconsign" ........ r532 | naufraghi | 2008-11-08 00:23:43 +0100 (Sat, 08 Nov 2008) | 1 line Add MacPython.org and MacPython.macports support ........ r533 | naufraghi | 2008-11-08 00:29:05 +0100 (Sat, 08 Nov 2008) | 1 line Run Configure continue only if the make is successful ........ r534 | naufraghi | 2008-11-08 00:32:00 +0100 (Sat, 08 Nov 2008) | 1 line Fix PyQt4 hooks ........ r535 | naufraghi | 2008-11-08 00:44:00 +0100 (Sat, 08 Nov 2008) | 1 line Do not compress any icon ........ r536 | naufraghi | 2008-11-08 00:51:07 +0100 (Sat, 08 Nov 2008) | 1 line Added support for multiple icons (by Giovanni) ........ r537 | naufraghi | 2008-11-08 00:55:17 +0100 (Sat, 08 Nov 2008) | 1 line Fix line endings ........ r538 | naufraghi | 2008-11-08 01:03:19 +0100 (Sat, 08 Nov 2008) | 1 line Pass wide-string command line through relaunch() to avoid losing information. (by Giovanni) ........ r539 | naufraghi | 2008-11-08 12:52:58 +0100 (Sat, 08 Nov 2008) | 1 line Line endings ........ r541 | naufraghi | 2008-11-09 10:08:19 +0100 (Sun, 09 Nov 2008) | 1 line Remove debug print ........ git-svn-id: http://svn.pyinstaller.org/trunk@545 8dd32b29-ccff-0310-8a9a-9233e24343b1
281 lines
8.3 KiB
C
281 lines
8.3 KiB
C
/*
|
|
* Bootloader for a DLL COM server.
|
|
* Copyright (C) 2005, Giovanni Bajo
|
|
* Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* In addition to the permissions in the GNU General Public License, the
|
|
* authors give you unlimited permission to link or embed the compiled
|
|
* version of this file into combinations with other programs, and to
|
|
* distribute those combinations without any restriction coming from the
|
|
* use of this file. (The General Public License restrictions do apply in
|
|
* other respects; for example, they cover modification of the file, and
|
|
* distribution when not linked into a combine executable.)
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
#include "launch.h"
|
|
#include <windows.h>
|
|
#include <olectl.h>
|
|
|
|
typedef int (__stdcall *__PROC__DllCanUnloadNow) (void);
|
|
__PROC__DllCanUnloadNow Pyc_DllCanUnloadNow = NULL;
|
|
typedef HRESULT (__stdcall *__PROC__DllGetClassObject) (REFCLSID, REFIID, LPVOID *);
|
|
__PROC__DllGetClassObject Pyc_DllGetClassObject = NULL;
|
|
typedef int (__cdecl *__PROC__DllRegisterServerEx) (const char *);
|
|
__PROC__DllRegisterServerEx Pyc_DllRegisterServerEx = NULL;
|
|
typedef int (__cdecl *__PROC__DllUnregisterServerEx) (const char *);
|
|
__PROC__DllUnregisterServerEx Pyc_DllUnregisterServerEx = NULL;
|
|
typedef void (__cdecl *__PROC__PyCom_CoUninitialize) (void);
|
|
__PROC__PyCom_CoUninitialize PyCom_CoUninitialize = NULL;
|
|
|
|
HINSTANCE gPythoncom = 0;
|
|
char here[_MAX_PATH + 1];
|
|
int LoadPythonCom(void);
|
|
void releasePythonCom(void);
|
|
HINSTANCE gInstance;
|
|
PyThreadState *thisthread = NULL;
|
|
|
|
int launch(char const * archivePath, char const * archiveName)
|
|
{
|
|
PyObject *obHandle;
|
|
int loadedNew = 0;
|
|
char pathnm[_MAX_PATH];
|
|
|
|
VS("START");
|
|
strcpy(pathnm, archivePath);
|
|
strcat(pathnm, archiveName);
|
|
/* Set up paths */
|
|
if (setPaths(archivePath, archiveName))
|
|
return -1;
|
|
VS("Got Paths");
|
|
/* Open the archive */
|
|
if (openArchive())
|
|
return -1;
|
|
VS("Opened Archive");
|
|
/* Load Python DLL */
|
|
if (attachPython(&loadedNew))
|
|
return -1;
|
|
|
|
if (loadedNew) {
|
|
/* Start Python with silly command line */
|
|
PI_PyEval_InitThreads();
|
|
if (startPython(1, (char**)&pathnm))
|
|
return -1;
|
|
VS("Started new Python");
|
|
thisthread = PI_PyThreadState_Swap(NULL);
|
|
PI_PyThreadState_Swap(thisthread);
|
|
}
|
|
else {
|
|
VS("Attached to existing Python");
|
|
|
|
/* start a mew interp */
|
|
thisthread = PI_PyThreadState_Swap(NULL);
|
|
PI_PyThreadState_Swap(thisthread);
|
|
if (thisthread == NULL) {
|
|
thisthread = PI_Py_NewInterpreter();
|
|
VS("created thisthread");
|
|
}
|
|
else
|
|
VS("grabbed thisthread");
|
|
PI_PyRun_SimpleString("import sys;sys.argv=[]");
|
|
}
|
|
|
|
/* a signal to scripts */
|
|
PI_PyRun_SimpleString("import sys;sys.frozen='dll'\n");
|
|
VS("set sys.frozen");
|
|
/* Create a 'frozendllhandle' as a counterpart to
|
|
sys.dllhandle (which is the Pythonxx.dll handle)
|
|
*/
|
|
obHandle = PI_Py_BuildValue("i", gInstance);
|
|
PI_PySys_SetObject("frozendllhandle", obHandle);
|
|
Py_XDECREF(obHandle);
|
|
/* Import modules from archive - this is to bootstrap */
|
|
if (importModules())
|
|
return -1;
|
|
VS("Imported Modules");
|
|
/* Install zlibs - now import hooks are in place */
|
|
if (installZlibs())
|
|
return -1;
|
|
VS("Installed Zlibs");
|
|
/* Run scripts */
|
|
if (runScripts())
|
|
return -1;
|
|
VS("All scripts run");
|
|
if (PI_PyErr_Occurred()) {
|
|
// PI_PyErr_Print();
|
|
//PI_PyErr_Clear();
|
|
VS("Some error occurred");
|
|
}
|
|
VS("PGL released");
|
|
// Abandon our thread state.
|
|
PI_PyEval_ReleaseThread(thisthread);
|
|
VS("OK.");
|
|
return 0;
|
|
}
|
|
void startUp()
|
|
{
|
|
char thisfile[_MAX_PATH + 1];
|
|
char *p;
|
|
int len;
|
|
|
|
if (!GetModuleFileNameA(gInstance, thisfile, _MAX_PATH)) {
|
|
FATALERROR("System error - unable to load!");
|
|
return;
|
|
}
|
|
// fill in here (directory of thisfile)
|
|
//GetModuleFileName returns an absolute path
|
|
strcpy(here, thisfile);
|
|
for (p=here+strlen(here); *p != '\\' && p >= here+2; --p);
|
|
*++p = '\0';
|
|
len = p - here;
|
|
//VS(here);
|
|
//VS(&thisfile[len]);
|
|
launch(here, &thisfile[len]);
|
|
LoadPythonCom();
|
|
// Now Python is up and running (any scripts have run)
|
|
}
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
|
|
{
|
|
if ( dwReason == DLL_PROCESS_ATTACH) {
|
|
VS("Attach from thread %x", GetCurrentThreadId());
|
|
gInstance = hInstance;
|
|
}
|
|
else if ( dwReason == DLL_PROCESS_DETACH ) {
|
|
VS("Process Detach");
|
|
//if (gPythoncom)
|
|
// releasePythonCom();
|
|
//finalizePython();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int LoadPythonCom()
|
|
{
|
|
char dllpath[_MAX_PATH+1];
|
|
VS("Loading Pythoncom");
|
|
// see if pythoncom is already loaded
|
|
sprintf(dllpath, "pythoncom%02d.dll", getPyVersion());
|
|
gPythoncom = GetModuleHandleA(dllpath);
|
|
if (gPythoncom == NULL) {
|
|
sprintf(dllpath, "%spythoncom%02d.dll", here, getPyVersion());
|
|
//VS(dllpath);
|
|
gPythoncom = LoadLibraryExA( dllpath, // points to name of executable module
|
|
NULL, // HANDLE hFile, // reserved, must be NULL
|
|
LOAD_WITH_ALTERED_SEARCH_PATH // DWORD dwFlags // entry-point execution flag
|
|
);
|
|
}
|
|
if (!gPythoncom) {
|
|
VS("Pythoncom failed to load");
|
|
return -1;
|
|
}
|
|
// debugging
|
|
GetModuleFileNameA(gPythoncom, dllpath, _MAX_PATH);
|
|
VS(dllpath);
|
|
|
|
Pyc_DllCanUnloadNow = (__PROC__DllCanUnloadNow)GetProcAddress(gPythoncom, "DllCanUnloadNow");
|
|
Pyc_DllGetClassObject = (__PROC__DllGetClassObject)GetProcAddress(gPythoncom, "DllGetClassObject");
|
|
// DllRegisterServerEx etc are mainly used for "scripts", so that regsvr32.exe can be run on
|
|
// a .py file, for example. They aren't really relevant here.
|
|
Pyc_DllRegisterServerEx = (__PROC__DllRegisterServerEx)GetProcAddress(gPythoncom, "DllRegisterServerEx");
|
|
Pyc_DllUnregisterServerEx = (__PROC__DllUnregisterServerEx)GetProcAddress(gPythoncom, "DllUnregisterServerEx");
|
|
PyCom_CoUninitialize = (__PROC__PyCom_CoUninitialize)GetProcAddress(gPythoncom, "PyCom_CoUninitialize");
|
|
if (Pyc_DllGetClassObject == NULL) {
|
|
VS("Couldn't get DllGetClassObject from pythoncom!");
|
|
return -1;
|
|
}
|
|
if (PyCom_CoUninitialize == NULL) {
|
|
VS("Couldn't get PyCom_CoUninitialize from pythoncom!");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
void releasePythonCom(void)
|
|
{
|
|
if (gPythoncom) {
|
|
PyCom_CoUninitialize();
|
|
FreeLibrary(gPythoncom);
|
|
gPythoncom = 0;
|
|
}
|
|
}
|
|
//__declspec(dllexport) int __stdcall DllCanUnloadNow(void)
|
|
//__declspec(dllexport)
|
|
//STDAPI
|
|
HRESULT __stdcall DllCanUnloadNow(void)
|
|
{
|
|
HRESULT rc;
|
|
|
|
VS("DllCanUnloadNow from thread %x", GetCurrentThreadId());
|
|
if (gPythoncom == 0)
|
|
startUp();
|
|
rc = Pyc_DllCanUnloadNow();
|
|
VS("DllCanUnloadNow returns %x", rc);
|
|
//if (rc == S_OK)
|
|
// PyCom_CoUninitialize();
|
|
return rc;
|
|
}
|
|
|
|
//__declspec(dllexport) int __stdcall DllGetClassObject(void *rclsid, void *riid, void *ppv)
|
|
HRESULT __stdcall DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
|
{
|
|
HRESULT rc;
|
|
|
|
VS("DllGetClassObject from thread %x", GetCurrentThreadId());
|
|
if (gPythoncom == 0)
|
|
startUp();
|
|
rc = Pyc_DllGetClassObject(rclsid, riid, ppv);
|
|
VS("DllGetClassObject set %x and returned %x", *ppv, rc);
|
|
|
|
return rc;
|
|
}
|
|
|
|
__declspec(dllexport) int DllRegisterServerEx(LPCSTR fileName)
|
|
{
|
|
VS("DllRegisterServerEx from thread %x", GetCurrentThreadId());
|
|
if (gPythoncom == 0)
|
|
startUp();
|
|
return Pyc_DllRegisterServerEx(fileName);
|
|
}
|
|
|
|
__declspec(dllexport) int DllUnregisterServerEx(LPCSTR fileName)
|
|
{
|
|
if (gPythoncom == 0)
|
|
startUp();
|
|
return Pyc_DllUnregisterServerEx(fileName);
|
|
}
|
|
|
|
STDAPI DllRegisterServer()
|
|
{
|
|
int rc, pyrc;
|
|
if (gPythoncom == 0)
|
|
startUp();
|
|
PI_PyEval_AcquireThread(thisthread);
|
|
rc = callSimpleEntryPoint("DllRegisterServer", &pyrc);
|
|
PI_PyEval_ReleaseThread(thisthread);
|
|
return rc==0 ? pyrc : SELFREG_E_CLASS;
|
|
}
|
|
|
|
STDAPI DllUnregisterServer()
|
|
{
|
|
int rc, pyrc;
|
|
if (gPythoncom == 0)
|
|
startUp();
|
|
PI_PyEval_AcquireThread(thisthread);
|
|
rc = callSimpleEntryPoint("DllUnregisterServer", &pyrc);
|
|
PI_PyEval_ReleaseThread(thisthread);
|
|
return rc==0 ? pyrc : SELFREG_E_CLASS;
|
|
}
|