Conor Boyd
Conor Boyd

Reputation: 1034

Translating Vista WinAPI C++ header for Delphi - any suggestions?

I'm needing to call a Windows API function introduced in Vista from my Delphi app, but I don't have any Delphi headers which describe the function.

Related functions are already documented in the JEDI Windows API library, but not this function.

My C++ is almost non-existent, and I'm struggling to work out the Delphi definitions that correspond to the function and it's parameter as documented on MSDN.

From http://msdn.microsoft.com/en-us/library/aa814417.aspx

NETIOAPI_API GetIpInterfaceEntry(__inout  PMIB_IPINTERFACE_ROW Row);

typedef struct _MIB_IPINTERFACE_ROW {
  ADDRESS_FAMILY                 Family;
  NET_LUID                       InterfaceLuid;
  NET_IFINDEX                    InterfaceIndex;
  ULONG                          MaxReassemblySize;
  ULONG64                        InterfaceIdentifier;
  ULONG                          MinRouterAdvertisementInterval;
  ULONG                          MaxRouterAdvertisementInterval;
  BOOLEAN                        AdvertisingEnabled;
  BOOLEAN                        ForwardingEnabled;
  BOOLEAN                        WeakHostSend;
  BOOLEAN                        WeakHostReceive;
  BOOLEAN                        UseAutomaticMetric;
  BOOLEAN                        UseNeighborUnreachabilityDetection;
  BOOLEAN                        ManagedAddressConfigurationSupported;
  BOOLEAN                        OtherStatefulConfigurationSupported;
  BOOLEAN                        AdvertiseDefaultRoute;
  NL_ROUTER_DISCOVERY_BEHAVIOR   RouterDiscoveryBehavior;
  ULONG                          DadTransmits;
  ULONG                          BaseReachableTime;
  ULONG                          RetransmitTime;
  ULONG                          PathMtuDiscoveryTimeout;
  NL_LINK_LOCAL_ADDRESS_BEHAVIOR LinkLocalAddressBehavior;
  ULONG                          LinkLocalAddressTimeout;
  ULONG                          ZoneIndices[ScopeLevelCount];
  ULONG                          SitePrefixLength;
  ULONG                          Metric;
  ULONG                          NlMtu;
  BOOLEAN                        Connected;
  BOOLEAN                        SupportsWakeUpPatterns;
  BOOLEAN                        SupportsNeighborDiscovery;
  BOOLEAN                        SupportsRouterDiscovery;
  ULONG                          ReachableTime;
  NL_INTERFACE_OFFLOAD_ROD       TransmitOffload;
  NL_INTERFACE_OFFLOAD_ROD       ReceiveOffload;
  BOOLEAN                        DisableDefaultRoutes;
}MIB_IPINTERFACE_ROW, *PMIB_IPINTERFACE_ROW;

Among other bits, the bit I'm struggling with at the minute is the ZoneIndices[ScopeLevelCount] field; I can't work out what size the array is supposed to be.

This is what I've defined so far, although I haven't worked out the enums in the original C++ definition yet. I'll be explicitly loading the Windows DLL on Vista and getting the address of the new function to call.

