mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
bpo-36085: Enable better DLL resolution on Windows (GH-12302)
This commit is contained in:
parent
32119e10b7
commit
2438cdf0e9
12 changed files with 492 additions and 22 deletions
|
@ -1442,17 +1442,23 @@ win32_error(const char* function, const char* filename)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
win32_error_object(const char* function, PyObject* filename)
|
||||
win32_error_object_err(const char* function, PyObject* filename, DWORD err)
|
||||
{
|
||||
/* XXX - see win32_error for comments on 'function' */
|
||||
errno = GetLastError();
|
||||
if (filename)
|
||||
return PyErr_SetExcFromWindowsErrWithFilenameObject(
|
||||
PyExc_OSError,
|
||||
errno,
|
||||
err,
|
||||
filename);
|
||||
else
|
||||
return PyErr_SetFromWindowsErr(errno);
|
||||
return PyErr_SetFromWindowsErr(err);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
win32_error_object(const char* function, PyObject* filename)
|
||||
{
|
||||
errno = GetLastError();
|
||||
return win32_error_object_err(function, filename, errno);
|
||||
}
|
||||
|
||||
#endif /* MS_WINDOWS */
|
||||
|
@ -13161,6 +13167,113 @@ error:
|
|||
}
|
||||
#endif /* HAVE_GETRANDOM_SYSCALL */
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
/* bpo-36085: Helper functions for managing DLL search directories
|
||||
* on win32
|
||||
*/
|
||||
|
||||
typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
|
||||
typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
|
||||
|
||||
/*[clinic input]
|
||||
os._add_dll_directory
|
||||
|
||||
path: path_t
|
||||
|
||||
Add a path to the DLL search path.
|
||||
|
||||
This search path is used when resolving dependencies for imported
|
||||
extension modules (the module itself is resolved through sys.path),
|
||||
and also by ctypes.
|
||||
|
||||
Returns an opaque value that may be passed to os.remove_dll_directory
|
||||
to remove this directory from the search path.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
os__add_dll_directory_impl(PyObject *module, path_t *path)
|
||||
/*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
|
||||
{
|
||||
HMODULE hKernel32;
|
||||
PAddDllDirectory AddDllDirectory;
|
||||
DLL_DIRECTORY_COOKIE cookie = 0;
|
||||
DWORD err = 0;
|
||||
|
||||
/* For Windows 7, we have to load this. As this will be a fairly
|
||||
infrequent operation, just do it each time. Kernel32 is always
|
||||
loaded. */
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
|
||||
!(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
|
||||
hKernel32, "AddDllDirectory")) ||
|
||||
!(cookie = (*AddDllDirectory)(path->wide))) {
|
||||
err = GetLastError();
|
||||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (err) {
|
||||
return win32_error_object_err("add_dll_directory",
|
||||
path->object, err);
|
||||
}
|
||||
|
||||
return PyCapsule_New(cookie, "DLL directory cookie", NULL);
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
os._remove_dll_directory
|
||||
|
||||
cookie: object
|
||||
|
||||
Removes a path from the DLL search path.
|
||||
|
||||
The parameter is an opaque value that was returned from
|
||||
os.add_dll_directory. You can only remove directories that you added
|
||||
yourself.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
|
||||
/*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
|
||||
{
|
||||
HMODULE hKernel32;
|
||||
PRemoveDllDirectory RemoveDllDirectory;
|
||||
DLL_DIRECTORY_COOKIE cookieValue;
|
||||
DWORD err = 0;
|
||||
|
||||
if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Provided cookie was not returned from os.add_dll_directory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
|
||||
cookie, "DLL directory cookie");
|
||||
|
||||
/* For Windows 7, we have to load this. As this will be a fairly
|
||||
infrequent operation, just do it each time. Kernel32 is always
|
||||
loaded. */
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
|
||||
!(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
|
||||
hKernel32, "RemoveDllDirectory")) ||
|
||||
!(*RemoveDllDirectory)(cookieValue)) {
|
||||
err = GetLastError();
|
||||
}
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (err) {
|
||||
return win32_error_object_err("remove_dll_directory",
|
||||
NULL, err);
|
||||
}
|
||||
|
||||
if (PyCapsule_SetName(cookie, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static PyMethodDef posix_methods[] = {
|
||||
|
||||
|
@ -13349,6 +13462,10 @@ static PyMethodDef posix_methods[] = {
|
|||
OS_SCANDIR_METHODDEF
|
||||
OS_FSPATH_METHODDEF
|
||||
OS_GETRANDOM_METHODDEF
|
||||
#ifdef MS_WINDOWS
|
||||
OS__ADD_DLL_DIRECTORY_METHODDEF
|
||||
OS__REMOVE_DLL_DIRECTORY_METHODDEF
|
||||
#endif
|
||||
{NULL, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
@ -13826,6 +13943,14 @@ all_ins(PyObject *m)
|
|||
if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
|
||||
#endif
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
|
||||
if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
|
||||
if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
|
||||
if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
|
||||
if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue