I am porting TaskSchedule API related code from Delphi 5 to Delphi XE6. I'm having an issue with structure alignment and `sizeof`.

The actual [`TASK_TRIGGER`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa383618(v=vs.85).aspx) structure is declared as:

```
typedef struct _TASK_TRIGGER {
  WORD               cbTriggerSize;
  WORD               Reserved1;
  WORD               wBeginYear;
  WORD               wBeginMonth;
  WORD               wBeginDay;
  WORD               wEndYear;
  WORD               wEndMonth;
  WORD               wEndDay;
  WORD               wStartHour;
  WORD               wStartMinute;
  DWORD              MinutesDuration;
  DWORD              MinutesInterval;
  DWORD              rgFlags;
  TASK_TRIGGER_TYPE  TriggerType;
  TRIGGER_TYPE_UNION Type;
  WORD               Reserved2;
  WORD               wRandomMinutesInterval;
} TASK_TRIGGER

```

The old translation of `MsTask.pas` i'm using (and current JCL transactions of MsTask) translate it as:

```
  _TASK_TRIGGER = record
    cbTriggerSize: WORD;
    Reserved1: WORD;
    wBeginYear: WORD;
    wBeginMonth: WORD;
    wBeginDay: WORD;
    wEndYear: WORD;
    wEndMonth: WORD;
    wEndDay: WORD;
    wStartHour: WORD;
    wStartMinute: WORD;
    MinutesDuration: DWORD;
    MinutesInterval: DWORD;
    rgFlags: DWORD;
    TriggerType: TTaskTriggerType;
    Type_: TTriggerTypeUnion;
    Reserved2: WORD;
    wRandomMinutesInterval: WORD;
  end;

```

The `sizeof` this record differs between Delphi 5 and XE6:

* Delphi 5: `SizeOf(TASK_TRIGGER) = 48`
* Delphi XE6 `SizeOf(TASK_TRIGGER) = 47`

The function call of `ITaskTrigger.SetTrigger(TASK_TRIGGER)` succeeds in Dephi5, but fails with Delphi XE6 with `The parameters are incorrect`.

The layouts
===========

If i were to naively guess the layout of the record, i would it is:

```
□□□□ □□□□       //cbTriggerSize, Reserved1    (4 bytes)
□□□□ □□□□       //wBeginYear,    wBeginMonth  (8 bytes)
□□□□ □□□□       //wBeginDay,     wEndYear     (12 bytes)
□□□□ □□□□       //wEndMonth,     wEndDay      (16 bytes)
□□□□ □□□□       //wStartHour,    wStartMinute (20 bytes)
□□□□□□□□        //MinutesDuration             (24 bytes)
□□□□□□□□        //MinutesInterval             (28 bytes)
□□□□□□□□        //rgFlags                     (32 bytes)
□□□□□□□□        //TriggerType                 (36 bytes)
□□□□□□□□        //Type_                       (40 bytes)
□□□□ □□□□       //Reserved2      wRandomMinutesInterval    (44 bytes)

```

But when i actually examine the populated structure inside the Delphi 5 debugger, the actual structure is 48 bytes, with extra 4 bytes padding between `TriggerType` and `Type_`:

```
□□□□ □□□□       //cbTriggerSize, Reserved1    (4 bytes)
□□□□ □□□□       //wBeginYear,    wBeginMonth  (8 bytes)
□□□□ □□□□       //wBeginDay,     wEndYear     (12 bytes)
□□□□ □□□□       //wEndMonth,     wEndDay      (16 bytes)
□□□□ □□□□       //wStartHour,    wStartMinute (20 bytes)
□□□□□□□□        //MinutesDuration             (24 bytes)
□□□□□□□□        //MinutesInterval             (28 bytes)
□□□□□□□□        //rgFlags                     (32 bytes)
□□□□□□□□        //TriggerType                 (36 bytes)
□□□□□□□□        //4 bytes padding
□□□□□□□□        //Type_                       (44 bytes)
□□□□ □□□□       //Reserved2      wRandomMinutesInterval    (48 bytes)

```

Ok, if that's how Delphi 5 wants to do it who am i to argue. It certainly knows more about Windows structure packing than i do.

