diff -r ffa851df0825 -r 2fb8b9db1c86 symbian-qemu-0.9.1-12/python-2.6.1/Python/dynload_win.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symbian-qemu-0.9.1-12/python-2.6.1/Python/dynload_win.c Fri Jul 31 15:01:17 2009 +0100 @@ -0,0 +1,266 @@ + +/* Support for dynamic loading of extension modules */ + +#include "Python.h" + +#ifdef HAVE_DIRECT_H +#include +#endif +#include + +#include "importdl.h" +#include + +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; + /* 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)) + /* XXX This call doesn't exist in Windows CE */ + hDLL = LoadLibraryEx(pathname, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH); + + /* 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; +}