|
1 |
|
2 /* Support for dynamic loading of extension modules */ |
|
3 |
|
4 #include "Python.h" |
|
5 |
|
6 #ifdef HAVE_DIRECT_H |
|
7 #include <direct.h> |
|
8 #endif |
|
9 #include <ctype.h> |
|
10 |
|
11 #include "importdl.h" |
|
12 #include <windows.h> |
|
13 |
|
14 const struct filedescr _PyImport_DynLoadFiletab[] = { |
|
15 #ifdef _DEBUG |
|
16 {"_d.pyd", "rb", C_EXTENSION}, |
|
17 #else |
|
18 {".pyd", "rb", C_EXTENSION}, |
|
19 #endif |
|
20 {0, 0} |
|
21 }; |
|
22 |
|
23 |
|
24 /* Case insensitive string compare, to avoid any dependencies on particular |
|
25 C RTL implementations */ |
|
26 |
|
27 static int strcasecmp (char *string1, char *string2) |
|
28 { |
|
29 int first, second; |
|
30 |
|
31 do { |
|
32 first = tolower(*string1); |
|
33 second = tolower(*string2); |
|
34 string1++; |
|
35 string2++; |
|
36 } while (first && first == second); |
|
37 |
|
38 return (first - second); |
|
39 } |
|
40 |
|
41 |
|
42 /* Function to return the name of the "python" DLL that the supplied module |
|
43 directly imports. Looks through the list of imported modules and |
|
44 returns the first entry that starts with "python" (case sensitive) and |
|
45 is followed by nothing but numbers until the separator (period). |
|
46 |
|
47 Returns a pointer to the import name, or NULL if no matching name was |
|
48 located. |
|
49 |
|
50 This function parses through the PE header for the module as loaded in |
|
51 memory by the system loader. The PE header is accessed as documented by |
|
52 Microsoft in the MSDN PE and COFF specification (2/99), and handles |
|
53 both PE32 and PE32+. It only worries about the direct import table and |
|
54 not the delay load import table since it's unlikely an extension is |
|
55 going to be delay loading Python (after all, it's already loaded). |
|
56 |
|
57 If any magic values are not found (e.g., the PE header or optional |
|
58 header magic), then this function simply returns NULL. */ |
|
59 |
|
60 #define DWORD_AT(mem) (*(DWORD *)(mem)) |
|
61 #define WORD_AT(mem) (*(WORD *)(mem)) |
|
62 |
|
63 static char *GetPythonImport (HINSTANCE hModule) |
|
64 { |
|
65 unsigned char *dllbase, *import_data, *import_name; |
|
66 DWORD pe_offset, opt_offset; |
|
67 WORD opt_magic; |
|
68 int num_dict_off, import_off; |
|
69 |
|
70 /* Safety check input */ |
|
71 if (hModule == NULL) { |
|
72 return NULL; |
|
73 } |
|
74 |
|
75 /* Module instance is also the base load address. First portion of |
|
76 memory is the MS-DOS loader, which holds the offset to the PE |
|
77 header (from the load base) at 0x3C */ |
|
78 dllbase = (unsigned char *)hModule; |
|
79 pe_offset = DWORD_AT(dllbase + 0x3C); |
|
80 |
|
81 /* The PE signature must be "PE\0\0" */ |
|
82 if (memcmp(dllbase+pe_offset,"PE\0\0",4)) { |
|
83 return NULL; |
|
84 } |
|
85 |
|
86 /* Following the PE signature is the standard COFF header (20 |
|
87 bytes) and then the optional header. The optional header starts |
|
88 with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+ |
|
89 uses 64-bits for some fields). It might also be 0x107 for a ROM |
|
90 image, but we don't process that here. |
|
91 |
|
92 The optional header ends with a data dictionary that directly |
|
93 points to certain types of data, among them the import entries |
|
94 (in the second table entry). Based on the header type, we |
|
95 determine offsets for the data dictionary count and the entry |
|
96 within the dictionary pointing to the imports. */ |
|
97 |
|
98 opt_offset = pe_offset + 4 + 20; |
|
99 opt_magic = WORD_AT(dllbase+opt_offset); |
|
100 if (opt_magic == 0x10B) { |
|
101 /* PE32 */ |
|
102 num_dict_off = 92; |
|
103 import_off = 104; |
|
104 } else if (opt_magic == 0x20B) { |
|
105 /* PE32+ */ |
|
106 num_dict_off = 108; |
|
107 import_off = 120; |
|
108 } else { |
|
109 /* Unsupported */ |
|
110 return NULL; |
|
111 } |
|
112 |
|
113 /* Now if an import table exists, offset to it and walk the list of |
|
114 imports. The import table is an array (ending when an entry has |
|
115 empty values) of structures (20 bytes each), which contains (at |
|
116 offset 12) a relative address (to the module base) at which a |
|
117 string constant holding the import name is located. */ |
|
118 |
|
119 if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) { |
|
120 /* We have at least 2 tables - the import table is the second |
|
121 one. But still it may be that the table size is zero */ |
|
122 if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD))) |
|
123 return NULL; |
|
124 import_data = dllbase + DWORD_AT(dllbase + |
|
125 opt_offset + |
|
126 import_off); |
|
127 while (DWORD_AT(import_data)) { |
|
128 import_name = dllbase + DWORD_AT(import_data+12); |
|
129 if (strlen(import_name) >= 6 && |
|
130 !strncmp(import_name,"python",6)) { |
|
131 char *pch; |
|
132 |
|
133 /* Ensure python prefix is followed only |
|
134 by numbers to the end of the basename */ |
|
135 pch = import_name + 6; |
|
136 #ifdef _DEBUG |
|
137 while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') { |
|
138 #else |
|
139 while (*pch && *pch != '.') { |
|
140 #endif |
|
141 if (*pch >= '0' && *pch <= '9') { |
|
142 pch++; |
|
143 } else { |
|
144 pch = NULL; |
|
145 break; |
|
146 } |
|
147 } |
|
148 |
|
149 if (pch) { |
|
150 /* Found it - return the name */ |
|
151 return import_name; |
|
152 } |
|
153 } |
|
154 import_data += 20; |
|
155 } |
|
156 } |
|
157 |
|
158 return NULL; |
|
159 } |
|
160 |
|
161 |
|
162 dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, |
|
163 const char *pathname, FILE *fp) |
|
164 { |
|
165 dl_funcptr p; |
|
166 char funcname[258], *import_python; |
|
167 |
|
168 PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname); |
|
169 |
|
170 { |
|
171 HINSTANCE hDLL = NULL; |
|
172 char pathbuf[260]; |
|
173 LPTSTR dummy; |
|
174 unsigned int old_mode; |
|
175 /* We use LoadLibraryEx so Windows looks for dependent DLLs |
|
176 in directory of pathname first. However, Windows95 |
|
177 can sometimes not work correctly unless the absolute |
|
178 path is used. If GetFullPathName() fails, the LoadLibrary |
|
179 will certainly fail too, so use its error code */ |
|
180 |
|
181 /* Don't display a message box when Python can't load a DLL */ |
|
182 old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); |
|
183 |
|
184 if (GetFullPathName(pathname, |
|
185 sizeof(pathbuf), |
|
186 pathbuf, |
|
187 &dummy)) |
|
188 /* XXX This call doesn't exist in Windows CE */ |
|
189 hDLL = LoadLibraryEx(pathname, NULL, |
|
190 LOAD_WITH_ALTERED_SEARCH_PATH); |
|
191 |
|
192 /* restore old error mode settings */ |
|
193 SetErrorMode(old_mode); |
|
194 |
|
195 if (hDLL==NULL){ |
|
196 char errBuf[256]; |
|
197 unsigned int errorCode; |
|
198 |
|
199 /* Get an error string from Win32 error code */ |
|
200 char theInfo[256]; /* Pointer to error text |
|
201 from system */ |
|
202 int theLength; /* Length of error text */ |
|
203 |
|
204 errorCode = GetLastError(); |
|
205 |
|
206 theLength = FormatMessage( |
|
207 FORMAT_MESSAGE_FROM_SYSTEM | |
|
208 FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */ |
|
209 NULL, /* message source */ |
|
210 errorCode, /* the message (error) ID */ |
|
211 0, /* default language environment */ |
|
212 (LPTSTR) theInfo, /* the buffer */ |
|
213 sizeof(theInfo), /* the buffer size */ |
|
214 NULL); /* no additional format args. */ |
|
215 |
|
216 /* Problem: could not get the error message. |
|
217 This should not happen if called correctly. */ |
|
218 if (theLength == 0) { |
|
219 PyOS_snprintf(errBuf, sizeof(errBuf), |
|
220 "DLL load failed with error code %d", |
|
221 errorCode); |
|
222 } else { |
|
223 size_t len; |
|
224 /* For some reason a \r\n |
|
225 is appended to the text */ |
|
226 if (theLength >= 2 && |
|
227 theInfo[theLength-2] == '\r' && |
|
228 theInfo[theLength-1] == '\n') { |
|
229 theLength -= 2; |
|
230 theInfo[theLength] = '\0'; |
|
231 } |
|
232 strcpy(errBuf, "DLL load failed: "); |
|
233 len = strlen(errBuf); |
|
234 strncpy(errBuf+len, theInfo, |
|
235 sizeof(errBuf)-len); |
|
236 errBuf[sizeof(errBuf)-1] = '\0'; |
|
237 } |
|
238 PyErr_SetString(PyExc_ImportError, errBuf); |
|
239 return NULL; |
|
240 } else { |
|
241 char buffer[256]; |
|
242 |
|
243 #ifdef _DEBUG |
|
244 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll", |
|
245 #else |
|
246 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", |
|
247 #endif |
|
248 PY_MAJOR_VERSION,PY_MINOR_VERSION); |
|
249 import_python = GetPythonImport(hDLL); |
|
250 |
|
251 if (import_python && |
|
252 strcasecmp(buffer,import_python)) { |
|
253 PyOS_snprintf(buffer, sizeof(buffer), |
|
254 "Module use of %.150s conflicts " |
|
255 "with this version of Python.", |
|
256 import_python); |
|
257 PyErr_SetString(PyExc_ImportError,buffer); |
|
258 FreeLibrary(hDLL); |
|
259 return NULL; |
|
260 } |
|
261 } |
|
262 p = GetProcAddress(hDLL, funcname); |
|
263 } |
|
264 |
|
265 return p; |
|
266 } |