views:

490

answers:

9

Hi,

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

+1  A: 

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

A: 

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

avar
Thanks, although most of the functions related to this one are readily available in, among other places, the JEDI Windows API headers project. Just not this one unfortunately. ;-)
Conor Boyd
+1  A: 

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.

DR
+1  A: 

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;
Lawrence Barsanti
+1  A: 

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

Rob Kennedy
A: 

The ZoneIndices array should be defined like this:

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

ScopeLevelCount is a constant that is 16

Christer Fahlgren
A: 

Thanks for all the suggestions. If I get it successfully converted, I'll post it back here for posterity.

Conor Boyd
A: 

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.

Marco van de Voort