diff options
author | Steve Dower <steve.dower@microsoft.com> | 2015-01-24 16:18:24 (GMT) |
---|---|---|
committer | Steve Dower <steve.dower@microsoft.com> | 2015-01-24 16:18:24 (GMT) |
commit | 7d0e0c9f7b0b86a25f10739b3c01195c8154f495 (patch) | |
tree | f6bc4c600d5426acadd34d8d7f3a954908fcf7d3 | |
parent | b95b56150fc3e7834783b54acdddeaed4fe44e27 (diff) | |
download | cpython-7d0e0c9f7b0b86a25f10739b3c01195c8154f495.zip cpython-7d0e0c9f7b0b86a25f10739b3c01195c8154f495.tar.gz cpython-7d0e0c9f7b0b86a25f10739b3c01195c8154f495.tar.bz2 |
Closes #23253: Delay-load ShellExecute
-rw-r--r-- | Doc/library/os.rst | 4 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Modules/posixmodule.c | 47 |
3 files changed, 50 insertions, 4 deletions
diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 2c14f8f..c4b8bac 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3024,6 +3024,10 @@ written in Python, such as a mail server's external command delivery program. doesn't work if it is. Use the :func:`os.path.normpath` function to ensure that the path is properly encoded for Win32. + To reduce interpreter startup overhead, the Win32 :c:func:`ShellExecute` + function is not resolved until this function is first called. If the function + cannot be resolved, :exc:`NotImplementedError` will be raised. + Availability: Windows. @@ -10,6 +10,9 @@ Release date: TBA Core and Builtins ----------------- +- Issue #23253: Delay-load ShellExecute[AW] in os.startfile for reduced + startup overhead on Windows. + - Issue #22038: pyatomic.h now uses stdatomic.h or GCC built-in functions for atomic memory access if available. Patch written by Vitor de Lima and Gustavo Temple. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 542e600..502e933 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -15128,6 +15128,37 @@ The filepath is relative to the current directory. If you want to use\n\ an absolute path, make sure the first character is not a slash (\"/\");\n\ the underlying Win32 ShellExecute function doesn't work if it is."); +/* Grab ShellExecute dynamically from shell32 */ +static int has_ShellExecute = -1; +static HINSTANCE (CALLBACK *Py_ShellExecuteA)(HWND, LPCSTR, LPCSTR, LPCSTR, + LPCSTR, INT); +static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, + LPCWSTR, INT); +static int +check_ShellExecute() +{ + HINSTANCE hShell32; + + /* only recheck */ + if (-1 == has_ShellExecute) { + Py_BEGIN_ALLOW_THREADS + hShell32 = LoadLibraryW(L"SHELL32"); + Py_END_ALLOW_THREADS + if (hShell32) { + *(FARPROC*)&Py_ShellExecuteA = GetProcAddress(hShell32, + "ShellExecuteA"); + *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, + "ShellExecuteW"); + has_ShellExecute = Py_ShellExecuteA && + Py_ShellExecuteW; + } else { + has_ShellExecute = 0; + } + } + return has_ShellExecute; +} + + static PyObject * win32_startfile(PyObject *self, PyObject *args) { @@ -15138,6 +15169,14 @@ win32_startfile(PyObject *self, PyObject *args) HINSTANCE rc; PyObject *unipath, *uoperation = NULL; + + if(!check_ShellExecute()) { + /* If the OS doesn't have ShellExecute, return a + NotImplementedError. */ + return PyErr_Format(PyExc_NotImplementedError, + "startfile not available on this platform"); + } + if (!PyArg_ParseTuple(args, "U|s:startfile", &unipath, &operation)) { PyErr_Clear(); @@ -15166,8 +15205,8 @@ win32_startfile(PyObject *self, PyObject *args) woperation = NULL; Py_BEGIN_ALLOW_THREADS - rc = ShellExecuteW((HWND)0, woperation, wpath, - NULL, NULL, SW_SHOWNORMAL); + rc = Py_ShellExecuteW((HWND)0, woperation, wpath, + NULL, NULL, SW_SHOWNORMAL); Py_END_ALLOW_THREADS Py_XDECREF(uoperation); @@ -15189,8 +15228,8 @@ normal: } filepath = PyBytes_AsString(ofilepath); Py_BEGIN_ALLOW_THREADS - rc = ShellExecute((HWND)0, operation, filepath, - NULL, NULL, SW_SHOWNORMAL); + rc = Py_ShellExecuteA((HWND)0, operation, filepath, + NULL, NULL, SW_SHOWNORMAL); Py_END_ALLOW_THREADS if (rc <= (HINSTANCE)32) { PyObject *errval = win32_error("startfile", filepath); |