blob: 4896c6dc8c25dd0a6c826d0e3853d366a2aed541 [file] [log] [blame]
Guido van Rossum22a1d361999-12-20 21:18:49 +00001
2/* Support for dynamic loading of extension modules */
3
Christian Heimesfaf2f632008-01-06 16:59:19 +00004#include "Python.h"
5
Thomas Wouters0e3f5912006-08-11 14:57:12 +00006#ifdef HAVE_DIRECT_H
Guido van Rossum22a1d361999-12-20 21:18:49 +00007#include <direct.h>
Thomas Wouters0e3f5912006-08-11 14:57:12 +00008#endif
Mark Hammond1f7838b2000-10-05 10:54:45 +00009#include <ctype.h>
Guido van Rossum22a1d361999-12-20 21:18:49 +000010
Guido van Rossum22a1d361999-12-20 21:18:49 +000011#include "importdl.h"
Steve Dower03a144b2014-12-15 20:45:23 -080012#include "patchlevel.h"
Guido van Rossume7ba4952007-06-06 23:52:48 +000013#include <windows.h>
Guido van Rossum22a1d361999-12-20 21:18:49 +000014
Mark Hammond9844a1f2009-01-27 23:46:57 +000015// "activation context" magic - see dl_nt.c...
Brian Curtin401f9f32012-05-13 11:19:23 -050016#if HAVE_SXS
Mark Hammond9844a1f2009-01-27 23:46:57 +000017extern ULONG_PTR _Py_ActivateActCtx();
18void _Py_DeactivateActCtx(ULONG_PTR cookie);
Brian Curtin401f9f32012-05-13 11:19:23 -050019#endif
Mark Hammond9844a1f2009-01-27 23:46:57 +000020
Guido van Rossum22a1d361999-12-20 21:18:49 +000021#ifdef _DEBUG
Steve Dower03a144b2014-12-15 20:45:23 -080022#define PYD_DEBUG_SUFFIX "_d"
Guido van Rossum22a1d361999-12-20 21:18:49 +000023#else
Steve Dower03a144b2014-12-15 20:45:23 -080024#define PYD_DEBUG_SUFFIX ""
Guido van Rossum22a1d361999-12-20 21:18:49 +000025#endif
Steve Dower03a144b2014-12-15 20:45:23 -080026
Steve Dower03a144b2014-12-15 20:45:23 -080027#ifdef PYD_PLATFORM_TAG
Serhiy Storchaka12b25382015-11-05 17:43:42 +020028#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) "-" PYD_PLATFORM_TAG ".pyd"
Steve Dower03a144b2014-12-15 20:45:23 -080029#else
Serhiy Storchaka12b25382015-11-05 17:43:42 +020030#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) ".pyd"
Steve Dower03a144b2014-12-15 20:45:23 -080031#endif
32
33#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX ".pyd"
34
35const char *_PyImport_DynLoadFiletab[] = {
36 PYD_TAGGED_SUFFIX,
37 PYD_UNTAGGED_SUFFIX,
Brett Cannon2657df42012-05-04 15:20:40 -040038 NULL
Guido van Rossum22a1d361999-12-20 21:18:49 +000039};
40
Mark Hammond1f7838b2000-10-05 10:54:45 +000041/* Function to return the name of the "python" DLL that the supplied module
42 directly imports. Looks through the list of imported modules and
43 returns the first entry that starts with "python" (case sensitive) and
44 is followed by nothing but numbers until the separator (period).
45
46 Returns a pointer to the import name, or NULL if no matching name was
47 located.
48
49 This function parses through the PE header for the module as loaded in
50 memory by the system loader. The PE header is accessed as documented by
51 Microsoft in the MSDN PE and COFF specification (2/99), and handles
52 both PE32 and PE32+. It only worries about the direct import table and
53 not the delay load import table since it's unlikely an extension is
54 going to be delay loading Python (after all, it's already loaded).
55
56 If any magic values are not found (e.g., the PE header or optional
57 header magic), then this function simply returns NULL. */
58
59#define DWORD_AT(mem) (*(DWORD *)(mem))
60#define WORD_AT(mem) (*(WORD *)(mem))
61
62static char *GetPythonImport (HINSTANCE hModule)
63{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 unsigned char *dllbase, *import_data, *import_name;
65 DWORD pe_offset, opt_offset;
66 WORD opt_magic;
67 int num_dict_off, import_off;
Mark Hammond1f7838b2000-10-05 10:54:45 +000068
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000069 /* Safety check input */
70 if (hModule == NULL) {
71 return NULL;
72 }
Mark Hammond1f7838b2000-10-05 10:54:45 +000073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 /* Module instance is also the base load address. First portion of
75 memory is the MS-DOS loader, which holds the offset to the PE
76 header (from the load base) at 0x3C */
77 dllbase = (unsigned char *)hModule;
78 pe_offset = DWORD_AT(dllbase + 0x3C);
Mark Hammond1f7838b2000-10-05 10:54:45 +000079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000080 /* The PE signature must be "PE\0\0" */
81 if (memcmp(dllbase+pe_offset,"PE\0\0",4)) {
82 return NULL;
83 }
Mark Hammond1f7838b2000-10-05 10:54:45 +000084
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 /* Following the PE signature is the standard COFF header (20
86 bytes) and then the optional header. The optional header starts
87 with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+
88 uses 64-bits for some fields). It might also be 0x107 for a ROM
89 image, but we don't process that here.
Mark Hammond1f7838b2000-10-05 10:54:45 +000090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 The optional header ends with a data dictionary that directly
92 points to certain types of data, among them the import entries
93 (in the second table entry). Based on the header type, we
94 determine offsets for the data dictionary count and the entry
95 within the dictionary pointing to the imports. */
Mark Hammond1f7838b2000-10-05 10:54:45 +000096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 opt_offset = pe_offset + 4 + 20;
98 opt_magic = WORD_AT(dllbase+opt_offset);
99 if (opt_magic == 0x10B) {
100 /* PE32 */
101 num_dict_off = 92;
102 import_off = 104;
103 } else if (opt_magic == 0x20B) {
104 /* PE32+ */
105 num_dict_off = 108;
106 import_off = 120;
107 } else {
108 /* Unsupported */
109 return NULL;
110 }
Mark Hammond1f7838b2000-10-05 10:54:45 +0000111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 /* Now if an import table exists, offset to it and walk the list of
113 imports. The import table is an array (ending when an entry has
114 empty values) of structures (20 bytes each), which contains (at
115 offset 12) a relative address (to the module base) at which a
116 string constant holding the import name is located. */
Mark Hammond1f7838b2000-10-05 10:54:45 +0000117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) {
119 /* We have at least 2 tables - the import table is the second
120 one. But still it may be that the table size is zero */
121 if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD)))
122 return NULL;
123 import_data = dllbase + DWORD_AT(dllbase +
124 opt_offset +
125 import_off);
126 while (DWORD_AT(import_data)) {
127 import_name = dllbase + DWORD_AT(import_data+12);
128 if (strlen(import_name) >= 6 &&
129 !strncmp(import_name,"python",6)) {
130 char *pch;
Mark Hammond1f7838b2000-10-05 10:54:45 +0000131
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000132#ifndef _DEBUG
133 /* In a release version, don't claim that python3.dll is
134 a Python DLL. */
135 if (strcmp(import_name, "python3.dll") == 0) {
136 import_data += 20;
137 continue;
138 }
139#endif
140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 /* Ensure python prefix is followed only
142 by numbers to the end of the basename */
143 pch = import_name + 6;
Thomas Heller1df04612004-07-02 08:53:57 +0000144#ifdef _DEBUG
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {
Thomas Heller1df04612004-07-02 08:53:57 +0000146#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 while (*pch && *pch != '.') {
Thomas Heller1df04612004-07-02 08:53:57 +0000148#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000149 if (*pch >= '0' && *pch <= '9') {
150 pch++;
151 } else {
152 pch = NULL;
153 break;
154 }
155 }
Mark Hammond1f7838b2000-10-05 10:54:45 +0000156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000157 if (pch) {
158 /* Found it - return the name */
159 return import_name;
160 }
161 }
162 import_data += 20;
163 }
164 }
165
166 return NULL;
Mark Hammond1f7838b2000-10-05 10:54:45 +0000167}
Mark Hammond1f7838b2000-10-05 10:54:45 +0000168
Nick Coghland5cacbb2015-05-23 22:24:10 +1000169dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
170 const char *shortname,
171 PyObject *pathname, FILE *fp)
Guido van Rossum22a1d361999-12-20 21:18:49 +0000172{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000173 dl_funcptr p;
174 char funcname[258], *import_python;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300175 const wchar_t *wpathname;
Guido van Rossum96a8fb71999-12-22 14:09:35 +0000176
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000177 _Py_CheckPython3();
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000178
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300179 wpathname = _PyUnicode_AsUnicode(pathname);
Victor Stinner33354472011-11-21 02:01:41 +0100180 if (wpathname == NULL)
181 return NULL;
182
Steve Dower76891542015-05-23 08:59:25 -0700183 PyOS_snprintf(funcname, sizeof(funcname), "%.20s_%.200s", prefix, shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +0000184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000185 {
186 HINSTANCE hDLL = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000187 unsigned int old_mode;
Brian Curtin401f9f32012-05-13 11:19:23 -0500188#if HAVE_SXS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000189 ULONG_PTR cookie = 0;
Brian Curtin401f9f32012-05-13 11:19:23 -0500190#endif
Victor Stinner67002af2011-10-02 20:35:10 +0200191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000192 /* Don't display a message box when Python can't load a DLL */
193 old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
Christian Heimesbbffeb62008-01-24 09:42:52 +0000194
Brian Curtin401f9f32012-05-13 11:19:23 -0500195#if HAVE_SXS
Brian Curtin589f89e2011-06-09 17:55:54 -0500196 cookie = _Py_ActivateActCtx();
Brian Curtin401f9f32012-05-13 11:19:23 -0500197#endif
Steve Dower2438cdf2019-03-29 16:37:16 -0700198 /* bpo-36085: We use LoadLibraryEx with restricted search paths
199 to avoid DLL preloading attacks and enable use of the
200 AddDllDirectory function. We add SEARCH_DLL_LOAD_DIR to
201 ensure DLLs adjacent to the PYD are preferred. */
Tony Roberts4860f012019-02-02 18:16:42 +0100202 Py_BEGIN_ALLOW_THREADS
Victor Stinner33354472011-11-21 02:01:41 +0100203 hDLL = LoadLibraryExW(wpathname, NULL,
Steve Dower2438cdf2019-03-29 16:37:16 -0700204 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
205 LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
Tony Roberts4860f012019-02-02 18:16:42 +0100206 Py_END_ALLOW_THREADS
Brian Curtin401f9f32012-05-13 11:19:23 -0500207#if HAVE_SXS
Brian Curtin589f89e2011-06-09 17:55:54 -0500208 _Py_DeactivateActCtx(cookie);
Brian Curtin401f9f32012-05-13 11:19:23 -0500209#endif
Christian Heimesbbffeb62008-01-24 09:42:52 +0000210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000211 /* restore old error mode settings */
212 SetErrorMode(old_mode);
Christian Heimesbbffeb62008-01-24 09:42:52 +0000213
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000214 if (hDLL==NULL){
215 PyObject *message;
216 unsigned int errorCode;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000217
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000218 /* Get an error string from Win32 error code */
219 wchar_t theInfo[256]; /* Pointer to error text
220 from system */
221 int theLength; /* Length of error text */
Guido van Rossum22a1d361999-12-20 21:18:49 +0000222
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000223 errorCode = GetLastError();
Guido van Rossum22a1d361999-12-20 21:18:49 +0000224
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 theLength = FormatMessageW(
226 FORMAT_MESSAGE_FROM_SYSTEM |
227 FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */
228 NULL, /* message source */
229 errorCode, /* the message (error) ID */
230 MAKELANGID(LANG_NEUTRAL,
231 SUBLANG_DEFAULT),
232 /* Default language */
233 theInfo, /* the buffer */
Gregory P. Smithb803c6c2013-03-23 16:05:36 -0700234 sizeof(theInfo) / sizeof(wchar_t), /* size in wchars */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000235 NULL); /* no additional format args. */
Guido van Rossum22a1d361999-12-20 21:18:49 +0000236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000237 /* Problem: could not get the error message.
238 This should not happen if called correctly. */
239 if (theLength == 0) {
240 message = PyUnicode_FromFormat(
Miss Islington (bot)786a4e12019-08-17 14:11:28 -0700241 "DLL load failed with error code %u while importing %s",
242 errorCode, shortname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000243 } else {
244 /* For some reason a \r\n
245 is appended to the text */
246 if (theLength >= 2 &&
247 theInfo[theLength-2] == '\r' &&
248 theInfo[theLength-1] == '\n') {
249 theLength -= 2;
250 theInfo[theLength] = '\0';
251 }
Miss Islington (bot)786a4e12019-08-17 14:11:28 -0700252 message = PyUnicode_FromFormat(
253 "DLL load failed while importing %s: ", shortname);
Amaury Forgeot d'Arcd6179e12008-01-03 23:42:13 +0000254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000255 PyUnicode_AppendAndDel(&message,
Victor Stinner9d3b93b2011-11-22 02:27:30 +0100256 PyUnicode_FromWideChar(
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257 theInfo,
258 theLength));
259 }
Victor Stinner67002af2011-10-02 20:35:10 +0200260 if (message != NULL) {
Richard Oudkerk409f9022013-06-10 15:38:54 +0100261 PyObject *shortname_obj = PyUnicode_FromString(shortname);
262 PyErr_SetImportError(message, shortname_obj, pathname);
263 Py_XDECREF(shortname_obj);
Brian Curtin09b86d12012-04-17 16:57:09 -0500264 Py_DECREF(message);
Victor Stinner67002af2011-10-02 20:35:10 +0200265 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 return NULL;
267 } else {
268 char buffer[256];
Mark Hammond1f7838b2000-10-05 10:54:45 +0000269
Victor Stinner2d322272011-04-04 23:05:53 +0200270 PyOS_snprintf(buffer, sizeof(buffer),
Thomas Heller1df04612004-07-02 08:53:57 +0000271#ifdef _DEBUG
Victor Stinner2d322272011-04-04 23:05:53 +0200272 "python%d%d_d.dll",
Thomas Heller1df04612004-07-02 08:53:57 +0000273#else
Victor Stinner2d322272011-04-04 23:05:53 +0200274 "python%d%d.dll",
Thomas Heller1df04612004-07-02 08:53:57 +0000275#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000276 PY_MAJOR_VERSION,PY_MINOR_VERSION);
277 import_python = GetPythonImport(hDLL);
Mark Hammond1f7838b2000-10-05 10:54:45 +0000278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279 if (import_python &&
Miss Islington (bot)920ec4b2019-08-24 03:22:14 -0700280 _stricmp(buffer,import_python)) {
Victor Stinner2d322272011-04-04 23:05:53 +0200281 PyErr_Format(PyExc_ImportError,
282 "Module use of %.150s conflicts "
283 "with this version of Python.",
284 import_python);
Tony Roberts4860f012019-02-02 18:16:42 +0100285 Py_BEGIN_ALLOW_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000286 FreeLibrary(hDLL);
Tony Roberts4860f012019-02-02 18:16:42 +0100287 Py_END_ALLOW_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 return NULL;
289 }
290 }
Tony Roberts4860f012019-02-02 18:16:42 +0100291 Py_BEGIN_ALLOW_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000292 p = GetProcAddress(hDLL, funcname);
Tony Roberts4860f012019-02-02 18:16:42 +0100293 Py_END_ALLOW_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000294 }
Guido van Rossum22a1d361999-12-20 21:18:49 +0000295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 return p;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000297}