From e843605b238a754c819f0a1f80242ee7f35deda1 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Mon, 22 Nov 2021 17:07:56 +0300 Subject: [PATCH] advapi32: Improve perflib provider registration stubs. Signed-off-by: Paul Gofman Signed-off-by: Alexandre Julliard --- dlls/advapi32/tests/Makefile.in | 1 + dlls/advapi32/tests/perf.c | 100 ++++++++++++++++++++++++++++++++ dlls/kernelbase/main.c | 49 +++++++++++++--- include/perflib.h | 4 ++ 4 files changed, 146 insertions(+), 8 deletions(-) create mode 100644 dlls/advapi32/tests/perf.c diff --git a/dlls/advapi32/tests/Makefile.in b/dlls/advapi32/tests/Makefile.in index 12583e59f57..2e9b007a91f 100644 --- a/dlls/advapi32/tests/Makefile.in +++ b/dlls/advapi32/tests/Makefile.in @@ -10,6 +10,7 @@ C_SRCS = \ crypt_sha.c \ eventlog.c \ lsa.c \ + perf.c \ registry.c \ security.c \ service.c diff --git a/dlls/advapi32/tests/perf.c b/dlls/advapi32/tests/perf.c new file mode 100644 index 00000000000..34fedd2b645 --- /dev/null +++ b/dlls/advapi32/tests/perf.c @@ -0,0 +1,100 @@ +/* + * Unit tests for Perflib functions + * + * Copyright (c) 2021 Paul Gofman for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "perflib.h" + +#include "wine/test.h" + +static ULONG WINAPI test_provider_callback(ULONG code, void *buffer, ULONG size) +{ + ok(0, "Provider callback called.\n"); + return ERROR_SUCCESS; +} + +void test_provider_init(void) +{ + static GUID test_guid = {0xdeadbeef, 0x0001, 0x0002, {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00 ,0x0a}}; + PERF_PROVIDER_CONTEXT prov_context; + HANDLE prov, prov2; + ULONG ret; + BOOL bret; + + prov = (HANDLE)0xdeadbeef; + ret = PerfStartProvider(NULL, test_provider_callback, &prov); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret); + ok(prov == (HANDLE)0xdeadbeef, "Got unexpected prov %p.\n", prov); + + prov = (HANDLE)0xdeadbeef; + ret = PerfStartProvider(&test_guid, test_provider_callback, NULL); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret); + ok(prov == (HANDLE)0xdeadbeef, "Got unexpected prov %p.\n", prov); + + prov = (HANDLE)0xdeadbeef; + ret = PerfStartProvider(&test_guid, test_provider_callback, &prov); + ok(!ret, "Got unexpected ret %u.\n", ret); + ok(prov != (HANDLE)0xdeadbeef, "Provider handle is not set.\n"); + + prov2 = prov; + ret = PerfStartProvider(&test_guid, test_provider_callback, &prov2); + ok(!ret, "Got unexpected ret %u.\n", ret); + ok(prov2 != prov, "Got the same provider handle.\n"); + + ret = PerfStopProvider(prov2); + ok(!ret, "Got unexpected ret %u.\n", ret); + + if (0) + { + /* Access violation on Windows. */ + PerfStopProvider(prov2); + } + + /* Provider handle is a pointer and not a kernel object handle. */ + bret = DuplicateHandle(GetCurrentProcess(), prov, GetCurrentProcess(), &prov2, 0, FALSE, DUPLICATE_SAME_ACCESS); + ok(!bret && GetLastError() == ERROR_INVALID_HANDLE, "Got unexpected bret %d, err %u.\n", bret, GetLastError()); + bret = IsBadWritePtr(prov, 8); + ok(!bret, "Handle does not point to the data.\n"); + + ret = PerfStopProvider(prov); + ok(!ret, "Got unexpected ret %u.\n", ret); + + memset( &prov_context, 0, sizeof(prov_context) ); + prov = (HANDLE)0xdeadbeef; + ret = PerfStartProviderEx( &test_guid, &prov_context, &prov ); + ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret); + ok(prov == (HANDLE)0xdeadbeef, "Got unexpected prov %p.\n", prov); + + prov_context.ContextSize = sizeof(prov_context) + 1; + ret = PerfStartProviderEx( &test_guid, &prov_context, &prov ); + ok(!ret, "Got unexpected ret %u.\n", ret); + ok(prov != (HANDLE)0xdeadbeef, "Provider handle is not set.\n"); + + ret = PerfStopProvider(prov); + ok(!ret, "Got unexpected ret %u.\n", ret); +} + +START_TEST(perf) +{ + test_provider_init(); +} diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c index e6cf892a4dc..d468c84f619 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -154,6 +154,17 @@ LONG WINAPI AppPolicyGetWindowingModel(HANDLE token, AppPolicyWindowingModel *po return ERROR_SUCCESS; } +struct perf_provider +{ + GUID guid; + PERFLIBREQUEST callback; +}; + +static struct perf_provider *perf_provider_from_handle(HANDLE prov) +{ + return (struct perf_provider *)prov; +} + /*********************************************************************** * PerfCreateInstance (KERNELBASE.@) */ @@ -195,19 +206,37 @@ ULONG WINAPI PerfSetCounterRefValue(HANDLE provider, PPERF_COUNTERSET_INSTANCE i /*********************************************************************** * PerfStartProvider (KERNELBASE.@) */ -ULONG WINAPI PerfStartProvider(GUID *guid, PERFLIBREQUEST callback, HANDLE *provider) +ULONG WINAPI PerfStartProvider( GUID *guid, PERFLIBREQUEST callback, HANDLE *provider ) { - FIXME("%s %p %p: stub\n", debugstr_guid(guid), callback, provider); - return ERROR_CALL_NOT_IMPLEMENTED; + PERF_PROVIDER_CONTEXT ctx; + + FIXME( "guid %s, callback %p, provider %p semi-stub.\n", debugstr_guid(guid), callback, provider ); + + memset( &ctx, 0, sizeof(ctx) ); + ctx.ContextSize = sizeof(ctx); + ctx.ControlCallback = callback; + + return PerfStartProviderEx( guid, &ctx, provider ); } /*********************************************************************** * PerfStartProviderEx (KERNELBASE.@) */ -ULONG WINAPI PerfStartProviderEx(GUID *guid, PPERF_PROVIDER_CONTEXT context, HANDLE *provider) +ULONG WINAPI PerfStartProviderEx( GUID *guid, PERF_PROVIDER_CONTEXT *context, HANDLE *provider ) { - FIXME("%s %p %p: stub\n", debugstr_guid(guid), context, provider); - return ERROR_CALL_NOT_IMPLEMENTED; + struct perf_provider *prov; + + FIXME( "guid %s, context %p, provider %p semi-stub.\n", debugstr_guid(guid), context, provider ); + + if (!guid || !context || !provider) return ERROR_INVALID_PARAMETER; + if (context->ContextSize < sizeof(*context)) return ERROR_INVALID_PARAMETER; + + if (!(prov = heap_alloc_zero( sizeof(*prov) ))) return ERROR_OUTOFMEMORY; + memcpy( &prov->guid, guid, sizeof(prov->guid) ); + prov->callback = context->ControlCallback; + *provider = prov; + + return STATUS_SUCCESS; } /*********************************************************************** @@ -215,8 +244,12 @@ ULONG WINAPI PerfStartProviderEx(GUID *guid, PPERF_PROVIDER_CONTEXT context, HAN */ ULONG WINAPI PerfStopProvider(HANDLE handle) { - FIXME("%p: stub\n", handle); - return ERROR_CALL_NOT_IMPLEMENTED; + struct perf_provider *prov = perf_provider_from_handle( handle ); + + TRACE( "handle %p.\n", handle ); + + heap_free( prov ); + return STATUS_SUCCESS; } /*********************************************************************** diff --git a/include/perflib.h b/include/perflib.h index 2d3f6efb419..47bc0716541 100644 --- a/include/perflib.h +++ b/include/perflib.h @@ -51,6 +51,10 @@ typedef struct _PROVIDER_CONTEXT { LPVOID pMemContext; } PERF_PROVIDER_CONTEXT, * PPERF_PROVIDER_CONTEXT; +ULONG WINAPI PerfStartProvider(GUID *, PERFLIBREQUEST, HANDLE *); +ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *); +ULONG WINAPI PerfStopProvider(HANDLE); + #ifdef __cplusplus } /* extern "C" */ #endif