These functions are used by Visual Studio 2019, when opening or converting some projects.
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it
-- v17: kernelbase: Check for PERF_SIZE_LARGE in PerfSetULongLongCounterValue and PerfSetULongCounterValue kernelbase : Check for PERF_ATTRIB_BY_REFERENCE attribute in PerfSetCounterRefValue advapi/test: Add Test For PerfSetULongLongCounterValue advapi32/tests: Create Tests for PerfSetULongCounterValue advapi32: Forward PerfSetULongCounterValue and PerfSetULongLongCounterValue to kernelbase kernelbase: Add implementation for PerfSetULongLongCounterValue kernelbase: Add implementation of PerfSetULongCounterValue
From: Lorenzo Ferrillo lorenzofersteam@live.it
This function is used by Visual Studio 2019, when opening or converting some projects
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it --- dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/main.c | 30 ++++++++++++++++++++++++++++++ include/perflib.h | 1 + 3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 8e3d269ca47..c6d7c301f90 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1195,7 +1195,7 @@ # @ stub PerfQueryInstance @ stdcall PerfSetCounterRefValue(long ptr long ptr) @ stdcall PerfSetCounterSetInfo(long ptr long) -# @ stub PerfSetULongCounterValue +@ stdcall PerfSetULongCounterValue(long ptr long long) # @ stub PerfSetULongLongCounterValue @ stdcall PerfStartProvider(ptr ptr ptr) @ stdcall PerfStartProviderEx(ptr ptr ptr) diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c index 60173ba6513..1f08e6edf9d 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -329,6 +329,36 @@ ULONG WINAPI PerfSetCounterRefValue(HANDLE provider, PERF_COUNTERSET_INSTANCE *i return STATUS_SUCCESS; }
+/*********************************************************************** + * PerfSetULongCounterValue (KERNELBASE.@) + */ +ULONG WINAPI PerfSetULongCounterValue(HANDLE provider, PERF_COUNTERSET_INSTANCE *instance, + ULONG counterid, ULONG value) +{ + struct perf_provider *prov = perf_provider_from_handle( provider ); + struct counterset_template *template; + struct counterset_instance *inst; + unsigned int i; + + TRACE( "provider %p, instance %p, counterid %lu, address %lu semi-stub.\n", + provider, instance, counterid, value ); + + if (!prov || !instance) return ERROR_INVALID_PARAMETER; + + inst = CONTAINING_RECORD(instance, struct counterset_instance, instance); + template = inst->template; + + for (i = 0; i < template->counterset.NumCounters; ++i) + if (template->counter[i].CounterId == counterid) break; + + if (i == template->counterset.NumCounters) return ERROR_NOT_FOUND; + if (template->counter[i].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + + *(ULONG*)((BYTE *)&inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[i].Offset) = value; + + return STATUS_SUCCESS; +} + /*********************************************************************** * PerfStartProvider (KERNELBASE.@) */ diff --git a/include/perflib.h b/include/perflib.h index 188f26e3e74..53c17f9efe8 100644 --- a/include/perflib.h +++ b/include/perflib.h @@ -106,6 +106,7 @@ typedef struct _PERF_DATA_HEADER { PERF_COUNTERSET_INSTANCE WINAPI *PerfCreateInstance(HANDLE, const GUID *, const WCHAR *, ULONG); ULONG WINAPI PerfDeleteInstance(HANDLE, PERF_COUNTERSET_INSTANCE *); ULONG WINAPI PerfSetCounterRefValue(HANDLE, PERF_COUNTERSET_INSTANCE *, ULONG, void *); +ULONG WINAPI PerfSetULongCounterValue(HANDLE, PERF_COUNTERSET_INSTANCE *, ULONG, ULONG); ULONG WINAPI PerfSetCounterSetInfo(HANDLE, PERF_COUNTERSET_INFO *, ULONG); ULONG WINAPI PerfStartProvider(GUID *, PERFLIBREQUEST, HANDLE *); ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *);
From: Lorenzo Ferrillo lorenzofersteam@live.it
This function is used by Visual Studio 2019, when opening or converting some projects
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it --- dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/main.c | 29 +++++++++++++++++++++++++++++ include/perflib.h | 1 + 3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index c6d7c301f90..0655c40c243 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1196,7 +1196,7 @@ @ stdcall PerfSetCounterRefValue(long ptr long ptr) @ stdcall PerfSetCounterSetInfo(long ptr long) @ stdcall PerfSetULongCounterValue(long ptr long long) -# @ stub PerfSetULongLongCounterValue +@ stdcall PerfSetULongLongCounterValue(long ptr long int64) @ stdcall PerfStartProvider(ptr ptr ptr) @ stdcall PerfStartProviderEx(ptr ptr ptr) @ stdcall PerfStopProvider(long) diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c index 1f08e6edf9d..89fc2008e38 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -359,6 +359,35 @@ ULONG WINAPI PerfSetULongCounterValue(HANDLE provider, PERF_COUNTERSET_INSTANCE return STATUS_SUCCESS; }
+/*********************************************************************** + * PerfSetULongLongCounterValue (KERNELBASE.@) + */ +ULONG WINAPI PerfSetULongLongCounterValue(HANDLE provider, PERF_COUNTERSET_INSTANCE *instance, + ULONG counterid, ULONGLONG value) +{ + struct perf_provider *prov = perf_provider_from_handle( provider ); + struct counterset_template *template; + struct counterset_instance *inst; + unsigned int i; + + TRACE( "provider %p, instance %p, counterid %lu, address %I64u semi-stub.\n", + provider, instance, counterid, value ); + + if (!prov || !instance) return ERROR_INVALID_PARAMETER; + + inst = CONTAINING_RECORD(instance, struct counterset_instance, instance); + template = inst->template; + + for (i = 0; i < template->counterset.NumCounters; ++i) + if (template->counter[i].CounterId == counterid) break; + if (i == template->counterset.NumCounters) return ERROR_NOT_FOUND; + if (template->counter[i].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + + *(ULONGLONG*)((BYTE *)&inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[i].Offset) = value; + + return STATUS_SUCCESS; +} + /*********************************************************************** * PerfStartProvider (KERNELBASE.@) */ diff --git a/include/perflib.h b/include/perflib.h index 53c17f9efe8..6d14daffc4d 100644 --- a/include/perflib.h +++ b/include/perflib.h @@ -107,6 +107,7 @@ PERF_COUNTERSET_INSTANCE WINAPI *PerfCreateInstance(HANDLE, const GUID *, const ULONG WINAPI PerfDeleteInstance(HANDLE, PERF_COUNTERSET_INSTANCE *); ULONG WINAPI PerfSetCounterRefValue(HANDLE, PERF_COUNTERSET_INSTANCE *, ULONG, void *); ULONG WINAPI PerfSetULongCounterValue(HANDLE, PERF_COUNTERSET_INSTANCE *, ULONG, ULONG); +ULONG WINAPI PerfSetULongLongCounterValue(HANDLE, PERF_COUNTERSET_INSTANCE *, ULONG, ULONGLONG); ULONG WINAPI PerfSetCounterSetInfo(HANDLE, PERF_COUNTERSET_INFO *, ULONG); ULONG WINAPI PerfStartProvider(GUID *, PERFLIBREQUEST, HANDLE *); ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *);
From: Lorenzo Ferrillo lorenzofersteam@live.it
VS2019 call these functions from advapi32
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it --- dlls/advapi32/advapi32.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index dde83cc7045..dcea5ea46ef 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -577,8 +577,8 @@ # @ stub PerfRegSetValue @ stdcall -import PerfSetCounterRefValue(long ptr long ptr) @ stdcall -import PerfSetCounterSetInfo(long ptr long) -# @ stub PerfSetULongCounterValue -# @ stub PerfSetULongLongCounterValue +@ stdcall -import PerfSetULongCounterValue(long ptr long long) +@ stdcall -import PerfSetULongLongCounterValue(long ptr long int64) @ stdcall -import PerfStartProvider(ptr ptr ptr) @ stdcall -import PerfStartProviderEx(ptr ptr ptr) @ stdcall -import PerfStopProvider(long)
From: Lorenzo Ferrillo lorenzofersteam@live.it
Also add test showing that PerfSetCounterRefValue cannot be used without BYREF counters
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it --- dlls/advapi32/tests/perf.c | 80 ++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 7 deletions(-)
diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c index 7481020dd4e..826b670986d 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -45,6 +45,7 @@ static void init_functions(void) GET_FUNCTION(PerfOpenQueryHandle); GET_FUNCTION(PerfAddCounters); GET_FUNCTION(PerfQueryCounterData); + #undef GET_FUNCTION }
@@ -54,17 +55,19 @@ static ULONG WINAPI test_provider_callback(ULONG code, void *buffer, ULONG size) return ERROR_SUCCESS; }
+struct template +{ + PERF_COUNTERSET_INFO counterset; + PERF_COUNTER_INFO counter[2]; +}; + 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[2]; - } - pc_template = + + struct template pc_template = { {{0}}, { @@ -74,7 +77,16 @@ void test_provider_init(void) PERF_DETAIL_NOVICE, 0, 0xdeadbeef}, }, }; - + struct template pc_template_val = + { + {{0}}, + { + {1, PERF_COUNTER_COUNTER, 0, sizeof(PERF_COUNTER_INFO), + PERF_DETAIL_NOVICE, 0, 0xdeadbeef}, + {2, PERF_COUNTER_COUNTER, 0, sizeof(PERF_COUNTER_INFO), + PERF_DETAIL_NOVICE, 0, 0xdeadbeef}, + }, + }; PERF_COUNTERSET_INSTANCE *instance; PERF_PROVIDER_CONTEXT prov_context; UINT64 counter1, counter2; @@ -187,6 +199,60 @@ void test_provider_init(void) ok(*(void **)((BYTE *)instance + sizeof(*instance) + sizeof(UINT64)) == &counter2, "Got unexpected counter value %p.\n", *(void **)(instance + 1));
+ /*Counter defined as BYREF error if modified with SetValue functions*/ + ret = PerfSetULongCounterValue(prov, instance, 1, 666L); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ret = PerfSetULongCounterValue(prov, instance, 2, 900000L); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + + ret = PerfSetULongCounterValue(prov, instance, 0, 42L); + ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %lu.\n", ret); + + ret = PerfDeleteInstance(prov, instance); + ok(!ret, "Got unexpected ret %lu.\n", ret); + ret = PerfStopProvider(prov); + ok(!ret, "Got unexpected ret %lu.\n", ret); + + ret = PerfStartProvider(&test_guid, test_provider_callback, &prov); + ok(!ret, "Got unexpected ret %lu.\n", ret); + + pc_template_val.counterset.CounterSetGuid = test_set_guid; + pc_template_val.counterset.ProviderGuid = test_guid; + pc_template_val.counterset.NumCounters = 2; + pc_template_val.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE; + ret = PerfSetCounterSetInfo(prov, &pc_template_val.counterset, sizeof(pc_template_val)); + ok(!ret, "Got unexpected ret %lu.\n", ret); + + instance = PerfCreateInstance(prov, &test_set_guid, L"11", 1); + ok(!!instance, "Got NULL instance.\n"); + ok(instance->InstanceId == 1, "Got unexpected InstanceId %lu.\n", instance->InstanceId); + ok(instance->InstanceNameSize == 6, "Got unexpected InstanceNameSize %lu.\n", instance->InstanceNameSize); + ok(IsEqualGUID(&instance->CounterSetGuid, &test_set_guid), "Got unexpected guid %s.\n", + debugstr_guid(&instance->CounterSetGuid)); + + ret = PerfSetULongCounterValue(prov, instance, 1, 666L); + ok(!ret, "Got unexpected ret %lu.\n", ret); + ret = PerfSetULongCounterValue(prov, instance, 2, 900000L); + ok(!ret, "Got unexpected ret %lu.\n", ret); + + ret = PerfSetULongCounterValue(prov, instance, 0, 42); + ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %lu.\n", ret); + + ok(*(ULONG *)(instance + 1) == 666L, "Got unexpected counter value %lu.\n", + *(ULONG *)(instance + 1)); + ok(*(ULONG *)((BYTE *)instance + sizeof(*instance) + sizeof(UINT64)) == 900000L, + "Got unexpected counter value %lu.\n", *(ULONG *)(instance + 1)); + + ret = PerfSetULongCounterValue(prov, instance, 1, 55L); + ok(!ret, "Got unexpected ret %lu.\n", ret); + ret = PerfSetULongCounterValue(prov, instance, 2, 9000L); + ok(!ret, "Got unexpected ret %lu.\n", ret); + + ret = PerfSetCounterRefValue(prov, instance, 1, &counter1); + todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ret = PerfSetCounterRefValue(prov, instance, 2, &counter2); + todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ret = PerfDeleteInstance(prov, instance); ok(!ret, "Got unexpected ret %lu.\n", ret);
From: Lorenzo Ferrillo lorenzofersteam@live.it
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it --- dlls/advapi32/tests/perf.c | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+)
diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c index 826b670986d..f6252ac9b92 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -87,6 +87,16 @@ void test_provider_init(void) PERF_DETAIL_NOVICE, 0, 0xdeadbeef}, }, }; + struct template pc_template_val_long = + { + {{0}}, + { + {1, (PERF_COUNTER_COUNTER & ~PERF_SIZE_DWORD) | PERF_SIZE_LARGE, 0, sizeof(PERF_COUNTER_INFO), + PERF_DETAIL_NOVICE, 0, 0xdeadbeef}, + {2, (PERF_COUNTER_COUNTER & ~PERF_SIZE_DWORD) | PERF_SIZE_LARGE, 0, sizeof(PERF_COUNTER_INFO), + PERF_DETAIL_NOVICE, 0, 0xdeadbeef}, + }, + }; PERF_COUNTERSET_INSTANCE *instance; PERF_PROVIDER_CONTEXT prov_context; UINT64 counter1, counter2; @@ -204,9 +214,15 @@ void test_provider_init(void) ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); ret = PerfSetULongCounterValue(prov, instance, 2, 900000L); ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ret = PerfSetULongLongCounterValue(prov, instance, 1, 666L); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ret = PerfSetULongLongCounterValue(prov, instance, 2, 900000L); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
ret = PerfSetULongCounterValue(prov, instance, 0, 42L); ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %lu.\n", ret); + ret = PerfSetULongLongCounterValue(prov, instance, 0, 42L); + ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %lu.\n", ret);
ret = PerfDeleteInstance(prov, instance); ok(!ret, "Got unexpected ret %lu.\n", ret); @@ -248,6 +264,15 @@ void test_provider_init(void) ret = PerfSetULongCounterValue(prov, instance, 2, 9000L); ok(!ret, "Got unexpected ret %lu.\n", ret);
+ /*Cannot be used with PERF_SIZE_DWORD*/ + ret = PerfSetULongLongCounterValue(prov, instance, 1, 900000L); + todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ret = PerfSetULongLongCounterValue(prov, instance, 2, 666L); + todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + + ret = PerfSetULongLongCounterValue(prov, instance, 0, 42); + ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %lu.\n", ret); + ret = PerfSetCounterRefValue(prov, instance, 1, &counter1); todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); ret = PerfSetCounterRefValue(prov, instance, 2, &counter2); @@ -259,6 +284,48 @@ void test_provider_init(void) ret = PerfStopProvider(prov); ok(!ret, "Got unexpected ret %lu.\n", ret);
+ ret = PerfStartProvider(&test_guid, test_provider_callback, &prov); + ok(!ret, "Got unexpected ret %lu.\n", ret); + + pc_template_val_long.counterset.CounterSetGuid = test_set_guid; + pc_template_val_long.counterset.ProviderGuid = test_guid; + pc_template_val_long.counterset.NumCounters = 2; + pc_template_val_long.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE; + ret = PerfSetCounterSetInfo(prov, &pc_template_val_long.counterset, sizeof(pc_template_val_long)); + ok(!ret, "Got unexpected ret %lu.\n", ret); + + instance = PerfCreateInstance(prov, &test_set_guid, L"11", 1); + ok(!!instance, "Got NULL instance.\n"); + ok(instance->InstanceId == 1, "Got unexpected InstanceId %lu.\n", instance->InstanceId); + ok(instance->InstanceNameSize == 6, "Got unexpected InstanceNameSize %lu.\n", instance->InstanceNameSize); + ok(IsEqualGUID(&instance->CounterSetGuid, &test_set_guid), "Got unexpected guid %s.\n", + debugstr_guid(&instance->CounterSetGuid)); + + ret = PerfSetULongLongCounterValue(prov, instance, 1, 900000L); + ok(!ret, "Got unexpected ret %lu.\n", ret); + ret = PerfSetULongLongCounterValue(prov, instance, 2, 666L); + ok(!ret, "Got unexpected ret %lu.\n", ret); + + ret = PerfSetULongLongCounterValue(prov, instance, 0, 42); + ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %lu.\n", ret); + + ok(*(ULONGLONG *)(instance + 1) == 900000L, "Got unexpected counter value %I64u.\n", + *(ULONGLONG *)(instance + 1)); + ok(*(ULONGLONG *)((BYTE *)instance + sizeof(*instance) + sizeof(UINT64)) == 666L, + "Got unexpected counter value %I64u.\n", *(ULONGLONG *)(instance + 1)); + + /* Don't work on PERF_SIZE_LARGE */ + ret = PerfSetULongCounterValue(prov, instance, 1, 666L); + todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ret = PerfSetULongCounterValue(prov, instance, 2, 900000L); + todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + + ret = PerfDeleteInstance(prov, instance); + ok(!ret, "Got unexpected ret %lu.\n", ret); + + ret = PerfStopProvider(prov); + ok(!ret, "Got unexpected ret %lu.\n", ret); + memset( &prov_context, 0, sizeof(prov_context) ); prov = (HANDLE)0xdeadbeef; ret = PerfStartProviderEx( &test_guid, &prov_context, &prov );
From: Lorenzo Ferrillo lorenzofersteam@live.it
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it --- dlls/advapi32/tests/perf.c | 4 ++-- dlls/kernelbase/main.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c index f6252ac9b92..b237b15bc84 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -274,9 +274,9 @@ void test_provider_init(void) ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %lu.\n", ret);
ret = PerfSetCounterRefValue(prov, instance, 1, &counter1); - todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); ret = PerfSetCounterRefValue(prov, instance, 2, &counter2); - todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
ret = PerfDeleteInstance(prov, instance); ok(!ret, "Got unexpected ret %lu.\n", ret); diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c index 89fc2008e38..036d14bc5dc 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -324,6 +324,8 @@ ULONG WINAPI PerfSetCounterRefValue(HANDLE provider, PERF_COUNTERSET_INSTANCE *i if (template->counter[i].CounterId == counterid) break;
if (i == template->counterset.NumCounters) return ERROR_NOT_FOUND; + if (!(template->counter[i].Attrib & PERF_ATTRIB_BY_REFERENCE)) return ERROR_INVALID_PARAMETER; + *(void **)((BYTE *)&inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[i].Offset) = address;
return STATUS_SUCCESS;
From: Lorenzo Ferrillo lorenzofersteam@live.it
Cannot check for PERF_SIZE_DWORD as it have a value of 0x0
v2: Fix test failure Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it --- dlls/advapi32/tests/perf.c | 8 ++++---- dlls/kernelbase/main.c | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c index b237b15bc84..b2727d2ea4e 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -266,9 +266,9 @@ void test_provider_init(void)
/*Cannot be used with PERF_SIZE_DWORD*/ ret = PerfSetULongLongCounterValue(prov, instance, 1, 900000L); - todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); ret = PerfSetULongLongCounterValue(prov, instance, 2, 666L); - todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
ret = PerfSetULongLongCounterValue(prov, instance, 0, 42); ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %lu.\n", ret); @@ -316,9 +316,9 @@ void test_provider_init(void)
/* Don't work on PERF_SIZE_LARGE */ ret = PerfSetULongCounterValue(prov, instance, 1, 666L); - todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); ret = PerfSetULongCounterValue(prov, instance, 2, 900000L); - todo_wine ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
ret = PerfDeleteInstance(prov, instance); ok(!ret, "Got unexpected ret %lu.\n", ret); diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c index 036d14bc5dc..ad54f55d09f 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -26,6 +26,7 @@ #include "shlwapi.h" #include "perflib.h" #include "winternl.h" +#include "winperf.h"
#include "wine/debug.h" #include "kernelbase.h" @@ -355,6 +356,7 @@ ULONG WINAPI PerfSetULongCounterValue(HANDLE provider, PERF_COUNTERSET_INSTANCE
if (i == template->counterset.NumCounters) return ERROR_NOT_FOUND; if (template->counter[i].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + if (template->counter[i].Type & PERF_SIZE_LARGE) return ERROR_INVALID_PARAMETER;
*(ULONG*)((BYTE *)&inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[i].Offset) = value;
@@ -384,6 +386,7 @@ ULONG WINAPI PerfSetULongLongCounterValue(HANDLE provider, PERF_COUNTERSET_INSTA if (template->counter[i].CounterId == counterid) break; if (i == template->counterset.NumCounters) return ERROR_NOT_FOUND; if (template->counter[i].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + if (!(template->counter[i].Type & PERF_SIZE_LARGE)) return ERROR_INVALID_PARAMETER;
*(ULONGLONG*)((BYTE *)&inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[i].Offset) = value;
Alexandre Julliard (@julliard) commented about dlls/kernelbase/main.c:
- if (!prov || !instance) return ERROR_INVALID_PARAMETER;
- inst = CONTAINING_RECORD(instance, struct counterset_instance, instance);
- template = inst->template;
- for (i = 0; i < template->counterset.NumCounters; ++i)
if (template->counter[i].CounterId == counterid) break;
- if (i == template->counterset.NumCounters) return ERROR_NOT_FOUND;
- if (template->counter[i].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER;
- if (template->counter[i].Type & PERF_SIZE_LARGE) return ERROR_INVALID_PARAMETER;
- *(ULONG*)((BYTE *)&inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[i].Offset) = value;
- return STATUS_SUCCESS;
+}
This could use some kind of helper function.
On Mon Mar 31 18:41:41 2025 +0000, Alexandre Julliard wrote:
This could use some kind of helper function.
Hi @julliard The checks are different for the various functions, so the actually shared parts are the for loop to extract the index and actually set the value. Maybe the
` for (i = 0; i < template->counterset.NumCounters; ++i) if (template->counter[i].CounterId == counterid) break; `
loop could be replaced with a get_performance_counter_index function and the line to set the value with a set_perfromance_counter_value function. Or did you mean to have a global helper called by any of these functions? Maybe passing an enum as arguments to select from what function that was called, to properly address the different checks?
The checks are different for the various functions, so the actually shared parts are the for loop to extract the index and actually set the value. Maybe the
` for (i = 0; i < template->counterset.NumCounters; ++i) if (template->counter[i].CounterId == counterid) break;`
loop could be replaced with a get_performance_counter_index function and the line to set the value with a set_perfromance_counter_value function.
Yes, something like that, though you should be able to abstract pretty much everything except the checks.