Hans Leidekker : pdh: Implement and test PdhCollectQueryDataEx.
Alexandre Julliard
julliard at winehq.org
Mon Oct 1 07:55:00 CDT 2007
Module: wine
Branch: master
Commit: 0389ec60d98381c8f99fa518434455742f6ee439
URL: http://source.winehq.org/git/wine.git/?a=commit;h=0389ec60d98381c8f99fa518434455742f6ee439
Author: Hans Leidekker <hans at it.vu.nl>
Date: Sat Sep 29 21:06:35 2007 +0200
pdh: Implement and test PdhCollectQueryDataEx.
---
dlls/pdh/pdh.spec | 2 +-
dlls/pdh/pdh_main.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++
dlls/pdh/tests/pdh.c | 52 ++++++++++++++++++++++++++++
include/pdh.h | 1 +
4 files changed, 145 insertions(+), 1 deletions(-)
diff --git a/dlls/pdh/pdh.spec b/dlls/pdh/pdh.spec
index 795a45e..8735c0f 100644
--- a/dlls/pdh/pdh.spec
+++ b/dlls/pdh/pdh.spec
@@ -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
diff --git a/dlls/pdh/pdh_main.c b/dlls/pdh/pdh_main.c
index 8d5c081..479fe3b 100644
--- a/dlls/pdh/pdh_main.c
+++ b/dlls/pdh/pdh_main.c
@@ -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.@)
*/
diff --git a/dlls/pdh/tests/pdh.c b/dlls/pdh/tests/pdh.c
index 85b0853..2853f8b 100644
--- a/dlls/pdh/tests/pdh.c
+++ b/dlls/pdh/tests/pdh.c
@@ -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();
}
diff --git a/include/pdh.h b/include/pdh.h
index 3aff6db..7018247 100644
--- a/include/pdh.h
+++ b/include/pdh.h
@@ -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);
More information about the wine-cvs
mailing list