3 Entry point for the Windows NT DLL.
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.
14 #ifdef Py_ENABLE_SHARED
15 char dllVersionBuffer
[16] = ""; // a private buffer
18 HMODULE PyWin_DLLhModule
= NULL
;
19 const char *PyWin_DLLVersionString
= dllVersionBuffer
;
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.
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
);
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
;
47 void _LoadActCtxPointers()
49 HINSTANCE hKernel32
= GetModuleHandleW(L
"kernel32.dll");
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");
61 ULONG_PTR
_Py_ActivateActCtx()
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!
72 void _Py_DeactivateActCtx(ULONG_PTR cookie
)
74 if (cookie
&& pfnDeactivateActCtx
)
75 if (!(*pfnDeactivateActCtx
)(0, cookie
))
76 OutputDebugString("Python failed to de-activate the activation context\n");
79 BOOL WINAPI
DllMain (HANDLE hInst
,
80 ULONG ul_reason_for_call
,
83 switch (ul_reason_for_call
)
85 case DLL_PROCESS_ATTACH
:
86 PyWin_DLLhModule
= hInst
;
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
));
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");
98 case DLL_PROCESS_DETACH
:
100 (*pfnReleaseActCtx
)(PyWin_DLLhActivationContext
);
106 #endif /* Py_ENABLE_SHARED */