These functions are used by Visual Studio 2019, when opening or converting some projects.
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it
-- v20: kernelbase:return pointer for counter instead of index. remove auxilliary function to set the value
From: Lorenzo Ferrillo lorenzofersteam@live.it
--- dlls/kernelbase/main.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c index 60173ba6513..4c373f06e57 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -301,6 +301,29 @@ ULONG WINAPI PerfSetCounterSetInfo( HANDLE handle, PERF_COUNTERSET_INFO *templat return STATUS_SUCCESS; }
+ +static unsigned int get_performance_counter_index(PERF_COUNTERSET_INSTANCE *instance, ULONG counter_id, struct counterset_template ** out_template,struct counterset_instance ** out_instance) +{ + unsigned int i; + struct counterset_template *template; + struct counterset_instance *inst; + + inst = CONTAINING_RECORD(instance, struct counterset_instance, instance); + template = inst->template; + + *out_instance = inst; + *out_template = template; + + for (i = 0; i < template->counterset.NumCounters; ++i) + if (template->counter[i].CounterId == counter_id) return i; + return template->counterset.NumCounters; +} + +static BYTE* get_performance_counter_address(struct counterset_template* template, struct counterset_instance* instance, unsigned int counter_index) +{ + return (BYTE*) &instance->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[counter_index].Offset; +} + /*********************************************************************** * PerfSetCounterRefValue (KERNELBASE.@) */ @@ -310,21 +333,17 @@ ULONG WINAPI PerfSetCounterRefValue(HANDLE provider, PERF_COUNTERSET_INSTANCE *i struct perf_provider *prov = perf_provider_from_handle( provider ); struct counterset_template *template; struct counterset_instance *inst; - unsigned int i; + unsigned int counter_index;;
FIXME( "provider %p, instance %p, counterid %lu, address %p semi-stub.\n", provider, instance, counterid, address );
if (!prov || !instance || !address) 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; + counter_index = get_performance_counter_index(instance, counterid, &template, &inst);
- if (i == template->counterset.NumCounters) return ERROR_NOT_FOUND; - *(void **)((BYTE *)&inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[i].Offset) = address; + if (counter_index== template->counterset.NumCounters) return ERROR_NOT_FOUND; + *(void **)(get_performance_counter_address(template,inst, counter_index)) = address;
return STATUS_SUCCESS; }
From: Lorenzo Ferrillo lorenzofersteam@live.it
--- dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/main.c | 26 ++++++++++++++++++++++++++ include/perflib.h | 1 + 3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index d11a4417d48..fa6858a893a 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 4c373f06e57..c50fb193178 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -348,6 +348,32 @@ 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 counter_index; + + TRACE( "provider %p, instance %p, counterid %lu, address %lu semi-stub.\n", + provider, instance, counterid, value ); + + if (!prov || !instance) return ERROR_INVALID_PARAMETER; + + counter_index = get_performance_counter_index(instance, counterid, &template, &inst); + + if (counter_index == template->counterset.NumCounters) return ERROR_NOT_FOUND; + if (template->counter[counter_index].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + + *(ULONG*)(get_performance_counter_address(template,inst, counter_index)) = 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
--- dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/main.c | 26 ++++++++++++++++++++++++++ include/perflib.h | 1 + 3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index fa6858a893a..daab63e85e2 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 c50fb193178..1b3b450cfff 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -374,6 +374,32 @@ 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 counter_index; + + TRACE( "provider %p, instance %p, counterid %lu, address %I64u semi-stub.\n", + provider, instance, counterid, value ); + + if (!prov || !instance) return ERROR_INVALID_PARAMETER; + + counter_index = get_performance_counter_index(instance, counterid, &template, &inst); + + if (counter_index == template->counterset.NumCounters) return ERROR_NOT_FOUND; + if (template->counter[counter_index].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + + *(ULONGLONG*)(get_performance_counter_address(template,inst, counter_index)) = 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 kernelbase --- 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 79b64df8abb..e4b6c5a981a 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 tests showing that PerfSetCounterRefValue cannot be used without BYREF counters --- dlls/advapi32/tests/perf.c | 77 +++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 6 deletions(-)
diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c index 7481020dd4e..f8b29662d7c 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -54,17 +54,18 @@ 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,6 +75,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; @@ -187,6 +198,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
--- 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 f8b29662d7c..82114449c66 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -85,6 +85,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; @@ -203,9 +213,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); @@ -247,6 +263,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); @@ -258,6 +283,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
Tests shown that counters that have this attribute not set should be rejected in the SetCounterRefValue function --- 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 82114449c66..409ebff95d5 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -273,9 +273,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 1b3b450cfff..e478e2ab919 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -343,6 +343,8 @@ ULONG WINAPI PerfSetCounterRefValue(HANDLE provider, PERF_COUNTERSET_INSTANCE *i counter_index = get_performance_counter_index(instance, counterid, &template, &inst);
if (counter_index== template->counterset.NumCounters) return ERROR_NOT_FOUND; + if (!(template->counter[counter_index].Attrib & PERF_ATTRIB_BY_REFERENCE)) return ERROR_INVALID_PARAMETER; + *(void **)(get_performance_counter_address(template,inst, counter_index)) = address;
return STATUS_SUCCESS;
From: Lorenzo Ferrillo lorenzofersteam@live.it
Should be setted for SetULongULong function and unsetted fo SetULong one, as test shown. --- 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 409ebff95d5..f46eca1397a 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -265,9 +265,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); @@ -315,9 +315,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 e478e2ab919..c000413e900 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" @@ -370,6 +371,7 @@ ULONG WINAPI PerfSetULongCounterValue(HANDLE provider, PERF_COUNTERSET_INSTANCE
if (counter_index == template->counterset.NumCounters) return ERROR_NOT_FOUND; if (template->counter[counter_index].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + if (template->counter[counter_index].Type & PERF_SIZE_LARGE) return ERROR_INVALID_PARAMETER;
*(ULONG*)(get_performance_counter_address(template,inst, counter_index)) = value;
@@ -396,6 +398,7 @@ ULONG WINAPI PerfSetULongLongCounterValue(HANDLE provider, PERF_COUNTERSET_INSTA
if (counter_index == template->counterset.NumCounters) return ERROR_NOT_FOUND; if (template->counter[counter_index].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + if (!(template->counter[counter_index].Type & PERF_SIZE_LARGE)) return ERROR_INVALID_PARAMETER;
*(ULONGLONG*)(get_performance_counter_address(template,inst, counter_index)) = value;
From: Lorenzo Ferrillo lorenzofersteam@live.it
--- dlls/kernelbase/main.c | 50 +++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 30 deletions(-)
diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c index c000413e900..dd7c7951b45 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -303,7 +303,7 @@ ULONG WINAPI PerfSetCounterSetInfo( HANDLE handle, PERF_COUNTERSET_INFO *templat }
-static unsigned int get_performance_counter_index(PERF_COUNTERSET_INSTANCE *instance, ULONG counter_id, struct counterset_template ** out_template,struct counterset_instance ** out_instance) +static PERF_COUNTER_INFO* get_performance_counter_info(PERF_COUNTERSET_INSTANCE *instance, ULONG counter_id ,struct counterset_instance ** out_instance) { unsigned int i; struct counterset_template *template; @@ -313,16 +313,10 @@ static unsigned int get_performance_counter_index(PERF_COUNTERSET_INSTANCE *inst template = inst->template;
*out_instance = inst; - *out_template = template;
for (i = 0; i < template->counterset.NumCounters; ++i) - if (template->counter[i].CounterId == counter_id) return i; - return template->counterset.NumCounters; -} - -static BYTE* get_performance_counter_address(struct counterset_template* template, struct counterset_instance* instance, unsigned int counter_index) -{ - return (BYTE*) &instance->instance + sizeof(PERF_COUNTERSET_INSTANCE) + template->counter[counter_index].Offset; + if (template->counter[i].CounterId == counter_id) return &template->counter[i]; + return NULL; }
/*********************************************************************** @@ -332,22 +326,20 @@ ULONG WINAPI PerfSetCounterRefValue(HANDLE provider, PERF_COUNTERSET_INSTANCE *i ULONG counterid, void *address) { struct perf_provider *prov = perf_provider_from_handle( provider ); - struct counterset_template *template; struct counterset_instance *inst; - unsigned int counter_index;; + PERF_COUNTER_INFO* counter;;
FIXME( "provider %p, instance %p, counterid %lu, address %p semi-stub.\n", provider, instance, counterid, address );
if (!prov || !instance || !address) return ERROR_INVALID_PARAMETER;
- counter_index = get_performance_counter_index(instance, counterid, &template, &inst); + counter = get_performance_counter_info(instance, counterid, &inst);
- if (counter_index== template->counterset.NumCounters) return ERROR_NOT_FOUND; - if (!(template->counter[counter_index].Attrib & PERF_ATTRIB_BY_REFERENCE)) return ERROR_INVALID_PARAMETER; - - *(void **)(get_performance_counter_address(template,inst, counter_index)) = address; + if (counter == NULL) return ERROR_NOT_FOUND; + if (!(counter->Attrib & PERF_ATTRIB_BY_REFERENCE)) return ERROR_INVALID_PARAMETER;
+ *(void**)((BYTE*) &inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + counter->Offset) = address; return STATUS_SUCCESS; }
@@ -358,22 +350,21 @@ ULONG WINAPI PerfSetULongCounterValue(HANDLE provider, PERF_COUNTERSET_INSTANCE ULONG counterid, ULONG value) { struct perf_provider *prov = perf_provider_from_handle( provider ); - struct counterset_template *template; struct counterset_instance *inst; - unsigned int counter_index; + PERF_COUNTER_INFO* counter;
TRACE( "provider %p, instance %p, counterid %lu, address %lu semi-stub.\n", provider, instance, counterid, value );
if (!prov || !instance) return ERROR_INVALID_PARAMETER;
- counter_index = get_performance_counter_index(instance, counterid, &template, &inst); + counter = get_performance_counter_info(instance, counterid, &inst);
- if (counter_index == template->counterset.NumCounters) return ERROR_NOT_FOUND; - if (template->counter[counter_index].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; - if (template->counter[counter_index].Type & PERF_SIZE_LARGE) return ERROR_INVALID_PARAMETER; + if (counter == NULL) return ERROR_NOT_FOUND; + if (counter->Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + if (counter->Type & PERF_SIZE_LARGE) return ERROR_INVALID_PARAMETER;
- *(ULONG*)(get_performance_counter_address(template,inst, counter_index)) = value; + *(ULONG*)((BYTE*) &inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + counter->Offset) = value;
return STATUS_SUCCESS; } @@ -385,22 +376,21 @@ ULONG WINAPI PerfSetULongLongCounterValue(HANDLE provider, PERF_COUNTERSET_INSTA ULONG counterid, ULONGLONG value) { struct perf_provider *prov = perf_provider_from_handle( provider ); - struct counterset_template *template; struct counterset_instance *inst; - unsigned int counter_index; + PERF_COUNTER_INFO* counter;
TRACE( "provider %p, instance %p, counterid %lu, address %I64u semi-stub.\n", provider, instance, counterid, value );
if (!prov || !instance) return ERROR_INVALID_PARAMETER;
- counter_index = get_performance_counter_index(instance, counterid, &template, &inst); + counter = get_performance_counter_info(instance, counterid, &inst);
- if (counter_index == template->counterset.NumCounters) return ERROR_NOT_FOUND; - if (template->counter[counter_index].Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; - if (!(template->counter[counter_index].Type & PERF_SIZE_LARGE)) return ERROR_INVALID_PARAMETER; + if (counter == NULL) return ERROR_NOT_FOUND; + if (counter->Attrib & PERF_ATTRIB_BY_REFERENCE) return ERROR_INVALID_PARAMETER; + if (!(counter->Type & PERF_SIZE_LARGE)) return ERROR_INVALID_PARAMETER;
- *(ULONGLONG*)(get_performance_counter_address(template,inst, counter_index)) = value; + *(ULONGLONG*)((BYTE*) &inst->instance + sizeof(PERF_COUNTERSET_INSTANCE) + counter->Offset) = value;
return STATUS_SUCCESS; }
On Mon Apr 7 08:50:18 2025 +0000, Lorenzo Ferrillo wrote:
Hi, I did try your suggestions, and I like returning the pointer directly more. However It seems I'm not able to make the setter works: I did try this:
static void set_performance_counter_value(PERF_COUNTER_INFO* counter, struct counterset_instance* instance, void* new_value, size_t size) { void* address = ((BYTE*) &instance->instance + sizeof(PERF_COUNTERSET_INSTANCE) + counter->Offset); memcpy(address, new_value, size); }
However compilation is still failing with ../wine/dlls/kernelbase/main.c:325:5: error: writing 8 bytes into a region of size 0 [-Werror=stringop-overflow=] 325 | memcpy(address, new_value, size); Using memcpy, this error happens in all cases, while using the direct assignment with casting, it seems to happen only when the byte pointer is calculated inside an inner function (if I put pointer calculation and assignment inside the top function works) Do you have any idea? @julliard
I uploaded the last version, with however the set part removed and reinserted into the main function. It's the only way I can pass a -Werror compilation. (using memcpy give the same stringop-overflow warning ) The fact it works on top level but not inside a function make it seems to me like a compiler (maybe the static analyzer part) bug.
p.s for simplicity I added a new commit to show modification. If you prefers, once the code is ok, I can rework the commit history.