我正在尝试调用Windows API函数EnumerateTraceGuids:
ULONG EnumerateTraceGuids(
__inout PTRACE_GUID_PROPERTIES *GuidPropertiesArray,
__in ULONG PropertyArrayCount,
__out PULONG GuidCount
);
从代码示例on MSDN开始:
ULONG status = ERROR_SUCCESS;
PTRACE_GUID_PROPERTIES *pProviders = NULL;
ULONG RegisteredProviderCount = 0;
ULONG ProviderCount = 0;
pProviders = (PTRACE_GUID_PROPERTIES *) malloc(sizeof(PTRACE_GUID_PROPERTIES));
status = EnumerateTraceGuids(pProviders, ProviderCount, &RegisteredProviderCount);
我将代码转换为Delphi:
var
providers: PPointerList;
providerCount: LongWord;
registeredProviderCount: LongWord;
res: LongWord;
begin
providerCount := 0;
registeredProviderCount := 0;
providers := AllocMem(SizeOf(Pointer));
ZeroMemory(providers, SizeOf(Pointer));
res := EnumerateTraceGuids(providers, providerCount, {out}registeredProviderCount);
end;
使用api电话:
function EnumerateTraceGuids(
GuidPropertiesArray: Pointer;
PropertyArrayCount: Cardinal;
var GuidCount: Cardinal): Cardinal; stdcall; external 'advapi32.dll';
我得到结果代码ERROR_INVALID_PARAMETER
(87,参数不正确)。
我做错了什么?
MSDN描述了导致ERROR_INVALID_PARAMETER
:
ERROR_INVALID_PARAMETER
以下其中一项是正确的:
- PropertyArrayCount为零
- GuidPropertiesArray为NULL
第一种情况属实,我的第二个参数PropertyArrayCount
为零 - 正如样本所说的那样。
答案 0 :(得分:3)
据我所知,您的代码应该与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
。
我可能会编写类似这样的代码:
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
的指针。