Jump to page: 1 2
Thread overview
Top-Down Structs
Mar 10, 2006
Bob W
Mar 10, 2006
AgentOrange
Mar 10, 2006
Bob W
Mar 11, 2006
John C
Mar 12, 2006
Bob W
Mar 12, 2006
Bob W
Mar 12, 2006
Regan Heath
Mar 12, 2006
Regan Heath
Mar 12, 2006
Bob W
Mar 12, 2006
Brad Roberts
Mar 12, 2006
Regan Heath
March 10, 2006
After using some Win32 declarations, wich are
obviously not part of "std.c.windows.windows",
I have noticed that a resulting program crashes with

    "Error: Win32 Exception" .

This happens if the main structure ("INPUT_RECORD")
is declared before the other structures contained in
the main structure. The problem will not arise if
sub-structs [B] are declared earlier than the main
struct [A].

Before that incident I was convinced that the
D compiler would handle "top-down" declarations
correctly.



----- "Problematic" declaration sequence: -----


// INPUT_RECORD [A]

struct INPUT_RECORD {
  WORD EventType;
  union {
    KEY_EVENT_RECORD KeyEvent;
    MOUSE_EVENT_RECORD MouseEvent;
    WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
    MENU_EVENT_RECORD MenuEvent;
    FOCUS_EVENT_RECORD FocusEvent;
} }


// Structs contained in INPUT_RECORD [B]

struct KEY_EVENT_RECORD {
  BOOL bKeyDown;
  WORD wRepeatCount;
  WORD wVirtualKeyCode;
  WORD wVirtualScanCode;
  union  {  WCHAR UnicodeChar;  CHAR AsciiChar;  }
  DWORD dwControlKeyState;
}

struct MOUSE_EVENT_RECORD {
  COORD dwMousePosition;
  DWORD dwButtonState;
  DWORD dwControlKeyState;
  DWORD dwEventFlags;
}

struct WINDOW_BUFFER_SIZE_RECORD { COORD dwSize; }
struct MENU_EVENT_RECORD { UINT dwCommandId; }
struct FOCUS_EVENT_RECORD { BOOL bSetFocus; }



March 10, 2006
In article <duropj$o85$1@digitaldaemon.com>, Bob W says...
>
>
>After using some Win32 declarations, wich are
>obviously not part of "std.c.windows.windows",
>I have noticed that a resulting program crashes with
>
>    "Error: Win32 Exception" .
>
>This happens if the main structure ("INPUT_RECORD")
>is declared before the other structures contained in
>the main structure. The problem will not arise if
>sub-structs [B] are declared earlier than the main
>struct [A].
>
>Before that incident I was convinced that the
>D compiler would handle "top-down" declarations
>correctly.
>
>
>
>----- "Problematic" declaration sequence: -----
>
>
>// INPUT_RECORD [A]
>
>struct INPUT_RECORD {
>  WORD EventType;
>  union {
>    KEY_EVENT_RECORD KeyEvent;
>    MOUSE_EVENT_RECORD MouseEvent;
>    WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
>    MENU_EVENT_RECORD MenuEvent;
>    FOCUS_EVENT_RECORD FocusEvent;
>} }
>
>
>// Structs contained in INPUT_RECORD [B]
>
>struct KEY_EVENT_RECORD {
>  BOOL bKeyDown;
>  WORD wRepeatCount;
>  WORD wVirtualKeyCode;
>  WORD wVirtualScanCode;
>  union  {  WCHAR UnicodeChar;  CHAR AsciiChar;  }
>  DWORD dwControlKeyState;
>}
>
>struct MOUSE_EVENT_RECORD {
>  COORD dwMousePosition;
>  DWORD dwButtonState;
>  DWORD dwControlKeyState;
>  DWORD dwEventFlags;
>}
>
>struct WINDOW_BUFFER_SIZE_RECORD { COORD dwSize; }
>struct MENU_EVENT_RECORD { UINT dwCommandId; }
>struct FOCUS_EVENT_RECORD { BOOL bSetFocus; }
>
>
>

align(1) ?


March 10, 2006
"AgentOrange" <AgentOrange_member@pathlink.com> wrote in message news:dusnj5$2bh1$1@digitaldaemon.com...
>
> align(1) ?
>

Nope.


