| /* | 
 |  | 
 | 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 */ |