summaryrefslogtreecommitdiffstats
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@microsoft.com>2019-03-29 23:37:16 (GMT)
committerGitHub <noreply@github.com>2019-03-29 23:37:16 (GMT)
commit2438cdf0e932a341c7613bf4323d06b91ae9f1f1 (patch)
tree231cdf3f22e1d5eb9f88fe7a511ab47e3cf8d225 /Modules/posixmodule.c
parent32119e10b792ad7ee4e5f951a2d89ddbaf111cc5 (diff)
downloadcpython-2438cdf0e932a341c7613bf4323d06b91ae9f1f1.zip
cpython-2438cdf0e932a341c7613bf4323d06b91ae9f1f1.tar.gz
cpython-2438cdf0e932a341c7613bf4323d06b91ae9f1f1.tar.bz2
bpo-36085: Enable better DLL resolution on Windows (GH-12302)
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r--Modules/posixmodule.c133
1 files changed, 129 insertions, 4 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 3f76018..7c4e5f0 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -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;
}