blob: 2bf3384b9eb5e1f46e6ea30471465fa7052d4d74 [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
Guido van Rossum22a1d361999-12-20 21:18:49 +000015#ifdef _DEBUG
Steve Dower03a144b2014-12-15 20:45:23 -080016#define PYD_DEBUG_SUFFIX "_d"
Guido van Rossum22a1d361999-12-20 21:18:49 +000017#else
Steve Dower03a144b2014-12-15 20:45:23 -080018#define PYD_DEBUG_SUFFIX ""
Guido van Rossum22a1d361999-12-20 21:18:49 +000019#endif
Steve Dower03a144b2014-12-15 20:45:23 -080020
Steve Dower03a144b2014-12-15 20:45:23 -080021#ifdef PYD_PLATFORM_TAG
Serhiy Storchaka12b25382015-11-05 17:43:42 +020022#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 -080023#else
Serhiy Storchaka12b25382015-11-05 17:43:42 +020024#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 -080025#endif
26
27#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX ".pyd"
28
29const char *_PyImport_DynLoadFiletab[] = {
30 PYD_TAGGED_SUFFIX,
31 PYD_UNTAGGED_SUFFIX,
Brett Cannon2657df42012-05-04 15:20:40 -040032 NULL
Guido van Rossum22a1d361999-12-20 21:18:49 +000033};
34
Mark Hammond1f7838b2000-10-05 10:54:45 +000035/* Function to return the name of the "python" DLL that the supplied module
36 directly imports. Looks through the list of imported modules and
37 returns the first entry that starts with "python" (case sensitive) and
38 is followed by nothing but numbers until the separator (period).
39
40 Returns a pointer to the import name, or NULL if no matching name was
41 located.
42
43 This function parses through the PE header for the module as loaded in
44 memory by the system loader. The PE header is accessed as documented by
45 Microsoft in the MSDN PE and COFF specification (2/99), and handles
46 both PE32 and PE32+. It only worries about the direct import table and
47 not the delay load import table since it's unlikely an extension is
48 going to be delay loading Python (after all, it's already loaded).
49
50 If any magic values are not found (e.g., the PE header or optional
51 header magic), then this function simply returns NULL. */
52
53#define DWORD_AT(mem) (*(DWORD *)(mem))
54#define WORD_AT(mem) (*(WORD *)(mem))
55
56static char *GetPythonImport (HINSTANCE hModule)
57{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000058 unsigned char *dllbase, *import_data, *import_name;
59 DWORD pe_offset, opt_offset;
60 WORD opt_magic;
61 int num_dict_off, import_off;
Mark Hammond1f7838b2000-10-05 10:54:45 +000062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 /* Safety check input */
64 if (hModule == NULL) {
65 return NULL;
66 }
Mark Hammond1f7838b2000-10-05 10:54:45 +000067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 /* Module instance is also the base load address. First portion of
69 memory is the MS-DOS loader, which holds the offset to the PE
70 header (from the load base) at 0x3C */
71 dllbase = (unsigned char *)hModule;
72 pe_offset = DWORD_AT(dllbase + 0x3C);
Mark Hammond1f7838b2000-10-05 10:54:45 +000073
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000074 /* The PE signature must be "PE\0\0" */
75 if (memcmp(dllbase+pe_offset,"PE\0\0",4)) {
76 return NULL;
77 }
Mark Hammond1f7838b2000-10-05 10:54:45 +000078
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 /* Following the PE signature is the standard COFF header (20
80 bytes) and then the optional header. The optional header starts
81 with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+
82 uses 64-bits for some fields). It might also be 0x107 for a ROM
83 image, but we don't process that here.
Mark Hammond1f7838b2000-10-05 10:54:45 +000084
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 The optional header ends with a data dictionary that directly
86 points to certain types of data, among them the import entries
87 (in the second table entry). Based on the header type, we
88 determine offsets for the data dictionary count and the entry
89 within the dictionary pointing to the imports. */
Mark Hammond1f7838b2000-10-05 10:54:45 +000090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 opt_offset = pe_offset + 4 + 20;
92 opt_magic = WORD_AT(dllbase+opt_offset);
93 if (opt_magic == 0x10B) {
94 /* PE32 */
95 num_dict_off = 92;
96 import_off = 104;
97 } else if (opt_magic == 0x20B) {
98 /* PE32+ */
99 num_dict_off = 108;
100 import_off = 120;
101 } else {
102 /* Unsupported */
103 return NULL;
104 }
Mark Hammond1f7838b2000-10-05 10:54:45 +0000105
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000106 /* Now if an import table exists, offset to it and walk the list of
107 imports. The import table is an array (ending when an entry has
108 empty values) of structures (20 bytes each), which contains (at
109 offset 12) a relative address (to the module base) at which a
110 string constant holding the import name is located. */
Mark Hammond1f7838b2000-10-05 10:54:45 +0000111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) {
113 /* We have at least 2 tables - the import table is the second
114 one. But still it may be that the table size is zero */
115 if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD)))
116 return NULL;
117 import_data = dllbase + DWORD_AT(dllbase +
118 opt_offset +
119 import_off);
120 while (DWORD_AT(import_data)) {
121 import_name = dllbase + DWORD_AT(import_data+12);
122 if (strlen(import_name) >= 6 &&
123 !strncmp(import_name,"python",6)) {
124 char *pch;
Mark Hammond1f7838b2000-10-05 10:54:45 +0000125
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000126#ifndef _DEBUG
127 /* In a release version, don't claim that python3.dll is
128 a Python DLL. */
129 if (strcmp(import_name, "python3.dll") == 0) {
130 import_data += 20;
131 continue;
132 }
133#endif
134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 /* Ensure python prefix is followed only
136 by numbers to the end of the basename */
137 pch = import_name + 6;
Thomas Heller1df04612004-07-02 08:53:57 +0000138#ifdef _DEBUG
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {
Thomas Heller1df04612004-07-02 08:53:57 +0000140#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 while (*pch && *pch != '.') {
Thomas Heller1df04612004-07-02 08:53:57 +0000142#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 if (*pch >= '0' && *pch <= '9') {
144 pch++;
145 } else {
146 pch = NULL;
147 break;
148 }
149 }
Mark Hammond1f7838b2000-10-05 10:54:45 +0000150
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000151 if (pch) {
152 /* Found it - return the name */
153 return import_name;
154 }
155 }
156 import_data += 20;
157 }
158 }
159
160 return NULL;
Mark Hammond1f7838b2000-10-05 10:54:45 +0000161}
Mark Hammond1f7838b2000-10-05 10:54:45 +0000162
Nick Coghland5cacbb2015-05-23 22:24:10 +1000163dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
164 const char *shortname,
165 PyObject *pathname, FILE *fp)
Guido van Rossum22a1d361999-12-20 21:18:49 +0000166{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000167 dl_funcptr p;
168 char funcname[258], *import_python;
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300169 const wchar_t *wpathname;
Guido van Rossum96a8fb71999-12-22 14:09:35 +0000170
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000171#ifndef _DEBUG
172 _Py_CheckPython3();
173#endif
174
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300175 wpathname = _PyUnicode_AsUnicode(pathname);
Victor Stinner33354472011-11-21 02:01:41 +0100176 if (wpathname == NULL)
177 return NULL;
178
Steve Dower76891542015-05-23 08:59:25 -0700179 PyOS_snprintf(funcname, sizeof(funcname), "%.20s_%.200s", prefix, shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +0000180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 {
182 HINSTANCE hDLL = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000183 unsigned int old_mode;
Victor Stinner67002af2011-10-02 20:35:10 +0200184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000185 /* Don't display a message box when Python can't load a DLL */
186 old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
Christian Heimesbbffeb62008-01-24 09:42:52 +0000187
Steve Dower2438cdf2019-03-29 16:37:16 -0700188 /* bpo-36085: We use LoadLibraryEx with restricted search paths
189 to avoid DLL preloading attacks and enable use of the
190 AddDllDirectory function. We add SEARCH_DLL_LOAD_DIR to
191 ensure DLLs adjacent to the PYD are preferred. */
Tony Roberts4860f012019-02-02 18:16:42 +0100192 Py_BEGIN_ALLOW_THREADS
Victor Stinner33354472011-11-21 02:01:41 +0100193 hDLL = LoadLibraryExW(wpathname, NULL,
Steve Dower2438cdf2019-03-29 16:37:16 -0700194 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
195 LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
Tony Roberts4860f012019-02-02 18:16:42 +0100196 Py_END_ALLOW_THREADS
Christian Heimesbbffeb62008-01-24 09:42:52 +0000197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 /* restore old error mode settings */
199 SetErrorMode(old_mode);
Christian Heimesbbffeb62008-01-24 09:42:52 +0000200
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 if (hDLL==NULL){
202 PyObject *message;
203 unsigned int errorCode;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000204
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 /* Get an error string from Win32 error code */
206 wchar_t theInfo[256]; /* Pointer to error text
207 from system */
208 int theLength; /* Length of error text */
Guido van Rossum22a1d361999-12-20 21:18:49 +0000209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000210 errorCode = GetLastError();
Guido van Rossum22a1d361999-12-20 21:18:49 +0000211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 theLength = FormatMessageW(
213 FORMAT_MESSAGE_FROM_SYSTEM |
214 FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */
215 NULL, /* message source */
216 errorCode, /* the message (error) ID */
217 MAKELANGID(LANG_NEUTRAL,
218 SUBLANG_DEFAULT),
219 /* Default language */
220 theInfo, /* the buffer */
Gregory P. Smithb803c6c2013-03-23 16:05:36 -0700221 sizeof(theInfo) / sizeof(wchar_t), /* size in wchars */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000222 NULL); /* no additional format args. */
Guido van Rossum22a1d361999-12-20 21:18:49 +0000223
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000224 /* Problem: could not get the error message.
225 This should not happen if called correctly. */
226 if (theLength == 0) {
227 message = PyUnicode_FromFormat(
shireenrao24fe4602019-08-17 16:50:39 -0400228 "DLL load failed with error code %u while importing %s",
229 errorCode, shortname);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000230 } else {
231 /* For some reason a \r\n
232 is appended to the text */
233 if (theLength >= 2 &&
234 theInfo[theLength-2] == '\r' &&
235 theInfo[theLength-1] == '\n') {
236 theLength -= 2;
237 theInfo[theLength] = '\0';
238 }
shireenrao24fe4602019-08-17 16:50:39 -0400239 message = PyUnicode_FromFormat(
240 "DLL load failed while importing %s: ", shortname);
Amaury Forgeot d'Arcd6179e12008-01-03 23:42:13 +0000241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 PyUnicode_AppendAndDel(&message,
Victor Stinner9d3b93b2011-11-22 02:27:30 +0100243 PyUnicode_FromWideChar(
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000244 theInfo,
245 theLength));
246 }
Victor Stinner67002af2011-10-02 20:35:10 +0200247 if (message != NULL) {
Richard Oudkerk409f9022013-06-10 15:38:54 +0100248 PyObject *shortname_obj = PyUnicode_FromString(shortname);
249 PyErr_SetImportError(message, shortname_obj, pathname);
250 Py_XDECREF(shortname_obj);
Brian Curtin09b86d12012-04-17 16:57:09 -0500251 Py_DECREF(message);
Victor Stinner67002af2011-10-02 20:35:10 +0200252 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000253 return NULL;
254 } else {
255 char buffer[256];
Mark Hammond1f7838b2000-10-05 10:54:45 +0000256
Victor Stinner2d322272011-04-04 23:05:53 +0200257 PyOS_snprintf(buffer, sizeof(buffer),
Thomas Heller1df04612004-07-02 08:53:57 +0000258#ifdef _DEBUG
Victor Stinner2d322272011-04-04 23:05:53 +0200259 "python%d%d_d.dll",
Thomas Heller1df04612004-07-02 08:53:57 +0000260#else
Victor Stinner2d322272011-04-04 23:05:53 +0200261 "python%d%d.dll",
Thomas Heller1df04612004-07-02 08:53:57 +0000262#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 PY_MAJOR_VERSION,PY_MINOR_VERSION);
264 import_python = GetPythonImport(hDLL);
Mark Hammond1f7838b2000-10-05 10:54:45 +0000265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 if (import_python &&
Minmin Gong05f2d842019-07-13 06:11:43 -0700267 _stricmp(buffer,import_python)) {
Victor Stinner2d322272011-04-04 23:05:53 +0200268 PyErr_Format(PyExc_ImportError,
269 "Module use of %.150s conflicts "
270 "with this version of Python.",
271 import_python);
Tony Roberts4860f012019-02-02 18:16:42 +0100272 Py_BEGIN_ALLOW_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273 FreeLibrary(hDLL);
Tony Roberts4860f012019-02-02 18:16:42 +0100274 Py_END_ALLOW_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275 return NULL;
276 }
277 }
Tony Roberts4860f012019-02-02 18:16:42 +0100278 Py_BEGIN_ALLOW_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279 p = GetProcAddress(hDLL, funcname);
Tony Roberts4860f012019-02-02 18:16:42 +0100280 Py_END_ALLOW_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281 }
Guido van Rossum22a1d361999-12-20 21:18:49 +0000282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000283 return p;
Guido van Rossum22a1d361999-12-20 21:18:49 +0000284}