Do smarter OS/2 binary handling

Andreas Mohr andi at rhlx01.fht-esslingen.de
Sun Sep 5 04:18:55 CDT 2004


Hi all,

(some of) Dell's system diag/upgrade utilities use a hybrid
DOS/OS/2 program to extract their data (disk image).

Until now Wine's behaviour was rather not so useful:
Upon detecting an OS/2 program, it immediately rejected it.
This is fatal for hybrid programs which contain a fully functional
DOS part.

Thus:
- don't reject OS/2 programs in the Wine loader parts used by
  commandline and by wcmd, but instead print a warning message
  and try to carry on in DOS mode
- do reject OS/2 programs in the Windows loader in order to let
  Wine figure out later that it's an OS/2 program which should
  be loaded as DOS
- document all ne_exetyp values known so far (from RB's intlist)

Andreas Mohr
-------------- next part --------------
Determining best CVS host...
Using CVSROOT :pserver:cvs at rhlx01.fht-esslingen.de:/home/wine
Index: dlls/kernel/module.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/module.c,v
retrieving revision 1.9
diff -u -r1.9 module.c
--- dlls/kernel/module.c	3 Jun 2004 00:25:08 -0000	1.9
+++ dlls/kernel/module.c	5 Sep 2004 09:09:53 -0000
@@ -118,7 +118,7 @@
     }
 
 broken:
-    ERR("Hmm, an error occurred. Is this binary file broken ?\n");
+    ERR("Hmm, an error occurred. Is this binary file broken?\n");
 
 good:
     HeapFree( GetProcessHeap(), 0, modtab);
@@ -169,7 +169,7 @@
         return BINARY_UNKNOWN;
     }
 
-    /* Mach-o File with Endian set to Big Endian  or Little Endian*/
+    /* Mach-o File with Endian set to Big Endian or Little Endian */
     if (header.macho.magic == 0xfeedface || header.macho.magic == 0xecafdeef)
     {
         switch(header.macho.filetype)
@@ -230,8 +230,12 @@
             {
                 switch ( ext_header.os2.ne_exetyp )
                 {
-                case 2:  return BINARY_WIN16;
-                case 5:  return BINARY_DOS;
+		case 1:  return BINARY_OS216; /* OS/2 */
+                case 2:  return BINARY_WIN16; /* Windows */
+		case 3:  return BINARY_DOS; /* European MS-DOS 4.x */
+		case 4:  return BINARY_WIN16; /* Windows 386; FIXME: is this 32bit??? */
+                case 5:  return BINARY_DOS; /* BOSS, Borland Operating System Services */
+		/* other types, e.g. 0 is: "unknown" */
                 default: return MODULE_Decide_OS2_OldWin(hfile, &header.mz, &ext_header.os2);
                 }
             }
Index: dlls/kernel/ne_module.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/ne_module.c,v
retrieving revision 1.25
diff -u -r1.25 ne_module.c
--- dlls/kernel/ne_module.c	10 Aug 2004 23:43:21 -0000	1.25
+++ dlls/kernel/ne_module.c	5 Sep 2004 09:09:54 -0000
@@ -644,13 +644,20 @@
 
     if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21;  /* win32 exe */
     if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
-        MESSAGE("Sorry, this is an OS/2 linear executable (LX) file !\n");
+        MESSAGE("Sorry, this is an OS/2 linear executable (LX) file!\n");
         return (HMODULE16)12;
     }
     if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE16)11;  /* invalid exe */
 
     /* We now have a valid NE header */
 
+    /* check to be able to fall back to loading OS/2 programs as DOS
+     * FIXME: should this check be reversed in order to be less strict?
+     * (only fail for OS/2 ne_exetyp 0x01 here?) */
+    if ((ne_header.ne_exetyp != 0x02 /* Windows */)
+    &&  (ne_header.ne_exetyp != 0x04) /* Windows 386 */)
+	    return (HMODULE16)11;  /* invalid exe */
+
     size = sizeof(NE_MODULE) +
              /* segment table */
            ne_header.ne_cseg * sizeof(SEGTABLEENTRY) +
