advapi32: Improve PerfCreateInstance() stub.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ee8af8ff28
commit
eec443afc2
|
@ -42,17 +42,24 @@ void test_provider_init(void)
|
|||
static struct
|
||||
{
|
||||
PERF_COUNTERSET_INFO counterset;
|
||||
PERF_COUNTER_INFO counter;
|
||||
PERF_COUNTER_INFO counter[2];
|
||||
}
|
||||
pc_template =
|
||||
{
|
||||
{{0}},
|
||||
{1, PERF_COUNTER_COUNTER, PERF_ATTRIB_BY_REFERENCE, sizeof(PERF_COUNTER_INFO), PERF_DETAIL_NOVICE, 0, 0},
|
||||
{
|
||||
{1, PERF_COUNTER_COUNTER, PERF_ATTRIB_BY_REFERENCE, sizeof(PERF_COUNTER_INFO),
|
||||
PERF_DETAIL_NOVICE, 0, 0xdeadbeef},
|
||||
{2, PERF_COUNTER_COUNTER, PERF_ATTRIB_BY_REFERENCE, sizeof(PERF_COUNTER_INFO),
|
||||
PERF_DETAIL_NOVICE, 0, 0xdeadbeef},
|
||||
},
|
||||
};
|
||||
|
||||
PERF_COUNTERSET_INSTANCE *instance;
|
||||
PERF_PROVIDER_CONTEXT prov_context;
|
||||
UINT64 counter1, counter2;
|
||||
HANDLE prov, prov2;
|
||||
ULONG ret;
|
||||
ULONG ret, size;
|
||||
BOOL bret;
|
||||
|
||||
prov = (HANDLE)0xdeadbeef;
|
||||
|
@ -99,7 +106,7 @@ void test_provider_init(void)
|
|||
|
||||
pc_template.counterset.CounterSetGuid = test_set_guid;
|
||||
pc_template.counterset.ProviderGuid = test_guid;
|
||||
pc_template.counterset.NumCounters = 1;
|
||||
pc_template.counterset.NumCounters = 2;
|
||||
pc_template.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE;
|
||||
ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
|
||||
ok(!ret, "Got unexpected ret %u.\n", ret);
|
||||
|
@ -115,6 +122,54 @@ void test_provider_init(void)
|
|||
ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
|
||||
ok(ret == ERROR_ALREADY_EXISTS, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
instance = PerfCreateInstance(prov, NULL, L"1", 1);
|
||||
ok(!instance, "Got unexpected instance %p.\n", instance);
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %u.\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
instance = PerfCreateInstance(prov, &test_guid, L"1", 1);
|
||||
ok(!instance, "Got unexpected instance %p.\n", instance);
|
||||
ok(GetLastError() == ERROR_NOT_FOUND, "Got unexpected error %u.\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
instance = PerfCreateInstance(prov, &test_guid, NULL, 1);
|
||||
ok(!instance, "Got unexpected instance %p.\n", instance);
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %u.\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
instance = PerfCreateInstance(prov, &test_set_guid, L"11", 1);
|
||||
ok(!!instance, "Got NULL instance.\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "Got unexpected error %u.\n", GetLastError());
|
||||
ok(instance->InstanceId == 1, "Got unexpected InstanceId %u.\n", instance->InstanceId);
|
||||
ok(instance->InstanceNameSize == 6, "Got unexpected InstanceNameSize %u.\n", instance->InstanceNameSize);
|
||||
ok(IsEqualGUID(&instance->CounterSetGuid, &test_set_guid), "Got unexpected guid %s.\n",
|
||||
debugstr_guid(&instance->CounterSetGuid));
|
||||
|
||||
ok(instance->InstanceNameOffset == sizeof(*instance) + sizeof(UINT64) * 2,
|
||||
"Got unexpected InstanceNameOffset %u.\n", instance->InstanceNameOffset);
|
||||
ok(!lstrcmpW((WCHAR *)((BYTE *)instance + instance->InstanceNameOffset), L"11"),
|
||||
"Got unexpected instance name %s.\n",
|
||||
debugstr_w((WCHAR *)((BYTE *)instance + instance->InstanceNameOffset)));
|
||||
size = ((sizeof(*instance) + sizeof(UINT64) * 2 + instance->InstanceNameSize) + 7) & ~7;
|
||||
ok(size == instance->dwSize, "Got unexpected size %u, instance->dwSize %u.\n", size, instance->dwSize);
|
||||
|
||||
ret = PerfSetCounterRefValue(prov, instance, 1, &counter1);
|
||||
todo_wine ok(!ret, "Got unexpected ret %u.\n", ret);
|
||||
ret = PerfSetCounterRefValue(prov, instance, 2, &counter2);
|
||||
todo_wine ok(!ret, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
ret = PerfSetCounterRefValue(prov, instance, 0, &counter2);
|
||||
todo_wine ok(ret == ERROR_NOT_FOUND, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
todo_wine ok(*(void **)(instance + 1) == &counter1, "Got unexpected counter value %p.\n",
|
||||
*(void **)(instance + 1));
|
||||
todo_wine ok(*(void **)((BYTE *)instance + sizeof(*instance) + sizeof(UINT64)) == &counter2,
|
||||
"Got unexpected counter value %p.\n", *(void **)(instance + 1));
|
||||
|
||||
ret = PerfDeleteInstance(prov, instance);
|
||||
ok(!ret, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
ret = PerfStopProvider(prov);
|
||||
ok(!ret, "Got unexpected ret %u.\n", ret);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "wine/debug.h"
|
||||
#include "kernelbase.h"
|
||||
#include "wine/heap.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(kernelbase);
|
||||
|
||||
|
@ -160,12 +161,21 @@ struct counterset_template
|
|||
PERF_COUNTER_INFO counter[1];
|
||||
};
|
||||
|
||||
struct counterset_instance
|
||||
{
|
||||
struct list entry;
|
||||
struct counterset_template *template;
|
||||
PERF_COUNTERSET_INSTANCE instance;
|
||||
};
|
||||
|
||||
struct perf_provider
|
||||
{
|
||||
GUID guid;
|
||||
PERFLIBREQUEST callback;
|
||||
struct counterset_template **countersets;
|
||||
unsigned int counterset_count;
|
||||
|
||||
struct list instance_list;
|
||||
};
|
||||
|
||||
static struct perf_provider *perf_provider_from_handle(HANDLE prov)
|
||||
|
@ -176,20 +186,82 @@ static struct perf_provider *perf_provider_from_handle(HANDLE prov)
|
|||
/***********************************************************************
|
||||
* PerfCreateInstance (KERNELBASE.@)
|
||||
*/
|
||||
PPERF_COUNTERSET_INSTANCE WINAPI PerfCreateInstance(HANDLE handle, LPCGUID guid,
|
||||
const WCHAR *name, ULONG id)
|
||||
PERF_COUNTERSET_INSTANCE WINAPI *PerfCreateInstance( HANDLE handle, const GUID *guid,
|
||||
const WCHAR *name, ULONG id )
|
||||
{
|
||||
FIXME("%p %s %s %u: stub\n", handle, debugstr_guid(guid), debugstr_w(name), id);
|
||||
return NULL;
|
||||
struct perf_provider *prov = perf_provider_from_handle( handle );
|
||||
struct counterset_template *template;
|
||||
struct counterset_instance *inst;
|
||||
unsigned int i;
|
||||
ULONG size;
|
||||
|
||||
FIXME( "handle %p, guid %s, name %s, id %u semi-stub.\n", handle, debugstr_guid(guid), debugstr_w(name), id );
|
||||
|
||||
if (!prov || !guid || !name)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < prov->counterset_count; ++i)
|
||||
if (IsEqualGUID(guid, &prov->countersets[i]->counterset.CounterSetGuid)) break;
|
||||
|
||||
if (i == prov->counterset_count)
|
||||
{
|
||||
SetLastError( ERROR_NOT_FOUND );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template = prov->countersets[i];
|
||||
|
||||
LIST_FOR_EACH_ENTRY(inst, &prov->instance_list, struct counterset_instance, entry)
|
||||
{
|
||||
if (inst->template == template && inst->instance.InstanceId == id)
|
||||
{
|
||||
SetLastError( ERROR_ALREADY_EXISTS );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
size = (sizeof(PERF_COUNTERSET_INSTANCE) + template->counterset.NumCounters * sizeof(UINT64)
|
||||
+ (lstrlenW( name ) + 1) * sizeof(WCHAR) + 7) & ~7;
|
||||
inst = heap_alloc_zero( offsetof(struct counterset_instance, instance) + size );
|
||||
if (!inst)
|
||||
{
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inst->template = template;
|
||||
inst->instance.CounterSetGuid = *guid;
|
||||
inst->instance.dwSize = size;
|
||||
inst->instance.InstanceId = id;
|
||||
inst->instance.InstanceNameOffset = sizeof(PERF_COUNTERSET_INSTANCE)
|
||||
+ template->counterset.NumCounters * sizeof(UINT64);
|
||||
inst->instance.InstanceNameSize = (lstrlenW( name ) + 1) * sizeof(WCHAR);
|
||||
memcpy( (BYTE *)&inst->instance + inst->instance.InstanceNameOffset, name, inst->instance.InstanceNameSize );
|
||||
list_add_tail( &prov->instance_list, &inst->entry );
|
||||
|
||||
return &inst->instance;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* PerfDeleteInstance (KERNELBASE.@)
|
||||
*/
|
||||
ULONG WINAPI PerfDeleteInstance(HANDLE provider, PPERF_COUNTERSET_INSTANCE block)
|
||||
ULONG WINAPI PerfDeleteInstance(HANDLE provider, PERF_COUNTERSET_INSTANCE *block)
|
||||
{
|
||||
FIXME("%p %p: stub\n", provider, block);
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
struct perf_provider *prov = perf_provider_from_handle( provider );
|
||||
struct counterset_instance *inst;
|
||||
|
||||
TRACE( "provider %p, block %p.\n", provider, block );
|
||||
|
||||
if (!prov || !block) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
inst = CONTAINING_RECORD(block, struct counterset_instance, instance);
|
||||
list_remove( &inst->entry );
|
||||
heap_free( inst );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -229,6 +301,8 @@ ULONG WINAPI PerfSetCounterSetInfo( HANDLE handle, PERF_COUNTERSET_INFO *templat
|
|||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
memcpy( new, template, size );
|
||||
for (i = 0; i < template->NumCounters; ++i)
|
||||
new->counter[i].Offset = i * sizeof(UINT64);
|
||||
new_array[prov->counterset_count++] = new;
|
||||
prov->countersets = new_array;
|
||||
|
||||
|
@ -273,7 +347,11 @@ ULONG WINAPI PerfStartProviderEx( GUID *guid, PERF_PROVIDER_CONTEXT *context, HA
|
|||
if (!guid || !context || !provider) return ERROR_INVALID_PARAMETER;
|
||||
if (context->ContextSize < sizeof(*context)) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (context->MemAllocRoutine || context->MemFreeRoutine)
|
||||
FIXME("Memory allocation routine is not supported.\n");
|
||||
|
||||
if (!(prov = heap_alloc_zero( sizeof(*prov) ))) return ERROR_OUTOFMEMORY;
|
||||
list_init( &prov->instance_list );
|
||||
memcpy( &prov->guid, guid, sizeof(prov->guid) );
|
||||
prov->callback = context->ControlCallback;
|
||||
*provider = prov;
|
||||
|
@ -287,10 +365,20 @@ ULONG WINAPI PerfStartProviderEx( GUID *guid, PERF_PROVIDER_CONTEXT *context, HA
|
|||
ULONG WINAPI PerfStopProvider(HANDLE handle)
|
||||
{
|
||||
struct perf_provider *prov = perf_provider_from_handle( handle );
|
||||
struct counterset_instance *inst, *next;
|
||||
unsigned int i;
|
||||
|
||||
TRACE( "handle %p.\n", handle );
|
||||
|
||||
if (!list_empty( &prov->instance_list ))
|
||||
WARN( "Stopping provider with active counter instances.\n" );
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(inst, next, &prov->instance_list, struct counterset_instance, entry)
|
||||
{
|
||||
list_remove( &inst->entry );
|
||||
heap_free( inst );
|
||||
}
|
||||
|
||||
for (i = 0; i < prov->counterset_count; ++i)
|
||||
heap_free( prov->countersets[i] );
|
||||
heap_free( prov->countersets );
|
||||
|
|
|
@ -81,6 +81,9 @@ typedef struct _PROVIDER_CONTEXT {
|
|||
LPVOID pMemContext;
|
||||
} PERF_PROVIDER_CONTEXT, * PPERF_PROVIDER_CONTEXT;
|
||||
|
||||
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 PerfSetCounterSetInfo(HANDLE, PERF_COUNTERSET_INFO *, ULONG);
|
||||
ULONG WINAPI PerfStartProvider(GUID *, PERFLIBREQUEST, HANDLE *);
|
||||
ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *);
|
||||
|
|
Loading…
Reference in New Issue