Commit 0389ec60 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

pdh: Implement and test PdhCollectQueryDataEx.

parent 2f80bc0e
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
@ stdcall PdhCloseQuery(ptr) @ stdcall PdhCloseQuery(ptr)
@ stdcall PdhCollectQueryData(ptr) @ stdcall PdhCollectQueryData(ptr)
@ stdcall PdhCollectQueryDataWithTime(ptr ptr) @ stdcall PdhCollectQueryDataWithTime(ptr ptr)
@ stub PdhCollectQueryDataEx @ stdcall PdhCollectQueryDataEx(ptr long ptr)
@ stub PdhComputeCounterStatistics @ stub PdhComputeCounterStatistics
@ stub PdhConnectMachineA @ stub PdhConnectMachineA
@ stub PdhConnectMachineW @ stub PdhConnectMachineW
......
...@@ -151,6 +151,10 @@ struct query ...@@ -151,6 +151,10 @@ struct query
{ {
DWORD magic; /* signature */ DWORD magic; /* signature */
DWORD_PTR user; /* user data */ DWORD_PTR user; /* user data */
HANDLE thread; /* collect thread */
DWORD interval; /* collect interval */
HANDLE wait; /* wait event */
HANDLE stop; /* stop event */
struct list counters; /* counter list */ struct list counters; /* counter list */
}; };
...@@ -315,6 +319,18 @@ PDH_STATUS WINAPI PdhAddEnglishCounterW( PDH_HQUERY query, LPCWSTR path, ...@@ -315,6 +319,18 @@ PDH_STATUS WINAPI PdhAddEnglishCounterW( PDH_HQUERY query, LPCWSTR path,
return PdhAddCounterW( query, path, userdata, counter ); return PdhAddCounterW( query, path, userdata, counter );
} }
/* caller must hold query lock */
static void shutdown_query_thread( struct query *query )
{
SetEvent( query->stop );
WaitForSingleObject( query->thread, INFINITE );
CloseHandle( query->stop );
CloseHandle( query->thread );
query->thread = NULL;
}
/*********************************************************************** /***********************************************************************
* PdhCloseQuery (PDH.@) * PdhCloseQuery (PDH.@)
*/ */
...@@ -332,6 +348,8 @@ PDH_STATUS WINAPI PdhCloseQuery( PDH_HQUERY handle ) ...@@ -332,6 +348,8 @@ PDH_STATUS WINAPI PdhCloseQuery( PDH_HQUERY handle )
return PDH_INVALID_HANDLE; return PDH_INVALID_HANDLE;
} }
if (query->thread) shutdown_query_thread( query );
LIST_FOR_EACH_SAFE( item, next, &query->counters ) LIST_FOR_EACH_SAFE( item, next, &query->counters )
{ {
struct counter *counter = LIST_ENTRY( item, struct counter, entry ); struct counter *counter = LIST_ENTRY( item, struct counter, entry );
...@@ -391,6 +409,79 @@ PDH_STATUS WINAPI PdhCollectQueryData( PDH_HQUERY handle ) ...@@ -391,6 +409,79 @@ PDH_STATUS WINAPI PdhCollectQueryData( PDH_HQUERY handle )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static DWORD CALLBACK collect_query_thread( void *arg )
{
struct query *query = arg;
DWORD interval = query->interval;
HANDLE stop = query->stop;
SetEvent( stop );
for (;;)
{
if (WaitForSingleObject( stop, interval ) != WAIT_TIMEOUT) ExitThread( 0 );
EnterCriticalSection( &pdh_handle_cs );
if (!query || query->magic != PDH_MAGIC_QUERY)
{
LeaveCriticalSection( &pdh_handle_cs );
ExitThread( PDH_INVALID_HANDLE );
}
collect_query_data( query );
if (!SetEvent( query->wait ))
{
LeaveCriticalSection( &pdh_handle_cs );
ExitThread( 0 );
}
LeaveCriticalSection( &pdh_handle_cs );
}
}
/***********************************************************************
* PdhCollectQueryDataEx (PDH.@)
*/
PDH_STATUS WINAPI PdhCollectQueryDataEx( PDH_HQUERY handle, DWORD interval, HANDLE event )
{
PDH_STATUS ret;
struct query *query = handle;
TRACE("%p %d %p\n", handle, interval, event);
EnterCriticalSection( &pdh_handle_cs );
if (!query || query->magic != PDH_MAGIC_QUERY)
{
LeaveCriticalSection( &pdh_handle_cs );
return PDH_INVALID_HANDLE;
}
if (list_empty( &query->counters ))
{
LeaveCriticalSection( &pdh_handle_cs );
return PDH_NO_DATA;
}
if (query->thread) shutdown_query_thread( query );
if (!(query->stop = CreateEventW( NULL, FALSE, FALSE, NULL )))
{
ret = GetLastError();
LeaveCriticalSection( &pdh_handle_cs );
return ret;
}
query->wait = event;
query->interval = interval * 1000;
if (!(query->thread = CreateThread( NULL, 0, collect_query_thread, query, 0, NULL )))
{
ret = GetLastError();
CloseHandle( query->stop );
LeaveCriticalSection( &pdh_handle_cs );
return ret;
}
WaitForSingleObject( query->stop, INFINITE );
LeaveCriticalSection( &pdh_handle_cs );
return ERROR_SUCCESS;
}
/*********************************************************************** /***********************************************************************
* PdhCollectQueryDataWithTime (PDH.@) * PdhCollectQueryDataWithTime (PDH.@)
*/ */
......
...@@ -797,6 +797,56 @@ static void test_PdhValidatePathExW( void ) ...@@ -797,6 +797,56 @@ static void test_PdhValidatePathExW( void )
ok(ret == ERROR_SUCCESS, "PdhValidatePathExW failed 0x%08x\n", ret); ok(ret == ERROR_SUCCESS, "PdhValidatePathExW failed 0x%08x\n", ret);
} }
static void test_PdhCollectQueryDataEx(void)
{
PDH_STATUS status;
PDH_HQUERY query;
PDH_HCOUNTER counter;
HANDLE event;
BOOL ret;
UINT i;
status = PdhOpenQueryA( NULL, 0, &query );
ok(status == ERROR_SUCCESS, "PdhOpenQuery failed 0x%08x\n", status);
event = CreateEventA( NULL, FALSE, FALSE, "winetest" );
ok(event != NULL, "CreateEvent failed\n");
status = PdhAddCounterA( query, "\\System\\System Up Time", 0, &counter );
ok(status == ERROR_SUCCESS, "PdhAddCounterA failed 0x%08x\n", status);
status = PdhCollectQueryDataEx( NULL, 1, event );
ok(status == PDH_INVALID_HANDLE, "PdhCollectQueryDataEx failed 0x%08x\n", status);
status = PdhCollectQueryDataEx( query, 1, NULL );
ok(status == ERROR_SUCCESS, "PdhCollectQueryDataEx failed 0x%08x\n", status);
status = PdhCollectQueryDataEx( query, 1, event );
ok(status == ERROR_SUCCESS, "PdhCollectQueryDataEx failed 0x%08x\n", status);
status = PdhCollectQueryData( query );
ok(status == ERROR_SUCCESS, "PdhCollectQueryData failed 0x%08x\n", status);
for (i = 0; i < 3; i++)
{
if (WaitForSingleObject( event, INFINITE ) == WAIT_OBJECT_0)
{
PDH_FMT_COUNTERVALUE value;
status = PdhGetFormattedCounterValue( counter, PDH_FMT_LARGE, NULL, &value );
ok(status == ERROR_SUCCESS, "PdhGetFormattedCounterValue failed 0x%08x\n", status);
trace( "uptime %x%08x\n", (DWORD)(value.largeValue >> 32), (DWORD)value.largeValue );
}
}
ret = CloseHandle( event );
ok(ret, "CloseHandle failed\n");
status = PdhCloseQuery( query );
ok(status == ERROR_SUCCESS, "PdhCloseQuery failed 0x%08x\n", status);
}
START_TEST(pdh) START_TEST(pdh)
{ {
init_function_ptrs(); init_function_ptrs();
...@@ -830,4 +880,6 @@ START_TEST(pdh) ...@@ -830,4 +880,6 @@ START_TEST(pdh)
if (pPdhValidatePathExA) test_PdhValidatePathExA(); if (pPdhValidatePathExA) test_PdhValidatePathExA();
if (pPdhValidatePathExW) test_PdhValidatePathExW(); if (pPdhValidatePathExW) test_PdhValidatePathExW();
test_PdhCollectQueryDataEx();
} }
...@@ -173,6 +173,7 @@ PDH_STATUS WINAPI PdhAddEnglishCounterW(PDH_HQUERY, LPCWSTR, DWORD_PTR, PDH_HCOU ...@@ -173,6 +173,7 @@ PDH_STATUS WINAPI PdhAddEnglishCounterW(PDH_HQUERY, LPCWSTR, DWORD_PTR, PDH_HCOU
#define PdhAddEnglishCounter WINELIB_NAME_AW(PdhAddEnglishCounter) #define PdhAddEnglishCounter WINELIB_NAME_AW(PdhAddEnglishCounter)
PDH_STATUS WINAPI PdhCloseQuery(PDH_HQUERY); PDH_STATUS WINAPI PdhCloseQuery(PDH_HQUERY);
PDH_STATUS WINAPI PdhCollectQueryData(PDH_HQUERY); PDH_STATUS WINAPI PdhCollectQueryData(PDH_HQUERY);
PDH_STATUS WINAPI PdhCollectQueryDataEx(PDH_HQUERY, DWORD, HANDLE);
PDH_STATUS WINAPI PdhCollectQueryDataWithTime(PDH_HQUERY,LONGLONG *); PDH_STATUS WINAPI PdhCollectQueryDataWithTime(PDH_HQUERY,LONGLONG *);
PDH_STATUS WINAPI PdhGetCounterInfoA(PDH_HCOUNTER, BOOLEAN, LPDWORD, PPDH_COUNTER_INFO_A); PDH_STATUS WINAPI PdhGetCounterInfoA(PDH_HCOUNTER, BOOLEAN, LPDWORD, PPDH_COUNTER_INFO_A);
PDH_STATUS WINAPI PdhGetCounterInfoW(PDH_HCOUNTER, BOOLEAN, LPDWORD, PPDH_COUNTER_INFO_W); PDH_STATUS WINAPI PdhGetCounterInfoW(PDH_HCOUNTER, BOOLEAN, LPDWORD, PPDH_COUNTER_INFO_W);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment