views:

139

answers:

4

Hi, can somebody tell me where I am making mistake in the converting:

C:

typedef struct _REGISTRY_EVENT {
    REG_NOTIFY_CLASS eventType;
    TIME_FIELDS time;
    HANDLE processId;
    ULONG dataType;
    ULONG dataLengthB;
    ULONG registryPathLengthB;
    /* Contains path and optionally data */
    UCHAR registryData[];
} REGISTRY_EVENT, * PREGISTRY_EVENT;

Delphi:

_Registry_Event = record
    EventType: REG_NOTIFY_CLASS;
    Time: TIME_FIELDS;
    processID: THandle;
    DataType: ULONG;
    DataLength: ULONG;
    registryPathLength: ULONG;
    registryData: array of UCHAR;
end;

from the c code sizeof(REGISTRY_EVENT) = 36

from the delphi code sizeof(REGISTRY_EVENT) = 40

Thanks in advance

Bojan

+2  A: 

I'm not sure it's a mistake -- it may well be the compiler inserting some padding between fields. Try adding {$Align off} before the record definition, or change = Record to = Packed Record and see if that helps.

Edit: while this may also be a problem, @Serg's answer strikes me as a lot more likely.

Jerry Coffin
And {$Align off} and packed record makes wrong result.with record, for Time I am receiving year = 0, month = 2010, day = 7, hour = 31, minute = 22 etc. But Event type and process ID are correct.
bojan gavrilovic
That is structure returned from the kernel driver for registry monitoring. In the registryData are stored registry path, data etc, and with dataLength, registryPathLengthB define the bytes used in the registrydata.
bojan gavrilovic
in c code for reading this isUINT offset = 0;do {/* e->registryData contains the registry path first and then optionally some data */PREGISTRY_EVENT e = (PREGISTRY_EVENT)(registryEventsBuffer + offset);BYTE* registryData = NULL;wchar_t* szRegistryPath = NULL;szRegistryPath = (wchar_t*)malloc(e->registryPathLengthB);CopyMemory(szRegistryPath, e->registryData, e->registryPathLengthB);...offset += sizeof(REGISTRY_EVENT) + e->registryPathLengthB + e->dataLengthB;when I decrease in delphi the previous line for 4 I am receiving chain of the events.
bojan gavrilovic
But, in copyMemory always have mistake
bojan gavrilovic
A: 

This is probably due to either different sizes of the data types of each field, or due to different padding. For the field sizes, print the sizeof() or size() for each and compare. If they are all the same, then it's padding, and you may need to find a compiler option to adjust that.

That is, if you care. Why do you care if the sizes are the same?

Lars Wirzenius
At a guess, he cares because this structure will be returned by the operating system, and the size being wrong means some of his fields won't coincide with what the OS is sending.
Jerry Coffin
+7  A: 

The error is here

registryData: array of UCHAR;

You don't need a dynamic array here.


Updated:

I assume that

UCHAR registryData[];

is a C hack to create a zero-length field at the end of structure. An equivalent Delphi hack is

registryData: record end;

to access this dummy field as an array in Delphi, you should typecast:

type
  PByteArr = ^TByteArr;
  TByteArr = array[0..$FFFF] of Byte;

  PRec = ^TRec;
  TRec = packed record
    Data: Integer;
    MoreData: record end;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  P: PRec;
  PMoreData: PByteArr;

begin
  P:= AllocMem(SizeOf(TRec) + 4);
  PMoreData:= @P^.MoreData;
  PMoreData^[2]:= 3;
  ShowMessage(IntToStr(PMoreData^[2]));
  FreeMem(P);
end;

but probably you need to typecast this dummy field to something else since the field definition is just a hack.

And finally: Never use Delphi dynamic arrays (like registryData: array of UCHAR;) while converting C structures to Delphi. Dynamic array in Delphi is a lifetime-managed reference type that has no exact equivalent in C.

Serg
RegistryData: array of charregistrydata: array[0..0] of ucharregistrydata: ucharall are with size 40
bojan gavrilovic
Bojan: remove the uchar array in C and see if the size changes.If not, that is the problem. There is afaik only one type with sizeof(x)=0, namely "record end;" and there is afaik no equivalent for pascal to have a zero length array. IOW this kind of C syntax is a C-centric hack.
Marco van de Voort
Thanks a lot to all. Using empty record I solved the problem. This c structures, even RegistryData has and more then 200 wide characters has size always = 36.
bojan gavrilovic
+1  A: 
UCHAR registryData[];

is

registryData: array[0..0] of UCHAR;

With packed records and packed array for the types the size of _Registry_Event equals 34.

pani
size ofREG_NOTIFY_CLASS; = 4TIME_FIELDS; = 16THandle; = 43 x ULONG; 3 x 4 =12UCHAR; = 4Sum = 40 not 34
bojan gavrilovic
If REG_NOTIFY_CLASS is 4 bytes the size of _Registry_Event equals 37.Note that array[0..0] of UCHAR equals 1 byte and not 4.
pani