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 |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 6 | be called, removing that burden (and possible source of frustration if |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 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" |
Guido van Rossum | e7ba495 | 2007-06-06 23:52:48 +0000 | [diff] [blame] | 12 | #include "windows.h" |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 13 | |
Christian Heimes | d59c64c | 2007-11-30 19:27:20 +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 | |
Brian Curtin | 401f9f3 | 2012-05-13 11:19:23 -0500 | [diff] [blame] | 21 | #if HAVE_SXS |
| 22 | // Windows "Activation Context" work. |
Mark Hammond | 9844a1f | 2009-01-27 23:46:57 +0000 | [diff] [blame] | 23 | // Our .pyd extension modules are generally built without a manifest (ie, |
| 24 | // those included with Python and those built with a default distutils. |
| 25 | // This requires we perform some "activation context" magic when loading our |
| 26 | // extensions. In summary: |
| 27 | // * As our DLL loads we save the context being used. |
| 28 | // * Before loading our extensions we re-activate our saved context. |
| 29 | // * After extension load is complete we restore the old context. |
| 30 | // As an added complication, this magic only works on XP or later - we simply |
| 31 | // use the existence (or not) of the relevant function pointers from kernel32. |
| 32 | // See bug 4566 (http://python.org/sf/4566) for more details. |
Brian Curtin | 401f9f3 | 2012-05-13 11:19:23 -0500 | [diff] [blame] | 33 | // In Visual Studio 2010, side by side assemblies are no longer used by |
| 34 | // default. |
Mark Hammond | 9844a1f | 2009-01-27 23:46:57 +0000 | [diff] [blame] | 35 | |
| 36 | typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *); |
| 37 | typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *); |
| 38 | typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR); |
| 39 | typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE); |
| 40 | typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE); |
| 41 | |
| 42 | // locals and function pointers for this activation context magic. |
| 43 | static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public |
| 44 | static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL; |
| 45 | static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL; |
| 46 | static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL; |
| 47 | static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL; |
| 48 | static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL; |
| 49 | |
| 50 | void _LoadActCtxPointers() |
| 51 | { |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 52 | HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll"); |
| 53 | if (hKernel32) |
| 54 | pfnGetCurrentActCtx = (PFN_GETCURRENTACTCTX) GetProcAddress(hKernel32, "GetCurrentActCtx"); |
| 55 | // If we can't load GetCurrentActCtx (ie, pre XP) , don't bother with the rest. |
| 56 | if (pfnGetCurrentActCtx) { |
| 57 | pfnActivateActCtx = (PFN_ACTIVATEACTCTX) GetProcAddress(hKernel32, "ActivateActCtx"); |
| 58 | pfnDeactivateActCtx = (PFN_DEACTIVATEACTCTX) GetProcAddress(hKernel32, "DeactivateActCtx"); |
| 59 | pfnAddRefActCtx = (PFN_ADDREFACTCTX) GetProcAddress(hKernel32, "AddRefActCtx"); |
| 60 | pfnReleaseActCtx = (PFN_RELEASEACTCTX) GetProcAddress(hKernel32, "ReleaseActCtx"); |
| 61 | } |
Mark Hammond | 9844a1f | 2009-01-27 23:46:57 +0000 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | ULONG_PTR _Py_ActivateActCtx() |
| 65 | { |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 66 | ULONG_PTR ret = 0; |
| 67 | if (PyWin_DLLhActivationContext && pfnActivateActCtx) |
| 68 | if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) { |
| 69 | OutputDebugString("Python failed to activate the activation context before loading a DLL\n"); |
| 70 | ret = 0; // no promise the failing function didn't change it! |
| 71 | } |
| 72 | return ret; |
Mark Hammond | 9844a1f | 2009-01-27 23:46:57 +0000 | [diff] [blame] | 73 | } |
| 74 | |
| 75 | void _Py_DeactivateActCtx(ULONG_PTR cookie) |
| 76 | { |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 77 | if (cookie && pfnDeactivateActCtx) |
| 78 | if (!(*pfnDeactivateActCtx)(0, cookie)) |
| 79 | OutputDebugString("Python failed to de-activate the activation context\n"); |
Mark Hammond | 9844a1f | 2009-01-27 23:46:57 +0000 | [diff] [blame] | 80 | } |
Brian Curtin | 401f9f3 | 2012-05-13 11:19:23 -0500 | [diff] [blame] | 81 | #endif /* HAVE_SXS */ |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 82 | |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 83 | BOOL WINAPI DllMain (HANDLE hInst, |
| 84 | ULONG ul_reason_for_call, |
| 85 | LPVOID lpReserved) |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 86 | { |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 87 | switch (ul_reason_for_call) |
| 88 | { |
| 89 | case DLL_PROCESS_ATTACH: |
| 90 | PyWin_DLLhModule = hInst; |
| 91 | // 1000 is a magic number I picked out of the air. Could do with a #define, I spose... |
| 92 | LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer)); |
Mark Hammond | 9844a1f | 2009-01-27 23:46:57 +0000 | [diff] [blame] | 93 | |
Brian Curtin | 401f9f3 | 2012-05-13 11:19:23 -0500 | [diff] [blame] | 94 | #if HAVE_SXS |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 95 | // and capture our activation context for use when loading extensions. |
| 96 | _LoadActCtxPointers(); |
| 97 | if (pfnGetCurrentActCtx && pfnAddRefActCtx) |
| 98 | if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext)) |
| 99 | if (!(*pfnAddRefActCtx)(PyWin_DLLhActivationContext)) |
| 100 | OutputDebugString("Python failed to load the default activation context\n"); |
Brian Curtin | 401f9f3 | 2012-05-13 11:19:23 -0500 | [diff] [blame] | 101 | #endif |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 102 | break; |
Mark Hammond | 9844a1f | 2009-01-27 23:46:57 +0000 | [diff] [blame] | 103 | |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 104 | case DLL_PROCESS_DETACH: |
Brian Curtin | 401f9f3 | 2012-05-13 11:19:23 -0500 | [diff] [blame] | 105 | #if HAVE_SXS |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 106 | if (pfnReleaseActCtx) |
| 107 | (*pfnReleaseActCtx)(PyWin_DLLhActivationContext); |
Brian Curtin | 401f9f3 | 2012-05-13 11:19:23 -0500 | [diff] [blame] | 108 | #endif |
Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 109 | break; |
| 110 | } |
| 111 | return TRUE; |
Guido van Rossum | 6dbd190 | 1996-08-21 15:03:37 +0000 | [diff] [blame] | 112 | } |
Christian Heimes | d59c64c | 2007-11-30 19:27:20 +0000 | [diff] [blame] | 113 | |
| 114 | #endif /* Py_ENABLE_SHARED */ |