Paul Gofman : advapi32: Improve PerfSetCounterSetInfo() stub.

Alexandre Julliard julliard at winehq.org
Mon Nov 22 16:05:18 CST 2021


Module: wine
Branch: master
Commit: ee8af8ff280389aa9188505e7c9a60c72d4e30dd
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=ee8af8ff280389aa9188505e7c9a60c72d4e30dd

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Mon Nov 22 17:07:57 2021 +0300

advapi32: Improve PerfSetCounterSetInfo() stub.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/advapi32/tests/perf.c | 39 ++++++++++++++++++++++++++++++++++
 dlls/kernelbase/main.c     | 52 +++++++++++++++++++++++++++++++++++++++++++---
 include/perflib.h          | 31 +++++++++++++++++++++++++++
 include/winperf.h          | 29 ++++++++++++++++++++++++++
 4 files changed, 148 insertions(+), 3 deletions(-)

diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c
index 34fedd2b645..d76d6ddd44a 100644
--- a/dlls/advapi32/tests/perf.c
+++ b/dlls/advapi32/tests/perf.c
@@ -24,6 +24,7 @@
 #include "winbase.h"
 #include "winerror.h"
 #include "perflib.h"
+#include "winperf.h"
 
 #include "wine/test.h"
 
@@ -35,7 +36,20 @@ static ULONG WINAPI test_provider_callback(ULONG code, void *buffer, ULONG size)
 
 void test_provider_init(void)
 {
+    static GUID test_set_guid = {0xdeadbeef, 0x0002, 0x0003, {0x0f, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00 ,0x0a}};
+    static GUID test_set_guid2 = {0xdeadbeef, 0x0003, 0x0003, {0x0f, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00 ,0x0a}};
     static GUID test_guid = {0xdeadbeef, 0x0001, 0x0002, {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00 ,0x0a}};
+    static struct
+    {
+        PERF_COUNTERSET_INFO counterset;
+        PERF_COUNTER_INFO counter;
+    }
+    pc_template =
+    {
+        {{0}},
+        {1, PERF_COUNTER_COUNTER, PERF_ATTRIB_BY_REFERENCE, sizeof(PERF_COUNTER_INFO), PERF_DETAIL_NOVICE, 0, 0},
+    };
+
     PERF_PROVIDER_CONTEXT prov_context;
     HANDLE prov, prov2;
     ULONG ret;
@@ -76,6 +90,31 @@ void test_provider_init(void)
     bret = IsBadWritePtr(prov, 8);
     ok(!bret, "Handle does not point to the data.\n");
 
+    pc_template.counterset.CounterSetGuid = test_set_guid;
+    pc_template.counterset.ProviderGuid = test_guid;
+    pc_template.counterset.NumCounters = 0;
+    pc_template.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE;
+    ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template.counterset));
+    ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
+
+    pc_template.counterset.CounterSetGuid = test_set_guid;
+    pc_template.counterset.ProviderGuid = test_guid;
+    pc_template.counterset.NumCounters = 1;
+    pc_template.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE;
+    ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
+    ok(!ret, "Got unexpected ret %u.\n", ret);
+
+    pc_template.counterset.CounterSetGuid = test_set_guid2;
+    /* Looks like ProviderGuid doesn't need to match provider. */
+    pc_template.counterset.ProviderGuid = test_set_guid;
+    pc_template.counterset.NumCounters = 1;
+    pc_template.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE;
+    ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
+    ok(!ret, "Got unexpected ret %u.\n", ret);
+
+    ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
+    ok(ret == ERROR_ALREADY_EXISTS, "Got unexpected ret %u.\n", ret);
+
     ret = PerfStopProvider(prov);
     ok(!ret, "Got unexpected ret %u.\n", ret);
 
diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c
index d468c84f619..403c0cf6cd2 100644
--- a/dlls/kernelbase/main.c
+++ b/dlls/kernelbase/main.c
@@ -154,10 +154,18 @@ LONG WINAPI AppPolicyGetWindowingModel(HANDLE token, AppPolicyWindowingModel *po
     return ERROR_SUCCESS;
 }
 
+struct counterset_template
+{
+    PERF_COUNTERSET_INFO counterset;
+    PERF_COUNTER_INFO counter[1];
+};
+
 struct perf_provider
 {
     GUID guid;
     PERFLIBREQUEST callback;
+    struct counterset_template **countersets;
+    unsigned int counterset_count;
 };
 
 static struct perf_provider *perf_provider_from_handle(HANDLE prov)
