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