1 /* 2 3 Entry point for the Windows NT DLL. 4 5 About the only reason for having this, is so initall() can automatically 6 be called, removing that burden (and possible source of frustration if 7 forgotten) from the programmer. 8 9 */ 10 11 #include "Python.h" 12 #include "windows.h" 13 14 #ifdef Py_ENABLE_SHARED 15 char dllVersionBuffer[16] = ""; // a private buffer 16 17 // Python Globals 18 HMODULE PyWin_DLLhModule = NULL; 19 const 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 33 typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *); 34 typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *); 35 typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR); 36 typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE); 37 typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE); 38 39 // locals and function pointers for this activation context magic. 40 static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public 41 static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL; 42 static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL; 43 static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL; 44 static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL; 45 static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL; 46 47 void _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 61 ULONG_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 72 void _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 79 BOOL 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 */ 107