4

Background:

Translating the IP_OPTION_INFORMATION32 and ICMP_ECHO_REPLY32 structures for 64-bit compiler I got stucked with data types to use there. Structure definitions from the reference:

The IP_OPTION_INFORMATION32 structure:

typedef struct _IP_OPTION_INFORMATION32 {
  UCHAR              Ttl;
  UCHAR              Tos;
  UCHAR              Flags;
  UCHAR              OptionsSize;
  UCHAR * POINTER_32 OptionsData;
} IP_OPTION_INFORMATION32, *PIP_OPTION_INFORMATION32;

I would translate this way (for Delphi XE2, 64-bit target platform). As you can see, I don't know what type to use for the OptionsData field of the structure:

IP_OPTION_INFORMATION32 = record
  Ttl: UCHAR;
  Tos: UCHAR;
  Flags: UCHAR;
  OptionsSize: UCHAR;
  OptionsData:       // what should I use here for UCHAR * POINTER_32 ?
end;

ICMP_ECHO_REPLY32 structure:

typedef struct icmp_echo_reply32 {
  IPAddr                         Address;
  ULONG                          Status;
  ULONG                          RoundTripTime;
  USHORT                         DataSize;
  USHORT                         Reserved;
  VOID * POINTER_32              Data;
  struct ip_option_information32  Options;
} ICMP_ECHO_REPLY32, *PICMP_ECHO_REPLY32;

For Delphi XE2 64-bit target platform I would write:

ICMP_ECHO_REPLY32 = record
  Address: TIPAddr;  // defined before
  Status: ULONG;
  RoundTripTime: ULONG;
  DataSize: USHORT;
  Reserved: USHORT;
  Data:              // what should I use here for VOID * POINTER_32 ?
  Options: IP_OPTION_INFORMATION32;
end;

Question:

How would you define the UCHAR * POINTER_32 and VOID * POINTER_32 types in Delphi for 64-bit platform target ? As far as I know, there is no 32-bit pointer type available for 64-bit platform target and I just don't like it to be defined e.g. as a Int32 type :-)

What is the most precise translation for the mentioned types ?

TLama
  • 75,147
  • 17
  • 214
  • 392

2 Answers2

4

The issue of what POINTER_32 is covered in another Stack Overflow question: POINTER_32 - what is it, and why?

You would use it when performing interop with structs that are defined in a different process, one that has 32 bit pointers.

You don't have the equivalent of __ptr32 in Delphi so you have simply no choice other than to declare it as a 32 bit integer. I would use an unsigned type.

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks! I've tried to use `Cardinal` for that field, but either I've translated the structures wrong or MS have incorrect documentation for them. My testing [`project is here`](https://code.google.com/p/projects-stackoverflow-tlama/source/browse/#svn%2Ftrunk%2F17084031) if someone would like to play with. For 64-bit platform target the function call succeeded [`only if I used`](https://code.google.com/p/projects-stackoverflow-tlama/source/browse/trunk/17084031/PingUnit.pas#32) `Pointer` for the `POINTER_32` data type. Quite strange... – TLama Jul 11 '13 at 11:51
  • And yes, I have tried even to send some data as a request (the `RequestData` parameter), but it's the same. The `IcmpSendEcho` function call just fails with the error 87 (`ERROR_INVALID_PARAMETER`) unless I defined the `POINTER_32` data type as `Pointer`, which is against original `POINTER_32` definition. – TLama Jul 11 '13 at 11:56
  • @TLama I don't know what the problem is with your program, but my answer is clearly accurate as demonstrated by this simple program: http://pastebin.com/e7hGhtuf – David Heffernan Jul 11 '13 at 12:15
  • The problem was that I was assuming that field to be a 32-bit pointer, but it's actually a pointer to a 32-bit pointer, isn't it ? So although your post is correct, the answer to my question (how to define `UCHAR * POINTER_32` and `VOID * POINTER_32` types in Delphi for 64-bit platform target) is actually just a `Pointer` or am I wrong ? – TLama Jul 11 '13 at 12:54
  • No, when you target 64 bit, the `POINTER_32` macro evaluates to `__ptr32`. And `UCHAR * __ptr32` is a 32 bit pointer to `UCHAR`. – David Heffernan Jul 11 '13 at 12:56
0

In this case UInt32 (or Cardinal, DWORD etc - anything unsigned 32 bit) would be fine. All you need to do is to declare unsigned 32 bit at proper position of structure (record). CPU would not care, compiler would not care (you can typecast to pointer if needed) is it actually a pointer or not. Even signed 32 bit would work unless you would do some math with value and processor's flags checking. And another thing in structure translations from C to Delphi: be sure that original alignment was 4 bytes (32 bit per item), because record unlike packed record (no alignment) by default using same 4 bytes alignment. Else you can have issues by applying your records to data like

type
  Picmp_echo_reply32 = ^icmp_echo_reply32;
...
  data_size := Picmp_echo_reply32(@mybuf[some_offset]).DataSize;

or

var
  icmp_echo: Picmp_echo_reply32;
...
  icmp_echo := @buf[offset];
  reserved := icmp_echo.Reserved;
user2091150
  • 978
  • 12
  • 25