March 11, 2006
Bob W wrote:
> After using some Win32 declarations, wich are
> obviously not part of "std.c.windows.windows",
> I have noticed that a resulting program crashes with
> 
>     "Error: Win32 Exception" .
> 
> This happens if the main structure ("INPUT_RECORD")
> is declared before the other structures contained in
> the main structure. The problem will not arise if
> sub-structs [B] are declared earlier than the main
> struct [A].
> 
> Before that incident I was convinced that the
> D compiler would handle "top-down" declarations
> correctly.
> 
> 
> 
> ----- "Problematic" declaration sequence: -----
> 
> 
> // INPUT_RECORD [A]
> 
> struct INPUT_RECORD {
>   WORD EventType;
>   union {
>     KEY_EVENT_RECORD KeyEvent;
>     MOUSE_EVENT_RECORD MouseEvent;
>     WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
>     MENU_EVENT_RECORD MenuEvent;
>     FOCUS_EVENT_RECORD FocusEvent;
> } }
> 
> 
> // Structs contained in INPUT_RECORD [B]
> 
> struct KEY_EVENT_RECORD {
>   BOOL bKeyDown;
>   WORD wRepeatCount;
>   WORD wVirtualKeyCode;
>   WORD wVirtualScanCode;
>   union  {  WCHAR UnicodeChar;  CHAR AsciiChar;  }
>   DWORD dwControlKeyState;
> }
> 
> struct MOUSE_EVENT_RECORD {
>   COORD dwMousePosition;
>   DWORD dwButtonState;
>   DWORD dwControlKeyState;
>   DWORD dwEventFlags;
> }
> 
> struct WINDOW_BUFFER_SIZE_RECORD { COORD dwSize; }
> struct MENU_EVENT_RECORD { UINT dwCommandId; }
> struct FOCUS_EVENT_RECORD { BOOL bSetFocus; }
> 
> 
> 

Couldn't repro on my Windows XP machine. Runs without throwing exceptions here.
March 12, 2006
"John C" <johnch_atms@hotmail.com> wrote in message news:duuj4n$2ui9$1@digitaldaemon.com...


> Couldn't repro on my Windows XP machine. Runs without throwing exceptions here.

It all depends what you were doing with the structs.
Just declaring them won't cause any trouble.

In my case I was calling the Win32 functions
PeekConsoleInputA() and/or ReadConsoleInputA(),
which was sufficient to upset Win XP.

Both functions expect a pointer to an INPUT_RECORD structure.



March 12, 2006
I just wanted to add this info:

Check INPUT_RECORD.sizeof if it is declared before
and after its related sub-structs. In the first case
the size of INPUT_RECORD will be 4, otherwise the
size is 20.



March 12, 2006
On Sun, 12 Mar 2006 02:02:48 +0100, Bob W <nospam@aol.com> wrote:
> I just wanted to add this info:
>
> Check INPUT_RECORD.sizeof if it is declared before
> and after its related sub-structs. In the first case
> the size of INPUT_RECORD will be 4, otherwise the
> size is 20.

Interestingly naming the union fixes the problem. eg.

struct INPUT_RECORD {
	WORD EventType;
	union bob {
		KEY_EVENT_RECORD KeyEvent;
		MOUSE_EVENT_RECORD MouseEvent;
		WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
		MENU_EVENT_RECORD MenuEvent;
		FOCUS_EVENT_RECORD FocusEvent;
	}
	bob a;
}

(rest of wrong declaration order as given by OP)

results in an INPUT_RECORD.sizeof of 20. I think the bug lies in the handling of anonymous unions.

Regan
March 12, 2006
Here is the code I used to test this, to save someone else the trouble.

Regan

-----------

import std.c.windows.windows;
import std.stdio;

// INPUT_RECORD [A]

struct INPUT_RECORD {
	WORD EventType;
	union bob {
		KEY_EVENT_RECORD KeyEvent;
		MOUSE_EVENT_RECORD MouseEvent;
		WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
		MENU_EVENT_RECORD MenuEvent;
		FOCUS_EVENT_RECORD FocusEvent;
	}
	bob a;
}

alias INPUT_RECORD* PINPUT_RECORD;

// Structs contained in INPUT_RECORD [B]

struct KEY_EVENT_RECORD {
  BOOL bKeyDown;
  WORD wRepeatCount;
  WORD wVirtualKeyCode;
  WORD wVirtualScanCode;
  union  {  WCHAR UnicodeChar;  CHAR AsciiChar;  }
  DWORD dwControlKeyState;
}

struct MOUSE_EVENT_RECORD {
  COORD dwMousePosition;
  DWORD dwButtonState;
  DWORD dwControlKeyState;
  DWORD dwEventFlags;
}

struct COORD {
    SHORT X;
    SHORT Y;
}

