srcanamdw/codescanner/pyinstaller/source/windows/dllmain.c
changeset 1 22878952f6e2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srcanamdw/codescanner/pyinstaller/source/windows/dllmain.c	Thu Feb 18 12:29:02 2010 +0530
@@ -0,0 +1,289 @@
+/*
+ * 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 */
+		PyEval_InitThreads();
+		if (startPython(1, (char**)&pathnm))
+			return -1;
+		VS("Started new Python");
+		thisthread = PyThreadState_Swap(NULL);
+		PyThreadState_Swap(thisthread);
+	}
+	else {
+		VS("Attached to existing Python");
+
+		/* start a mew interp */
+		thisthread = PyThreadState_Swap(NULL);
+		PyThreadState_Swap(thisthread);
+		if (thisthread == NULL) {
+			thisthread = Py_NewInterpreter();
+			VS("created thisthread");
+		}
+		else
+			VS("grabbed thisthread");
+		PyRun_SimpleString("import sys;sys.argv=[]");
+	}
+
+	/* a signal to scripts */
+	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 = Py_BuildValue("i", gInstance);
+	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 (PyErr_Occurred()) {
+		// PyErr_Print();
+		//PyErr_Clear();
+		VS("Some error occurred");
+    }
+	VS("PGL released");
+	// Abandon our thread state.
+	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)
+{
+	char msg[40];
+
+	if ( dwReason == DLL_PROCESS_ATTACH) {
+		sprintf(msg, "Attach from thread %x", GetCurrentThreadId()); 
+		VS(msg);
+		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 = GetModuleHandle(dllpath);
+	if (gPythoncom == NULL) {
+		sprintf(dllpath, "%spythoncom%02d.dll", here, getPyVersion());
+		//VS(dllpath);
+		gPythoncom = LoadLibraryEx( 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)
+{
+	char msg[80];
+	HRESULT rc;
+
+	sprintf(msg, "DllCanUnloadNow from thread %x", GetCurrentThreadId()); 
+	VS(msg);
+	if (gPythoncom == 0)
+		startUp();
+	rc = Pyc_DllCanUnloadNow();
+	sprintf(msg, "DllCanUnloadNow returns %x", rc); 
+	VS(msg);
+	//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)
+{
+	char msg[80];
+	HRESULT rc;
+	sprintf(msg, "DllGetClassObject from thread %x", GetCurrentThreadId()); 
+	VS(msg);
+	if (gPythoncom == 0)
+		startUp();
+	rc = Pyc_DllGetClassObject(rclsid, riid, ppv);
+	sprintf(msg, "DllGetClassObject set %x and returned %x", *ppv, rc);
+	VS(msg);
+	return rc;
+}
+
+__declspec(dllexport) int DllRegisterServerEx(LPCSTR fileName)
+{
+	char msg[40];
+	sprintf(msg, "DllRegisterServerEx from thread %x", GetCurrentThreadId()); 
+	VS(msg);
+	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();
+	PyEval_AcquireThread(thisthread);
+	rc = callSimpleEntryPoint("DllRegisterServer", &pyrc);
+	PyEval_ReleaseThread(thisthread);
+	return rc==0 ? pyrc : SELFREG_E_CLASS;
+}
+
+STDAPI DllUnregisterServer()
+{
+	int rc, pyrc;
+	if (gPythoncom == 0)
+		startUp();
+	PyEval_AcquireThread(thisthread);
+	rc = callSimpleEntryPoint("DllUnregisterServer", &pyrc);
+	PyEval_ReleaseThread(thisthread);
+	return rc==0 ? pyrc : SELFREG_E_CLASS;
+}