diff options
author | AN Long <aisk@users.noreply.github.com> | 2023-12-07 17:26:29 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-07 17:26:29 (GMT) |
commit | a955fd68d6451bd42199110c978e99b3d2959db2 (patch) | |
tree | 14eb0414ba650d58b64b4ee21a34ceaf6f65380e /PC | |
parent | b2923a61a10dc2717f4662b590cc9f6d181c6983 (diff) | |
download | cpython-a955fd68d6451bd42199110c978e99b3d2959db2.zip cpython-a955fd68d6451bd42199110c978e99b3d2959db2.tar.gz cpython-a955fd68d6451bd42199110c978e99b3d2959db2.tar.bz2 |
gh-112278: Disable WMI queries on Windows after they time out (GH-112658)
Diffstat (limited to 'PC')
-rw-r--r-- | PC/_wmimodule.cpp | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/PC/_wmimodule.cpp b/PC/_wmimodule.cpp index fdf09ec..215350a 100644 --- a/PC/_wmimodule.cpp +++ b/PC/_wmimodule.cpp @@ -44,6 +44,7 @@ struct _query_data { LPCWSTR query; HANDLE writePipe; HANDLE readPipe; + HANDLE connectEvent; }; @@ -86,6 +87,9 @@ _query_thread(LPVOID param) NULL, NULL, 0, NULL, 0, 0, &services ); } + if (!SetEvent(data->connectEvent)) { + hr = HRESULT_FROM_WIN32(GetLastError()); + } if (SUCCEEDED(hr)) { hr = CoSetProxyBlanket( services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, @@ -231,7 +235,8 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) Py_BEGIN_ALLOW_THREADS - if (!CreatePipe(&data.readPipe, &data.writePipe, NULL, 0)) { + data.connectEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!data.connectEvent || !CreatePipe(&data.readPipe, &data.writePipe, NULL, 0)) { err = GetLastError(); } else { hThread = CreateThread(NULL, 0, _query_thread, (LPVOID*)&data, 0, NULL); @@ -243,6 +248,21 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) } } + // gh-112278: If current user doesn't have permission to query the WMI, the + // function IWbemLocator::ConnectServer will hang for 5 seconds, and there + // is no way to specify the timeout. So we use an Event object to simulate + // a timeout. + switch (WaitForSingleObject(data.connectEvent, 100)) { + case WAIT_OBJECT_0: + break; + case WAIT_TIMEOUT: + err = WAIT_TIMEOUT; + break; + default: + err = GetLastError(); + break; + } + while (!err) { if (ReadFile( data.readPipe, @@ -265,7 +285,7 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) } // Allow the thread some time to clean up - switch (WaitForSingleObject(hThread, 1000)) { + switch (WaitForSingleObject(hThread, 100)) { case WAIT_OBJECT_0: // Thread ended cleanly if (!GetExitCodeThread(hThread, (LPDWORD)&err)) { @@ -286,6 +306,7 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) } CloseHandle(hThread); + CloseHandle(data.connectEvent); hThread = NULL; Py_END_ALLOW_THREADS |