These functions are used by Visual Studio 2019, when opening or converting some projects.
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it
-- v9: kernelbase: Check for PERF_SIZE_LARGE in PerfSetULongLongCounterValue and PerfSetULongCounterValue
From: Lorenzo Ferrillo lorenzofersteam@live.it
These functions are used by Visual Studio 2019, when opening or converting some projects
Signed-off-by: Lorenzo Ferrillo lorenzofersteam@live.it --- dlls/kernelbase/kernelbase.spec | 4 +-- dlls/kernelbase/main.c | 58 +++++++++++++++++++++++++++++++++ include/perflib.h | 3 ++ 3 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 104dd99d619..f34276af021 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1188,8 +1188,8 @@ # @ stub PerfQueryInstance @ stdcall PerfSetCounterRefValue(long ptr long ptr) @ stdcall PerfSetCounterSetInfo(long ptr long) -# @ stub PerfSetULongCounterValue -# @ stub PerfSetULongLongCounterValue +@ stdcall PerfSetULongCounterValue(long ptr long long) +@ 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 0309ec91589..7d02b1eeee9 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -338,6 +338,64 @@ 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; +} +/*********************************************************************** + * 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 188f26e3e74..b84bdfa2466 100644 --- a/include/perflib.h +++ b/include/perflib.h @@ -106,6 +106,9 @@ 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 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 b69186d07a7..26622f17137 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 | 147 +++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 7 deletions(-)
diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c index 7481020dd4e..f6252ac9b92 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,26 @@ 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}, + }, + }; + 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; @@ -187,6 +209,117 @@ 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 = 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); + 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); + + /*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); + 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); + + 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);
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 7d02b1eeee9..63156f04988 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -333,6 +333,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 63156f04988..2f23409a683 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" @@ -364,6 +365,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;
@@ -392,6 +394,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;
Zhiyi Zhang (@zhiyi) commented about dlls/kernelbase/kernelbase.spec:
# @ stub PerfQueryInstance @ stdcall PerfSetCounterRefValue(long ptr long ptr) @ stdcall PerfSetCounterSetInfo(long ptr long) -# @ stub PerfSetULongCounterValue -# @ stub PerfSetULongLongCounterValue +@ stdcall PerfSetULongCounterValue(long ptr long long) +@ stdcall PerfSetULongLongCounterValue(long ptr long int64)
Please separate this commit and add function implementation one commit at a time. The tests can be separated as individual commits as well.