/PC/dl_nt.c
http://unladen-swallow.googlecode.com/ · C · 106 lines · 68 code · 13 blank · 25 comment · 14 complexity · 53de5f3b32cdf5c251440fd20e0fa27e MD5 · raw file
- /*
- Entry point for the Windows NT DLL.
- About the only reason for having this, is so initall() can automatically
- be called, removing that burden (and possible source of frustration if
- forgotten) from the programmer.
- */
- #include "Python.h"
- #include "windows.h"
- #ifdef Py_ENABLE_SHARED
- char dllVersionBuffer[16] = ""; // a private buffer
- // Python Globals
- HMODULE PyWin_DLLhModule = NULL;
- 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,
- ULONG ul_reason_for_call,
- LPVOID lpReserved)
- {
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- PyWin_DLLhModule = hInst;
- // 1000 is a magic number I picked out of the air. Could do with a #define, I spose...
- LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer));
- // 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;
- case DLL_PROCESS_DETACH:
- if (pfnReleaseActCtx)
- (*pfnReleaseActCtx)(PyWin_DLLhActivationContext);
- break;
- }
- return TRUE;
- }
- #endif /* Py_ENABLE_SHARED */