[PATCH v2 0/1] MR11389: pdh: Implement PdhGetFormattedCounterArrayA/W.
These functions were stubs that raised EXCEPTION_WINE_STUB when called. Needed by some applications such as FormatFactory. Signed-off-by: chenzhengyong <chenzhengyong@uniontech.com> -- v2: pdh: Implement PdhGetFormattedCounterArrayA/W. https://gitlab.winehq.org/wine/wine/-/merge_requests/11389
From: chenzhengyong <chenzhengyong@uniontech.com> These functions were stubs that raised EXCEPTION_WINE_STUB when called. Needed by some applications such as FormatFactory. Signed-off-by: chenzhengyong <chenzhengyong@uniontech.com> --- dlls/pdh/pdh.spec | 4 +- dlls/pdh/pdh_main.c | 102 ++++++++++++++++++++++++ dlls/pdh/tests/pdh.c | 180 +++++++++++++++++++++++++++++++++++++++++++ include/pdh.h | 18 +++++ 4 files changed, 302 insertions(+), 2 deletions(-) diff --git a/dlls/pdh/pdh.spec b/dlls/pdh/pdh.spec index 1e6289c5584..93db4f56eea 100644 --- a/dlls/pdh/pdh.spec +++ b/dlls/pdh/pdh.spec @@ -58,8 +58,8 @@ @ stub PdhGetDefaultPerfObjectHW @ stub PdhGetDefaultPerfObjectW @ stdcall PdhGetDllVersion(ptr) -@ stub PdhGetFormattedCounterArrayA -@ stub PdhGetFormattedCounterArrayW +@ stdcall PdhGetFormattedCounterArrayA(ptr long ptr ptr ptr) +@ stdcall PdhGetFormattedCounterArrayW(ptr long ptr ptr ptr) @ stdcall PdhGetFormattedCounterValue(ptr long ptr ptr) @ stub PdhGetLogFileSize @ stdcall PdhGetLogFileTypeA(str ptr) diff --git a/dlls/pdh/pdh_main.c b/dlls/pdh/pdh_main.c index 2cd7afeed58..55315cda71a 100644 --- a/dlls/pdh/pdh_main.c +++ b/dlls/pdh/pdh_main.c @@ -761,6 +761,108 @@ PDH_STATUS WINAPI PdhGetFormattedCounterValue( PDH_HCOUNTER handle, DWORD format return ret; } +/* caller must hold counter lock; PDH_FMT_COUNTERVALUE_ITEM_A and _W share the same layout */ +static PDH_STATUS get_formatted_counter_array( PDH_HCOUNTER handle, DWORD format, + LPDWORD bufsize, LPDWORD count, void *buffer, BOOL wide ) +{ + PDH_STATUS ret; + struct counter *counter = handle; + PDH_FMT_COUNTERVALUE value; + DWORD needed = sizeof(PDH_FMT_COUNTERVALUE_ITEM_W) + (wide ? sizeof(WCHAR) : sizeof(CHAR)); + + *count = 1; + + if (!buffer || *bufsize < needed) + { + *bufsize = needed; + return PDH_MORE_DATA; + } + + if (!(ret = format_value( counter, format, &counter->one, &counter->two, &value ))) + { + PPDH_FMT_COUNTERVALUE_ITEM_W item = buffer; + char *name = (char *)buffer + sizeof(PDH_FMT_COUNTERVALUE_ITEM_W); + item->FmtValue = value; + item->FmtValue.CStatus = ERROR_SUCCESS; + if (wide) + { + item->szName = (LPWSTR)name; + *(WCHAR *)name = 0; + } + else + { + ((PPDH_FMT_COUNTERVALUE_ITEM_A)item)->szName = (LPSTR)name; + *name = 0; + } + } + *bufsize = needed; + return ret; +} + +/*********************************************************************** + * PdhGetFormattedCounterArrayW (PDH.@) + */ +PDH_STATUS WINAPI PdhGetFormattedCounterArrayW( PDH_HCOUNTER handle, DWORD format, + LPDWORD bufsize, LPDWORD count, + PPDH_FMT_COUNTERVALUE_ITEM_W buffer ) +{ + PDH_STATUS ret; + struct counter *counter = handle; + + TRACE("%p %lx %p %p %p\n", handle, format, bufsize, count, buffer); + + if (!bufsize || !count || !handle) return PDH_INVALID_ARGUMENT; + + EnterCriticalSection( &pdh_handle_cs ); + if (counter->magic != PDH_MAGIC_COUNTER) + { + LeaveCriticalSection( &pdh_handle_cs ); + return PDH_INVALID_HANDLE; + } + if (counter->status) + { + LeaveCriticalSection( &pdh_handle_cs ); + return PDH_INVALID_DATA; + } + + ret = get_formatted_counter_array( handle, format, bufsize, count, buffer, TRUE ); + + LeaveCriticalSection( &pdh_handle_cs ); + return ret; +} + +/*********************************************************************** + * PdhGetFormattedCounterArrayA (PDH.@) + */ +PDH_STATUS WINAPI PdhGetFormattedCounterArrayA( PDH_HCOUNTER handle, DWORD format, + LPDWORD bufsize, LPDWORD count, + PPDH_FMT_COUNTERVALUE_ITEM_A buffer ) +{ + PDH_STATUS ret; + struct counter *counter = handle; + + TRACE("%p %lx %p %p %p\n", handle, format, bufsize, count, buffer); + + if (!bufsize || !count || !handle) return PDH_INVALID_ARGUMENT; + + EnterCriticalSection( &pdh_handle_cs ); + if (counter->magic != PDH_MAGIC_COUNTER) + { + LeaveCriticalSection( &pdh_handle_cs ); + return PDH_INVALID_HANDLE; + } + if (counter->status) + { + LeaveCriticalSection( &pdh_handle_cs ); + return PDH_INVALID_DATA; + } + + ret = get_formatted_counter_array( handle, format, bufsize, count, buffer, FALSE ); + + LeaveCriticalSection( &pdh_handle_cs ); + return ret; +} + /*********************************************************************** * PdhGetRawCounterValue (PDH.@) */ diff --git a/dlls/pdh/tests/pdh.c b/dlls/pdh/tests/pdh.c index 5408e4cc3f3..4920289475a 100644 --- a/dlls/pdh/tests/pdh.c +++ b/dlls/pdh/tests/pdh.c @@ -426,6 +426,184 @@ static void test_PdhGetRawCounterValue( void ) ok(ret == ERROR_SUCCESS, "PdhCloseQuery failed 0x%08lx\n", ret); } +static void test_PdhGetFormattedCounterArrayW( void ) +{ + PDH_STATUS ret; + PDH_HQUERY query; + PDH_HCOUNTER counter; + PDH_FMT_COUNTERVALUE_ITEM_W buffer[2]; + PDH_FMT_COUNTERVALUE value; + DWORD size, count; + + ret = PdhOpenQueryW( NULL, 0, &query ); + ok(ret == ERROR_SUCCESS, "PdhOpenQueryW failed 0x%08lx\n", ret); + + ret = PdhAddCounterW( query, system_uptime, 0, &counter ); + ok(ret == ERROR_SUCCESS, "PdhAddCounterW failed 0x%08lx\n", ret); + + ret = PdhGetFormattedCounterArrayW( NULL, PDH_FMT_LARGE, NULL, NULL, NULL ); + ok(ret == PDH_INVALID_ARGUMENT, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + + ret = PdhGetFormattedCounterArrayW( NULL, PDH_FMT_LARGE, &size, &count, NULL ); + ok(ret == PDH_INVALID_ARGUMENT, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_LARGE, NULL, &count, NULL ); + ok(ret == PDH_INVALID_ARGUMENT, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_LARGE, &size, NULL, NULL ); + ok(ret == PDH_INVALID_ARGUMENT, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + + size = 0; + count = 0; + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_LARGE, &size, &count, NULL ); + ok(ret == PDH_MORE_DATA, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + ok(size == sizeof(*buffer) + sizeof(WCHAR), "expected %lu got %lu\n", + (DWORD)(sizeof(*buffer) + sizeof(WCHAR)), size); + ok(count == 1, "expected 1 got %lu\n", count); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_LARGE, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + ok(size == sizeof(*buffer) + sizeof(WCHAR), "expected %lu got %lu\n", + (DWORD)(sizeof(*buffer) + sizeof(WCHAR)), size); + ok(count == 1, "expected 1 got %lu\n", count); + ok(buffer[0].szName == (LPWSTR)((char *)buffer + sizeof(*buffer)), + "expected %p got %p\n", (LPWSTR)((char *)buffer + sizeof(*buffer)), buffer[0].szName); + ok(buffer[0].FmtValue.CStatus == ERROR_SUCCESS, "expected ERROR_SUCCESS got %lx\n", buffer[0].FmtValue.CStatus); + + ret = PdhCollectQueryData( query ); + ok(ret == ERROR_SUCCESS, "PdhCollectQueryData failed 0x%08lx\n", ret); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_LARGE, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + ok(count == 1, "expected 1 got %lu\n", count); + + ret = PdhGetFormattedCounterValue( counter, PDH_FMT_LARGE, NULL, &value ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterValue failed 0x%08lx\n", ret); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_LARGE, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + ok(buffer[0].FmtValue.largeValue == value.largeValue, + "expected %s got %s\n", wine_dbgstr_longlong(value.largeValue), + wine_dbgstr_longlong(buffer[0].FmtValue.largeValue)); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_LONG, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_DOUBLE, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_LARGE | PDH_FMT_1000, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + + size = 0; + ret = PdhGetFormattedCounterArrayW( counter, PDH_FMT_LARGE, &size, &count, buffer ); + ok(ret == PDH_MORE_DATA, "PdhGetFormattedCounterArrayW failed 0x%08lx\n", ret); + + ret = PdhCloseQuery( query ); + ok(ret == ERROR_SUCCESS, "PdhCloseQuery failed 0x%08lx\n", ret); +} + +static void test_PdhGetFormattedCounterArrayA( void ) +{ + PDH_STATUS ret; + PDH_HQUERY query; + PDH_HCOUNTER counter; + PDH_FMT_COUNTERVALUE_ITEM_A buffer[2]; + PDH_FMT_COUNTERVALUE value; + DWORD size, count; + + ret = PdhOpenQueryA( NULL, 0, &query ); + ok(ret == ERROR_SUCCESS, "PdhOpenQueryA failed 0x%08lx\n", ret); + + ret = PdhAddCounterA( query, "\\System\\System Up Time", 0, &counter ); + ok(ret == ERROR_SUCCESS, "PdhAddCounterA failed 0x%08lx\n", ret); + + ret = PdhGetFormattedCounterArrayA( NULL, PDH_FMT_LARGE, NULL, NULL, NULL ); + ok(ret == PDH_INVALID_ARGUMENT, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + + ret = PdhGetFormattedCounterArrayA( NULL, PDH_FMT_LARGE, &size, &count, NULL ); + ok(ret == PDH_INVALID_ARGUMENT, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_LARGE, NULL, &count, NULL ); + ok(ret == PDH_INVALID_ARGUMENT, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_LARGE, &size, NULL, NULL ); + ok(ret == PDH_INVALID_ARGUMENT, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + + size = 0; + count = 0; + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_LARGE, &size, &count, NULL ); + ok(ret == PDH_MORE_DATA, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + ok(size == sizeof(*buffer) + sizeof(CHAR), "expected %lu got %lu\n", + (DWORD)(sizeof(*buffer) + sizeof(CHAR)), size); + ok(count == 1, "expected 1 got %lu\n", count); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_LARGE, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + ok(size == sizeof(*buffer) + sizeof(CHAR), "expected %lu got %lu\n", + (DWORD)(sizeof(*buffer) + sizeof(CHAR)), size); + ok(count == 1, "expected 1 got %lu\n", count); + ok(buffer[0].szName == (LPSTR)((char *)buffer + sizeof(*buffer)), + "expected %p got %p\n", (LPSTR)((char *)buffer + sizeof(*buffer)), buffer[0].szName); + ok(buffer[0].FmtValue.CStatus == ERROR_SUCCESS, "expected ERROR_SUCCESS got %lx\n", buffer[0].FmtValue.CStatus); + + ret = PdhCollectQueryData( query ); + ok(ret == ERROR_SUCCESS, "PdhCollectQueryData failed 0x%08lx\n", ret); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_LARGE, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + ok(count == 1, "expected 1 got %lu\n", count); + + ret = PdhGetFormattedCounterValue( counter, PDH_FMT_LARGE, NULL, &value ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterValue failed 0x%08lx\n", ret); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_LARGE, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + ok(buffer[0].FmtValue.largeValue == value.largeValue, + "expected %s got %s\n", wine_dbgstr_longlong(value.largeValue), + wine_dbgstr_longlong(buffer[0].FmtValue.largeValue)); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_LONG, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_DOUBLE, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + + size = sizeof(buffer); + count = 0; + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_LARGE | PDH_FMT_1000, &size, &count, buffer ); + ok(ret == ERROR_SUCCESS, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + + size = 0; + ret = PdhGetFormattedCounterArrayA( counter, PDH_FMT_LARGE, &size, &count, buffer ); + ok(ret == PDH_MORE_DATA, "PdhGetFormattedCounterArrayA failed 0x%08lx\n", ret); + + ret = PdhCloseQuery( query ); + ok(ret == ERROR_SUCCESS, "PdhCloseQuery failed 0x%08lx\n", ret); +} + static void test_PdhVbGetDoubleCounterValue(void) { PDH_FMT_COUNTERVALUE value; @@ -1037,6 +1215,8 @@ START_TEST(pdh) test_PdhGetFormattedCounterValue(); test_PdhGetRawCounterValue(); + test_PdhGetFormattedCounterArrayW(); + test_PdhGetFormattedCounterArrayA(); test_PdhSetCounterScaleFactor(); test_PdhGetCounterTimeBase(); diff --git a/include/pdh.h b/include/pdh.h index 5ef76b07abe..1f9a9ee2381 100644 --- a/include/pdh.h +++ b/include/pdh.h @@ -189,6 +189,21 @@ typedef struct _PDH_COUNTER_INFO_W DWORD DataBuffer[1]; } PDH_COUNTER_INFO_W, *PPDH_COUNTER_INFO_W; +typedef struct _PDH_FMT_COUNTERVALUE_ITEM_A +{ + LPSTR szName; + PDH_FMT_COUNTERVALUE FmtValue; +} PDH_FMT_COUNTERVALUE_ITEM_A,*PPDH_FMT_COUNTERVALUE_ITEM_A; + +typedef struct _PDH_FMT_COUNTERVALUE_ITEM_W +{ + LPWSTR szName; + PDH_FMT_COUNTERVALUE FmtValue; +} PDH_FMT_COUNTERVALUE_ITEM_W,*PPDH_FMT_COUNTERVALUE_ITEM_W; + +DECL_PDH_TYPE_AW(PDH_FMT_COUNTERVALUE_ITEM) +DECL_PDH_TYPE_AW(PPDH_FMT_COUNTERVALUE_ITEM) + typedef struct _PDH_RAW_COUNTER_ITEM_A { LPSTR szName; @@ -231,6 +246,9 @@ PDH_STATUS WINAPI PdhGetCounterInfoW(PDH_HCOUNTER, BOOLEAN, LPDWORD, PPDH_COUNTE PDH_STATUS WINAPI PdhGetCounterTimeBase(PDH_HCOUNTER, LONGLONG *); PDH_STATUS WINAPI PdhGetDllVersion(LPDWORD); PDH_STATUS WINAPI PdhGetFormattedCounterValue(PDH_HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE); +PDH_STATUS WINAPI PdhGetFormattedCounterArrayA(PDH_HCOUNTER, DWORD, LPDWORD, LPDWORD, PPDH_FMT_COUNTERVALUE_ITEM_A); +PDH_STATUS WINAPI PdhGetFormattedCounterArrayW(PDH_HCOUNTER, DWORD, LPDWORD, LPDWORD, PPDH_FMT_COUNTERVALUE_ITEM_W); +#define PdhGetFormattedCounterArray WINELIB_NAME_AW(PdhGetFormattedCounterArray) PDH_STATUS WINAPI PdhGetRawCounterArrayA(PDH_HCOUNTER, LPDWORD, LPDWORD, PPDH_RAW_COUNTER_ITEM_A); PDH_STATUS WINAPI PdhGetRawCounterArrayW(PDH_HCOUNTER, LPDWORD, LPDWORD, PPDH_RAW_COUNTER_ITEM_W); #define PdhGetRawCounterArray WINELIB_NAME_AW(PdhGetRawCounterArray) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11389
participants (2)
-
chenzhengyong -
zhengyong chen (@chenzhengyong)