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
|
static struct
|
||||||
{
|
{
|
||||||
PERF_COUNTERSET_INFO counterset;
|
PERF_COUNTERSET_INFO counterset;
|
||||||
PERF_COUNTER_INFO counter;
|
PERF_COUNTER_INFO counter[2];
|
||||||
}
|
}
|
||||||
pc_template =
|
pc_template =
|
||||||
{
|
{
|
||||||
{{0}},
|
{{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;
|
PERF_PROVIDER_CONTEXT prov_context;
|
||||||
|
UINT64 counter1, counter2;
|
||||||
HANDLE prov, prov2;
|
HANDLE prov, prov2;
|
||||||
ULONG ret;
|
ULONG ret, size;
|
||||||
BOOL bret;
|
BOOL bret;
|
||||||
|
|
||||||
prov = (HANDLE)0xdeadbeef;
|
prov = (HANDLE)0xdeadbeef;
|
||||||
|
@ -99,7 +106,7 @@ void test_provider_init(void)
|
||||||
|
|
||||||
pc_template.counterset.CounterSetGuid = test_set_guid;
|
pc_template.counterset.CounterSetGuid = test_set_guid;
|
||||||
pc_template.counterset.ProviderGuid = test_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;
|
pc_template.counterset.InstanceType = PERF_COUNTERSET_SINGLE_INSTANCE;
|
||||||
ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
|
ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
|
||||||
ok(!ret, "Got unexpected ret %u.\n", ret);
|
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));
|
ret = PerfSetCounterSetInfo(prov, &pc_template.counterset, sizeof(pc_template));
|
||||||
ok(ret == ERROR_ALREADY_EXISTS, "Got unexpected ret %u.\n", ret);
|
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);
|
ret = PerfStopProvider(prov);
|
||||||
ok(!ret, "Got unexpected ret %u.\n", ret);
|
ok(!ret, "Got unexpected ret %u.\n", ret);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "kernelbase.h"
|
#include "kernelbase.h"
|
||||||
#include "wine/heap.h"
|
#include "wine/heap.h"
|
||||||
|
#include "wine/list.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(kernelbase);
|
WINE_DEFAULT_DEBUG_CHANNEL(kernelbase);
|
||||||
|
|
||||||
|
@ -160,12 +161,21 @@ struct counterset_template
|
||||||
PERF_COUNTER_INFO counter[1];
|
PERF_COUNTER_INFO counter[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct counterset_instance
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
struct counterset_template *template;
|
||||||
|
PERF_COUNTERSET_INSTANCE instance;
|
||||||
|
};
|
||||||
|
|
||||||
struct perf_provider
|
struct perf_provider
|
||||||
{
|
{
|
||||||
GUID guid;
|
GUID guid;
|
||||||
PERFLIBREQUEST callback;
|
PERFLIBREQUEST callback;
|
||||||
struct counterset_template **countersets;
|
struct counterset_template **countersets;
|
||||||
unsigned int counterset_count;
|
unsigned int counterset_count;
|
||||||
|
|
||||||
|
struct list instance_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct perf_provider *perf_provider_from_handle(HANDLE prov)
|
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.@)
|
* PerfCreateInstance (KERNELBASE.@)
|
||||||
*/
|
*/
|
||||||
PPERF_COUNTERSET_INSTANCE WINAPI PerfCreateInstance(HANDLE handle, LPCGUID guid,
|
PERF_COUNTERSET_INSTANCE WINAPI *PerfCreateInstance( HANDLE handle, const GUID *guid,
|
||||||
const WCHAR *name, ULONG id)
|
const WCHAR *name, ULONG id )
|
||||||
{
|
{
|
||||||
FIXME("%p %s %s %u: stub\n", handle, debugstr_guid(guid), debugstr_w(name), id);
|
struct perf_provider *prov = perf_provider_from_handle( handle );
|
||||||
return NULL;
|
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.@)
|
* 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);
|
struct perf_provider *prov = perf_provider_from_handle( provider );
|
||||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
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;
|
return ERROR_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
memcpy( new, template, size );
|
memcpy( new, template, size );
|
||||||
|
for (i = 0; i < template->NumCounters; ++i)
|
||||||
|
new->counter[i].Offset = i * sizeof(UINT64);
|
||||||
new_array[prov->counterset_count++] = new;
|
new_array[prov->counterset_count++] = new;
|
||||||
prov->countersets = new_array;
|
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 (!guid || !context || !provider) return ERROR_INVALID_PARAMETER;
|
||||||
if (context->ContextSize < sizeof(*context)) 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;
|
if (!(prov = heap_alloc_zero( sizeof(*prov) ))) return ERROR_OUTOFMEMORY;
|
||||||
|
list_init( &prov->instance_list );
|
||||||
memcpy( &prov->guid, guid, sizeof(prov->guid) );
|
memcpy( &prov->guid, guid, sizeof(prov->guid) );
|
||||||
prov->callback = context->ControlCallback;
|
prov->callback = context->ControlCallback;
|
||||||
*provider = prov;
|
*provider = prov;
|
||||||
|
@ -287,10 +365,20 @@ ULONG WINAPI PerfStartProviderEx( GUID *guid, PERF_PROVIDER_CONTEXT *context, HA
|
||||||
ULONG WINAPI PerfStopProvider(HANDLE handle)
|
ULONG WINAPI PerfStopProvider(HANDLE handle)
|
||||||
{
|
{
|
||||||
struct perf_provider *prov = perf_provider_from_handle( handle );
|
struct perf_provider *prov = perf_provider_from_handle( handle );
|
||||||
|
struct counterset_instance *inst, *next;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
TRACE( "handle %p.\n", handle );
|
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)
|
for (i = 0; i < prov->counterset_count; ++i)
|
||||||
heap_free( prov->countersets[i] );
|
heap_free( prov->countersets[i] );
|
||||||
heap_free( prov->countersets );
|
heap_free( prov->countersets );
|
||||||
|
|
|
@ -81,6 +81,9 @@ typedef struct _PROVIDER_CONTEXT {
|
||||||
LPVOID pMemContext;
|
LPVOID pMemContext;
|
||||||
} PERF_PROVIDER_CONTEXT, * PPERF_PROVIDER_CONTEXT;
|
} 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 PerfSetCounterSetInfo(HANDLE, PERF_COUNTERSET_INFO *, ULONG);
|
||||||
ULONG WINAPI PerfStartProvider(GUID *, PERFLIBREQUEST, HANDLE *);
|
ULONG WINAPI PerfStartProvider(GUID *, PERFLIBREQUEST, HANDLE *);
|
||||||
ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *);
|
ULONG WINAPI PerfStartProviderEx(GUID *, PERF_PROVIDER_CONTEXT *, HANDLE *);
|
||||||
|
|
Loading…
Reference in New Issue