Index: dlls/kernel/process.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/process.c,v
retrieving revision 1.73
diff -u -r1.73 process.c
--- dlls/kernel/process.c	3 Sep 2004 01:05:30 -0000	1.73
+++ dlls/kernel/process.c	5 Sep 2004 09:09:57 -0000
@@ -79,8 +79,8 @@
 #define PDB32_FILE_APIS_OEM 0x0040  /* File APIs are OEM */
 #define PDB32_WIN32S_PROC   0x8000  /* Win32s process */
 
-static const WCHAR comW[] = {'.','c','o','m',0};
 static const WCHAR batW[] = {'.','b','a','t',0};
+static const WCHAR comW[] = {'.','c','o','m',0};
 static const WCHAR winevdmW[] = {'w','i','n','e','v','d','m','.','e','x','e',0};
 
 extern void SHELL_LoadRegistry(void);
@@ -1033,6 +1033,7 @@
     DWORD stack_size = 0;
     int file_exists;
     PEB *peb = NtCurrentTeb()->Peb;
+    int bintype;
 
     /* Initialize everything */
     if (!process_init()) exit(1);
@@ -1084,7 +1085,8 @@
         ExitProcess(1);
     }
 
-    switch( MODULE_GetBinaryType( main_exe_file, NULL, NULL ))
+    bintype = MODULE_GetBinaryType( main_exe_file, NULL, NULL );
+    switch(bintype)
     {
     case BINARY_PE_EXE:
         TRACE( "starting Win32 binary %s\n", debugstr_w(main_exe_name) );
@@ -1104,6 +1106,10 @@
             ExitProcess(1);
         }
         /* fall through */
+    case BINARY_OS216:
+	if (bintype == BINARY_OS216) /* check against other fall-through cases */
+            MESSAGE( "wine: %s is an OS/2 binary, not supported. Since some OS/2 programs have a fully functional DOS part, we will do a last desperate attempt by starting it in DOS mode now.\n", debugstr_w(main_exe_name) );
+        /* fall through */
     case BINARY_WIN16:
     case BINARY_DOS:
         TRACE( "starting Win16/DOS binary %s\n", debugstr_w(main_exe_name) );
@@ -1117,9 +1123,6 @@
         MESSAGE( "wine: trying to run %s, cannot open builtin library for 'winevdm.exe': %s\n",
                  debugstr_w(main_exe_name), error );
         ExitProcess(1);
-    case BINARY_OS216:
-        MESSAGE( "wine: %s is an OS/2 binary, not supported\n", debugstr_w(main_exe_name) );
-        ExitProcess(1);
     case BINARY_UNIX_EXE:
         MESSAGE( "wine: %s is a Unix binary, not supported\n", debugstr_w(main_exe_name) );
         ExitProcess(1);
@@ -1901,18 +1904,17 @@
         retv = create_process( hFile, name, tidy_cmdline, envW, cur_dir, process_attr, thread_attr,
                                inherit, flags, startup_info, info, unixdir, res_start, res_end );
         break;
+    case BINARY_OS216:
+        FIXME( "%s is an OS/2 binary, not supported. Since some OS/2 programs have a fully functional DOS part, we will do a last desperate attempt by starting it in DOS mode now.\n", debugstr_w(name) );
+	/* fall through */
     case BINARY_WIN16:
     case BINARY_DOS:
         TRACE( "starting %s as Win16/DOS binary\n", debugstr_w(name) );
         retv = create_vdm_process( name, tidy_cmdline, envW, cur_dir, process_attr, thread_attr,
                                    inherit, flags, startup_info, info, unixdir );
         break;
-    case BINARY_OS216:
-        FIXME( "%s is OS/2 binary, not supported\n", debugstr_w(name) );
-        SetLastError( ERROR_BAD_EXE_FORMAT );
-        break;
     case BINARY_PE_DLL:
-        TRACE( "not starting %s since it is a dll\n", debugstr_w(name) );
+        TRACE( "not starting %s since it is a DLL\n", debugstr_w(name) );
         SetLastError( ERROR_BAD_EXE_FORMAT );
         break;
     case BINARY_UNIX_LIB:


More information about the wine-patches mailing list