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 15#ifdef MS_DLL_ID 16// The string is available at build, so fill the buffer immediately 17char dllVersionBuffer[16] = MS_DLL_ID; 18#else 19char dllVersionBuffer[16] = ""; // a private buffer 20#endif 21 22// Python Globals 23HMODULE PyWin_DLLhModule = NULL; 24const char *PyWin_DLLVersionString = dllVersionBuffer; 25 26#if HAVE_SXS 27// Windows "Activation Context" work. 28// Our .pyd extension modules are generally built without a manifest (ie, 29// those included with Python and those built with a default distutils. 30// This requires we perform some "activation context" magic when loading our 31// extensions. In summary: 32// * As our DLL loads we save the context being used. 33// * Before loading our extensions we re-activate our saved context. 34// * After extension load is complete we restore the old context. 35// As an added complication, this magic only works on XP or later - we simply 36// use the existence (or not) of the relevant function pointers from kernel32. 37// See bug 4566 (http://python.org/sf/4566) for more details. 38// In Visual Studio 2010, side by side assemblies are no longer used by 39// default. 40 41typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *); 42typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *); 43typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR); 44typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE); 45typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE); 46 47// locals and function pointers for this activation context magic. 48static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public 49static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL; 50static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL; 51static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL; 52static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL; 53static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL; 54 55void _LoadActCtxPointers() 56{ 57 HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll"); 58 if (hKernel32) 59 pfnGetCurrentActCtx = (PFN_GETCURRENTACTCTX) GetProcAddress(hKernel32, "GetCurrentActCtx"); 60 // If we can't load GetCurrentActCtx (ie, pre XP) , don't bother with the rest. 61 if (pfnGetCurrentActCtx) { 62 pfnActivateActCtx = (PFN_ACTIVATEACTCTX) GetProcAddress(hKernel32, "ActivateActCtx"); 63 pfnDeactivateActCtx = (PFN_DEACTIVATEACTCTX) GetProcAddress(hKernel32, "DeactivateActCtx"); 64 pfnAddRefActCtx = (PFN_ADDREFACTCTX) GetProcAddress(hKernel32, "AddRefActCtx"); 65 pfnReleaseActCtx = (PFN_RELEASEACTCTX) GetProcAddress(hKernel32, "ReleaseActCtx"); 66 } 67} 68 69ULONG_PTR _Py_ActivateActCtx() 70{ 71 ULONG_PTR ret = 0; 72 if (PyWin_DLLhActivationContext && pfnActivateActCtx) 73 if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) { 74 OutputDebugString("Python failed to activate the activation context before loading a DLL\n"); 75 ret = 0; // no promise the failing function didn't change it! 76 } 77 return ret; 78} 79 80void _Py_DeactivateActCtx(ULONG_PTR cookie) 81{ 82 if (cookie && pfnDeactivateActCtx) 83 if (!(*pfnDeactivateActCtx)(0, cookie)) 84 OutputDebugString("Python failed to de-activate the activation context\n"); 85} 86#endif /* HAVE_SXS */ 87 88BOOL WINAPI DllMain (HANDLE hInst, 89 ULONG ul_reason_for_call, 90 LPVOID lpReserved) 91{ 92 switch (ul_reason_for_call) 93 { 94 case DLL_PROCESS_ATTACH: 95 PyWin_DLLhModule = hInst; 96#ifndef MS_DLL_ID 97 // If we have MS_DLL_ID, we don't need to load the string. 98 // 1000 is a magic number I picked out of the air. Could do with a #define, I spose... 99 LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer)); 100#endif 101 102#if HAVE_SXS 103 // and capture our activation context for use when loading extensions. 104 _LoadActCtxPointers(); 105 if (pfnGetCurrentActCtx && pfnAddRefActCtx) 106 if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext)) 107 if (!(*pfnAddRefActCtx)(PyWin_DLLhActivationContext)) 108 OutputDebugString("Python failed to load the default activation context\n"); 109#endif 110 break; 111 112 case DLL_PROCESS_DETACH: 113#if HAVE_SXS 114 if (pfnReleaseActCtx) 115 (*pfnReleaseActCtx)(PyWin_DLLhActivationContext); 116#endif 117 break; 118 } 119 return TRUE; 120} 121 122#endif /* Py_ENABLE_SHARED */ 123