Mercurial > cpython-lru_cache-weakref
comparison Python/dynload_win.c @ 61465:e38335d4df91 2.6
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 15:15:40 +0000 |
| parents | 1434d1bc667f |
| children |
comparison
equal
deleted
inserted
replaced
| 61461:b6e03ca8a206 | 61465:e38335d4df91 |
|---|---|
| 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), "init%.200s", shortname); | 172 PyOS_snprintf(funcname, sizeof(funcname), "init%.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 char errBuf[256]; | 204 char errBuf[256]; |
| 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 char theInfo[256]; /* Pointer to error text | 208 char 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 = FormatMessage( | 214 theLength = FormatMessage( |
| 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 0, /* default language environment */ | 219 0, /* default language environment */ |
| 220 (LPTSTR) theInfo, /* the buffer */ | 220 (LPTSTR) theInfo, /* the buffer */ |
| 221 sizeof(theInfo), /* the buffer size */ | 221 sizeof(theInfo), /* the buffer size */ |
| 222 NULL); /* no additional format args. */ | 222 NULL); /* no additional format args. */ |
| 223 | 223 |
| 224 /* Problem: could not get the error message. | 224 /* Problem: could not get the error message. |
| 225 This should not happen if called correctly. */ | 225 This should not happen if called correctly. */ |
| 226 if (theLength == 0) { | 226 if (theLength == 0) { |
| 227 PyOS_snprintf(errBuf, sizeof(errBuf), | 227 PyOS_snprintf(errBuf, sizeof(errBuf), |
| 228 "DLL load failed with error code %d", | 228 "DLL load failed with error code %d", |
| 229 errorCode); | 229 errorCode); |
| 230 } else { | 230 } else { |
| 231 size_t len; | 231 size_t len; |
| 232 /* For some reason a \r\n | 232 /* For some reason a \r\n |
| 233 is appended to the text */ | 233 is appended to the text */ |
| 234 if (theLength >= 2 && | 234 if (theLength >= 2 && |
| 235 theInfo[theLength-2] == '\r' && | 235 theInfo[theLength-2] == '\r' && |
| 236 theInfo[theLength-1] == '\n') { | 236 theInfo[theLength-1] == '\n') { |
| 237 theLength -= 2; | 237 theLength -= 2; |
| 238 theInfo[theLength] = '\0'; | 238 theInfo[theLength] = '\0'; |
| 239 } | 239 } |
| 240 strcpy(errBuf, "DLL load failed: "); | 240 strcpy(errBuf, "DLL load failed: "); |
| 241 len = strlen(errBuf); | 241 len = strlen(errBuf); |
| 242 strncpy(errBuf+len, theInfo, | 242 strncpy(errBuf+len, theInfo, |
| 243 sizeof(errBuf)-len); | 243 sizeof(errBuf)-len); |
| 244 errBuf[sizeof(errBuf)-1] = '\0'; | 244 errBuf[sizeof(errBuf)-1] = '\0'; |
| 245 } | 245 } |
| 246 PyErr_SetString(PyExc_ImportError, errBuf); | 246 PyErr_SetString(PyExc_ImportError, errBuf); |
| 247 return NULL; | 247 return NULL; |
| 248 } else { | 248 } else { |
| 249 char buffer[256]; | 249 char buffer[256]; |
| 250 | 250 |
| 251 #ifdef _DEBUG | 251 #ifdef _DEBUG |
| 252 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll", | 252 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll", |
| 253 #else | 253 #else |
| 254 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", | 254 PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", |
| 255 #endif | 255 #endif |
| 256 PY_MAJOR_VERSION,PY_MINOR_VERSION); | 256 PY_MAJOR_VERSION,PY_MINOR_VERSION); |
| 257 import_python = GetPythonImport(hDLL); | 257 import_python = GetPythonImport(hDLL); |
| 258 | 258 |
| 259 if (import_python && | 259 if (import_python && |
| 260 strcasecmp(buffer,import_python)) { | 260 strcasecmp(buffer,import_python)) { |
| 261 PyOS_snprintf(buffer, sizeof(buffer), | 261 PyOS_snprintf(buffer, sizeof(buffer), |
| 262 "Module use of %.150s conflicts " | 262 "Module use of %.150s conflicts " |
| 263 "with this version of Python.", | 263 "with this version of Python.", |
| 264 import_python); | 264 import_python); |
| 265 PyErr_SetString(PyExc_ImportError,buffer); | 265 PyErr_SetString(PyExc_ImportError,buffer); |
| 266 FreeLibrary(hDLL); | 266 FreeLibrary(hDLL); |
| 267 return NULL; | 267 return NULL; |
| 268 } | 268 } |
| 269 } | 269 } |
| 270 p = GetProcAddress(hDLL, funcname); | 270 p = GetProcAddress(hDLL, funcname); |
| 271 } | 271 } |
| 272 | 272 |
| 273 return p; | 273 return p; |
| 274 } | 274 } |