struct WINDOW_BUFFER_SIZE_RECORD { COORD dwSize; }
struct MENU_EVENT_RECORD { UINT dwCommandId; }
struct FOCUS_EVENT_RECORD { BOOL bSetFocus; }

extern(Windows) {
	BOOL ReadConsoleInputA(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
	BOOL ReadConsoleInputW(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
	
	HANDLE GetStdHandle(DWORD nStdHandle);
	
	DWORD STD_INPUT_HANDLE    = cast(DWORD)-10;
	DWORD STD_OUTPUT_HANDLE   = cast(DWORD)-11;
	DWORD STD_ERROR_HANDLE    = cast(DWORD)-12;

	WORD KEY_EVENT					= 0x0001; // Event contains key event record
	WORD MOUSE_EVENT				= 0x0002; // Event contains mouse event record
	WORD WINDOW_BUFFER_SIZE_EVENT	= 0x0004; // Event contains window change event record
	WORD MENU_EVENT					= 0x0008; // Event contains menu event record
	WORD FOCUS_EVENT				= 0x0010; // event contains focus change
}

char[][WORD] types;

static this()
{
	types[KEY_EVENT] = "Key Event";
	types[MOUSE_EVENT] = "Mouse Event";
	types[WINDOW_BUFFER_SIZE_EVENT] = "Window Buffer Size Event";
	types[MENU_EVENT] = "Menu Event";
	types[FOCUS_EVENT] = "Focus Event";
}

void main()
{
	HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
	INPUT_RECORD rec;
	DWORD rd;

	writefln("INPUT_RECORD.sizeof = ",INPUT_RECORD.sizeof);
	
	if (ReadConsoleInputA(hIn,&rec,cast(DWORD)1,&rd) == 0) {
		writefln("ReadConsoleInputA failed");
		return ;
	}
	
	writefln(rd," records read:");
	writefln("Type: ",types[rec.EventType]);
}
March 12, 2006
"Regan Heath" <regan@netwin.co.nz> wrote in message news:ops6amc90r23k2f5@nrage.netwin.co.nz...
> On Sun, 12 Mar 2006 02:02:48 +0100, Bob W <nospam@aol.com> wrote:
>> I just wanted to add this info:
>>
>> Check INPUT_RECORD.sizeof if it is declared before
>> and after its related sub-structs. In the first case
>> the size of INPUT_RECORD will be 4, otherwise the
>> size is 20.
>
> Interestingly naming the union fixes the problem. eg.
>
> struct INPUT_RECORD {
> WORD EventType;
> union bob {
> KEY_EVENT_RECORD KeyEvent;
> MOUSE_EVENT_RECORD MouseEvent;
> WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
> MENU_EVENT_RECORD MenuEvent;
> FOCUS_EVENT_RECORD FocusEvent;
> }
> bob a;
> }
>
> (rest of wrong declaration order as given by OP)
>
> results in an INPUT_RECORD.sizeof of 20. I think the bug lies in the handling of anonymous unions.
>
> Regan

Good job! Looks like a usable workaround. But in the long term I would rather like to see the D compiler to stick to its promises:

"anonymous structs/unions are allowed as members of other structs/unions"



March 12, 2006
On Sun, 12 Mar 2006, Bob W wrote:

> "Regan Heath" <regan@netwin.co.nz> wrote in message news:ops6amc90r23k2f5@nrage.netwin.co.nz...
> > On Sun, 12 Mar 2006 02:02:48 +0100, Bob W <nospam@aol.com> wrote:
> >> I just wanted to add this info:
> >>
> >> Check INPUT_RECORD.sizeof if it is declared before
> >> and after its related sub-structs. In the first case
> >> the size of INPUT_RECORD will be 4, otherwise the
> >> size is 20.
> >
> > Interestingly naming the union fixes the problem. eg.
> >
> > struct INPUT_RECORD {
> > WORD EventType;
> > union bob {
> > KEY_EVENT_RECORD KeyEvent;
> > MOUSE_EVENT_RECORD MouseEvent;
> > WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
> > MENU_EVENT_RECORD MenuEvent;
> > FOCUS_EVENT_RECORD FocusEvent;
> > }
> > bob a;
> > }
> >
> > (rest of wrong declaration order as given by OP)
> >
> > results in an INPUT_RECORD.sizeof of 20. I think the bug lies in the handling of anonymous unions.
> >
> > Regan
> 
> Good job! Looks like a usable workaround. But in the long term I would rather like to see the D compiler to stick to its promises:
> 
> "anonymous structs/unions are allowed as members of other structs/unions"

Would one of you finish minimizing the test case and file it in bugzilla?

Thanks,
Brad
« First   ‹ Prev
1 2