From: <th...@us...> - 2013-05-24 19:59:46
|
Revision: 723 http://py2exe.svn.sourceforge.net/py2exe/?rev=723&view=rev Author: theller Date: 2013-05-24 19:59:36 +0000 (Fri, 24 May 2013) Log Message: ----------- Add a fix that my college Oliver Freyd implemented: properly implemented the activation context handling like it works in the python dll itself: We store the actctx, and wrap calls to MemoryLoadLibrary with _My_ActivateActCtx() and _My_DeactivateActCtx(). Modified Paths: -------------- trunk/py2exe/setup.py trunk/py2exe/source/Python-dynload.c trunk/py2exe/source/_memimporter.c trunk/py2exe/source/run_ctypes_dll.c Added Paths: ----------- trunk/py2exe/source/actctx.c Modified: trunk/py2exe/setup.py =================================================================== --- trunk/py2exe/setup.py 2013-02-04 08:00:26 UTC (rev 722) +++ trunk/py2exe/setup.py 2013-05-24 19:59:36 UTC (rev 723) @@ -376,7 +376,8 @@ _memimporter = Extension("_memimporter", ["source/MemoryModule.c", - "source/_memimporter_module.c"], + "source/_memimporter_module.c", + "source/actctx.c"], depends=depends + ["source/_memimporter.c"], define_macros=macros, ) @@ -386,6 +387,7 @@ "source/Python-dynload.c", "source/MemoryModule.c", "source/_memimporter.c", + "source/actctx.c", ], depends=depends, define_macros=macros, @@ -396,6 +398,7 @@ "source/Python-dynload.c", "source/MemoryModule.c", "source/_memimporter.c", + "source/actctx.c", ], libraries=["user32"], depends=depends, @@ -407,6 +410,7 @@ "source/Python-dynload.c", "source/MemoryModule.c", "source/_memimporter.c", + "source/actctx.c", ], libraries=["user32"], export_symbols=["DllCanUnloadNow,PRIVATE", @@ -424,6 +428,7 @@ "source/Python-dynload.c", "source/MemoryModule.c", "source/_memimporter.c", + "source/actctx.c", ], libraries=["user32"], export_symbols=["DllCanUnloadNow,PRIVATE", @@ -441,6 +446,7 @@ "source/Python-dynload.c", "source/MemoryModule.c", "source/_memimporter.c", + "source/actctx.c", "source/icon.rc"], libraries=["user32", "advapi32"], export_symbols=["HttpExtensionProc", Modified: trunk/py2exe/source/Python-dynload.c =================================================================== --- trunk/py2exe/source/Python-dynload.c 2013-02-04 08:00:26 UTC (rev 722) +++ trunk/py2exe/source/Python-dynload.c 2013-05-24 19:59:36 UTC (rev 723) @@ -1,6 +1,7 @@ /* **************** Python-dynload.c **************** */ #include "Python-dynload.h" #include "MemoryModule.h" +#include "actctx.h" #include <stdio.h> struct IMPORT imports[] = { @@ -64,11 +65,13 @@ int i; struct IMPORT *p = imports; HMODULE hmod; - + ULONG_PTR cookie = 0; if (!bytes) return _load_python_FromFile(dllname); - + + cookie = _My_ActivateActCtx();//try some windows manifest magic... hmod = MemoryLoadLibrary(dllname, bytes); + _My_DeactivateActCtx(cookie); if (hmod == NULL) { return 0; } Modified: trunk/py2exe/source/_memimporter.c =================================================================== --- trunk/py2exe/source/_memimporter.c 2013-02-04 08:00:26 UTC (rev 722) +++ trunk/py2exe/source/_memimporter.c 2013-05-24 19:59:36 UTC (rev 723) @@ -16,6 +16,7 @@ "Importer which can load extension modules from memory"; #include "MemoryModule.h" +#include "actctx.h" static void *memdup(void *ptr, Py_ssize_t size) { @@ -77,13 +78,16 @@ FARPROC do_init; char *oldcontext; - + ULONG_PTR cookie = 0; /* code, initfuncname, fqmodulename, path */ if (!PyArg_ParseTuple(args, "s#sss:import_module", &data, &size, &initfuncname, &modname, &pathname)) return NULL; + + cookie = _My_ActivateActCtx();//try some windows manifest magic... hmem = MemoryLoadLibrary(pathname, data); + _My_DeactivateActCtx(cookie); if (!hmem) { PyErr_Format(PyExc_ImportError, "MemoryLoadLibrary failed loading %s", pathname); Added: trunk/py2exe/source/actctx.c =================================================================== --- trunk/py2exe/source/actctx.c (rev 0) +++ trunk/py2exe/source/actctx.c 2013-05-24 19:59:36 UTC (rev 723) @@ -0,0 +1,40 @@ +#include "actctx.h" + +HANDLE PyWin_DLLhActivationContext=NULL; +PFN_GETCURRENTACTCTX pfnGetCurrentActCtx=NULL; +PFN_ACTIVATEACTCTX pfnActivateActCtx=NULL; +PFN_DEACTIVATEACTCTX pfnDeactivateActCtx=NULL; +PFN_ADDREFACTCTX pfnAddRefActCtx=NULL; +PFN_RELEASEACTCTX pfnReleaseActCtx=NULL; + +void _MyLoadActCtxPointers() +{ + HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll"); + if (hKernel32) + pfnGetCurrentActCtx = (PFN_GETCURRENTACTCTX) GetProcAddress(hKernel32, "GetCurrentActCtx"); + // If we can't load GetCurrentActCtx (ie, pre XP) , don't bother with the rest. + if (pfnGetCurrentActCtx) { + pfnActivateActCtx = (PFN_ACTIVATEACTCTX) GetProcAddress(hKernel32, "ActivateActCtx"); + pfnDeactivateActCtx = (PFN_DEACTIVATEACTCTX) GetProcAddress(hKernel32, "DeactivateActCtx"); + pfnAddRefActCtx = (PFN_ADDREFACTCTX) GetProcAddress(hKernel32, "AddRefActCtx"); + pfnReleaseActCtx = (PFN_RELEASEACTCTX) GetProcAddress(hKernel32, "ReleaseActCtx"); + } +} + +ULONG_PTR _My_ActivateActCtx() +{ + ULONG_PTR ret = 0; + if (PyWin_DLLhActivationContext && pfnActivateActCtx) + if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) { + OutputDebugString("py2exe failed to activate the activation context before loading a DLL\n"); + ret = 0; // no promise the failing function didn't change it! + } + return ret; +} + +void _My_DeactivateActCtx(ULONG_PTR cookie) +{ + if (cookie && pfnDeactivateActCtx) + if (!(*pfnDeactivateActCtx)(0, cookie)) + OutputDebugString("py2exe failed to de-activate the activation context\n"); +} Modified: trunk/py2exe/source/run_ctypes_dll.c =================================================================== --- trunk/py2exe/source/run_ctypes_dll.c 2013-02-04 08:00:26 UTC (rev 722) +++ trunk/py2exe/source/run_ctypes_dll.c 2013-05-24 19:59:36 UTC (rev 723) @@ -29,6 +29,7 @@ #include <assert.h> #include "Python-dynload.h" #include "MemoryModule.h" +#include "actctx.h" // Function pointers we load from _ctypes.pyd typedef int (__stdcall *__PROC__DllCanUnloadNow) (void); @@ -39,6 +40,9 @@ __PROC__DllCanUnloadNow Pyc_DllCanUnloadNow = NULL; __PROC__DllGetClassObject Pyc_DllGetClassObject = NULL; +extern BOOL _LoadPythonDLL(HMODULE hmod); +extern BOOL _LocateScript(HMODULE hmod); + extern void init_memimporter(void); void SystemError(int error, char *msg) @@ -81,11 +85,13 @@ // shouldn't do this twice assert(g_ctypes == NULL); + #ifdef _DEBUG strcpy(dll_path, "_ctypes_d.pyd"); #else strcpy(dll_path, "_ctypes.pyd"); #endif + g_ctypes = MyGetModuleHandle(dll_path); /* if (g_ctypes == NULL) { @@ -113,9 +119,11 @@ // give up in disgust return -1; } - + Pyc_DllCanUnloadNow = (__PROC__DllCanUnloadNow)MyGetProcAddress(g_ctypes, "DllCanUnloadNow"); Pyc_DllGetClassObject = (__PROC__DllGetClassObject)MyGetProcAddress(g_ctypes, "DllGetClassObject"); + assert(Pyc_DllGetClassObject); + return 0; } @@ -132,6 +140,17 @@ call in. */ PyGILState_STATE restore_state = PyGILState_UNLOCKED; + if (!Py_IsInitialized) { + // Python function pointers are yet to be loaded + // - force that now. See above for why we *must* + // know about the initialized state of Python so + // we can setup the thread-state correctly + // before calling init_with_instance(); This is + // wasteful, but fixing it would involve a + // restructure of init_with_instance() + _LocateScript(gInstance); + _LoadPythonDLL(gInstance); + } if (Py_IsInitialized && Py_IsInitialized()) { restore_state = PyGILState_Ensure(); } @@ -166,10 +185,17 @@ if ( dwReason == DLL_PROCESS_ATTACH) { gInstance = hInstance; InitializeCriticalSection(&csInit); + _MyLoadActCtxPointers(); + if (pfnGetCurrentActCtx && pfnAddRefActCtx) + if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext)) + if (!(*pfnAddRefActCtx)(PyWin_DLLhActivationContext)) + OutputDebugString("Python failed to load the default activation context\n"); } else if ( dwReason == DLL_PROCESS_DETACH ) { gInstance = 0; DeleteCriticalSection(&csInit); + if (pfnReleaseActCtx) + (*pfnReleaseActCtx)(PyWin_DLLhActivationContext); // not much else safe to do here } return TRUE; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |