EnumerateTraceGuids returns "The parameter is invalid" (87)

I am trying to call the Windows API EnumerateTraceGuids function:

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

Starting with the sample code 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 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 ERROR_INVALID_PARAMETER will ERROR_INVALID_PARAMETER :

ERROR_INVALID_PARAMETER

One of the following statements is true:

  • PropertyArrayCount property is zero
  • GuidPropertiesArray - NULL

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

+4
source share
1 answer

As far as I can see, your code should be identical to the MSDN sample. However, as Code says, the MSDN pattern looks a bit scared. Indeed, it seems to me that the MSDN sample only works by chance.

Note that the comment in this code that reads:

 // 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 one pointer. However, the value contained in pProviders does matter. It cannot be NULL . In Delphi code, you actually nullify that memory twice. Once with AllocMem and once with ZeroMemory . If you simply modify the Delphi code so that the content of the providers non-zero, then the Delphi code will start working.

Here is a very simple project that accurately illustrates what is happening:

 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 this explains the problem, but I would solve it more fully. I will move on to the next step of your work and declare EnumerateTraceGuids completely using real Delphi equivalent to the TRACE_GUID_PROPERTIES structure.

I would probably write code 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. 

Instead of trying to be too cute in GetRegisteredProviderCount , I passed a pointer to the real TRACE_GUID_PROPERTIES .

+2
source

Source: https://habr.com/ru/post/1396337/


All Articles