Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 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 | */ |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 10 | |
Guido van Rossum | a1ebdbd | 1997-05-05 22:18:50 +0000 | [diff] [blame] | 11 | #include "Python.h" |
Kristján Valur Jónsson | 629ec26 | 2007-05-26 19:31:39 +0000 | [diff] [blame] | 12 | #include "windows.h" |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 13 | |
Christian Heimes | 3971f6b | 2007-11-30 19:18:08 +0000 | [diff] [blame] | 14 | #ifdef Py_ENABLE_SHARED |
Guido van Rossum | ec68092 | 1997-09-29 23:37:12 +0000 | [diff] [blame] | 15 | char dllVersionBuffer[16] = ""; // a private buffer |
| 16 | |
| 17 | // Python Globals |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 18 | HMODULE PyWin_DLLhModule = NULL; |
Guido van Rossum | ec68092 | 1997-09-29 23:37:12 +0000 | [diff] [blame] | 19 | const char *PyWin_DLLVersionString = dllVersionBuffer; |
| 20 | |
Mark Hammond | 9f4f56d | 2009-01-27 23:12:23 +0000 | [diff] [blame] | 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 | } |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 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; |
Guido van Rossum | ec68092 | 1997-09-29 23:37:12 +0000 | [diff] [blame] | 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)); |
Mark Hammond | 9f4f56d | 2009-01-27 23:12:23 +0000 | [diff] [blame] | 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"); |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 96 | break; |
Mark Hammond | 9f4f56d | 2009-01-27 23:12:23 +0000 | [diff] [blame] | 97 | |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 98 | case DLL_PROCESS_DETACH: |
Mark Hammond | 9f4f56d | 2009-01-27 23:12:23 +0000 | [diff] [blame] | 99 | if (pfnReleaseActCtx) |
| 100 | (*pfnReleaseActCtx)(PyWin_DLLhActivationContext); |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 101 | break; |
| 102 | } |
| 103 | return TRUE; |
| 104 | } |
Christian Heimes | 3971f6b | 2007-11-30 19:18:08 +0000 | [diff] [blame] | 105 | |
| 106 | #endif /* Py_ENABLE_SHARED */ |