Commit 9844a1ff authored by Mark Hammond's avatar Mark Hammond

Merged revisions 69038 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r69038 | mark.hammond | 2009-01-28 10:12:23 +1100 (Wed, 28 Jan 2009) | 3 lines

  On Windows, use the Python 'Activation Context' when loading extensions
  to avoid problems loading the CRT from a private assembly.  Via bug 4566.
........
parent 4fcc4cf1
...@@ -18,6 +18,63 @@ char dllVersionBuffer[16] = ""; // a private buffer ...@@ -18,6 +18,63 @@ char dllVersionBuffer[16] = ""; // a private buffer
HMODULE PyWin_DLLhModule = NULL; HMODULE PyWin_DLLhModule = NULL;
const char *PyWin_DLLVersionString = dllVersionBuffer; const char *PyWin_DLLVersionString = dllVersionBuffer;
// Windows "Activation Context" work:
// Our .pyd extension modules are generally built without a manifest (ie,
// those included with Python and those built with a default distutils.
// This requires we perform some "activation context" magic when loading our
// extensions. In summary:
// * As our DLL loads we save the context being used.
// * Before loading our extensions we re-activate our saved context.
// * After extension load is complete we restore the old context.
// As an added complication, this magic only works on XP or later - we simply
// use the existence (or not) of the relevant function pointers from kernel32.
// See bug 4566 (http://python.org/sf/4566) for more details.
typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *);
typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *);
typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR);
typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE);
typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE);
// locals and function pointers for this activation context magic.
static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public
static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL;
static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL;
static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL;
static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL;
static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL;
void _LoadActCtxPointers()
{
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 _Py_ActivateActCtx()
{
ULONG_PTR ret = 0;
if (PyWin_DLLhActivationContext && pfnActivateActCtx)
if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) {
OutputDebugString("Python 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 _Py_DeactivateActCtx(ULONG_PTR cookie)
{
if (cookie && pfnDeactivateActCtx)
if (!(*pfnDeactivateActCtx)(0, cookie))
OutputDebugString("Python failed to de-activate the activation context\n");
}
BOOL WINAPI DllMain (HANDLE hInst, BOOL WINAPI DllMain (HANDLE hInst,
ULONG ul_reason_for_call, ULONG ul_reason_for_call,
...@@ -29,9 +86,18 @@ BOOL WINAPI DllMain (HANDLE hInst, ...@@ -29,9 +86,18 @@ BOOL WINAPI DllMain (HANDLE hInst,
PyWin_DLLhModule = hInst; PyWin_DLLhModule = hInst;
// 1000 is a magic number I picked out of the air. Could do with a #define, I spose... // 1000 is a magic number I picked out of the air. Could do with a #define, I spose...
LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer)); LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer));
//initall();
// and capture our activation context for use when loading extensions.
_LoadActCtxPointers();
if (pfnGetCurrentActCtx && pfnAddRefActCtx)
if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext))
if (!(*pfnAddRefActCtx)(PyWin_DLLhActivationContext))
OutputDebugString("Python failed to load the default activation context\n");
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
if (pfnReleaseActCtx)
(*pfnReleaseActCtx)(PyWin_DLLhActivationContext);
break; break;
} }
return TRUE; return TRUE;
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
#include "importdl.h" #include "importdl.h"
#include <windows.h> #include <windows.h>
// "activation context" magic - see dl_nt.c...
extern ULONG_PTR _Py_ActivateActCtx();
void _Py_DeactivateActCtx(ULONG_PTR cookie);
const struct filedescr _PyImport_DynLoadFiletab[] = { const struct filedescr _PyImport_DynLoadFiletab[] = {
#ifdef _DEBUG #ifdef _DEBUG
{"_d.pyd", "rb", C_EXTENSION}, {"_d.pyd", "rb", C_EXTENSION},
...@@ -172,6 +176,7 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, ...@@ -172,6 +176,7 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
char pathbuf[260]; char pathbuf[260];
LPTSTR dummy; LPTSTR dummy;
unsigned int old_mode; unsigned int old_mode;
ULONG_PTR cookie = 0;
/* We use LoadLibraryEx so Windows looks for dependent DLLs /* We use LoadLibraryEx so Windows looks for dependent DLLs
in directory of pathname first. However, Windows95 in directory of pathname first. However, Windows95
can sometimes not work correctly unless the absolute can sometimes not work correctly unless the absolute
...@@ -184,10 +189,13 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, ...@@ -184,10 +189,13 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
if (GetFullPathName(pathname, if (GetFullPathName(pathname,
sizeof(pathbuf), sizeof(pathbuf),
pathbuf, pathbuf,
&dummy)) &dummy)) {
ULONG_PTR cookie = _Py_ActivateActCtx();
/* XXX This call doesn't exist in Windows CE */ /* XXX This call doesn't exist in Windows CE */
hDLL = LoadLibraryEx(pathname, NULL, hDLL = LoadLibraryEx(pathname, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH); LOAD_WITH_ALTERED_SEARCH_PATH);
_Py_DeactivateActCtx(cookie);
}
/* restore old error mode settings */ /* restore old error mode settings */
SetErrorMode(old_mode); SetErrorMode(old_mode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment