@@ -18,6 +18,63 @@ char dllVersionBuffer[16] = ""; // a private buffer
18
18
HMODULE PyWin_DLLhModule = NULL ;
19
19
const char * PyWin_DLLVersionString = dllVersionBuffer ;
20
20
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.
32
+
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 );
38
+
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 ;
46
+
47
+ void _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
+
61
+ ULONG_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
+
72
+ void _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
+ }
21
78
22
79
BOOL WINAPI DllMain (HANDLE hInst ,
23
80
ULONG ul_reason_for_call ,
@@ -29,9 +86,18 @@ BOOL WINAPI DllMain (HANDLE hInst,
29
86
PyWin_DLLhModule = hInst ;
30
87
// 1000 is a magic number I picked out of the air. Could do with a #define, I spose...
31
88
LoadString (hInst , 1000 , dllVersionBuffer , sizeof (dllVersionBuffer ));
32
- //initall();
89
+
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" );
33
96
break ;
97
+
34
98
case DLL_PROCESS_DETACH :
99
+ if (pfnReleaseActCtx )
100
+ (* pfnReleaseActCtx )(PyWin_DLLhActivationContext );
35
101
break ;
36
102
}
37
103
return TRUE;
0 commit comments