The way i examined the layout was to place known sentinel values in the record:

```
trigger.cbTriggerSize := $1111; // WORD;
trigger.Reserved1 := $2222; // WORD;
trigger.wBeginYear := $3333; // WORD;
trigger.wBeginMonth := $4444; // WORD;
trigger.wBeginDay := $5555; // WORD;
trigger.wEndYear := $6666; // WORD;
trigger.wEndMonth := $7777; // WORD;
trigger.wEndDay := $8888; // WORD;
trigger.wStartHour := $9999; // WORD;
trigger.wStartMinute := $aaaa; // WORD;
trigger.MinutesDuration := $bbbbbbbb; // DWORD;
trigger.MinutesInterval := $cccccccc; // DWORD;
trigger.rgFlags := $dddddddd; // DWORD;
trigger.TriggerType := TASK_TIME_TRIGGER_DAILY; // TTaskTriggerType;
trigger.Type_.Daily.DaysInterval := $ffff; // TTriggerTypeUnion;
trigger.Reserved2 := $1111; // WORD;
trigger.wRandomMinutesInterval := $2222; // WORD;

```

And look at the resulting memory layout in the CPU window:

![enter image description here](https://i.stack.imgur.com/VtkG2.png)

(alternating members red and green, red is the padding);

For a total of `48 bytes` in Delphi 5.

Enter XE6
=========

When i do the same test in Delphi XE6, it is packed differently (and terrifyingly):

![enter image description here](https://i.stack.imgur.com/TTaq4.png)

First, it couldn't manage to allocate a stack variable the on 32-bit boundary; but that's fine.  

The CPU window refused to start the view exactly on the structure - insisting it start showing memory on a DWORD boundary; but that's fine.  

The record really is not aligned at `$18EB31`:

![enter image description here](https://i.stack.imgur.com/xHFsd.png)

so we'll go with that.

```
□□□□ □□□□       //cbTriggerSize, Reserved1    (4 bytes)
□□□□ □□□□       //wBeginYear,    wBeginMonth  (8 bytes)
□□□□ □□□□       //wBeginDay,     wEndYear     (12 bytes)
□□□□ □□□□       //wEndMonth,     wEndDay      (16 bytes)
□□□□ □□□□       //wStartHour,    wStartMinute (20 bytes)
□□□□□□□□        //MinutesDuration             (24 bytes)
□□□□□□□□        //MinutesInterval             (28 bytes)
□□□□□□□□        //rgFlags                     (32 bytes)
□□ □□□□ □□      //TriggerType, Type_, 1 byte padding (36 bytes)
□□□□□□□□        //4 bytes padding                    (40 bytes)
□□□□□□ □□       //3 bytes padding, part of Reserved2 (44 bytes)
□□ □□□□         //Remainnder of Reserved2, wRandomMinutesInterval    (47 bytes)

```

Is this monstrosity by design, or a compiler code-gen bug?

Did you try {$ALIGN ON}?
========================

Sure. 

```
sizeof(TASK_TRIGGER) = 52

```

![enter image description here](https://i.stack.imgur.com/BZSTv.png)

Fails.

What about {$MINENUMSIZE 4}?
============================

Okay.

```
sizeof(TASK_TRIGGER) = 50

```

![enter image description here](https://i.stack.imgur.com/G3UOw.png)

Fails.

Yeah, but did you try both together?
====================================

Touche.

```
sizeof(TASK_TRIGGER) = 52

```

![enter image description here](https://i.stack.imgur.com/OEQAk.png)

Fails.

It's almost like Delphi refuses to believe that it is Windows compiler.

Summary
=======

```
$ALIGN  $MINENUMSIZE  $OLDTYPELAYOUT    "packed"  |  sizeof
======  ============  ================  ========     ======
ON      4             ON                yes              57    
ON      4             OFF               yes              50    
ON      4             ON                no               52
ON      4             OFF               no               52

ON      2             ON                yes              50
ON      2             OFF               yes              50
ON      2             ON                no               52
ON      2             OFF               no               52

ON                    ON                yes              49
ON                    OFF               yes              49
ON                    ON                no               52
ON                    OFF               no               52

```

i'll add more as i get the patience.