c++winapistruct64-bitqb64

Byte packing for WinAPI STARTUPINFO 64 bit (QB64)


I am programming in QB64, which is a programming language that allows for QBASIC-like syntax, and is translated into C++ code and compiled.

If we want to use a struct in our code, then we have to declare it and create it manually. In 32-bit, no problem, as it matches the WinAPI MSDN pages and will almost always work. For 64-bit, however, structures have different byte packing and I cannot figure out the correct packing for the STARTUPINFO struct.

Below is my declaration of the struct as it works in 32-bit. I know that the struct needs to be 104 bytes and I am currently 8 bytes short; I have made sure that all my variables match the 64-bit sizing but I'm missing 8 bytes of padding somewhere in my struct. Can someone who knows about byte packing and about WinAPI structs help me solve this?

Type STARTUPINFO
    cb As Long '4 bytes
    lpReserved As _Offset '4 bytes in 32, 8 in 64
    lpDesktop As _Offset '4 bytes in 32, 8 in 64
    lpTitle As _Offset '4 bytes in 32, 8 in 64
    dwX As Long '4 bytes
    dwY As Long '4 bytes
    dwXSize As Long '4 bytes
    dwYSize As Long '4 bytes
    dwXCountChars As Long '4 bytes
    dwYCountChars As Long '4 bytes
    dwFillAttribute As Long '4 bytes
    dwFlags As Long '4 bytes
    wShowWindow As Integer '2 bytes
    cbReserved2 As Integer '2 bytes
    lpReserved2 As _Offset '4 bytes in 32, 8 in 64
    hStdInput As _Offset '4 bytes in 32, 8 in 64
    hStdOutput As _Offset '4 bytes in 32, 8 in 64
    hStdError As _Offset '4 bytes in 32, 8 in 64
End Type

Solution

  • The field sizes and positions for the STARTUPINFOW structure in 32-bit and 64-bit builds are summarized below. (Note that these sizes and offsets are the same for the equivalent STARTUPINFOA version of the structure, used for non-Unicode builds.)

    32-bit Windows (note that no padding is required – almost certainly by design):

    typedef struct _STARTUPINFOW {
        DWORD   cb;             // 4 bytes ->  4 total
        LPWSTR  lpReserved;     // 4           8
        LPWSTR  lpDesktop;      // 4          12
        LPWSTR  lpTitle;        // 4          16
        DWORD   dwX;            // 4          20
        DWORD   dwY;            // 4          24
        DWORD   dwXSize;        // 4          28
        DWORD   dwYSize;        // 4          32
        DWORD   dwXCountChars;  // 4          36
        DWORD   dwYCountChars;  // 4          40
        DWORD   dwFillAttribute;// 4          44
        DWORD   dwFlags;        // 4          48
        WORD    wShowWindow;    // 2          50
        WORD    cbReserved2;    // 2          52
        LPBYTE  lpReserved2;    // 4          56
        HANDLE  hStdInput;      // 4          60
        HANDLE  hStdOutput;     // 4          64
        HANDLE  hStdError;      // 4          68 bytes total
    };
    

    64-bit Windows (padding now required, as the 8-byte pointers should be 8-byte aligned):

    typedef struct _STARTUPINFOW {
        DWORD   cb;             // 4 bytes ->  4 total
        // 4 b padding to align next pointer:  8
        LPWSTR  lpReserved;     // 8          16
        LPWSTR  lpDesktop;      // 8          24
        LPWSTR  lpTitle;        // 8          32
        DWORD   dwX;            // 4          36
        DWORD   dwY;            // 4          40
        DWORD   dwXSize;        // 4          44
        DWORD   dwYSize;        // 4          48
        DWORD   dwXCountChars;  // 4          52
        DWORD   dwYCountChars;  // 4          56
        DWORD   dwFillAttribute;// 4          60
        DWORD   dwFlags;        // 4          64
        WORD    wShowWindow;    // 2          66
        WORD    cbReserved2;    // 2          68
        // 4 b padding to align next pointer: 72
        LPBYTE  lpReserved2;    // 8          80
        HANDLE  hStdInput;      // 8          88
        HANDLE  hStdOutput;     // 8          96
        HANDLE  hStdError;      // 8          104
    };