FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
cpython/Python/dynload_win.c at 2.7 · python-emscripten/cpython · GitHub
python-emscripten
cpython
Repository navigation
Code
Pull requests
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
274 lines (230 loc) · 9.22 KB
Breadcrumbs
cpython
/
Python
/
dynload_win.c
Copy path
File metadata and controls
274 lines (230 loc) · 9.22 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
/* 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
<windows.h>
// "activation context" magic - see dl_nt.c...
extern
ULONG_PTR
_Py_ActivateActCtx
();
void
_Py_DeactivateActCtx
(
ULONG_PTR
cookie
);
const
struct
filedescr
_PyImport_DynLoadFiletab
[]
=
{
#ifdef
_DEBUG
{
"_d.pyd"
,
"rb"
,
C_EXTENSION
},
#else
{
".pyd"
,
"rb"
,
C_EXTENSION
},
#endif
{
0
,
0
}
};
/* Case insensitive string compare, to avoid any dependencies on particular
C RTL implementations */
static
int
strcasecmp
(
char
*
string1
,
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
;
/* 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_GetDynLoadFunc
(
const
char
*
fqname
,
const
char
*
shortname
,
const
char
*
pathname
,
FILE
*
fp
)
{
dl_funcptr
p
;
char
funcname
[
258
],
*
import_python
;
PyOS_snprintf
(
funcname
,
sizeof
(
funcname
),
"init%.200s"
,
shortname
);
{
HINSTANCE
hDLL
=
NULL
;
char
pathbuf
[
260
];
LPTSTR
dummy
;
unsigned
int
old_mode
;
ULONG_PTR
cookie
=
0
;
/* We use LoadLibraryEx so Windows looks for dependent DLLs
in directory of pathname first. However, Windows95
can sometimes not work correctly unless the absolute
path is used. If GetFullPathName() fails, the LoadLibrary
will certainly fail too, so use its error code */
/* Don't display a message box when Python can't load a DLL */
old_mode
=
SetErrorMode
(
SEM_FAILCRITICALERRORS
);
if
(
GetFullPathName
(
pathname
,
sizeof
(
pathbuf
),
pathbuf
,
&
dummy
)) {
ULONG_PTR
cookie
=
_Py_ActivateActCtx
();
/* XXX This call doesn't exist in Windows CE */
hDLL
=
LoadLibraryEx
(
pathname
,
NULL
,
LOAD_WITH_ALTERED_SEARCH_PATH
);
_Py_DeactivateActCtx
(
cookie
);
}
/* restore old error mode settings */
SetErrorMode
(
old_mode
);
if
(
hDLL
==
NULL
){
char
errBuf
[
256
];
unsigned
int
errorCode
;
/* Get an error string from Win32 error code */
char
theInfo
[
256
];
/* Pointer to error text
from system */
int
theLength
;
/* Length of error text */
errorCode
=
GetLastError
();
theLength
=
FormatMessage
(
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
/* flags */
NULL
,
/* message source */
errorCode
,
/* the message (error) ID */
0
,
/* default language environment */
(
LPTSTR
)
theInfo
,
/* the buffer */
sizeof
(
theInfo
),
/* the buffer size */
NULL
);
/* no additional format args. */
/* Problem: could not get the error message.
This should not happen if called correctly. */
if
(
theLength
==
0
) {
PyOS_snprintf
(
errBuf
,
sizeof
(
errBuf
),
"DLL load failed with error code %d"
,
errorCode
);
}
else
{
size_t
len
;
/* 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'
;
}
strcpy
(
errBuf
,
"DLL load failed: "
);
len
=
strlen
(
errBuf
);
strncpy
(
errBuf
+
len
,
theInfo
,
sizeof
(
errBuf
)
-
len
);
errBuf
[
sizeof
(
errBuf
)
-
1
]
=
'\0'
;
}
PyErr_SetString
(
PyExc_ImportError
,
errBuf
);
return
NULL
;
}
else
{
char
buffer
[
256
];
#ifdef
_DEBUG
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
"python%d%d_d.dll"
,
#else
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
"python%d%d.dll"
,
#endif
PY_MAJOR_VERSION
,
PY_MINOR_VERSION
);
import_python
=
GetPythonImport
(
hDLL
);
if
(
import_python
&&
strcasecmp
(
buffer
,
import_python
)) {
PyOS_snprintf
(
buffer
,
sizeof
(
buffer
),
"Module use of %.150s conflicts "
"with this version of Python."
,
import_python
);
PyErr_SetString
(
PyExc_ImportError
,
buffer
);
FreeLibrary
(
hDLL
);
return
NULL
;
}
}
p
=
GetProcAddress
(
hDLL
,
funcname
);
}
return
p
;
}
Back
|
FazBrowse Home
|
New Git URL