diff options
Diffstat (limited to 'Python/dynload_win.c')
| -rw-r--r-- | Python/dynload_win.c | 407 | 
1 files changed, 213 insertions, 194 deletions
| diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 1c3b3ab..4e5555e 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -1,22 +1,27 @@  /* Support for dynamic loading of extension modules */ -#include <windows.h> +#include "Python.h" +  #ifdef HAVE_DIRECT_H  #include <direct.h>  #endif  #include <ctype.h> -#include "Python.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}, +    {"_d.pyd", "rb", C_EXTENSION},  #else -	{".pyd", "rb", C_EXTENSION}, +    {".pyd", "rb", C_EXTENSION},  #endif -	{0, 0} +    {0, 0}  }; @@ -24,18 +29,18 @@ const struct filedescr _PyImport_DynLoadFiletab[] = {     C RTL implementations */  static int strcasecmp (char *string1, char *string2) -{  -	int first, second; +{ +    int first, second; -	do { -		first  = tolower(*string1); -		second = tolower(*string2); -		string1++; -		string2++; -	} while (first && first == second); +    do { +        first  = tolower(*string1); +        second = tolower(*string2); +        string1++; +        string2++; +    } while (first && first == second); -	return (first - second); -}  +    return (first - second); +}  /* Function to return the name of the "python" DLL that the supplied module @@ -61,195 +66,209 @@ static int strcasecmp (char *string1, char *string2)  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; +    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] != '.') { +                while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {  #else -				while (*pch && *pch != '.') { +                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; +                    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) +                                    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; -		/* 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 */ -		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); -		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, /* 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]; +    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", +            PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll",  #else -			PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", +            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; +                          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;  } | 
