Mercurial > cpython-lru_cache-weakref
comparison Python/dynload_win.c @ 61467:f197407bdba2 3.1
Recorded merge of revisions 81032 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
................
r81032 | antoine.pitrou | 2010-05-09 17:52:27 +0200 (dim., 09 mai 2010) | 9 lines
Recorded merge of revisions 81029 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines
Untabify C files. Will watch buildbots.
........
................
| author | Antoine Pitrou <solipsis@pitrou.net> |
|---|---|
| date | Sun, 09 May 2010 16:14:21 +0000 |
| parents | 0522cfee879a |
| children | 62b61abd02b8 |
comparison
equal
deleted
inserted
replaced
| 61459:f8c19c5f5dd2 | 61467:f197407bdba2 |
|---|---|
| 15 extern ULONG_PTR _Py_ActivateActCtx(); | 15 extern ULONG_PTR _Py_ActivateActCtx(); |
| 16 void _Py_DeactivateActCtx(ULONG_PTR cookie); | 16 void _Py_DeactivateActCtx(ULONG_PTR cookie); |
| 17 | 17 |
| 18 const struct filedescr _PyImport_DynLoadFiletab[] = { | 18 const struct filedescr _PyImport_DynLoadFiletab[] = { |
| 19 #ifdef _DEBUG | 19 #ifdef _DEBUG |
| 20 {"_d.pyd", "rb", C_EXTENSION}, | 20 {"_d.pyd", "rb", C_EXTENSION}, |
| 21 #else | 21 #else |
| 22 {".pyd", "rb", C_EXTENSION}, | 22 {".pyd", "rb", C_EXTENSION}, |
| 23 #endif | 23 #endif |
| 24 {0, 0} | 24 {0, 0} |
| 25 }; | 25 }; |
| 26 | 26 |
| 27 | 27 |
| 28 /* Case insensitive string compare, to avoid any dependencies on particular | 28 /* Case insensitive string compare, to avoid any dependencies on particular |
| 29 C RTL implementations */ | 29 C RTL implementations */ |
| 30 | 30 |
| 31 static int strcasecmp (char *string1, char *string2) | 31 static int strcasecmp (char *string1, char *string2) |
| 32 { | 32 { |
| 33 int first, second; | 33 int first, second; |
| 34 | 34 |
| 35 do { | 35 do { |
| 36 first = tolower(*string1); | 36 first = tolower(*string1); |
| 37 second = tolower(*string2); | 37 second = tolower(*string2); |
| 38 string1++; | 38 string1++; |
| 39 string2++; | 39 string2++; |
| 40 } while (first && first == second); | 40 } while (first && first == second); |
| 41 | 41 |
| 42 return (first - second); | 42 return (first - second); |
| 43 } | 43 } |
| 44 | 44 |
| 45 | 45 |
| 46 /* Function to return the name of the "python" DLL that the supplied module | 46 /* Function to return the name of the "python" DLL that the supplied module |
| 47 directly imports. Looks through the list of imported modules and | 47 directly imports. Looks through the list of imported modules and |
| 48 returns the first entry that starts with "python" (case sensitive) and | 48 returns the first entry that starts with "python" (case sensitive) and |
| 64 #define DWORD_AT(mem) (*(DWORD *)(mem)) | 64 #define DWORD_AT(mem) (*(DWORD *)(mem)) |
| 65 #define WORD_AT(mem) (*(WORD *)(mem)) | 65 #define WORD_AT(mem) (*(WORD *)(mem)) |
| 66 | 66 |
| 67 static char *GetPythonImport (HINSTANCE hModule) | 67 static char *GetPythonImport (HINSTANCE hModule) |
| 68 { | 68 { |
| 69 unsigned char *dllbase, *import_data, *import_name; | 69 unsigned char *dllbase, *import_data, *import_name; |
| 70 DWORD pe_offset, opt_offset; | 70 DWORD pe_offset, opt_offset; |
| 71 WORD opt_magic; | 71 WORD opt_magic; |
| 72 int num_dict_off, import_off; | 72 int num_dict_off, import_off; |
| 73 | 73 |
| 74 /* Safety check input */ | 74 /* Safety check input */ |
| 75 if (hModule == NULL) { | 75 if (hModule == NULL) { |
| 76 return NULL; | 76 return NULL; |
| 77 } | 77 } |
| 78 | 78 |
| 79 /* Module instance is also the base load address. First portion of | 79 /* Module instance is also the base load address. First portion of |
| 80 memory is the MS-DOS loader, which holds the offset to the PE | 80 memory is the MS-DOS loader, which holds the offset to the PE |
| 81 header (from the load base) at 0x3C */ | 81 header (from the load base) at 0x3C */ |
| 82 dllbase = (unsigned char *)hModule; | 82 dllbase = (unsigned char *)hModule; |
| 83 pe_offset = DWORD_AT(dllbase + 0x3C); | 83 pe_offset = DWORD_AT(dllbase + 0x3C); |
| 84 | 84 |
| 85 /* The PE signature must be "PE\0\0" */ | 85 /* The PE signature must be "PE\0\0" */ |
| 86 if (memcmp(dllbase+pe_offset,"PE\0\0",4)) { | 86 if (memcmp(dllbase+pe_offset,"PE\0\0",4)) { |
| 87 return NULL; | 87 return NULL; |
| 88 } | 88 } |
| 89 | 89 |
| 90 /* Following the PE signature is the standard COFF header (20 | 90 /* Following the PE signature is the standard COFF header (20 |
| 91 bytes) and then the optional header. The optional header starts | 91 bytes) and then the optional header. The optional header starts |
| 92 with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+ | 92 with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+ |
| 93 uses 64-bits for some fields). It might also be 0x107 for a ROM | 93 uses 64-bits for some fields). It might also be 0x107 for a ROM |
| 94 image, but we don't process that here. | 94 image, but we don't process that here. |
| 95 | 95 |
| 96 The optional header ends with a data dictionary that directly | 96 The optional header ends with a data dictionary that directly |
| 97 points to certain types of data, among them the import entries | 97 points to certain types of data, among them the import entries |
| 98 (in the second table entry). Based on the header type, we | 98 (in the second table entry). Based on the header type, we |
| 99 determine offsets for the data dictionary count and the entry | 99 determine offsets for the data dictionary count and the entry |
| 100 within the dictionary pointing to the imports. */ | 100 within the dictionary pointing to the imports. */ |
| 101 | 101 |
| 102 opt_offset = pe_offset + 4 + 20; | 102 opt_offset = pe_offset + 4 + 20; |
| 103 opt_magic = WORD_AT(dllbase+opt_offset); | 103 opt_magic = WORD_AT(dllbase+opt_offset); |
| 104 if (opt_magic == 0x10B) { | 104 if (opt_magic == 0x10B) { |
| 105 /* PE32 */ | 105 /* PE32 */ |
| 106 num_dict_off = 92; | 106 num_dict_off = 92; |
| 107 import_off = 104; | 107 import_off = 104; |
| 108 } else if (opt_magic == 0x20B) { | 108 } else if (opt_magic == 0x20B) { |
| 109 /* PE32+ */ | 109 /* PE32+ */ |
| 110 num_dict_off = 108; | 110 num_dict_off = 108; |
| 111 import_off = 120; | 111 import_off = 120; |
| 112 } else { | 112 } else { |
| 113 /* Unsupported */ | 113 /* Unsupported */ |
| 114 return NULL; | 114 return NULL; |
| 115 } | 115 } |
| 116 | 116 |
| 117 /* Now if an import table exists, offset to it and walk the list of | 117 /* Now if an import table exists, offset to it and walk the list of |
| 118 imports. The import table is an array (ending when an entry has | 118 imports. The import table is an array (ending when an entry has |
| 119 empty values) of structures (20 bytes each), which contains (at | 119 empty values) of structures (20 bytes each), which contains (at |
| 120 offset 12) a relative address (to the module base) at which a | 120 offset 12) a relative address (to the module base) at which a |
| 121 string constant holding the import name is located. */ | 121 string constant holding the import name is located. */ |
| 122 | 122 |
| 123 if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) { | 123 if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) { |
| 124 /* We have at least 2 tables - the import table is the second | 124 /* We have at least 2 tables - the import table is the second |
| 125 one. But still it may be that the table size is zero */ | 125 one. But still it may be that the table size is zero */ |
| 126 if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD))) | 126 if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD))) |
| 127 return NULL; | 127 return NULL; |
| 128 import_data = dllbase + DWORD_AT(dllbase + | 128 import_data = dllbase + DWORD_AT(dllbase + |
| 129 opt_offset + | 129 opt_offset + |
| 130 import_off); | 130 import_off); |
| 131 while (DWORD_AT(import_data)) { | 131 while (DWORD_AT(import_data)) { |
| 132 import_name = dllbase + DWORD_AT(import_data+12); | 132 import_name = dllbase + DWORD_AT(import_data+12); |
| 133 if (strlen(import_name) >= 6 && | 133 if (strlen(import_name) >= 6 && |
| 134 !strncmp(import_name,"python",6)) { | 134 !strncmp(import_name,"python",6)) { |
| 135 char *pch; | 135 char *pch; |
| 136 | 136 |
| 137 /* Ensure python prefix is followed only | 137 /* Ensure python prefix is followed only |
| 138 by numbers to the end of the basename */ | 138 by numbers to the end of the basename */ |
| 139 pch = import_name + 6; | 139 pch = import_name + 6; |
| 140 #ifdef _DEBUG | 140 #ifdef _DEBUG |
| 141 while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') { | 141 while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') { |
| 142 #else | 142 #else |
| 143 while (*pch && *pch != '.') { | 143 while (*pch && *pch != '.') { |
| 144 #endif | 144 #endif |
| 145 if (*pch >= '0' && *pch <= '9') { | 145 if (*pch >= '0' && *pch <= '9') { |
| 146 pch++; | 146 pch++; |
| 147 } else { | 147 } else { |
| 148 pch = NULL; | 148 pch = NULL; |
| 149 break; | 149 break; |
| 150 } | 150 } |
| 151 } | 151 } |
| 152 | 152 |
| 153 if (pch) { | 153 if (pch) { |
| 154 /* Found it - return the name */ | 154 /* Found it - return the name */ |
| 155 return import_name; | 155 return import_name; |
| 156 } | 156 } |
| 157 } | 157 } |
| 158 import_data += 20; | 158 import_data += 20; |
| 159 } | 159 } |
| 160 } | 160 } |
| 161 | 161 |
| 162 return NULL; | 162 return NULL; |
| 163 } | 163 } |
| 164 | 164 |
| 165 | 165 |
| 166 dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, | 166 dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, |
| 167 const char *pathname, FILE *fp) | 167 const char *pathname, FILE *fp) |
| 168 { | 168 { |
| 169 dl_funcptr p; | 169 dl_funcptr p; |
| 170 char funcname[258], *import_python; | 170 char funcname[258], *import_python; |
| 171 | 171 |
| 172 PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); | 172 PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); |
| 173 | 173 |
| 174 { | 174 { |
| 175 HINSTANCE hDLL = NULL; | 175 HINSTANCE hDLL = NULL; |
| 176 char pathbuf[260]; | 176 char pathbuf[260]; |
| 177 LPTSTR dummy; | 177 LPTSTR dummy; |
| 178 unsigned int old_mode; | 178 unsigned int old_mode; |
| 179 ULONG_PTR cookie = 0; | 179 ULONG_PTR cookie = 0; |
| 180 /* We use LoadLibraryEx so Windows looks for dependent DLLs | 180 /* We use LoadLibraryEx so Windows looks for dependent DLLs |
| 181 in directory of pathname first. However, Windows95 | 181 in directory of pathname first. However, Windows95 |
| 182 can sometimes not work correctly unless the absolute | 182 can sometimes not work correctly unless the absolute |
| 183 path is used. If GetFullPathName() fails, the LoadLibrary | 183 path is used. If GetFullPathName() fails, the LoadLibrary |
| 184 will certainly fail too, so use its error code */ | 184 will certainly fail too, so use its error code */ |
| 185 | 185 |
| 186 /* Don't display a message box when Python can't load a DLL */ | 186 /* Don't display a message box when Python can't load a DLL */ |
| 187 old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); | 187 old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); |
| 188 | 188 |
| 189 if (GetFullPathName(pathname, | 189 if (GetFullPathName(pathname, |
| 190 sizeof(pathbuf), | 190 sizeof(pathbuf), |
| 191 pathbuf, | 191 pathbuf, |
| 192 &dummy)) { | 192 &dummy)) { |
| 193 ULONG_PTR cookie = _Py_ActivateActCtx(); | 193 ULONG_PTR cookie = _Py_ActivateActCtx(); |
| 194 /* XXX This call doesn't exist in Windows CE */ | 194 /* XXX This call doesn't exist in Windows CE */ |
| 195 hDLL = LoadLibraryEx(pathname, NULL, | 195 hDLL = LoadLibraryEx(pathname, NULL, |
| 196 LOAD_WITH_ALTERED_SEARCH_PATH); | 196 LOAD_WITH_ALTERED_SEARCH_PATH); |
| 197 _Py_DeactivateActCtx(cookie); | 197 _Py_DeactivateActCtx(cookie); |
| 198 } | 198 } |
| 199 | 199 |
| 200 /* restore old error mode settings */ | 200 /* restore old error mode settings */ |
| 201 SetErrorMode(old_mode); | 201 SetErrorMode(old_mode); |
| 202 | 202 |
| 203 if (hDLL==NULL){ | 203 if (hDLL==NULL){ |
| 204 PyObject *message; | 204 PyObject *message; |
| 205 unsigned int errorCode; | 205 unsigned int errorCode; |
| 206 | 206 |
| 207 /* Get an error string from Win32 error code */ | 207 /* Get an error string from Win32 error code */ |
| 208 wchar_t theInfo[256]; /* Pointer to error text | 208 wchar_t theInfo[256]; /* Pointer to error text |
| 209 from system */ | 209 from system */ |
| 210 int theLength; /* Length of error text */ | 210 int theLength; /* Length of error text */ |
| 211 | 211 |
| 212 errorCode = GetLastError(); | 212 errorCode = GetLastError(); |
| 213 | 213 |
| 214 theLength = FormatMessageW( | 214 theLength = FormatMessageW( |
| 215 FORMAT_MESSAGE_FROM_SYSTEM | | 215 FORMAT_MESSAGE_FROM_SYSTEM | |
| 216 FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */ | 216 FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */ |
| 217 NULL, /* message source */ | 217 NULL, /* message source */ |
| 218 errorCode, /* the message (error) ID */ | 218 errorCode, /* the message (error) ID */ |
| 219 MAKELANGID(LANG_NEUTRAL, | 219 MAKELANGID(LANG_NEUTRAL, |
| 220 SUBLANG_DEFAULT), | 220 SUBLANG_DEFAULT), |
| 221 /* Default language */ | 221 /* Default language */ |
| 222 theInfo, /* the buffer */ | 222 theInfo, /* the buffer */ |
| 223 sizeof(theInfo), /* the buffer size */ | 223 sizeof(theInfo), /* the buffer size */ |
| 224 NULL); /* no additional format args. */ | 224 NULL); /* no additional format args. */ |
| 225 | 225 |
| 226 /* Problem: could not get the error message. | 226 /* Problem: could not get the error message. |
| 227 This should not happen if called correctly. */ | 227 This should not happen if called correctly. */ |
| 228 if (theLength == 0) { | 228 if (theLength == 0) { |
| 229 message = PyUnicode_FromFormat( | 229 message = PyUnicode_FromFormat( |
| 230 "DLL load failed with error code %d", | 230 "DLL load failed with error code %d", |
| 231 errorCode); | 231 errorCode); |
| 232 } else { | 232 } else { |
| 233 /* For some reason a \r\n | 233 /* For some reason a \r\n |
| 234 is appended to the text */ | 234 is appended to the text */ |
| 235 if (theLength >= 2 && | 235 if (theLength >= 2 && |
| 236 theInfo[theLength-2] == '\r' && | 236 theInfo[theLength-2] == '\r' && |
| 237 theInfo[theLength-1] == '\n') { | 237 theInfo[theLength-1] == '\n') { |
| 238 theLength -= 2; | 238 theLength -= 2; |
| 239 theInfo[theLength] = '\0'; | 239 theInfo[theLength] = '\0'; |
| 240 } | 240 } |
| 241 message = PyUnicode_FromString( | 241 message = PyUnicode_FromString( |
| 242 "DLL load failed: "); | 242 "DLL load failed: "); |
| 243 | 243 |
| 244 PyUnicode_AppendAndDel(&message, | 244 PyUnicode_AppendAndDel(&message, |
| 245 PyUnicode_FromUnicode( | 245 PyUnicode_FromUnicode( |
| 246 theInfo, | 246 theInfo, |
| 247 theLength)); | 247 theLength)); |
| 248 } | 248 } |
| 249 PyErr_SetObject(PyExc_ImportError, message); | 249 PyErr_SetObject(PyExc_ImportError, message); |
| 250 Py_XDECREF(message); | 250 Py_XDECREF(message); |
| 251 return NULL; | 251 return NULL; |
| 252 } else { | 252 } else { |
| 253 char buffer[256]; | 253 char buffer[256]; |
| 254 | 254 |
| 255 #ifdef _DEBUG | 255 #ifdef _DEBUG |
| 256 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll", | 256 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll", |
| 257 #else | 257 #else |
| 258 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", | 258 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", |
| 259 #endif | 259 #endif |
| 260 PY_MAJOR_VERSION,PY_MINOR_VERSION); | 260 PY_MAJOR_VERSION,PY_MINOR_VERSION); |
| 261 import_python = GetPythonImport(hDLL); | 261 import_python = GetPythonImport(hDLL); |
| 262 | 262 |
| 263 if (import_python && | 263 if (import_python && |
| 264 strcasecmp(buffer,import_python)) { | 264 strcasecmp(buffer,import_python)) { |
| 265 PyOS_snprintf(buffer, sizeof(buffer), | 265 PyOS_snprintf(buffer, sizeof(buffer), |
| 266 "Module use of %.150s conflicts " | 266 "Module use of %.150s conflicts " |
| 267 "with this version of Python.", | 267 "with this version of Python.", |
| 268 import_python); | 268 import_python); |
| 269 PyErr_SetString(PyExc_ImportError,buffer); | 269 PyErr_SetString(PyExc_ImportError,buffer); |
| 270 FreeLibrary(hDLL); | 270 FreeLibrary(hDLL); |
| 271 return NULL; | 271 return NULL; |
| 272 } | 272 } |
| 273 } | 273 } |
| 274 p = GetProcAddress(hDLL, funcname); | 274 p = GetProcAddress(hDLL, funcname); |
| 275 } | 275 } |
| 276 | 276 |
| 277 return p; | 277 return p; |
| 278 } | 278 } |
