FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
cpython/Python/dynload_win.c at 3.7 · python/cpython · GitHub
python
cpython
Repository navigation
Code
Issues
5k+
(5k+)
Pull requests
2.5k
(2.5k)
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
cpython
/
Python
/
dynload_win.c
Copy path
More file actions
More file actions
Latest commit
History
History
History
307 lines (258 loc) · 9.98 KB
Breadcrumbs
cpython
/
Python
/
dynload_win.c
Copy path
File metadata and controls
307 lines (258 loc) · 9.98 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* Support for dynamic loading of extension modules */
#include
"Python.h"
#ifdef
HAVE_DIRECT_H
#include
<direct.h>
#endif
#include
<ctype.h>
#include
"importdl.h"
#include
"patchlevel.h"
#include
<windows.h>
// "activation context" magic - see dl_nt.c...
#if
HAVE_SXS
extern
ULONG_PTR
_Py_ActivateActCtx
();
void
_Py_DeactivateActCtx
(
ULONG_PTR
cookie
);
#endif
#ifdef
_DEBUG
#define
PYD_DEBUG_SUFFIX
"_d"
#else
#define
PYD_DEBUG_SUFFIX
""
#endif
#ifdef
PYD_PLATFORM_TAG
#define
PYD_TAGGED_SUFFIX
PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) "-" PYD_PLATFORM_TAG ".pyd"
#else
#define
PYD_TAGGED_SUFFIX
PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) ".pyd"
#endif
#define
PYD_UNTAGGED_SUFFIX
PYD_DEBUG_SUFFIX ".pyd"
const
char
*
_PyImport_DynLoadFiletab
[]
=
{
PYD_TAGGED_SUFFIX
,
PYD_UNTAGGED_SUFFIX
,
NULL
};
/* Case insensitive string compare, to avoid any dependencies on particular
C RTL implementations */
static
int
strcasecmp
(
const
char
*
string1
,
const
char
*
string2
)
{
int
first
,
second
;
do
{
first
=
tolower
(
*
string1
);
second
=
tolower
(
*
string2
);
string1
++
;
string2
++
;
}
while
(
first
&&
first
==
second
);
return
(
first
-
second
);
}
/* Function to return the name of the "python" DLL that the supplied module
directly imports. Looks through the list of imported modules and
returns the first entry that starts with "python" (case sensitive) and
is followed by nothing but numbers until the separator (period).
Returns a pointer to the import name, or NULL if no matching name was
located.
This function parses through the PE header for the module as loaded in
memory by the system loader. The PE header is accessed as documented by
Microsoft in the MSDN PE and COFF specification (2/99), and handles
both PE32 and PE32+. It only worries about the direct import table and
not the delay load import table since it's unlikely an extension is
going to be delay loading Python (after all, it's already loaded).
If any magic values are not found (e.g., the PE header or optional
header magic), then this function simply returns NULL. */
#define
DWORD_AT
(
mem
) (*(DWORD *)(mem))
#define
WORD_AT
(
mem
) (*(WORD *)(mem))
static
char
*
GetPythonImport
(
HINSTANCE
hModule
)
{
unsigned
char
*
dllbase
,
*
import_data
,
*
import_name
;
DWORD
pe_offset
,
opt_offset
;
WORD
opt_magic
;
int
num_dict_off
,
import_off
;
/* Safety check input */
if
(
hModule
==
NULL
) {
return
NULL
;
}
/* Module instance is also the base load address. First portion of
memory is the MS-DOS loader, which holds the offset to the PE
header (from the load base) at 0x3C */
dllbase
=
(
unsigned
char
*
)
hModule
;
pe_offset
=
DWORD_AT
(
dllbase
+
0x3C
);
/* The PE signature must be "PE\0\0" */
if
(
memcmp
(
dllbase
+
pe_offset
,
"PE\0\0"
,
4
)) {
return
NULL
;
}
/* Following the PE signature is the standard COFF header (20
bytes) and then the optional header. The optional header starts
with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+
uses 64-bits for some fields). It might also be 0x107 for a ROM
image, but we don't process that here.
The optional header ends with a data dictionary that directly
points to certain types of data, among them the import entries
(in the second table entry). Based on the header type, we
determine offsets for the data dictionary count and the entry
within the dictionary pointing to the imports. */
opt_offset
=
pe_offset
+
4
+
20
;
opt_magic
=
WORD_AT
(
dllbase
+
opt_offset
);
if
(
opt_magic
==
0x10B
) {
/* PE32 */
num_dict_off
=
92
;
import_off
=
104
;
}
else
if
(
opt_magic
==
0x20B
) {
/* PE32+ */
num_dict_off
=
108
;
import_off
=
120
;
}
else
{
/* Unsupported */
return
NULL
;
}
/* Now if an import table exists, offset to it and walk the list of
imports. The import table is an array (ending when an entry has
empty values) of structures (20 bytes each), which contains (at
offset 12) a relative address (to the module base) at which a
string constant holding the import name is located. */
if
(
DWORD_AT
(
dllbase
+
opt_offset
+
num_dict_off
) >=
2
) {
/* We have at least 2 tables - the import table is the second
one. But still it may be that the table size is zero */
if
(
0
==
DWORD_AT
(
dllbase
+
opt_offset
+
import_off
+
sizeof
(
DWORD
)))
return
NULL
;
import_data
=
dllbase
+
DWORD_AT
(
dllbase
+
opt_offset
+
import_off
);
while
(
DWORD_AT
(
import_data
)) {
import_name
=
dllbase
+
DWORD_AT
(
import_data
+
12
);
if
(
strlen
(
import_name
) >=
6
&&
!
strncmp
(
import_name
,
"python"
,
6
)) {
char
*
pch
;
#ifndef
_DEBUG
/* In a release version, don't claim that python3.dll is
a Python DLL. */
if
(
strcmp
(
import_name
,
"python3.dll"
)
==
0
) {
import_data
+=
20
;
continue
;
}
#endif
/* Ensure python prefix is followed only
by numbers to the end of the basename */
pch
=
import_name
+
6
;
#ifdef
_DEBUG
while
(
*
pch
&&
pch
[
0
]
!=
'_'
&&
pch
[
1
]
!=
'd'
&&
pch
[
2
]
!=
'.'
) {
#else
while
(
*
pch
&&
*
pch
!=
'.'
) {
#endif
if
(
*
pch
>=
'0'
&&
*
pch
<=
'9'
) {
pch
++
;
}
else
{
pch
=
NULL
;
break
;
}
}
if
(
pch
) {
/* Found it - return the name */
return
import_name
;
}
}
import_data
+=
20
;
}
}
return
NULL
;
}
dl_funcptr
_PyImport_FindSharedFuncptrWindows
(
const
char
*
prefix
,
const
char
*
shortname
,
PyObject
*
pathname
,
FILE
*
fp
)
{
dl_funcptr
p
;
char
funcname
[
258
],
*
import_python
;
const
wchar_t
*
wpathname
;
_Py_CheckPython3
();
wpathname
=
_PyUnicode_AsUnicode
(
pathname
);
if
(
wpathname
==
NULL
)
return
NULL
;
PyOS_snprintf
(
funcname
,
sizeof
(
funcname
),
"%.20s_%.200s"
,
prefix
,
shortname
);
{
HINSTANCE
hDLL
=
NULL
;
unsigned
int
old_mode
;
#if
HAVE_SXS
ULONG_PTR
cookie
=
0
;
#endif
/* Don't display a message box when Python can't load a DLL */
old_mode
=
SetErrorMode
(
SEM_FAILCRITICALERRORS
);
#if
HAVE_SXS
cookie
=
_Py_ActivateActCtx
();
#endif
/* We use LoadLibraryEx so Windows looks for dependent DLLs
in directory of pathname first. */
/* XXX This call doesn't exist in Windows CE */
hDLL
=
LoadLibraryExW
(
wpathname
,
NULL
,
LOAD_WITH_ALTERED_SEARCH_PATH
);
#if
HAVE_SXS
_Py_DeactivateActCtx
(
cookie
);
#endif
/* restore old error mode settings */
SetErrorMode
(
old_mode
);
if
(
hDLL
==
NULL
){
PyObject
*
message
;
unsigned
int
errorCode
;
/* Get an error string from Win32 error code */
wchar_t
theInfo
[
256
];
/* Pointer to error text
from system */
int
theLength
;
/* Length of error text */
errorCode
=
GetLastError
();
theLength
=
FormatMessageW
(
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
/* flags */
NULL
,
/* message source */
errorCode
,
/* the message (error) ID */
MAKELANGID
(
LANG_NEUTRAL
,
SUBLANG_DEFAULT
),
/* Default language */
theInfo
,
/* the buffer */
sizeof
(
theInfo
) /
sizeof
(
wchar_t
),
/* size in wchars */
NULL
);
/* no additional format args. */
/* Problem: could not get the error message.
This should not happen if called correctly. */
if
(
theLength
==
0
) {
message
=
PyUnicode_FromFormat
(
"DLL load failed with error code %u"
,
errorCode
);
}
else
{
/* For some reason a \r\n
is appended to the text */
if
(
theLength
>=
2
&&
theInfo
[
theLength
-
2
]
==
'\r'
&&
theInfo
[
theLength
-
1
]
==
'\n'
) {
theLength
-=
2
;
theInfo
[
theLength
]
=
'\0'
;
}
message
=
PyUnicode_FromString
(
"DLL load failed: "
);
PyUnicode_AppendAndDel
(
&
message
,
PyUnicode_FromWideChar
(
theInfo
,
theLength
));
}
if
(
message
!=
NULL
) {
PyObject
*
shortname_obj
=
PyUnicode_FromString
(
shortname
);
PyErr_SetImportError
(
message
,
shortname_obj
,
pathname
);
Py_XDECREF
(
shortname_obj
);
Py_DECREF
(
message
);
}
return
NULL
;
}
else
{
char
buffer
[
256
];
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
#ifdef
_DEBUG
"python%d%d_d.dll"
,
#else
"python%d%d.dll"
,
#endif
PY_MAJOR_VERSION
,
PY_MINOR_VERSION
);
import_python
=
GetPythonImport
(
hDLL
);
if
(
import_python
&&
strcasecmp
(
buffer
,
import_python
)) {
PyErr_Format
(
PyExc_ImportError
,
"Module use of %.150s conflicts "
"with this version of Python."
,
import_python
);
FreeLibrary
(
hDLL
);
return
NULL
;
}
}
p
=
GetProcAddress
(
hDLL
,
funcname
);
}
return
p
;
}
Back
|
FazBrowse Home
|
New Git URL