1 | n/a | /* |
---|
2 | n/a | |
---|
3 | n/a | Entry point for the Windows NT DLL. |
---|
4 | n/a | |
---|
5 | n/a | About the only reason for having this, is so initall() can automatically |
---|
6 | n/a | be called, removing that burden (and possible source of frustration if |
---|
7 | n/a | forgotten) from the programmer. |
---|
8 | n/a | |
---|
9 | n/a | */ |
---|
10 | n/a | |
---|
11 | n/a | #include "Python.h" |
---|
12 | n/a | #include "windows.h" |
---|
13 | n/a | |
---|
14 | n/a | #ifdef Py_ENABLE_SHARED |
---|
15 | n/a | #ifdef MS_DLL_ID |
---|
16 | n/a | // The string is available at build, so fill the buffer immediately |
---|
17 | n/a | char dllVersionBuffer[16] = MS_DLL_ID; |
---|
18 | n/a | #else |
---|
19 | n/a | char dllVersionBuffer[16] = ""; // a private buffer |
---|
20 | n/a | #endif |
---|
21 | n/a | |
---|
22 | n/a | // Python Globals |
---|
23 | n/a | HMODULE PyWin_DLLhModule = NULL; |
---|
24 | n/a | const char *PyWin_DLLVersionString = dllVersionBuffer; |
---|
25 | n/a | |
---|
26 | n/a | #if HAVE_SXS |
---|
27 | n/a | // Windows "Activation Context" work. |
---|
28 | n/a | // Our .pyd extension modules are generally built without a manifest (ie, |
---|
29 | n/a | // those included with Python and those built with a default distutils. |
---|
30 | n/a | // This requires we perform some "activation context" magic when loading our |
---|
31 | n/a | // extensions. In summary: |
---|
32 | n/a | // * As our DLL loads we save the context being used. |
---|
33 | n/a | // * Before loading our extensions we re-activate our saved context. |
---|
34 | n/a | // * After extension load is complete we restore the old context. |
---|
35 | n/a | // As an added complication, this magic only works on XP or later - we simply |
---|
36 | n/a | // use the existence (or not) of the relevant function pointers from kernel32. |
---|
37 | n/a | // See bug 4566 (http://python.org/sf/4566) for more details. |
---|
38 | n/a | // In Visual Studio 2010, side by side assemblies are no longer used by |
---|
39 | n/a | // default. |
---|
40 | n/a | |
---|
41 | n/a | typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *); |
---|
42 | n/a | typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *); |
---|
43 | n/a | typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR); |
---|
44 | n/a | typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE); |
---|
45 | n/a | typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE); |
---|
46 | n/a | |
---|
47 | n/a | // locals and function pointers for this activation context magic. |
---|
48 | n/a | static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public |
---|
49 | n/a | static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL; |
---|
50 | n/a | static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL; |
---|
51 | n/a | static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL; |
---|
52 | n/a | static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL; |
---|
53 | n/a | static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL; |
---|
54 | n/a | |
---|
55 | n/a | void _LoadActCtxPointers() |
---|
56 | n/a | { |
---|
57 | n/a | HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll"); |
---|
58 | n/a | if (hKernel32) |
---|
59 | n/a | pfnGetCurrentActCtx = (PFN_GETCURRENTACTCTX) GetProcAddress(hKernel32, "GetCurrentActCtx"); |
---|
60 | n/a | // If we can't load GetCurrentActCtx (ie, pre XP) , don't bother with the rest. |
---|
61 | n/a | if (pfnGetCurrentActCtx) { |
---|
62 | n/a | pfnActivateActCtx = (PFN_ACTIVATEACTCTX) GetProcAddress(hKernel32, "ActivateActCtx"); |
---|
63 | n/a | pfnDeactivateActCtx = (PFN_DEACTIVATEACTCTX) GetProcAddress(hKernel32, "DeactivateActCtx"); |
---|
64 | n/a | pfnAddRefActCtx = (PFN_ADDREFACTCTX) GetProcAddress(hKernel32, "AddRefActCtx"); |
---|
65 | n/a | pfnReleaseActCtx = (PFN_RELEASEACTCTX) GetProcAddress(hKernel32, "ReleaseActCtx"); |
---|
66 | n/a | } |
---|
67 | n/a | } |
---|
68 | n/a | |
---|
69 | n/a | ULONG_PTR _Py_ActivateActCtx() |
---|
70 | n/a | { |
---|
71 | n/a | ULONG_PTR ret = 0; |
---|
72 | n/a | if (PyWin_DLLhActivationContext && pfnActivateActCtx) |
---|
73 | n/a | if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) { |
---|
74 | n/a | OutputDebugString("Python failed to activate the activation context before loading a DLL\n"); |
---|
75 | n/a | ret = 0; // no promise the failing function didn't change it! |
---|
76 | n/a | } |
---|
77 | n/a | return ret; |
---|
78 | n/a | } |
---|
79 | n/a | |
---|
80 | n/a | void _Py_DeactivateActCtx(ULONG_PTR cookie) |
---|
81 | n/a | { |
---|
82 | n/a | if (cookie && pfnDeactivateActCtx) |
---|
83 | n/a | if (!(*pfnDeactivateActCtx)(0, cookie)) |
---|
84 | n/a | OutputDebugString("Python failed to de-activate the activation context\n"); |
---|
85 | n/a | } |
---|
86 | n/a | #endif /* HAVE_SXS */ |
---|
87 | n/a | |
---|
88 | n/a | BOOL WINAPI DllMain (HANDLE hInst, |
---|
89 | n/a | ULONG ul_reason_for_call, |
---|
90 | n/a | LPVOID lpReserved) |
---|
91 | n/a | { |
---|
92 | n/a | switch (ul_reason_for_call) |
---|
93 | n/a | { |
---|
94 | n/a | case DLL_PROCESS_ATTACH: |
---|
95 | n/a | PyWin_DLLhModule = hInst; |
---|
96 | n/a | #ifndef MS_DLL_ID |
---|
97 | n/a | // If we have MS_DLL_ID, we don't need to load the string. |
---|
98 | n/a | // 1000 is a magic number I picked out of the air. Could do with a #define, I spose... |
---|
99 | n/a | LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer)); |
---|
100 | n/a | #endif |
---|
101 | n/a | |
---|
102 | n/a | #if HAVE_SXS |
---|
103 | n/a | // and capture our activation context for use when loading extensions. |
---|
104 | n/a | _LoadActCtxPointers(); |
---|
105 | n/a | if (pfnGetCurrentActCtx && pfnAddRefActCtx) |
---|
106 | n/a | if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext)) |
---|
107 | n/a | if (!(*pfnAddRefActCtx)(PyWin_DLLhActivationContext)) |
---|
108 | n/a | OutputDebugString("Python failed to load the default activation context\n"); |
---|
109 | n/a | #endif |
---|
110 | n/a | break; |
---|
111 | n/a | |
---|
112 | n/a | case DLL_PROCESS_DETACH: |
---|
113 | n/a | #if HAVE_SXS |
---|
114 | n/a | if (pfnReleaseActCtx) |
---|
115 | n/a | (*pfnReleaseActCtx)(PyWin_DLLhActivationContext); |
---|
116 | n/a | #endif |
---|
117 | n/a | break; |
---|
118 | n/a | } |
---|
119 | n/a | return TRUE; |
---|
120 | n/a | } |
---|
121 | n/a | |
---|
122 | n/a | #endif /* Py_ENABLE_SHARED */ |
---|