EnumerateTraceGuids 返回“参数不正确” (87)

发布于 2025-01-05 16:51:20 字数 1863 浏览 1 评论 0原文

我正在尝试调用 Windows API 函数 EnumerateTraceGuids

ULONG EnumerateTraceGuids(
  __inout  PTRACE_GUID_PROPERTIES *GuidPropertiesArray,
  __in     ULONG PropertyArrayCount,
  __out    PULONG GuidCount
);

从代码示例开始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 为零 - 就像样本说应该是这样。

i am trying to call the Windows API function EnumerateTraceGuids:

ULONG EnumerateTraceGuids(
  __inout  PTRACE_GUID_PROPERTIES *GuidPropertiesArray,
  __in     ULONG PropertyArrayCount,
  __out    PULONG GuidCount
);

Starting from the code sample 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);

i convert the code to 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;

with the api call:

function EnumerateTraceGuids(
      GuidPropertiesArray: Pointer; 
      PropertyArrayCount: Cardinal; 
      var GuidCount: Cardinal): Cardinal; stdcall; external 'advapi32.dll';

i get the result code ERROR_INVALID_PARAMETER (87, The parameter is incorrect).

What am i doing wrong?


MSDN describes what would cause ERROR_INVALID_PARAMETER:

ERROR_INVALID_PARAMETER

One of the following is true:

  • PropertyArrayCount is zero
  • GuidPropertiesArray is NULL

The first case is true, my 2nd parameter PropertyArrayCount is zero - just like the sample says it should be.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

反目相谮 2025-01-12 16:51:20

据我所知,您的代码应该与 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.

所以我认为这解释了问题,但实际上我会比这更彻底地解决它。我将继续您工作的下一步,并完全使用与 TRACE_GUID_PROPERTIES 结构等效的真实 Delphi 来声明 EnumerateTraceGuids

我可能会编写这样的代码:

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 的指针。

So far as I can see, your code should be identical to the MSDN sample. However, as Code says, the MSDN sample does look a bit funky. Indeed, it seems to me that the MSDN sample is only working by chance.

Note that comment in that code that states:

// EnumerateTraceGuids requires a valid pointer. Create a dummy
// allocation, so that you can get the actual allocation size.

Then it allocates space in pProviders to store a single pointer. However, the value contained in pProviders actually matters. It cannot be NULL. In your Delphi code you zeroise that memory twice in fact. Once with AllocMem and once with ZeroMemory. If you just change your Delphi code to make the contents of providers non-zero then the Delphi code will start working.

Here is a very simple project that illustrates exactly what is going on:

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.

So I think that explains the problem, but I'd actually solve it more completely than that. I would move on to the next step of your work and declare EnumerateTraceGuids fully using a real Delphi equivalent to the TRACE_GUID_PROPERTIES struct.

I'd probably write the code something like this:

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.

Rather than trying to be too cute in GetRegisteredProviderCount, I have passed a pointer to a real TRACE_GUID_PROPERTIES.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文