4

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 です

最初のケースは真です。私の 2 番目のパラメーターPropertyArrayCount ゼロです。サンプルがそうあるべきだと言っているように。

4

1 に答える 1

3

私が見る限り、あなたのコードは MSDN のサンプルと同じはずです。ただし、Code が示すように、MSDN のサンプルは少し風変わりに見えます。実際、MSDN のサンプルが機能しているのは偶然にすぎないように思えます。

そのコードのコメントに次のように記載されていることに注意してください。

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

pProviders次に、1 つのポインターを格納するための領域を割り当てます。ただし、pProviders実際には含まれる値が重要です。することはできませんNULL。Delphi コードでは、実際にそのメモリを 2 回ゼロ化します。で一度AllocMem、一度でZeroMemory。Delphi コードを変更して 0 以外の内容を作成すると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

于 2012-02-14T07:42:43.447 に答える