Насколько я вижу, ваш код должен быть идентичен образцу MSDN. Однако, как говорит Code, образец MSDN выглядит немного странно. Действительно, мне кажется, что образец MSDN работает только случайно.
Обратите внимание, что комментарий в этом коде гласит:
// EnumerateTraceGuids requires a valid pointer. Create a dummy
// allocation, so that you can get the actual allocation size.
Затем он выделяет пространство в pProviders
для хранения одного указателя. Однако значение, содержащееся в pProviders
, действительно имеет значение. Это не может быть NULL
. В вашем Delphi-коде вы фактически обнуляете эту память дважды. Один раз с AllocMem
и один раз с ZeroMemory
. Если вы просто измените код Delphi, чтобы содержимое providers
отличалось от нуля, код Delphi начнет работать.
Вот очень простой проект, который точно иллюстрирует, что происходит:
program _EnumerateTraceGuidsFaultDemo;
{$APPTYPE CONSOLE}
function EnumerateTraceGuids(
GuidPropertiesArray: Pointer;
PropertyArrayCount: Cardinal;
var GuidCount: Cardinal): Cardinal; stdcall; external 'advapi32.dll';
var
providers: Pointer;
providerCount: LongWord;
registeredProviderCount: LongWord;
res: LongWord;
begin
providerCount := 0;
registeredProviderCount := 0;
providers := AllocMem(SizeOf(Pointer));//zeroises memory
res := EnumerateTraceGuids(providers, providerCount, registeredProviderCount);
Writeln(res);//outputs 87
PInteger(providers)^ := 1;
res := EnumerateTraceGuids(providers, providerCount, registeredProviderCount);
Writeln(res);//outputs 234
Readln;
end.
Так что я думаю, что это объясняет проблему, но я бы на самом деле решил ее более полно, чем это. Я хотел бы перейти к следующему этапу вашей работы и объявить EnumerateTraceGuids
полностью, используя реальный Delphi, эквивалентный TRACE_GUID_PROPERTIES
struct.
Я бы, наверное, написал код примерно так:
program _EnumerateTraceGuids;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, Windows;
type
PTraceGuidProperties = ^TTraceGuidProperties;
TTraceGuidProperties = record
Guid: TGUID;
GuidType: ULONG;
LoggerId: ULONG;
EnableLevel: ULONG;
EnableFlags: ULONG;
IsEnable: Boolean;
end;
function EnumerateTraceGuids(
var GuidPropertiesArray: PTraceGuidProperties;
PropertyArrayCount: ULONG;
var GuidCount: ULONG
): ULONG; stdcall; external 'advapi32.dll';
function GetRegisteredProviderCount: ULONG;
var
provider: TTraceGuidProperties;
pprovider: PTraceGuidProperties;
providerCount: LongWord;
registeredProviderCount: ULONG;
res: ULONG;
begin
providerCount := 0;
pprovider := @provider;
res := EnumerateTraceGuids(pprovider, providerCount, registeredProviderCount);
if (res<>ERROR_MORE_DATA) and (res<>ERROR_SUCCESS) then
RaiseLastOSError;
Result := registeredProviderCount;
end;
var
i: Integer;
provider: TTraceGuidProperties;
pprovider: PTraceGuidProperties;
providers: array of TTraceGuidProperties;
pproviders: array of PTraceGuidProperties;
providerCount: ULONG;
registeredProviderCount: ULONG;
res: ULONG;
begin
providerCount := GetRegisteredProviderCount;
SetLength(providers, providerCount);
SetLength(pproviders, providerCount);
for i := 0 to providerCount-1 do
pproviders[i] := @providers[i];
res := EnumerateTraceGuids(pproviders[0], providerCount, registeredProviderCount);
if res<>ERROR_SUCCESS then
RaiseLastOSError;
//do stuff with providers
end.
Вместо того, чтобы пытаться быть слишком милым в GetRegisteredProviderCount
, я передал указатель на настоящий TRACE_GUID_PROPERTIES
.