wbemprox: Add support for asynchronous queries.
This commit is contained in:
parent
633c3cb086
commit
46cbc36041
|
@ -135,11 +135,68 @@ static const IClientSecurityVtbl client_security_vtbl =
|
||||||
|
|
||||||
IClientSecurity client_security = { &client_security_vtbl };
|
IClientSecurity client_security = { &client_security_vtbl };
|
||||||
|
|
||||||
|
struct async_header
|
||||||
|
{
|
||||||
|
IWbemObjectSink *sink;
|
||||||
|
void (*proc)( struct async_header * );
|
||||||
|
HANDLE cancel;
|
||||||
|
HANDLE wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct async_query
|
||||||
|
{
|
||||||
|
struct async_header hdr;
|
||||||
|
WCHAR *str;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void free_async( struct async_header *async )
|
||||||
|
{
|
||||||
|
if (async->sink) IWbemObjectSink_Release( async->sink );
|
||||||
|
CloseHandle( async->cancel );
|
||||||
|
CloseHandle( async->wait );
|
||||||
|
heap_free( async );
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL init_async( struct async_header *async, IWbemObjectSink *sink,
|
||||||
|
void (*proc)(struct async_header *) )
|
||||||
|
{
|
||||||
|
if (!(async->wait = CreateEventW( NULL, FALSE, FALSE, NULL ))) return FALSE;
|
||||||
|
if (!(async->cancel = CreateEventW( NULL, FALSE, FALSE, NULL )))
|
||||||
|
{
|
||||||
|
CloseHandle( async->wait );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
async->proc = proc;
|
||||||
|
async->sink = sink;
|
||||||
|
IWbemObjectSink_AddRef( sink );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD CALLBACK async_proc( LPVOID param )
|
||||||
|
{
|
||||||
|
struct async_header *async = param;
|
||||||
|
HANDLE wait = async->wait;
|
||||||
|
|
||||||
|
async->proc( async );
|
||||||
|
|
||||||
|
WaitForSingleObject( async->cancel, INFINITE );
|
||||||
|
SetEvent( wait );
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT queue_async( struct async_header *async )
|
||||||
|
{
|
||||||
|
if (QueueUserWorkItem( async_proc, async, WT_EXECUTELONGFUNCTION )) return S_OK;
|
||||||
|
return HRESULT_FROM_WIN32( GetLastError() );
|
||||||
|
}
|
||||||
|
|
||||||
struct wbem_services
|
struct wbem_services
|
||||||
{
|
{
|
||||||
IWbemServices IWbemServices_iface;
|
IWbemServices IWbemServices_iface;
|
||||||
LONG refs;
|
LONG refs;
|
||||||
|
CRITICAL_SECTION cs;
|
||||||
WCHAR *namespace;
|
WCHAR *namespace;
|
||||||
|
struct async_header *async;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct wbem_services *impl_from_IWbemServices( IWbemServices *iface )
|
static inline struct wbem_services *impl_from_IWbemServices( IWbemServices *iface )
|
||||||
|
@ -162,6 +219,17 @@ static ULONG WINAPI wbem_services_Release(
|
||||||
if (!refs)
|
if (!refs)
|
||||||
{
|
{
|
||||||
TRACE("destroying %p\n", ws);
|
TRACE("destroying %p\n", ws);
|
||||||
|
|
||||||
|
EnterCriticalSection( &ws->cs );
|
||||||
|
if (ws->async) SetEvent( ws->async->cancel );
|
||||||
|
LeaveCriticalSection( &ws->cs );
|
||||||
|
if (ws->async)
|
||||||
|
{
|
||||||
|
WaitForSingleObject( ws->async->wait, INFINITE );
|
||||||
|
free_async( ws->async );
|
||||||
|
}
|
||||||
|
ws->cs.DebugInfo->Spare[0] = 0;
|
||||||
|
DeleteCriticalSection( &ws->cs );
|
||||||
heap_free( ws->namespace );
|
heap_free( ws->namespace );
|
||||||
heap_free( ws );
|
heap_free( ws );
|
||||||
}
|
}
|
||||||
|
@ -221,9 +289,27 @@ static HRESULT WINAPI wbem_services_CancelAsyncCall(
|
||||||
IWbemServices *iface,
|
IWbemServices *iface,
|
||||||
IWbemObjectSink *pSink )
|
IWbemObjectSink *pSink )
|
||||||
{
|
{
|
||||||
FIXME("%p, %p\n", iface, pSink);
|
struct wbem_services *services = impl_from_IWbemServices( iface );
|
||||||
|
struct async_header *async;
|
||||||
|
|
||||||
IWbemObjectSink_Release( pSink );
|
TRACE("%p, %p\n", iface, pSink);
|
||||||
|
|
||||||
|
if (!pSink) return WBEM_E_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
EnterCriticalSection( &services->cs );
|
||||||
|
|
||||||
|
if (!(async = services->async))
|
||||||
|
{
|
||||||
|
LeaveCriticalSection( &services->cs );
|
||||||
|
return WBEM_E_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
services->async = NULL;
|
||||||
|
SetEvent( async->cancel );
|
||||||
|
|
||||||
|
LeaveCriticalSection( &services->cs );
|
||||||
|
|
||||||
|
WaitForSingleObject( async->wait, INFINITE );
|
||||||
|
free_async( async );
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,6 +618,30 @@ static HRESULT WINAPI wbem_services_ExecQuery(
|
||||||
return exec_query( strQuery, ppEnum );
|
return exec_query( strQuery, ppEnum );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void async_exec_query( struct async_header *hdr )
|
||||||
|
{
|
||||||
|
struct async_query *query = (struct async_query *)hdr;
|
||||||
|
IEnumWbemClassObject *result;
|
||||||
|
IWbemClassObject *obj;
|
||||||
|
ULONG count;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = exec_query( query->str, &result );
|
||||||
|
if (hr == S_OK)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
|
||||||
|
if (!count) break;
|
||||||
|
IWbemObjectSink_Indicate( query->hdr.sink, 1, &obj );
|
||||||
|
IWbemClassObject_Release( obj );
|
||||||
|
}
|
||||||
|
IEnumWbemClassObject_Release( result );
|
||||||
|
}
|
||||||
|
IWbemObjectSink_SetStatus( query->hdr.sink, WBEM_STATUS_COMPLETE, hr, NULL, NULL );
|
||||||
|
heap_free( query->str );
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI wbem_services_ExecQueryAsync(
|
static HRESULT WINAPI wbem_services_ExecQueryAsync(
|
||||||
IWbemServices *iface,
|
IWbemServices *iface,
|
||||||
const BSTR strQueryLanguage,
|
const BSTR strQueryLanguage,
|
||||||
|
@ -540,8 +650,53 @@ static HRESULT WINAPI wbem_services_ExecQueryAsync(
|
||||||
IWbemContext *pCtx,
|
IWbemContext *pCtx,
|
||||||
IWbemObjectSink *pResponseHandler )
|
IWbemObjectSink *pResponseHandler )
|
||||||
{
|
{
|
||||||
FIXME("\n");
|
struct wbem_services *services = impl_from_IWbemServices( iface );
|
||||||
return WBEM_E_FAILED;
|
IWbemObjectSink *sink;
|
||||||
|
HRESULT hr = E_OUTOFMEMORY;
|
||||||
|
struct async_header *async;
|
||||||
|
struct async_query *query;
|
||||||
|
|
||||||
|
TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
|
||||||
|
lFlags, pCtx, pResponseHandler);
|
||||||
|
|
||||||
|
if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
EnterCriticalSection( &services->cs );
|
||||||
|
|
||||||
|
if (services->async)
|
||||||
|
{
|
||||||
|
FIXME("handle more than one pending async\n");
|
||||||
|
hr = WBEM_E_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (!(query = heap_alloc_zero( sizeof(*query) ))) goto done;
|
||||||
|
async = (struct async_header *)query;
|
||||||
|
|
||||||
|
if (!(init_async( async, sink, async_exec_query )))
|
||||||
|
{
|
||||||
|
free_async( async );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (!(query->str = heap_strdupW( strQuery )))
|
||||||
|
{
|
||||||
|
free_async( async );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
hr = queue_async( async );
|
||||||
|
if (hr == S_OK) services->async = async;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
heap_free( query->str );
|
||||||
|
free_async( async );
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
LeaveCriticalSection( &services->cs );
|
||||||
|
IWbemObjectSink_Release( sink );
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI wbem_services_ExecNotificationQuery(
|
static HRESULT WINAPI wbem_services_ExecNotificationQuery(
|
||||||
|
@ -564,11 +719,53 @@ static HRESULT WINAPI wbem_services_ExecNotificationQueryAsync(
|
||||||
IWbemContext *pCtx,
|
IWbemContext *pCtx,
|
||||||
IWbemObjectSink *pResponseHandler )
|
IWbemObjectSink *pResponseHandler )
|
||||||
{
|
{
|
||||||
FIXME("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
|
struct wbem_services *services = impl_from_IWbemServices( iface );
|
||||||
|
IWbemObjectSink *sink;
|
||||||
|
HRESULT hr = E_OUTOFMEMORY;
|
||||||
|
struct async_header *async;
|
||||||
|
struct async_query *query;
|
||||||
|
|
||||||
|
TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
|
||||||
lFlags, pCtx, pResponseHandler);
|
lFlags, pCtx, pResponseHandler);
|
||||||
|
|
||||||
IWbemObjectSink_AddRef( pResponseHandler );
|
if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
|
||||||
return S_OK;
|
|
||||||
|
hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
|
||||||
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
EnterCriticalSection( &services->cs );
|
||||||
|
|
||||||
|
if (services->async)
|
||||||
|
{
|
||||||
|
FIXME("handle more than one pending async\n");
|
||||||
|
hr = WBEM_E_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (!(query = heap_alloc_zero( sizeof(*query) ))) goto done;
|
||||||
|
async = (struct async_header *)query;
|
||||||
|
|
||||||
|
if (!(init_async( async, sink, async_exec_query )))
|
||||||
|
{
|
||||||
|
free_async( async );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (!(query->str = heap_strdupW( strQuery )))
|
||||||
|
{
|
||||||
|
free_async( async );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
hr = queue_async( async );
|
||||||
|
if (hr == S_OK) services->async = async;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
heap_free( query->str );
|
||||||
|
free_async( async );
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
LeaveCriticalSection( &services->cs );
|
||||||
|
IWbemObjectSink_Release( sink );
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI wbem_services_ExecMethod(
|
static HRESULT WINAPI wbem_services_ExecMethod(
|
||||||
|
@ -670,8 +867,11 @@ HRESULT WbemServices_create( IUnknown *pUnkOuter, const WCHAR *namespace, LPVOID
|
||||||
if (!ws) return E_OUTOFMEMORY;
|
if (!ws) return E_OUTOFMEMORY;
|
||||||
|
|
||||||
ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl;
|
ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl;
|
||||||
ws->refs = 1;
|
ws->refs = 1;
|
||||||
ws->namespace = heap_strdupW( namespace );
|
ws->namespace = heap_strdupW( namespace );
|
||||||
|
ws->async = NULL;
|
||||||
|
InitializeCriticalSection( &ws->cs );
|
||||||
|
ws->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wbemprox_services.cs");
|
||||||
|
|
||||||
*ppObj = &ws->IWbemServices_iface;
|
*ppObj = &ws->IWbemServices_iface;
|
||||||
|
|
||||||
|
|
|
@ -546,14 +546,14 @@ static ULONG WINAPI sink_Release(
|
||||||
static HRESULT WINAPI sink_Indicate(
|
static HRESULT WINAPI sink_Indicate(
|
||||||
IWbemObjectSink *iface, LONG count, IWbemClassObject **objects )
|
IWbemObjectSink *iface, LONG count, IWbemClassObject **objects )
|
||||||
{
|
{
|
||||||
trace("%d, %p\n", count, objects);
|
trace("Indicate: %d, %p\n", count, objects);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI sink_SetStatus(
|
static HRESULT WINAPI sink_SetStatus(
|
||||||
IWbemObjectSink *iface, LONG flags, HRESULT hresult, BSTR str_param, IWbemClassObject *obj_param )
|
IWbemObjectSink *iface, LONG flags, HRESULT hresult, BSTR str_param, IWbemClassObject *obj_param )
|
||||||
{
|
{
|
||||||
trace("%08x, %08x, %s, %p\n", flags, hresult, wine_dbgstr_w(str_param), obj_param);
|
trace("SetStatus: %08x, %08x, %s, %p\n", flags, hresult, wine_dbgstr_w(str_param), obj_param);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,11 +574,40 @@ static void test_notification_query_async( IWbemServices *services )
|
||||||
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','W','i','n','3','2','_',
|
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','W','i','n','3','2','_',
|
||||||
'D','e','v','i','c','e','C','h','a','n','g','e','E','v','e','n','t',0};
|
'D','e','v','i','c','e','C','h','a','n','g','e','E','v','e','n','t',0};
|
||||||
BSTR wql = SysAllocString( wqlW ), query = SysAllocString( queryW );
|
BSTR wql = SysAllocString( wqlW ), query = SysAllocString( queryW );
|
||||||
|
ULONG prev_sink_refs;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = IWbemServices_ExecNotificationQueryAsync( services, wql, query, 0, NULL, NULL );
|
||||||
|
ok( hr == WBEM_E_INVALID_PARAMETER, "got %08x\n", hr );
|
||||||
|
|
||||||
|
prev_sink_refs = sink_refs;
|
||||||
hr = IWbemServices_ExecNotificationQueryAsync( services, wql, query, 0, NULL, &sink );
|
hr = IWbemServices_ExecNotificationQueryAsync( services, wql, query, 0, NULL, &sink );
|
||||||
ok( hr == S_OK || broken(hr == WBEM_E_NOT_FOUND), "got %08x\n", hr );
|
ok( hr == S_OK || broken(hr == WBEM_E_NOT_FOUND), "got %08x\n", hr );
|
||||||
ok( sink_refs, "got %u\n", sink_refs );
|
ok( sink_refs > prev_sink_refs, "got %u refs\n", sink_refs );
|
||||||
|
|
||||||
|
hr = IWbemServices_CancelAsyncCall( services, &sink );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
SysFreeString( wql );
|
||||||
|
SysFreeString( query );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_query_async( IWbemServices *services )
|
||||||
|
{
|
||||||
|
static const WCHAR queryW[] =
|
||||||
|
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','W','i','n','3','2','_',
|
||||||
|
'P','r','o','c','e','s','s',0};
|
||||||
|
BSTR wql = SysAllocString( wqlW ), query = SysAllocString( queryW );
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = IWbemServices_ExecQueryAsync( services, wql, query, 0, NULL, NULL );
|
||||||
|
ok( hr == WBEM_E_INVALID_PARAMETER, "got %08x\n", hr );
|
||||||
|
|
||||||
|
hr = IWbemServices_ExecQueryAsync( services, wql, query, 0, NULL, &sink );
|
||||||
|
ok( hr == S_OK || broken(hr == WBEM_E_NOT_FOUND), "got %08x\n", hr );
|
||||||
|
|
||||||
|
hr = IWbemServices_CancelAsyncCall( services, NULL );
|
||||||
|
ok( hr == WBEM_E_INVALID_PARAMETER, "got %08x\n", hr );
|
||||||
|
|
||||||
hr = IWbemServices_CancelAsyncCall( services, &sink );
|
hr = IWbemServices_CancelAsyncCall( services, &sink );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
@ -617,6 +646,7 @@ START_TEST(query)
|
||||||
test_Win32_Service( services );
|
test_Win32_Service( services );
|
||||||
test_StdRegProv( services );
|
test_StdRegProv( services );
|
||||||
test_notification_query_async( services );
|
test_notification_query_async( services );
|
||||||
|
test_query_async( services );
|
||||||
|
|
||||||
SysFreeString( path );
|
SysFreeString( path );
|
||||||
IWbemServices_Release( services );
|
IWbemServices_Release( services );
|
||||||
|
|
|
@ -176,6 +176,13 @@ typedef [v1_enum] enum tag_WBEMSTATUS
|
||||||
WBEM_E_PROVIDER_DISABLED = 0x8004108a
|
WBEM_E_PROVIDER_DISABLED = 0x8004108a
|
||||||
} WBEMSTATUS;
|
} WBEMSTATUS;
|
||||||
|
|
||||||
|
typedef [v1_enum] enum tag_WBEM_STATUS_TYPE
|
||||||
|
{
|
||||||
|
WBEM_STATUS_COMPLETE = 0,
|
||||||
|
WBEM_STATUS_REQUIREMENTS = 1,
|
||||||
|
WBEM_STATUS_PROGRESS = 2
|
||||||
|
} WBEM_STATUS_TYPE;
|
||||||
|
|
||||||
typedef [v1_enum] enum tag_WBEM_TIMEOUT_TYPE
|
typedef [v1_enum] enum tag_WBEM_TIMEOUT_TYPE
|
||||||
{
|
{
|
||||||
WBEM_NO_WAIT = 0,
|
WBEM_NO_WAIT = 0,
|
||||||
|
|
Loading…
Reference in New Issue