From: Pali Rohár pali@kernel.org
On-disk NE structure contains at offset 38 field which contains the offset to the fastload/gangload area and at offset 3a field which contains the length of the fastload/gangload area.
Fields ne_pretthunks and ne_psegrefbytes were used only for the in-memory structure of loaded NE modules on Windows 1.x and 2.x systems.
IMAGE_OS2_HEADER describe the on-disk structure, not the loaded in-memory structure.
Fix the IMAGE_OS2_HEADER structure and also its all incorrect usage.
This was verified against the Windows 3.1 DDK file NEWEXE.INC and also against the Andrew Schulman's book Undocumented Windows. Both contains description of NE structures and uses ne_gang_start and ne_gang_length names. But for the consistency with other fields in IMAGE_OS2_HEADER, use just one underscore in names: ne_gangstart and ne_ganglength.
To have include file winnt.h compatible with Windows NT SDK, define both old incorrect field name and new correct field name via union. Same trick is used in struct from the Undocumented Windows book (Chapter 5: KERNEL).
Signed-off-by: Pali Rohár pali@kernel.org --- dlls/ntdll/tests/generated.c | 24 ++++++++++++------------ include/winnt.h | 18 ++++++++++++++++-- tools/sfnt2fon/sfnt2fon.c | 4 ++-- tools/winebuild/spec16.c | 8 ++++---- tools/winedump/ne.c | 4 ++-- 5 files changed, 36 insertions(+), 22 deletions(-)
diff --git a/dlls/ntdll/tests/generated.c b/dlls/ntdll/tests/generated.c index 2c3b462011e..191d1974d72 100644 --- a/dlls/ntdll/tests/generated.c +++ b/dlls/ntdll/tests/generated.c @@ -1311,12 +1311,12 @@ static void test_pack_IMAGE_OS2_HEADER(void) TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_flagsothers, 1) TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_flagsothers, 1) TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_flagsothers, 55) - TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_pretthunks, 2) - TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_pretthunks, 2) - TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_pretthunks, 56) - TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_psegrefbytes, 2) - TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_psegrefbytes, 2) - TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_psegrefbytes, 58) + TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_gangstart, 2) + TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_gangstart, 2) + TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_gangstart, 56) + TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_ganglength, 2) + TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_ganglength, 2) + TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_ganglength, 58) TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_swaparea, 2) TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_swaparea, 2) TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_swaparea, 60) @@ -4739,12 +4739,12 @@ static void test_pack_IMAGE_OS2_HEADER(void) TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_flagsothers, 1) TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_flagsothers, 1) TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_flagsothers, 55) - TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_pretthunks, 2) - TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_pretthunks, 2) - TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_pretthunks, 56) - TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_psegrefbytes, 2) - TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_psegrefbytes, 2) - TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_psegrefbytes, 58) + TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_gangstart, 2) + TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_gangstart, 2) + TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_gangstart, 56) + TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_ganglength, 2) + TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_ganglength, 2) + TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_ganglength, 58) TEST_FIELD_SIZE (IMAGE_OS2_HEADER, ne_swaparea, 2) TEST_FIELD_ALIGN (IMAGE_OS2_HEADER, ne_swaparea, 2) TEST_FIELD_OFFSET(IMAGE_OS2_HEADER, ne_swaparea, 60) diff --git a/include/winnt.h b/include/winnt.h index 722d2c3a542..080044e6ad6 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -2629,8 +2629,22 @@ typedef struct WORD ne_cres; /* 34 # of resource segments */ BYTE ne_exetyp; /* 36 Flags indicating target OS */ BYTE ne_flagsothers; /* 37 Additional information flags */ - WORD ne_pretthunks; /* 38 Offset to return thunks */ - WORD ne_psegrefbytes; /* 3a Offset to segment ref. bytes */ + union { + /* ne_pretthunks is the incorrect name specified in Windows NT SDK. + Offset to return thunks was used only for the in-memory structure + of loaded NE modules on Windows 1.x and 2.x. On-disk structure always + contains offset to gangload area (if gangload area is present). */ + WORD ne_pretthunks; + WORD ne_gangstart; /* 38 Offset to gangload area */ + }; + union { + /* ne_psegrefbytes is the incorrect name specified in Windows NT SDK. + Offset to segment ref. bytes was used only for the in-memory structure + of loaded NE modules on Windows 1.x and 2.x. On-disk structure always + contains length of gangload area (if gangload area is present). */ + WORD ne_psegrefbytes; + WORD ne_ganglength; /* 3a Length of gangload area */ + }; WORD ne_swaparea; /* 3c Reserved by Microsoft */ WORD ne_expver; /* 3e Expected Windows version number */ } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; diff --git a/tools/sfnt2fon/sfnt2fon.c b/tools/sfnt2fon/sfnt2fon.c index bf31124aa25..24d19ed1dee 100644 --- a/tools/sfnt2fon/sfnt2fon.c +++ b/tools/sfnt2fon/sfnt2fon.c @@ -956,8 +956,8 @@ int main(int argc, char **argv) put_word( 0 ); /* ne_cres */ put_byte( 2 ); /* ne_exetyp = NE_OSFLAGS_WINDOWS */ put_byte( 0 ); /* ne_flagsothers */ - put_word( 0 ); /* ne_pretthunks */ - put_word( 0 ); /* ne_psegrefbytes */ + put_word( 0 ); /* ne_gangstart */ + put_word( 0 ); /* ne_ganglength */ put_word( 0 ); /* ne_swaparea */ put_word( 0x400 ); /* ne_expver */
diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c index 630dc16b69d..15cba69f215 100644 --- a/tools/winebuild/spec16.c +++ b/tools/winebuild/spec16.c @@ -598,8 +598,8 @@ static void output_module16( DLLSPEC *spec ) output( "\t.short 0\n" ); /* ne_cres */ output( "\t.byte 0x02\n" ); /* ne_exetyp = NE_OSFLAGS_WINDOWS */ output( "\t.byte 0x08\n" ); /* ne_flagsothers = NE_AFLAGS_FASTLOAD */ - output( "\t.short 0\n" ); /* ne_pretthunks */ - output( "\t.short 0\n" ); /* ne_psegrefbytes */ + output( "\t.short 0\n" ); /* ne_gangstart */ + output( "\t.short 0\n" ); /* ne_ganglength */ output( "\t.short 0\n" ); /* ne_swaparea */ output( "\t.short 0\n" ); /* ne_expver */
@@ -915,8 +915,8 @@ void output_fake_module16( DLLSPEC *spec ) put_word( 0 ); /* ne_cres */ put_byte( 2 /*NE_OSFLAGS_WINDOWS*/ ); /* ne_exetyp */ put_byte( 8 /*NE_AFLAGS_FASTLOAD*/ ); /* ne_flagsothers */ - put_word( 0 ); /* ne_pretthunks */ - put_word( 0 ); /* ne_psegrefbytes */ + put_word( 0 ); /* ne_gangstart */ + put_word( 0 ); /* ne_ganglength */ put_word( 0 ); /* ne_swaparea */ put_word( 0 ); /* ne_expver */
diff --git a/tools/winedump/ne.c b/tools/winedump/ne.c index c27d7d6a9b7..e718ca3bf00 100644 --- a/tools/winedump/ne.c +++ b/tools/winedump/ne.c @@ -130,8 +130,8 @@ static void dump_ne_header( const IMAGE_OS2_HEADER *ne ) printf( "Non-resident table: %x\n", (UINT)ne->ne_nrestab ); printf( "Exe type: %x\n", ne->ne_exetyp ); printf( "Other flags: %x\n", ne->ne_flagsothers ); - printf( "Fast load area: %x-%x\n", ne->ne_pretthunks << ne->ne_align, - (ne->ne_pretthunks+ne->ne_psegrefbytes) << ne->ne_align ); + printf( "Fast load area: %x-%x\n", ne->ne_gangstart << ne->ne_align, + (ne->ne_gangstart+ne->ne_ganglength) << ne->ne_align ); printf( "Expected version: %d.%d\n", HIBYTE(ne->ne_expver), LOBYTE(ne->ne_expver) ); }