@@ -187,10 +195,44 @@ ULONG WINAPI PerfDeleteInstance(HANDLE provider, PPERF_COUNTERSET_INSTANCE block
 /***********************************************************************
  *           PerfSetCounterSetInfo   (KERNELBASE.@)
  */
-ULONG WINAPI PerfSetCounterSetInfo(HANDLE handle, PPERF_COUNTERSET_INFO template, ULONG size)
+ULONG WINAPI PerfSetCounterSetInfo( HANDLE handle, PERF_COUNTERSET_INFO *template, ULONG size )
 {
-    FIXME("%p %p %u: stub\n", handle, template, size);
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    struct perf_provider *prov = perf_provider_from_handle( handle );
+    struct counterset_template **new_array;
+    struct counterset_template *new;
+    unsigned int i;
+
+    FIXME( "handle %p, template %p, size %u semi-stub.\n", handle, template, size );
+
+    if (!prov || !template) return ERROR_INVALID_PARAMETER;
+    if (!template->NumCounters) return ERROR_INVALID_PARAMETER;
+    if (size < sizeof(*template) || (size - (sizeof(*template))) / sizeof(PERF_COUNTER_INFO) < template->NumCounters)
+        return ERROR_INVALID_PARAMETER;
+
+    for (i = 0; i < prov->counterset_count; ++i)
+    {
+        if (IsEqualGUID( &template->CounterSetGuid, &prov->countersets[i]->counterset.CounterSetGuid ))
+            return ERROR_ALREADY_EXISTS;
+    }
+
+    size = offsetof( struct counterset_template, counter[template->NumCounters] );
+    if (!(new = heap_alloc( size ))) return ERROR_OUTOFMEMORY;
+
+    if (prov->counterset_count)
+        new_array = heap_realloc( prov->countersets, sizeof(*prov->countersets) * (prov->counterset_count + 1) );
+    else
+        new_array = heap_alloc( sizeof(*prov->countersets) );
+
+    if (!new_array)
+    {
+        heap_free( new );
+        return ERROR_OUTOFMEMORY;
+    }
+    memcpy( new, template, size );
+    new_array[prov->counterset_count++] = new;
+    prov->countersets = new_array;
+
+    return STATUS_SUCCESS;
 }
 
 /***********************************************************************
@@ -245,9 +287,13 @@ ULONG WINAPI PerfStartProviderEx( GUID *guid, PERF_PROVIDER_CONTEXT *context, HA
 ULONG WINAPI PerfStopProvider(HANDLE handle)
 {
     struct perf_provider *prov = perf_provider_from_handle( handle );
+    unsigned int i;
 
     TRACE( "handle %p.\n", handle );
 
+    for (i = 0; i < prov->counterset_count; ++i)
+        heap_free( prov->countersets[i] );
+    heap_free( prov->countersets );
     heap_free( prov );
     return STATUS_SUCCESS;
 }
diff --git a/include/perflib.h b/include/perflib.h
index 47bc0716541..5a2a1162ae7 100644
--- a/include/perflib.h
+++ b/include/perflib.h
@@ -34,6 +34,19 @@ typedef struct _PERF_COUNTERSET_INFO {
     ULONG InstanceType;
 } PERF_COUNTERSET_INFO, * PPERF_COUNTERSET_INFO;
 
+/* PERF_COUNTERSET_INFO InstanceType values. */
+#define PERF_COUNTERSET_FLAG_MULTIPLE  0x00000002
+#define PERF_COUNTERSET_FLAG_AGGREGATE 0x00000004
+#define PERF_COUNTERSET_FLAG_HISTORY   0x00000008
+#define PERF_COUNTERSET_FLAG_INSTANCE  0x00000010
+
+#define PERF_COUNTERSET_SINGLE_INSTANCE          0
+#define PERF_COUNTERSET_MULTI_INSTANCES          PERF_COUNTERSET_FLAG_MULTIPLE
+#define PERF_COUNTERSET_SINGLE_AGGREGATE         PERF_COUNTERSET_FLAG_AGGREGATE
+#define PERF_COUNTERSET_MULTI_AGGREGATE          (PERF_COUNTERSET_FLAG_AGGREGATE | PERF_COUNTERSET_FLAG_MULTIPLE)
+#define PERF_COUNTERSET_SINGLE_AGGREGATE_HISTORY (PERF_COUNTERSET_FLAG_HISTORY | PERF_COUNTERSET_SINGLE_AGGREGATE)
+#define PERF_COUNTERSET_INSTANCE_AGGREGATE       (PERF_COUNTERSET_MULTI_AGGREGATE | PERF_COUNTERSET_FLAG_INSTANCE)
+
 typedef struct _PERF_COUNTERSET_INSTANCE {
     GUID CounterSetGuid;
     ULONG dwSize;
@@ -42,6 +55,23 @@ typedef struct _PERF_COUNTERSET_INSTANCE {
     ULONG InstanceNameSize;
 } PERF_COUNTERSET_INSTANCE, * PPERF_COUNTERSET_INSTANCE;
 
+typedef struct _PERF_COUNTER_INFO {
+    ULONG CounterId;
+    ULONG Type;
+    ULONGLONG Attrib;
+    ULONG Size;
+    ULONG DetailLevel;
+    LONG Scale;
+    ULONG Offset;
+} PERF_COUNTER_INFO, *PPERF_COUNTER_INFO;
+
+/* PERF_COUNTER_INFO Attrib flags. */
+#define PERF_ATTRIB_BY_REFERENCE       0x00000001
+#define PERF_ATTRIB_NO_DISPLAYABLE     0x00000002
+#define PERF_ATTRIB_NO_GROUP_SEPARATOR 0x00000004
+#define PERF_ATTRIB_DISPLAY_AS_REAL    0x00000008
+#define PERF_ATTRIB_DISPLAY_AS_HEX     0x00000010
+
 typedef struct _PROVIDER_CONTEXT {
     DWORD ContextSize;
     DWORD Reserved;
@@ -51,6 +81,7 @@ typedef struct _PROVIDER_CONTEXT {
     LPVOID pMemContext;
 } PERF_PROVIDER_CONTEXT, * PPERF_PROVIDER_CONTEXT;
 
+ULONG WINAPI PerfSetCounterSetInfo(HANDLE, PERF_COUNTERSET_INFO *, ULONG);
 ULONG WINAPI PerfStartProvider(GUID *, PERFLIBREQUEST, HANDLE *);
 ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *);
 ULONG WINAPI PerfStopProvider(HANDLE);
diff --git a/include/winperf.h b/include/winperf.h
index 113bfbae40f..926da8f8c4a 100644
--- a/include/winperf.h
+++ b/include/winperf.h
@@ -161,6 +161,35 @@ typedef struct _PERF_COUNTER_BLOCK
     DWORD ByteLength;
 } PERF_COUNTER_BLOCK, *PPERF_COUNTER_BLOCK;
 
+#define PERF_COUNTER_VALUE     0x00000000
+#define PERF_COUNTER_RATE      0x00010000
+#define PERF_COUNTER_FRACTION  0x00020000
+#define PERF_COUNTER_BASE      0x00030000
+#define PERF_COUNTER_ELAPSED   0x00040000
+#define PERF_COUNTER_QUEUELEN  0x00050000
+#define PERF_COUNTER_HISTOGRAM 0x00060000
+#define PERF_COUNTER_PRECISION 0x00070000
+
+#define PERF_TEXT_UNICODE 0x00000000
+#define PERF_TEXT_ASCII   0x00010000
+
+#define PERF_TIMER_TICK   0x00000000
+#define PERF_TIMER_100NS  0x00100000
+#define PERF_OBJECT_TIMER 0x00200000
+
+#define PERF_DELTA_COUNTER   0x00400000
+#define PERF_DELTA_BASE      0x00800000
+#define PERF_INVERSE_COUNTER 0x01000000
+#define PERF_MULTI_COUNTER   0x02000000
+
+#define PERF_DISPLAY_NO_SUFFIX 0x00000000
+#define PERF_DISPLAY_PER_SEC   0x10000000
+#define PERF_DISPLAY_PERCENT   0x20000000
+#define PERF_DISPLAY_SECONDS   0x30000000
+#define PERF_DISPLAY_NOSHOW    0x40000000
+
+#define PERF_COUNTER_COUNTER (PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | \
+                              PERF_TIMER_TICK | PERF_DELTA_COUNTER | PERF_DISPLAY_PER_SEC)
 
 #include <poppack.h>
 




More information about the wine-cvs mailing list