[PATCH v2 4/4] krnl386.exe16: NE files with linker major version 4 use a discard

Martin Payne development at martinpayne.me.uk
Sat Dec 16 15:04:47 CST 2017


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);
     }
 
-- 
2.15.1.windows.2




More information about the wine-devel mailing list