pdh: Implement and test PdhCollectQueryDataEx.
This commit is contained in:
parent
2f80bc0e68
commit
0389ec60d9
|
@ -16,7 +16,7 @@
|
|||
@ stdcall PdhCloseQuery(ptr)
|
||||
@ stdcall PdhCollectQueryData(ptr)
|
||||
@ stdcall PdhCollectQueryDataWithTime(ptr ptr)
|
||||
@ stub PdhCollectQueryDataEx
|
||||
@ stdcall PdhCollectQueryDataEx(ptr long ptr)
|
||||
@ stub PdhComputeCounterStatistics
|
||||
@ stub PdhConnectMachineA
|
||||
@ stub PdhConnectMachineW
|
||||
|
|
|
@ -151,6 +151,10 @@ struct query
|
|||
{
|
||||
DWORD magic; /* signature */
|
||||
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 */
|
||||
};
|
||||
|
||||
|
@ -315,6 +319,18 @@ PDH_STATUS WINAPI PdhAddEnglishCounterW( PDH_HQUERY query, LPCWSTR path,
|
|||
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.@)
|
||||
*/
|
||||
|
@ -332,6 +348,8 @@ PDH_STATUS WINAPI PdhCloseQuery( PDH_HQUERY handle )
|
|||
return PDH_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (query->thread) shutdown_query_thread( query );
|
||||
|
||||
LIST_FOR_EACH_SAFE( item, next, &query->counters )
|
||||
{
|
||||
struct counter *counter = LIST_ENTRY( item, struct counter, entry );
|
||||
|
@ -391,6 +409,79 @@ PDH_STATUS WINAPI PdhCollectQueryData( PDH_HQUERY handle )
|
|||
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.@)
|
||||
*/
|
||||
|
|
|
@ -797,6 +797,56 @@ static void test_PdhValidatePathExW( void )
|
|||
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)
|
||||
{
|
||||
init_function_ptrs();
|
||||
|
@ -830,4 +880,6 @@ START_TEST(pdh)
|
|||
|
||||
if (pPdhValidatePathExA) test_PdhValidatePathExA();
|
||||
if (pPdhValidatePathExW) test_PdhValidatePathExW();
|
||||
|
||||
test_PdhCollectQueryDataEx();
|
||||
}
|
||||
|
|
|
@ -173,6 +173,7 @@ PDH_STATUS WINAPI PdhAddEnglishCounterW(PDH_HQUERY, LPCWSTR, DWORD_PTR, PDH_HCOU
|
|||
#define PdhAddEnglishCounter WINELIB_NAME_AW(PdhAddEnglishCounter)
|
||||
PDH_STATUS WINAPI PdhCloseQuery(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 PdhGetCounterInfoA(PDH_HCOUNTER, BOOLEAN, LPDWORD, PPDH_COUNTER_INFO_A);
|
||||
PDH_STATUS WINAPI PdhGetCounterInfoW(PDH_HCOUNTER, BOOLEAN, LPDWORD, PPDH_COUNTER_INFO_W);
|
||||
|
|
Loading…
Reference in New Issue