blob: ae10fb56231b2e3581a93f33b8146fa1ed622557 [file] [log] [blame]
Guido van Rossum6dbd1901996-08-21 15:03:37 +00001/*
2
3Entry point for the Windows NT DLL.
4
5About the only reason for having this, is so initall() can automatically
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00006be called, removing that burden (and possible source of frustration if
Guido van Rossum6dbd1901996-08-21 15:03:37 +00007forgotten) from the programmer.
8
9*/
Guido van Rossum6dbd1901996-08-21 15:03:37 +000010
Guido van Rossuma1ebdbd1997-05-05 22:18:50 +000011#include "Python.h"
Guido van Rossume7ba4952007-06-06 23:52:48 +000012#include "windows.h"
Guido van Rossum6dbd1901996-08-21 15:03:37 +000013
Christian Heimesd59c64c2007-11-30 19:27:20 +000014#ifdef Py_ENABLE_SHARED
Guido van Rossumec680921997-09-29 23:37:12 +000015char dllVersionBuffer[16] = ""; // a private buffer
16
17// Python Globals
Guido van Rossum6dbd1901996-08-21 15:03:37 +000018HMODULE PyWin_DLLhModule = NULL;
Guido van Rossumec680921997-09-29 23:37:12 +000019const char *PyWin_DLLVersionString = dllVersionBuffer;
20
Brian Curtin401f9f32012-05-13 11:19:23 -050021#if HAVE_SXS
22// Windows "Activation Context" work.
Mark Hammond9844a1f2009-01-27 23:46:57 +000023// 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 Curtin401f9f32012-05-13 11:19:23 -050033// In Visual Studio 2010, side by side assemblies are no longer used by
34// default.
Mark Hammond9844a1f2009-01-27 23:46:57 +000035
36typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *);
37typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *);
38typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR);
39typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE);
40typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE);
41
42// locals and function pointers for this activation context magic.
43static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public
44static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL;
45static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL;
46static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL;
47static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL;
48static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL;
49
50void _LoadActCtxPointers()
51{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000052 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 Hammond9844a1f2009-01-27 23:46:57 +000062}
63
64ULONG_PTR _Py_ActivateActCtx()
65{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000066 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 Hammond9844a1f2009-01-27 23:46:57 +000073}
74
75void _Py_DeactivateActCtx(ULONG_PTR cookie)
76{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 if (cookie && pfnDeactivateActCtx)
78 if (!(*pfnDeactivateActCtx)(0, cookie))
79 OutputDebugString("Python failed to de-activate the activation context\n");
Mark Hammond9844a1f2009-01-27 23:46:57 +000080}
Brian Curtin401f9f32012-05-13 11:19:23 -050081#endif /* HAVE_SXS */
Guido van Rossum6dbd1901996-08-21 15:03:37 +000082
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083BOOL WINAPI DllMain (HANDLE hInst,
84 ULONG ul_reason_for_call,
85 LPVOID lpReserved)
Guido van Rossum6dbd1901996-08-21 15:03:37 +000086{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000087 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 Hammond9844a1f2009-01-27 23:46:57 +000093
Brian Curtin401f9f32012-05-13 11:19:23 -050094#if HAVE_SXS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 // 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 Curtin401f9f32012-05-13 11:19:23 -0500101#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000102 break;
Mark Hammond9844a1f2009-01-27 23:46:57 +0000103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 case DLL_PROCESS_DETACH:
Brian Curtin401f9f32012-05-13 11:19:23 -0500105#if HAVE_SXS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000106 if (pfnReleaseActCtx)
107 (*pfnReleaseActCtx)(PyWin_DLLhActivationContext);
Brian Curtin401f9f32012-05-13 11:19:23 -0500108#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 break;
110 }
111 return TRUE;
Guido van Rossum6dbd1901996-08-21 15:03:37 +0000112}
Christian Heimesd59c64c2007-11-30 19:27:20 +0000113
114#endif /* Py_ENABLE_SHARED */