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 #ifdef MS_DLL_ID 16 // The string is available at build, so fill the buffer immediately 17 char dllVersionBuffer[16] = MS_DLL_ID; 18 #else 19 char dllVersionBuffer[16] = ""; // a private buffer 20 #endif 21 22 // Python Globals 23 HMODULE PyWin_DLLhModule = NULL; 24 const 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 41 typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *); 42 typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *); 43 typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR); 44 typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE); 45 typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE); 46 47 // locals and function pointers for this activation context magic. 48 static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public 49 static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL; 50 static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL; 51 static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL; 52 static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL; 53 static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL; 54 55 void _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 69 ULONG_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 80 void _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 88 BOOL 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