priority rather than a DISCARDABLE flag.
Tested on Fedora 26 x86 --- dlls/krnl386.exe16/ne_module.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/dlls/krnl386.exe16/ne_module.c b/dlls/krnl386.exe16/ne_module.c index b3c0b75a4d..72043a90ff 100644 --- a/dlls/krnl386.exe16/ne_module.c +++ b/dlls/krnl386.exe16/ne_module.c @@ -662,6 +662,24 @@ static HMODULE16 build_module( const void *mapping, SIZE_T mapping_size, LPCSTR for (i = ne_header->ne_cseg; i > 0; i--, pSeg++) { memcpy( pData, pSeg, sizeof(*pSeg) ); + + /* The original NE spec (which link4 version 4.x follows) uses the top four bits of the segment flags to set a + discard priority (0 = not discardable, 15 = highest priority). Later specs repurpose the top three bits and + use a single bit for the discardable flag. The top three bits must be masked off and discardable flag set + appropriately, otherwise a discard priority could get misinterpreted as a 32 bit segment flag which results + in an application crash. */ + if (ne_header->ne_ver == 0x04) + { + WORD* seg_flags; + BOOL isDiscardable; + + seg_flags = (WORD*)(pData + FIELD_OFFSET(SEGTABLEENTRY, flags)); + isDiscardable = ((*seg_flags & 0xF000) > 0); + + if (isDiscardable) + *seg_flags = ((*seg_flags & 0x0FFF) | NE_SEGFLAGS_DISCARDABLE); + } + pData += sizeof(SEGTABLEENTRY); }