@@ -44,6 +44,7 @@ struct _query_data {
4444 LPCWSTR query;
4545 HANDLE writePipe;
4646 HANDLE readPipe;
47+ HANDLE initEvent;
4748 HANDLE connectEvent;
4849};
4950
@@ -81,13 +82,16 @@ _query_thread(LPVOID param)
8182 IID_IWbemLocator, (LPVOID *)&locator
8283 );
8384 }
85+ if (SUCCEEDED (hr) && !SetEvent (data->initEvent )) {
86+ hr =HRESULT_FROM_WIN32 (GetLastError ());
87+ }
8488if (SUCCEEDED (hr)) {
8589 hr = locator->ConnectServer (
8690bstr_t (L" ROOT\\ CIMV2" ),
8791NULL ,NULL ,0 ,NULL ,0 ,0 , &services
8892 );
8993 }
90- if (!SetEvent (data->connectEvent )) {
94+ if (SUCCEEDED (hr) && !SetEvent (data->connectEvent )) {
9195 hr =HRESULT_FROM_WIN32 (GetLastError ());
9296 }
9397if (SUCCEEDED (hr)) {
@@ -193,6 +197,24 @@ _query_thread(LPVOID param)
193197}
194198
195199
200+ static DWORD
201+ wait_event (HANDLE event, DWORD timeout)
202+ {
203+ DWORD err =0 ;
204+ switch (WaitForSingleObject (event, timeout)) {
205+ case WAIT_OBJECT_0:
206+ break ;
207+ case WAIT_TIMEOUT:
208+ err = WAIT_TIMEOUT;
209+ break ;
210+ default :
211+ err =GetLastError ();
212+ break ;
213+ }
214+ return err;
215+ }
216+
217+
196218/* [clinic input]
197219_wmi.exec_query
198220
@@ -235,8 +257,11 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
235257
236258 Py_BEGIN_ALLOW_THREADS
237259
260+ data.initEvent =CreateEvent (NULL ,TRUE ,FALSE ,NULL );
238261 data.connectEvent =CreateEvent (NULL ,TRUE ,FALSE ,NULL );
239- if (!data.connectEvent || !CreatePipe (&data.readPipe , &data.writePipe ,NULL ,0 )) {
262+ if (!data.initEvent || !data.connectEvent ||
263+ !CreatePipe (&data.readPipe , &data.writePipe ,NULL ,0 ))
264+ {
240265 err =GetLastError ();
241266 }else {
242267 hThread =CreateThread (NULL ,0 , _query_thread, (LPVOID*)&data,0 ,NULL );
@@ -251,16 +276,12 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
251276// gh-112278: If current user doesn't have permission to query the WMI, the
252277// function IWbemLocator::ConnectServer will hang for 5 seconds, and there
253278// is no way to specify the timeout. So we use an Event object to simulate
254- // a timeout.
255- switch (WaitForSingleObject (data.connectEvent ,100 )) {
256- case WAIT_OBJECT_0:
257- break ;
258- case WAIT_TIMEOUT:
259- err = WAIT_TIMEOUT;
260- break ;
261- default :
262- err =GetLastError ();
263- break ;
279+ // a timeout. The initEvent will be set after COM initialization, it will
280+ // take a longer time when first initialized. The connectEvent will be set
281+ // after connected to WMI.
282+ err =wait_event (data.initEvent ,1000 );
283+ if (!err) {
284+ err =wait_event (data.connectEvent ,100 );
264285 }
265286
266287while (!err) {
@@ -306,6 +327,7 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
306327 }
307328
308329CloseHandle (hThread);
330+ CloseHandle (data.initEvent );
309331CloseHandle (data.connectEvent );
310332 hThread =NULL ;
311333