blob: f8af8026f4cbfb1e74294cd5c2774ba8de130e13 [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
6be called, removing that burden (and possible source of frustration if
7forgotten) 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"
Kristján Valur Jónsson629ec262007-05-26 19:31:39 +000012#include "windows.h"
Guido van Rossum6dbd1901996-08-21 15:03:37 +000013
Christian Heimes3971f6b2007-11-30 19:18:08 +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
Mark Hammond9f4f56d2009-01-27 23:12:23 +000021// 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
33typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *);
34typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *);
35typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR);
36typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE);
37typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE);
38
39// locals and function pointers for this activation context magic.
40static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public
41static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL;
42static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL;
43static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL;
44static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL;
45static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL;
46
47void _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
61ULONG_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
72void _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 Rossum6dbd1901996-08-21 15:03:37 +000078
79BOOL 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 Rossumec680921997-09-29 23:37:12 +000087 // 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 Hammond9f4f56d2009-01-27 23:12:23 +000089
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 Rossum6dbd1901996-08-21 15:03:37 +000096 break;
Mark Hammond9f4f56d2009-01-27 23:12:23 +000097
Guido van Rossum6dbd1901996-08-21 15:03:37 +000098 case DLL_PROCESS_DETACH:
Mark Hammond9f4f56d2009-01-27 23:12:23 +000099 if (pfnReleaseActCtx)
100 (*pfnReleaseActCtx)(PyWin_DLLhActivationContext);
Guido van Rossum6dbd1901996-08-21 15:03:37 +0000101 break;
102 }
103 return TRUE;
104}
Christian Heimes3971f6b2007-11-30 19:18:08 +0000105
106#endif /* Py_ENABLE_SHARED */