PageRenderTime 49ms CodeModel.GetById 42ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/PC/dl_nt.c

http://unladen-swallow.googlecode.com/
C | 106 lines | 68 code | 13 blank | 25 comment | 14 complexity | 53de5f3b32cdf5c251440fd20e0fa27e MD5 | raw file
  1/*
  2
  3Entry point for the Windows NT DLL.
  4
  5About the only reason for having this, is so initall() can automatically
  6be called, removing that burden (and possible source of frustration if 
  7forgotten) from the programmer.
  8
  9*/
 10
 11#include "Python.h"
 12#include "windows.h"
 13
 14#ifdef Py_ENABLE_SHARED
 15char dllVersionBuffer[16] = ""; // a private buffer
 16
 17// Python Globals
 18HMODULE PyWin_DLLhModule = NULL;
 19const char *PyWin_DLLVersionString = dllVersionBuffer;
 20
 21// Windows "Activation Context" work:
 22// Our .pyd extension modules are generally built without a manifest (ie,
 23// those included with Python and those built with a default distutils.
 24// This requires we perform some "activation context" magic when loading our
 25// extensions.  In summary:
 26// * As our DLL loads we save the context being used.
 27// * Before loading our extensions we re-activate our saved context.
 28// * After extension load is complete we restore the old context.
 29// As an added complication, this magic only works on XP or later - we simply
 30// use the existence (or not) of the relevant function pointers from kernel32.
 31// See bug 4566 (http://python.org/sf/4566) for more details.
 32
 33typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *);
 34typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *);
 35typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR);
 36typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE);
 37typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE);
 38
 39// locals and function pointers for this activation context magic.
 40static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public
 41static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL;
 42static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL;
 43static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL;
 44static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL;
 45static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL;
 46
 47void _LoadActCtxPointers()
 48{
 49	HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll");
 50	if (hKernel32)
 51		pfnGetCurrentActCtx = (PFN_GETCURRENTACTCTX) GetProcAddress(hKernel32, "GetCurrentActCtx");
 52	// If we can't load GetCurrentActCtx (ie, pre XP) , don't bother with the rest.
 53	if (pfnGetCurrentActCtx) {
 54		pfnActivateActCtx = (PFN_ACTIVATEACTCTX) GetProcAddress(hKernel32, "ActivateActCtx");
 55		pfnDeactivateActCtx = (PFN_DEACTIVATEACTCTX) GetProcAddress(hKernel32, "DeactivateActCtx");
 56		pfnAddRefActCtx = (PFN_ADDREFACTCTX) GetProcAddress(hKernel32, "AddRefActCtx");
 57		pfnReleaseActCtx = (PFN_RELEASEACTCTX) GetProcAddress(hKernel32, "ReleaseActCtx");
 58	}
 59}
 60
 61ULONG_PTR _Py_ActivateActCtx()
 62{
 63	ULONG_PTR ret = 0;
 64	if (PyWin_DLLhActivationContext && pfnActivateActCtx)
 65		if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) {
 66			OutputDebugString("Python failed to activate the activation context before loading a DLL\n");
 67			ret = 0; // no promise the failing function didn't change it!
 68		}
 69	return ret;
 70}
 71
 72void _Py_DeactivateActCtx(ULONG_PTR cookie)
 73{
 74	if (cookie && pfnDeactivateActCtx)
 75		if (!(*pfnDeactivateActCtx)(0, cookie))
 76			OutputDebugString("Python failed to de-activate the activation context\n");
 77}
 78
 79BOOL	WINAPI	DllMain (HANDLE hInst, 
 80						ULONG ul_reason_for_call,
 81						LPVOID lpReserved)
 82{
 83	switch (ul_reason_for_call)
 84	{
 85		case DLL_PROCESS_ATTACH:
 86			PyWin_DLLhModule = hInst;
 87			// 1000 is a magic number I picked out of the air.  Could do with a #define, I spose...
 88			LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer));
 89
 90			// and capture our activation context for use when loading extensions.
 91			_LoadActCtxPointers();
 92			if (pfnGetCurrentActCtx && pfnAddRefActCtx)
 93				if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext))
 94					if (!(*pfnAddRefActCtx)(PyWin_DLLhActivationContext))
 95						OutputDebugString("Python failed to load the default activation context\n");
 96			break;
 97
 98		case DLL_PROCESS_DETACH:
 99			if (pfnReleaseActCtx)
100				(*pfnReleaseActCtx)(PyWin_DLLhActivationContext);
101			break;
102	}
103	return TRUE;
104}
105
106#endif /* Py_ENABLE_SHARED */