Used by Red Dead Redemption 2 after latest update.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/advapi32/advapi.c | 8 ++++++++ dlls/advapi32/advapi32.spec | 2 +- include/perflib.h | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/advapi32/advapi.c b/dlls/advapi32/advapi.c index cbd4612425d..a1f0385357e 100644 --- a/dlls/advapi32/advapi.c +++ b/dlls/advapi32/advapi.c @@ -31,6 +31,7 @@ #include "winerror.h" #include "wincred.h" #include "wct.h" +#include "perflib.h"
#include "wine/debug.h"
@@ -313,3 +314,10 @@ BOOL WINAPI GetThreadWaitChain(HWCT handle, DWORD_PTR ctx, DWORD flags, DWORD th SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } + +ULONG WINAPI PerfCloseQueryHandle( HANDLE query ) +{ + FIXME( "query %p stub.\n", query ); + + return ERROR_SUCCESS; +} diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index 3cbf5638ae4..21a76675bc5 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -554,7 +554,7 @@ # @ stub OperationEnd # @ stub OperationStart # @ stub PerfAddCounters -# @ stub PerfCloseQueryHandle +@ stdcall PerfCloseQueryHandle(long) @ stdcall -import PerfCreateInstance(long ptr wstr long) # @ stub PerfDecrementULongCounterValue # @ stub PerfDecrementULongLongCounterValue diff --git a/include/perflib.h b/include/perflib.h index 54ea8ccb614..27019bd842c 100644 --- a/include/perflib.h +++ b/include/perflib.h @@ -89,6 +89,8 @@ ULONG WINAPI PerfStartProvider(GUID *, PERFLIBREQUEST, HANDLE *); ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *); ULONG WINAPI PerfStopProvider(HANDLE);
+ULONG WINAPI PerfCloseQueryHandle(HANDLE); + #ifdef __cplusplus } /* extern "C" */ #endif
From: Paul Gofman pgofman@codeweavers.com
--- dlls/advapi32/advapi.c | 10 ++++++++++ dlls/advapi32/advapi32.spec | 2 +- dlls/advapi32/tests/perf.c | 38 +++++++++++++++++++++++++++++++++++++ include/perflib.h | 1 + 4 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/dlls/advapi32/advapi.c b/dlls/advapi32/advapi.c index a1f0385357e..c3d2e2d00e7 100644 --- a/dlls/advapi32/advapi.c +++ b/dlls/advapi32/advapi.c @@ -321,3 +321,13 @@ ULONG WINAPI PerfCloseQueryHandle( HANDLE query )
return ERROR_SUCCESS; } + +ULONG WINAPI PerfOpenQueryHandle( const WCHAR *machine, HANDLE *query ) +{ + FIXME( "machine %s, query %p.\n", debugstr_w(machine), query ); + + if (!query) return ERROR_INVALID_PARAMETER; + *query = (HANDLE)0xdeadbeef; + + return ERROR_SUCCESS; +} diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index 21a76675bc5..d80b4d938f6 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -564,7 +564,7 @@ # @ stub PerfEnumerateCounterSetInstances # @ stub PerfIncrementULongCounterValue # @ stub PerfIncrementULongLongCounterValue -# @ stub PerfOpenQueryHandle +@ stdcall PerfOpenQueryHandle(wstr ptr) # @ stub PerfQueryCounterData # @ stub PerfQueryCounterInfo # @ stub PerfQueryCounterSetRegistrationInfo diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c index fc07a09d327..2cd2a208677 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -28,6 +28,21 @@
#include "wine/test.h"
+#define DEFINE_FUNCTION(name) static typeof(name) *p##name; +DEFINE_FUNCTION(PerfCloseQueryHandle); +DEFINE_FUNCTION(PerfOpenQueryHandle); +#undef DEFINE_FUNCTION + +static void init_functions(void) +{ + HANDLE hadvapi = GetModuleHandleA("advapi32.dll"); + +#define GET_FUNCTION(name) p##name = (void *)GetProcAddress(hadvapi, #name) + GET_FUNCTION(PerfCloseQueryHandle); + GET_FUNCTION(PerfOpenQueryHandle); +#undef GET_FUNCTION +} + static ULONG WINAPI test_provider_callback(ULONG code, void *buffer, ULONG size) { ok(0, "Provider callback called.\n"); @@ -188,7 +203,30 @@ void test_provider_init(void) ok(!ret, "Got unexpected ret %lu.\n", ret); }
+static void test_perf_counters(void) +{ + HANDLE query; + ULONG ret; + + if (!pPerfOpenQueryHandle) + { + win_skip("PerfOpenQueryHandle not found.\n"); + return; + } + + ret = pPerfOpenQueryHandle(NULL, NULL); + ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret); + ret = pPerfOpenQueryHandle(NULL, &query); + ok(!ret, "got ret %lu.\n", ret); + + ret = pPerfCloseQueryHandle(query); + ok(!ret, "got ret %lu.\n", ret); +} + START_TEST(perf) { + init_functions(); + test_provider_init(); + test_perf_counters(); } diff --git a/include/perflib.h b/include/perflib.h index 27019bd842c..47b6bdefc84 100644 --- a/include/perflib.h +++ b/include/perflib.h @@ -90,6 +90,7 @@ ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *); ULONG WINAPI PerfStopProvider(HANDLE);
ULONG WINAPI PerfCloseQueryHandle(HANDLE); +ULONG WINAPI PerfOpenQueryHandle(const WCHAR *, HANDLE *);
#ifdef __cplusplus } /* extern "C" */
From: Paul Gofman pgofman@codeweavers.com
--- dlls/advapi32/advapi.c | 10 ++++++++++ dlls/advapi32/advapi32.spec | 2 +- dlls/advapi32/tests/perf.c | 25 +++++++++++++++++++++++++ include/perflib.h | 14 ++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/dlls/advapi32/advapi.c b/dlls/advapi32/advapi.c index c3d2e2d00e7..ecef33561b8 100644 --- a/dlls/advapi32/advapi.c +++ b/dlls/advapi32/advapi.c @@ -331,3 +331,13 @@ ULONG WINAPI PerfOpenQueryHandle( const WCHAR *machine, HANDLE *query )
return ERROR_SUCCESS; } + +ULONG WINAPI PerfAddCounters( HANDLE query, PERF_COUNTER_IDENTIFIER *id, DWORD size ) +{ + FIXME( "query %p, id %p, size %lu stub.\n", query, id, size ); + + if (!id || size < sizeof(*id) || id->Size < sizeof(*id)) return ERROR_INVALID_PARAMETER; + + id->Status = ERROR_WMI_GUID_NOT_FOUND; + return ERROR_SUCCESS; +} diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index d80b4d938f6..4009d33b5f8 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -553,7 +553,7 @@ @ stdcall -ret64 -import OpenTraceW(ptr) # @ stub OperationEnd # @ stub OperationStart -# @ stub PerfAddCounters +@ stdcall PerfAddCounters(long ptr long) @ stdcall PerfCloseQueryHandle(long) @ stdcall -import PerfCreateInstance(long ptr wstr long) # @ stub PerfDecrementULongCounterValue diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c index 2cd2a208677..bc8d0a71702 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -28,9 +28,12 @@
#include "wine/test.h"
+#include "initguid.h" + #define DEFINE_FUNCTION(name) static typeof(name) *p##name; DEFINE_FUNCTION(PerfCloseQueryHandle); DEFINE_FUNCTION(PerfOpenQueryHandle); +DEFINE_FUNCTION(PerfAddCounters); #undef DEFINE_FUNCTION
static void init_functions(void) @@ -40,6 +43,7 @@ static void init_functions(void) #define GET_FUNCTION(name) p##name = (void *)GetProcAddress(hadvapi, #name) GET_FUNCTION(PerfCloseQueryHandle); GET_FUNCTION(PerfOpenQueryHandle); + GET_FUNCTION(PerfAddCounters); #undef GET_FUNCTION }
@@ -203,8 +207,12 @@ void test_provider_init(void) ok(!ret, "Got unexpected ret %lu.\n", ret); }
+DEFINE_GUID(TestCounterGUID, 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33); + static void test_perf_counters(void) { + char buffer[sizeof(PERF_COUNTER_IDENTIFIER) + 8]; + PERF_COUNTER_IDENTIFIER *counter_id; HANDLE query; ULONG ret;
@@ -219,6 +227,23 @@ static void test_perf_counters(void) ret = pPerfOpenQueryHandle(NULL, &query); ok(!ret, "got ret %lu.\n", ret);
+ counter_id = (PERF_COUNTER_IDENTIFIER *)buffer; + memset(buffer, 0, sizeof(buffer)); + + counter_id->CounterSetGuid = TestCounterGUID; + counter_id->CounterId = PERF_WILDCARD_COUNTER; + counter_id->InstanceId = PERF_WILDCARD_COUNTER; + + ret = pPerfAddCounters(query, counter_id, sizeof(*counter_id)); + ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret); + + counter_id->Size = sizeof(*counter_id); + ret = pPerfAddCounters(query, counter_id, 8); + ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret); + ret = pPerfAddCounters(query, counter_id, sizeof(*counter_id)); + ok(!ret, "got ret %lu.\n", ret); + ok(counter_id->Status == ERROR_WMI_GUID_NOT_FOUND, "got Status %#lx.\n", counter_id->Status); + ret = pPerfCloseQueryHandle(query); ok(!ret, "got ret %lu.\n", ret); } diff --git a/include/perflib.h b/include/perflib.h index 47b6bdefc84..ef2b6c6d832 100644 --- a/include/perflib.h +++ b/include/perflib.h @@ -81,6 +81,19 @@ typedef struct _PROVIDER_CONTEXT { LPVOID pMemContext; } PERF_PROVIDER_CONTEXT, * PPERF_PROVIDER_CONTEXT;
+typedef struct _PERF_COUNTER_IDENTIFIER { + GUID CounterSetGuid; + ULONG Status; + ULONG Size; + ULONG CounterId; + ULONG InstanceId; + ULONG Index; + ULONG Reserved; +} PERF_COUNTER_IDENTIFIER, *PPERF_COUNTER_IDENTIFIER; + +#define PERF_WILDCARD_COUNTER 0xFFFFFFFF +#define PERF_WILDCARD_INSTANCE L"*" + 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 *); @@ -89,6 +102,7 @@ ULONG WINAPI PerfStartProvider(GUID *, PERFLIBREQUEST, HANDLE *); ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *); ULONG WINAPI PerfStopProvider(HANDLE);
+ULONG WINAPI PerfAddCounters(HANDLE, PERF_COUNTER_IDENTIFIER *, DWORD); ULONG WINAPI PerfCloseQueryHandle(HANDLE); ULONG WINAPI PerfOpenQueryHandle(const WCHAR *, HANDLE *);
On 9/12/22 20:09, Paul Gofman wrote:
+ULONG WINAPI PerfAddCounters( HANDLE query, PERF_COUNTER_IDENTIFIER *id, DWORD size ) +{
- FIXME( "query %p, id %p, size %lu stub.\n", query, id, size );
- if (!id || size < sizeof(*id) || id->Size < sizeof(*id)) return ERROR_INVALID_PARAMETER;
- id->Status = ERROR_WMI_GUID_NOT_FOUND;
- return ERROR_SUCCESS;
+}
Looks like a copy-paste error in the title for this patch.
Indeed, thanks.
On 12 Sep 2022, at 21:49, Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
On 9/12/22 20:09, Paul Gofman wrote:
+ULONG WINAPI PerfAddCounters( HANDLE query, PERF_COUNTER_IDENTIFIER *id, DWORD size ) +{
- FIXME( "query %p, id %p, size %lu stub.\n", query, id, size );
- if (!id || size < sizeof(*id) || id->Size < sizeof(*id)) return ERROR_INVALID_PARAMETER;
- id->Status = ERROR_WMI_GUID_NOT_FOUND;
- return ERROR_SUCCESS;
+}
Looks like a copy-paste error in the title for this patch.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/advapi32/advapi.c | 20 ++++++++++++++++ dlls/advapi32/advapi32.spec | 2 +- dlls/advapi32/tests/perf.c | 46 +++++++++++++++++++++++++++++++++++++ include/perflib.h | 10 ++++++++ 4 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/dlls/advapi32/advapi.c b/dlls/advapi32/advapi.c index ecef33561b8..6b3ffe2ea25 100644 --- a/dlls/advapi32/advapi.c +++ b/dlls/advapi32/advapi.c @@ -341,3 +341,23 @@ ULONG WINAPI PerfAddCounters( HANDLE query, PERF_COUNTER_IDENTIFIER *id, DWORD s id->Status = ERROR_WMI_GUID_NOT_FOUND; return ERROR_SUCCESS; } + +ULONG WINAPI PerfQueryCounterData( HANDLE query, PERF_DATA_HEADER *data, DWORD data_size, DWORD *size_needed ) +{ + FIXME( "query %p, data %p, data_size %lu, size_needed %p stub.\n", query, data, data_size, size_needed ); + + if (!size_needed) return ERROR_INVALID_PARAMETER; + + *size_needed = sizeof(PERF_DATA_HEADER); + + if (!data || data_size < sizeof(PERF_DATA_HEADER)) return ERROR_NOT_ENOUGH_MEMORY; + + data->dwTotalSize = sizeof(PERF_DATA_HEADER); + data->dwNumCounters = 0; + QueryPerformanceCounter( (LARGE_INTEGER *)&data->PerfTimeStamp ); + QueryPerformanceFrequency( (LARGE_INTEGER *)&data->PerfFreq ); + GetSystemTimeAsFileTime( (FILETIME *)&data->PerfTime100NSec ); + FileTimeToSystemTime( (FILETIME *)&data->PerfTime100NSec, &data->SystemTime ); + + return ERROR_SUCCESS; +} diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index 4009d33b5f8..b69186d07a7 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -565,7 +565,7 @@ # @ stub PerfIncrementULongCounterValue # @ stub PerfIncrementULongLongCounterValue @ stdcall PerfOpenQueryHandle(wstr ptr) -# @ stub PerfQueryCounterData +@ stdcall PerfQueryCounterData(long ptr long ptr) # @ stub PerfQueryCounterInfo # @ stub PerfQueryCounterSetRegistrationInfo # @ stub PerfQueryInstance diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c index bc8d0a71702..34b6e952842 100644 --- a/dlls/advapi32/tests/perf.c +++ b/dlls/advapi32/tests/perf.c @@ -25,6 +25,7 @@ #include "winerror.h" #include "perflib.h" #include "winperf.h" +#include "winternl.h"
#include "wine/test.h"
@@ -34,6 +35,7 @@ DEFINE_FUNCTION(PerfCloseQueryHandle); DEFINE_FUNCTION(PerfOpenQueryHandle); DEFINE_FUNCTION(PerfAddCounters); +DEFINE_FUNCTION(PerfQueryCounterData); #undef DEFINE_FUNCTION
static void init_functions(void) @@ -44,6 +46,7 @@ static void init_functions(void) GET_FUNCTION(PerfCloseQueryHandle); GET_FUNCTION(PerfOpenQueryHandle); GET_FUNCTION(PerfAddCounters); + GET_FUNCTION(PerfQueryCounterData); #undef GET_FUNCTION }
@@ -209,11 +212,19 @@ void test_provider_init(void)
DEFINE_GUID(TestCounterGUID, 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33);
+static ULONG64 trunc_nttime_ms(ULONG64 t) +{ + return (t / 10000) * 10000; +} + static void test_perf_counters(void) { + LARGE_INTEGER freq, qpc1, qpc2, nttime1, nttime2, systime; char buffer[sizeof(PERF_COUNTER_IDENTIFIER) + 8]; PERF_COUNTER_IDENTIFIER *counter_id; + PERF_DATA_HEADER dh; HANDLE query; + DWORD size; ULONG ret;
if (!pPerfOpenQueryHandle) @@ -244,6 +255,41 @@ static void test_perf_counters(void) ok(!ret, "got ret %lu.\n", ret); ok(counter_id->Status == ERROR_WMI_GUID_NOT_FOUND, "got Status %#lx.\n", counter_id->Status);
+ ret = pPerfQueryCounterData(query, NULL, 0, NULL); + ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret); + + size = 0xdeadbeef; + ret = pPerfQueryCounterData(query, NULL, 0, &size); + ok(ret == ERROR_NOT_ENOUGH_MEMORY, "got ret %lu.\n", ret); + ok(size == sizeof(dh), "got size %lu.\n", size); + + ret = pPerfQueryCounterData(query, &dh, sizeof(dh), NULL); + ok(ret == ERROR_INVALID_PARAMETER, "got ret %lu.\n", ret); + + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&qpc1); + NtQuerySystemTime(&nttime1); + + size = 0xdeadbeef; + ret = pPerfQueryCounterData(query, &dh, sizeof(dh), &size); + QueryPerformanceCounter(&qpc2); + NtQuerySystemTime(&nttime2); + SystemTimeToFileTime(&dh.SystemTime, (FILETIME *)&systime); + ok(!ret, "got ret %lu.\n", ret); + ok(size == sizeof(dh), "got size %lu.\n", size); + ok(dh.dwTotalSize == sizeof(dh), "got dwTotalSize %lu.\n", dh.dwTotalSize); + ok(!dh.dwNumCounters, "got dwNumCounters %lu.\n", dh.dwNumCounters); + ok(dh.PerfFreq == freq.QuadPart, "got PerfFreq %I64u.\n", dh.PerfFreq); + ok(dh.PerfTimeStamp >= qpc1.QuadPart && dh.PerfTimeStamp <= qpc2.QuadPart, + "got PerfTimeStamp %I64u, qpc1 %I64u, qpc2 %I64u.\n", + dh.PerfTimeStamp, qpc1.QuadPart, qpc2.QuadPart); + ok(dh.PerfTime100NSec >= nttime1.QuadPart && dh.PerfTime100NSec <= nttime2.QuadPart, + "got PerfTime100NSec %I64u, nttime1 %I64u, nttime2 %I64u.\n", + dh.PerfTime100NSec, nttime1.QuadPart, nttime2.QuadPart); + ok(systime.QuadPart >= trunc_nttime_ms(nttime1.QuadPart) && systime.QuadPart <= trunc_nttime_ms(nttime2.QuadPart), + "got systime %I64u, nttime1 %I64u, nttime2 %I64u, %d.\n", + systime.QuadPart, nttime1.QuadPart, nttime2.QuadPart, dh.SystemTime.wMilliseconds); + ret = pPerfCloseQueryHandle(query); ok(!ret, "got ret %lu.\n", ret); } diff --git a/include/perflib.h b/include/perflib.h index ef2b6c6d832..232ac308fce 100644 --- a/include/perflib.h +++ b/include/perflib.h @@ -94,6 +94,15 @@ typedef struct _PERF_COUNTER_IDENTIFIER { #define PERF_WILDCARD_COUNTER 0xFFFFFFFF #define PERF_WILDCARD_INSTANCE L"*"
+typedef struct _PERF_DATA_HEADER { + ULONG dwTotalSize; + ULONG dwNumCounters; + LONGLONG PerfTimeStamp; + LONGLONG PerfTime100NSec; + LONGLONG PerfFreq; + SYSTEMTIME SystemTime; +} PERF_DATA_HEADER, *PPERF_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 *); @@ -105,6 +114,7 @@ ULONG WINAPI PerfStopProvider(HANDLE); ULONG WINAPI PerfAddCounters(HANDLE, PERF_COUNTER_IDENTIFIER *, DWORD); ULONG WINAPI PerfCloseQueryHandle(HANDLE); ULONG WINAPI PerfOpenQueryHandle(const WCHAR *, HANDLE *); +ULONG WINAPI PerfQueryCounterData(HANDLE, PERF_DATA_HEADER *, DWORD, DWORD *);
#ifdef __cplusplus } /* extern "C" */