@@ -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+     }
8488    if  (SUCCEEDED (hr)) {
8589        hr = locator->ConnectServer (
8690            bstr_t (L" ROOT\\ CIMV2" 
8791            NULL , 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    }
9397    if  (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
266287    while  (!err) {
@@ -306,6 +327,7 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
306327    }
307328
308329    CloseHandle (hThread);
330+     CloseHandle (data.initEvent );
309331    CloseHandle (data.connectEvent );
310332    hThread = NULL ;
311333
0 commit comments