type
  PMIB_IPINTERFACE_ROW = ^MIB_IPINTERFACE_ROW;
  {$EXTERNALSYM PMIB_IPINTERFACE_ROW}
  _MIB_IPINTERFACE_ROW = record
    Family: ADDRESS_FAMILY;
    InterfaceLuid: NET_LUID;
    InterfaceIndex: NET_IFINDEX;
    MaxReassemblySize,
    InterfaceIdentifier,
    MinRouterAdvertisementInterval,
    MaxRouterAdvertisementInterval: Cardinal;
    AdvertisingEnabled,
    ForwardingEnabled,
    WeakHostSend,
    WeakHostReceive,
    UseAutomaticMetric,
    UseNeighborUnreachabilityDetection,
    ManagedAddressConfigurationSupported,
    OtherStatefulConfigurationSupported,
    AdvertiseDefaultRoute: LongBool;
    RouterDiscoveryBehavior: NL_ROUTER_DISCOVERY_BEHAVIOR;
    DadTransmits,
    BaseReachableTime,
    RetransmitTime,
    PathMtuDiscoveryTimeout: Cardinal;
    LinkLocalAddressBehavior: NL_LINK_LOCAL_ADDRESS_BEHAVIOR;
    LinkLocalAddressTimeout,
    ZoneIndices[ScopeLevelCount],
    SitePrefixLength,
    Metric,
    NlMtu: Cardinal;
    Connected,
    SupportsWakeUpPatterns,
    SupportsNeighborDiscovery,
    SupportsRouterDiscovery: LongBool;
    ReachableTime: Cardinal;
    TransmitOffload: NL_INTERFACE_OFFLOAD_ROD;
    ReceiveOffload: NL_INTERFACE_OFFLOAD_ROD;
    DisableDefaultRoutes: LongBool;
  end;
  {$EXTERNALSYM _MIB_IPINTERFACE_ROW}
  MIB_IPINTERFACE_ROW = _MIB_IPINTERFACE_ROW;
  {$EXTERNALSYM MIB_IPINTERFACE_ROW}
  TMibIpInterfaceRow = MIB_IPINTERFACE_ROW;
  PMibIpInterfaceRow = PMIB_IPINTERFACE_ROW;

const
  iphlpapilib = 'iphlpapi.dll';

var
  HIpHlpApi: THandle = 0;
  GetIpInterfaceEntry: function(const pArpEntry: MIB_IPINTERFACE_ROW): LongInt; stdcall;
  {$EXTERNALSYM GetIpInterfaceEntry}

Does anybody out there have suggestions or tips/tricks for translating a function definition like this?

Many thanks,

Conor

Upvotes: 3

Views: 1388

Answers (8)

Marco van de Voort
Marco van de Voort

Reputation: 26376

I don't see any field of type ULONG64 in the translation, but I do in the original.

Further, FPC also has an header converter which works fine for structs. Typically windows api structures are packed.

In doubt, use some free msvc product to write the sizeof(structure) and do the same under pascal. If that matches, and you still have doubts, calculate field offsets with a bit of pointer magic and compare them.

Upvotes: 0

Daniel Rikowski
Daniel Rikowski

Reputation: 72514

I often used Dr. Bob's Header Converter for this task, but mostly I took the long and tedious way of manually performing the conversion, because it helped me to understand the API better. (Because I was going to use it and I have to familiarize myself with it anyway)

Also see this article: http://www.delphi-jedi.org/api-howto.html

In general it's best not to put to much hopes on a header conversion tool, because C++ is a very powerful and complex language. Most conversion tools I tested only supported a subset of C++ and its preprocessor, thus making it necessary to manually make fixes to the generated source.

Upvotes: 1

Christer Fahlgren
Christer Fahlgren

Reputation: 2474

The ZoneIndices array should be defined like this:

ZoneIndices : array [0..ScopeLevelCount - 1] of Cardinal;

ScopeLevelCount is a constant that is 16

Upvotes: 1

Rob Kennedy
Rob Kennedy

Reputation: 163317

The Win32 BOOLEAN type is one byte, but Delphi's LongBool type is four. Use Delphi's ByteBool instead.

Upvotes: 2

Lawrence Barsanti
Lawrence Barsanti

Reputation: 33302

Make sure you use the packed command when defining your record because Delphi aligns complex data types on 2, 4 or 8 byte boundaries by default.

TExample = record 
 f1: Integer;   // start at offset 0x00
 f2: Char;      // start at offset 0x04 
 f3: Integer;   // start at offset 0x06 or 0x08 depending on alignment
end;

TExample = packed record // this is what c++ would do
 f1: Integer;   // start at offset 0x00
 f2: Char;      // start at offset 0x04 
 f3: Integer;   // start at offset 0x05
end;

Upvotes: 1

Matra
Matra

Reputation:

Hmm. A strange structore. But if you look into w2def.h, you can see that ScopeLevelCount=16. So your array should have 16 elements,

Upvotes: 1

avar
avar

Reputation: 1180

you can investigate some already translated APIs/structures that related to this subject and convert it yourself. for example this one

Upvotes: 0

Related Questions