- Notifications
You must be signed in to change notification settings - Fork 31.7k
/
Copy pathdl_nt.c
111 lines (95 loc) · 4.32 KB
/
dl_nt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
Entry point for the Windows NT DLL.
About the only reason for having this, is so initall() can automatically
be called, removing that burden (and possible source of frustration if
forgotten) from the programmer.
*/
#include"Python.h"
#include"windows.h"
#ifdefPy_ENABLE_SHARED
chardllVersionBuffer[16] =""; // a private buffer
// Python Globals
HMODULEPyWin_DLLhModule=NULL;
constchar*PyWin_DLLVersionString=dllVersionBuffer;
// Windows "Activation Context" work:
// Our .pyd extension modules are generally built without a manifest (ie,
// those included with Python and those built with a default distutils.
// This requires we perform some "activation context" magic when loading our
// extensions. In summary:
// * As our DLL loads we save the context being used.
// * Before loading our extensions we re-activate our saved context.
// * After extension load is complete we restore the old context.
// As an added complication, this magic only works on XP or later - we simply
// use the existence (or not) of the relevant function pointers from kernel32.
// See bug 4566 (http://python.org/sf/4566) for more details.
typedefBOOL (WINAPI*PFN_GETCURRENTACTCTX)(HANDLE*);
typedefBOOL (WINAPI*PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR*);
typedefBOOL (WINAPI*PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR);
typedefvoid (WINAPI*PFN_ADDREFACTCTX)(HANDLE);
typedefvoid (WINAPI*PFN_RELEASEACTCTX)(HANDLE);
// locals and function pointers for this activation context magic.
staticHANDLEPyWin_DLLhActivationContext=NULL; // one day it might be public
staticPFN_GETCURRENTACTCTXpfnGetCurrentActCtx=NULL;
staticPFN_ACTIVATEACTCTXpfnActivateActCtx=NULL;
staticPFN_DEACTIVATEACTCTXpfnDeactivateActCtx=NULL;
staticPFN_ADDREFACTCTXpfnAddRefActCtx=NULL;
staticPFN_RELEASEACTCTXpfnReleaseActCtx=NULL;
void_LoadActCtxPointers()
{
HINSTANCEhKernel32=GetModuleHandleW(L"kernel32.dll");
if (hKernel32)
pfnGetCurrentActCtx= (PFN_GETCURRENTACTCTX) GetProcAddress(hKernel32, "GetCurrentActCtx");
// If we can't load GetCurrentActCtx (ie, pre XP) , don't bother with the rest.
if (pfnGetCurrentActCtx) {
pfnActivateActCtx= (PFN_ACTIVATEACTCTX) GetProcAddress(hKernel32, "ActivateActCtx");
pfnDeactivateActCtx= (PFN_DEACTIVATEACTCTX) GetProcAddress(hKernel32, "DeactivateActCtx");
pfnAddRefActCtx= (PFN_ADDREFACTCTX) GetProcAddress(hKernel32, "AddRefActCtx");
pfnReleaseActCtx= (PFN_RELEASEACTCTX) GetProcAddress(hKernel32, "ReleaseActCtx");
}
}
ULONG_PTR_Py_ActivateActCtx()
{
ULONG_PTRret=0;
if (PyWin_DLLhActivationContext&&pfnActivateActCtx)
if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) {
OutputDebugString("Python failed to activate the activation context before loading a DLL\n");
ret=0; // no promise the failing function didn't change it!
}
returnret;
}
void_Py_DeactivateActCtx(ULONG_PTRcookie)
{
if (cookie&&pfnDeactivateActCtx)
if (!(*pfnDeactivateActCtx)(0, cookie))
OutputDebugString("Python failed to de-activate the activation context\n");
}
BOOLWINAPIDllMain (HANDLEhInst,
ULONGul_reason_for_call,
LPVOIDlpReserved)
{
switch (ul_reason_for_call)
{
caseDLL_PROCESS_ATTACH:
PyWin_DLLhModule=hInst;
// 1000 is a magic number I picked out of the air. Could do with a #define, I spose...
LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer));
// and capture our activation context for use when loading extensions.
_LoadActCtxPointers();
if (pfnGetCurrentActCtx&&pfnAddRefActCtx)
if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext)) {
(*pfnAddRefActCtx)(PyWin_DLLhActivationContext);
}
else {
OutputDebugString("Python failed to load the default "
"activation context\n");
return FALSE;
}
break;
caseDLL_PROCESS_DETACH:
if (pfnReleaseActCtx)
(*pfnReleaseActCtx)(PyWin_DLLhActivationContext);
break;
}
return TRUE;
}
#endif/* Py_ENABLE_SHARED */