? total-040730.diff
Index: dlls/kernel/dosmem.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/dosmem.c,v
retrieving revision 1.7
diff -u -r1.7 dosmem.c
--- dlls/kernel/dosmem.c	14 Jun 2004 17:04:35 -0000	1.7
+++ dlls/kernel/dosmem.c	30 Jul 2004 15:14:03 -0000
@@ -52,30 +52,12 @@
 WORD DOSMEM_BiosDataSeg;  /* BIOS data segment at 0x40:0 */
 WORD DOSMEM_BiosSysSeg;   /* BIOS ROM segment at 0xf000:0 */
 
-/* use 2 low bits of 'size' for the housekeeping */
 
-#define DM_BLOCK_DEBUG		0xABE00000
-#define DM_BLOCK_TERMINAL	0x00000001
-#define DM_BLOCK_FREE		0x00000002
-#define DM_BLOCK_MASK		0x001FFFFC
-
-/*
-#define __DOSMEM_DEBUG__
- */
-
-typedef struct {
-   unsigned	size;
-} dosmem_entry;
-
-typedef struct {
-  unsigned      blocks;
-  unsigned      free;
-} dosmem_info;
-
-#define NEXT_BLOCK(block) \
-        (dosmem_entry*)(((char*)(block)) + \
-	 sizeof(dosmem_entry) + ((block)->size & DM_BLOCK_MASK))
+#define DUMP_MCB(mc) TRACE ("base=0x%08x type=%d psp=0x%04x size=0x%04x\n", mc, mc->type, mc->psp, mc->size)
 
+#define NEXT_MCB(mc) \
+        (MCB*) ((mc->type==MCB_LAST) ? NULL : (char*)(mc) + (mc->size + 1)*16)
+	 
 #define VM_STUB(x) (0x90CF00CD|(x<<8)) /* INT x; IRET; NOP */
 #define VM_STUB_SEGMENT 0xf000         /* BIOS segment */
 
@@ -88,7 +70,7 @@
 static char *DOSMEM_sysmem;
 
 /* Start of DOS conventional memory */
-static char *DOSMEM_membase;
+static MCB *DOSMEM_membase;
 
 static void DOSMEM_InitMemory(void);
 
@@ -103,11 +85,11 @@
 }
 
 /***********************************************************************
- *           DOSMEM_InfoBlock
+ *           DOSMEM_FirstMCB
  *
- * Gets the DOS memory info block.
+ * Gets the first Memory Controll Block (MCB)
  */
-static dosmem_info *DOSMEM_InfoBlock(void)
+static MCB *DOSMEM_FirstMCB(void)
 {
     if (!DOSMEM_membase)
     {
@@ -134,25 +116,25 @@
         /*
          * Set DOS memory base and initialize conventional memory.
          */
-        DOSMEM_membase = DOSMEM_dosmem + reserve;
+        DOSMEM_membase = (MCB *) DOSMEM_dosmem + reserve;
         DOSMEM_InitMemory();
     }
 
-    return (dosmem_info*)DOSMEM_membase;
+    return DOSMEM_membase;
 }
 
+
 /***********************************************************************
- *           DOSMEM_RootBlock
+ *           DOSMEM_SegFirstMCB
  *
- * Gets the DOS memory root block.
+ * Gets the first Memory Controll Block (MCB)
  */
-static dosmem_entry *DOSMEM_RootBlock(void)
+WORD DOSMEM_SegFirstMCB(void)
 {
-    /* first block has to be paragraph-aligned */
-    return (dosmem_entry*)(((char*)DOSMEM_InfoBlock()) +
-                           ((((sizeof(dosmem_info) + 0xf) & ~0xf) - sizeof(dosmem_entry))));
+    return (WORD) (((char*)DOSMEM_FirstMCB() - (char*)DOSMEM_dosmem) >> 4);
 }
 
+
 /***********************************************************************
  *           DOSMEM_FillIsrTable
  *
@@ -277,25 +259,14 @@
  */
 static void DOSMEM_InitMemory(void)
 {
-    dosmem_info*        info_block = DOSMEM_InfoBlock();
-    dosmem_entry*       root_block = DOSMEM_RootBlock();
-    dosmem_entry*       dm;
-
-    root_block->size = DOSMEM_MemoryTop() - (((char*)root_block) + sizeof(dosmem_entry));
-
-    info_block->blocks = 0;
-    info_block->free = root_block->size;
-
-    dm = NEXT_BLOCK(root_block);
-    dm->size = DM_BLOCK_TERMINAL;
-    root_block->size |= DM_BLOCK_FREE
-#ifdef __DOSMEM_DEBUG__
-		     | DM_BLOCK_DEBUG
-#endif
-		     ;
+    MCB* first_mcb = DOSMEM_FirstMCB();
 
+    first_mcb->type = MCB_LAST;
+    first_mcb->size = (WORD) (((char *)DOSMEM_MemoryTop() - (char *)first_mcb) / 16) - 1;
+    first_mcb->psp = PSP_FREE;
+    
     TRACE( "DOS conventional memory initialized, %d bytes free.\n", 
-           DOSMEM_Available() );
+           DOSMEM_Available()*16 );
 }
 
 
@@ -414,104 +385,73 @@
  *           DOSMEM_GetBlock
  *
  * Carve a chunk of the DOS memory block (without selector).
+ * size is in paragraphs
  */
 LPVOID DOSMEM_GetBlock(UINT size, UINT16* pseg)
 {
-   UINT  	 blocksize;
-   char         *block = NULL;
-   dosmem_info  *info_block = DOSMEM_InfoBlock();
-   dosmem_entry *dm;
-#ifdef __DOSMEM_DEBUG_
-   dosmem_entry *prev = NULL;
-#endif
-
-   if( size > info_block->free ) return NULL;
-   dm = DOSMEM_RootBlock();
-
-   while (dm && dm->size != DM_BLOCK_TERMINAL)
+   MCB *curr = DOSMEM_FirstMCB();
+   MCB *next;
+   /* loop over all MCB and search the next large enough MCB*/
+   TRACE ("size= 0x%04x\n", size);
+   while (curr)
    {
-#ifdef __DOSMEM_DEBUG__
-       if( (dm->size & DM_BLOCK_DEBUG) != DM_BLOCK_DEBUG )
+DUMP_MCB (curr);
+       if( curr->psp==PSP_FREE )
        {
-	    WARN("MCB overrun! [prev = 0x%08x]\n", 4 + (UINT)prev);
-	    return NULL;
-       }
-       prev = dm;
-#endif
-       if( dm->size & DM_BLOCK_FREE )
-       {
-	   dosmem_entry  *next = NEXT_BLOCK(dm);
+	   next = NEXT_MCB(curr);
 
-	   while( next->size & DM_BLOCK_FREE ) /* collapse free blocks */
+	   while( next && next->psp==PSP_FREE ) /* collapse free blocks */
 	   {
-	       dm->size += sizeof(dosmem_entry) + (next->size & DM_BLOCK_MASK);
-	       next->size = (DM_BLOCK_FREE | DM_BLOCK_TERMINAL);
-	       next = NEXT_BLOCK(dm);
+	       curr->size += next->size + 1;
+	       next = NEXT_MCB(next);
 	   }
-
-	   blocksize = dm->size & DM_BLOCK_MASK;
-	   if( blocksize >= size )
+	   
+	   /* is it large enough (one paragaph for the MCB)? */
+	   if( curr->size >= size )
            {
-	       block = ((char*)dm) + sizeof(dosmem_entry);
-	       if( blocksize - size > 0x20 )
+	       if( curr->size > size )
 	       {
-		   /* split dm so that the next one stays
-		    * paragraph-aligned (and dm loses free bit) */
-
-	           dm->size = (((size + 0xf + sizeof(dosmem_entry)) & ~0xf) -
-			         	      sizeof(dosmem_entry));
-	           next = (dosmem_entry*)(((char*)dm) +
-	 		   sizeof(dosmem_entry) + dm->size);
-	           next->size = (blocksize - (dm->size +
-			   sizeof(dosmem_entry))) | DM_BLOCK_FREE
-#ifdef __DOSMEM_DEBUG__
-					          | DM_BLOCK_DEBUG
-#endif
-						  ;
-	       } else dm->size &= DM_BLOCK_MASK;
-
-	       info_block->blocks++;
-	       info_block->free -= dm->size;
-	       if( pseg ) *pseg = (block - DOSMEM_dosmem) >> 4;
-#ifdef __DOSMEM_DEBUG__
-               dm->size |= DM_BLOCK_DEBUG;
-#endif
-	       break;
+		   /* split curr so that the next one stays
+		    * paragraph-aligned */
+TRACE("split MCB\n");		   
+		   next = (MCB *) ((char*) curr + (size+1) * 16);
+		   next->psp = PSP_FREE;
+		   next->size = curr->size - (size+1);
+		   next->type = curr->type;
+DUMP_MCB (next);
+		   curr->type = MCB_NORMAL;
+		   curr->size = size;
+DUMP_MCB (curr);
+	       }
+	       /* curr is the found block */
+	       curr->psp = PSP_DOS;					  ;
+
+	       if( pseg ) *pseg = ((char*)curr - (char*)DOSMEM_dosmem) >> 4;
+TRACE("pseg=0x%04x\n", *pseg);		   
+	       return curr;
 	   }
- 	   dm = next;
        }
-       else dm = NEXT_BLOCK(dm);
+       curr = NEXT_MCB(curr);
    }
-   return (LPVOID)block;
+TRACE("return NULL\n");   
+   return NULL;
 }
 
 /***********************************************************************
  *           DOSMEM_FreeBlock
  */
-BOOL DOSMEM_FreeBlock(void* ptr)
+BOOL DOSMEM_FreeBlock(MCB* mcb)
 {
-   dosmem_info  *info_block = DOSMEM_InfoBlock();
-
-   if( ptr >= (void*)(((char*)DOSMEM_RootBlock()) + sizeof(dosmem_entry)) &&
-       ptr < (void*)DOSMEM_MemoryTop() && !((((char*)ptr)
-                  - DOSMEM_dosmem) & 0xf) )
+   MCB *next = NEXT_MCB(mcb);
+   
+   mcb->psp=PSP_FREE;
+   while( next && next->psp==PSP_FREE ) /* collapse free blocks */
    {
-       dosmem_entry  *dm = (dosmem_entry*)(((char*)ptr) - sizeof(dosmem_entry));
-
-       if( !(dm->size & (DM_BLOCK_FREE | DM_BLOCK_TERMINAL))
-#ifdef __DOSMEM_DEBUG__
-	 && ((dm->size & DM_BLOCK_DEBUG) == DM_BLOCK_DEBUG )
-#endif
-	 )
-       {
-	     info_block->blocks--;
-	     info_block->free += dm->size;
-
-	     dm->size |= DM_BLOCK_FREE;
-	     return TRUE;
-       }
+DUMP_MCB (next);
+      mcb->size += next->size + 1;
+      next = NEXT_MCB(next);
    }
-   return FALSE;
+   return TRUE;
 }
 
 /***********************************************************************
@@ -523,110 +463,75 @@
  * size. If exact is FALSE, block is expanded even if there is not
  * enough space for full requested block size.
  */
-UINT DOSMEM_ResizeBlock(void *ptr, UINT size, BOOL exact)
+UINT DOSMEM_ResizeBlock(MCB *mcb, UINT size, BOOL exact)
 {
-   char         *block = NULL;
-   dosmem_info  *info_block = DOSMEM_InfoBlock();
-   dosmem_entry *dm;
-   dosmem_entry *next;
-   UINT blocksize;
-   UINT orgsize;
-
-   if( (ptr < (void*)(sizeof(dosmem_entry) + (char*)DOSMEM_RootBlock())) ||
-       (ptr >= (void*)DOSMEM_MemoryTop()) ||
-       (((((char*)ptr) - DOSMEM_dosmem) & 0xf) != 0) )
-     return (UINT)-1;
-
-   dm = (dosmem_entry*)(((char*)ptr) - sizeof(dosmem_entry));
-   if( dm->size & (DM_BLOCK_FREE | DM_BLOCK_TERMINAL) )
-       return (UINT)-1;
-
-   next = NEXT_BLOCK(dm);
-   orgsize = dm->size & DM_BLOCK_MASK;
 
-   /* collapse free blocks */
-   while( next->size & DM_BLOCK_FREE )
+   MCB *next = NEXT_MCB(mcb);
+TRACE ( "size=0x%04x\n", size);
+DUMP_MCB (mcb);
+DUMP_MCB (next);
+   
+   if (size==mcb->size) return size;
+   
+   if (size<mcb->size)
    {
-       dm->size += sizeof(dosmem_entry) + (next->size & DM_BLOCK_MASK);
-       next->size = (DM_BLOCK_FREE | DM_BLOCK_TERMINAL);
-       next = NEXT_BLOCK(dm);
+TRACE ("shrink\n");      
+      next = (MCB *) ((char*) mcb + (size+1) * 16);
+      next->type = mcb->type;
+      next->psp = PSP_FREE;
+      next->size = mcb->size - (size+1);
+      mcb->type = MCB_NORMAL;
+      mcb->size = size;
+DUMP_MCB (mcb);
+DUMP_MCB (next);
+      return size;
    }
-
-   blocksize = dm->size & DM_BLOCK_MASK;
-
-   /*
-    * If collapse didn't help we either expand block to maximum
-    * available size (exact == FALSE) or give collapsed blocks
-    * back to free storage (exact == TRUE).
-    */
-   if (blocksize < size)
-       size = exact ? orgsize : blocksize;
-
-   block = ((char*)dm) + sizeof(dosmem_entry);
-   if( blocksize - size > 0x20 )
-   {
-       /*
-        * split dm so that the next one stays
-        * paragraph-aligned (and next gains free bit) 
-        */
-
-       dm->size = (((size + 0xf + sizeof(dosmem_entry)) & ~0xf) -
-                   sizeof(dosmem_entry));
-       next = (dosmem_entry*)(((char*)dm) +
-                              sizeof(dosmem_entry) + dm->size);
-       next->size = (blocksize - (dm->size +
-                                  sizeof(dosmem_entry))) | DM_BLOCK_FREE;
-   } 
-   else 
-   {
-       dm->size &= DM_BLOCK_MASK;
+   
+   if (!next || next->psp != PSP_FREE){
+      return -1;
+   }
+   
+   /* is there enough space ? */
+   if (mcb->size + next->size + 1 == size){
+      /* destroy next mcb */
+      mcb->size += next->size + 1;
+      return size; 
+   }
+   
+   if (mcb->size + next->size + 1 > size){
+      /* resize next block ? */
+      next->size -= size - mcb->size;
+      mcb->size = size;
+      return size;
    }
 
-   /*
-    * Adjust available memory if block size changes.
-    */
-   info_block->free += orgsize - dm->size;
-
-   return size;
+      
 }
 
 /***********************************************************************
  *           DOSMEM_Available
+ * returns available paragraphs
  */
 UINT DOSMEM_Available(void)
 {
-   UINT  	 blocksize, available = 0;
-   dosmem_entry *dm;
-
-   dm = DOSMEM_RootBlock();
-
-   while (dm && dm->size != DM_BLOCK_TERMINAL)
+   UINT  available = 0;
+   MCB *curr = DOSMEM_FirstMCB();
+   /* loop over all MCB an search the next large enough MCB*/
+   while (curr)
    {
-#ifdef __DOSMEM_DEBUG__
-       if( (dm->size & DM_BLOCK_DEBUG) != DM_BLOCK_DEBUG )
-       {
-	    WARN("MCB overrun! [prev = 0x%08x]\n", 4 + (UINT)prev);
-	    return NULL;
+DUMP_MCB (curr);
+       if (curr->type!=MCB_NORMAL && curr->type!=MCB_LAST){
+          ERR("MCB List Corrupt\n");
+          DUMP_MCB (curr);
+	  return 0;
        }
-       prev = dm;
-#endif
-       if( dm->size & DM_BLOCK_FREE )
+       if( curr->psp==PSP_FREE )
        {
-	   dosmem_entry  *next = NEXT_BLOCK(dm);
-
-	   while( next->size & DM_BLOCK_FREE ) /* collapse free blocks */
-	   {
-	       dm->size += sizeof(dosmem_entry) + (next->size & DM_BLOCK_MASK);
-	       next->size = (DM_BLOCK_FREE | DM_BLOCK_TERMINAL);
-	       next = NEXT_BLOCK(dm);
-	   }
-
-	   blocksize = dm->size & DM_BLOCK_MASK;
-	   if ( blocksize > available ) available = blocksize;
- 	   dm = next;
+	   if ( curr->size > available ) available = curr->size;
        }
-       else dm = NEXT_BLOCK(dm);
+       curr = NEXT_MCB(curr);
    }
+   TRACE (" 0x%04x paragraphs available\n", available);
    return available;
 }
 
Index: dlls/kernel/kernel32.spec
===================================================================
RCS file: /home/wine/wine/dlls/kernel/kernel32.spec,v
retrieving revision 1.137
diff -u -r1.137 kernel32.spec
--- dlls/kernel/kernel32.spec	7 Jul 2004 00:49:34 -0000	1.137
+++ dlls/kernel/kernel32.spec	30 Jul 2004 15:14:05 -0000
@@ -1180,3 +1180,4 @@
 @ cdecl LOCAL_Size(long long)
 @ cdecl LOCAL_Unlock(long long)
 @ stdcall NE_DefResourceHandler(long long long)
+@ cdecl DOSMEM_SegFirstMCB()
Index: dlls/ntdll/exception.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/exception.c,v
retrieving revision 1.69
diff -u -r1.69 exception.c
--- dlls/ntdll/exception.c	20 Feb 2004 20:19:23 -0000	1.69
+++ dlls/ntdll/exception.c	30 Jul 2004 15:14:07 -0000
@@ -236,12 +236,15 @@
 #ifdef __i386__
     else
     {
-        TRACE(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
+        TRACE(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx eip=%08lx\n",
               context->Eax, context->Ebx, context->Ecx,
-              context->Edx, context->Esi, context->Edi );
+              context->Edx, context->Esi, context->Edi, context->Eip );
         TRACE(" ebp=%08lx esp=%08lx cs=%04lx ds=%04lx es=%04lx fs=%04lx gs=%04lx flags=%08lx\n",
               context->Ebp, context->Esp, context->SegCs, context->SegDs,
               context->SegEs, context->SegFs, context->SegGs, context->EFlags );
+        TRACE(" dr0=%08lx dr1=%08lx dr2=%08lx dr3=%08lx dr6=%08lx dr7=%08lx\n",
+              context->Dr0, context->Dr1, context->Dr2, context->Dr3,
+              context->Dr6, context->Dr7 );
     }
 #endif
 
Index: dlls/winedos/devices.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/devices.c,v
retrieving revision 1.11
diff -u -r1.11 devices.c
--- dlls/winedos/devices.c	15 Nov 2003 00:13:21 -0000	1.11
+++ dlls/winedos/devices.c	30 Jul 2004 15:14:09 -0000
@@ -26,6 +26,8 @@
 
 #include "pshpack1.h"
 
+#include "miscemu.h"
+
 typedef struct {
   BYTE ljmp1;
   RMCBPROC strategy;
@@ -475,7 +477,7 @@
   DOS_LOL->sharing_retry_delay	= 1;
   DOS_LOL->ptr_disk_buf		= 0x0;
   DOS_LOL->offs_unread_CON		= 0x0;
-  DOS_LOL->seg_first_MCB		= 0x0;
+  DOS_LOL->seg_first_MCB		= DOSMEM_SegFirstMCB();
   DOS_LOL->ptr_first_DPB		= 0x0;
   DOS_LOL->ptr_first_SysFileTable	= 0x0;
   DOS_LOL->ptr_clock_dev_hdr		= 0x0;
Index: dlls/winedos/int21.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int21.c,v
retrieving revision 1.64
diff -u -r1.64 int21.c
--- dlls/winedos/int21.c	12 Jul 2004 19:53:24 -0000	1.64
+++ dlls/winedos/int21.c	30 Jul 2004 15:14:16 -0000
@@ -2668,7 +2668,15 @@
     struct stat st;
     int status, i, fd;
     HANDLE handle = DosFileHandleToWin32Handle(BX_reg(context));
-
+    int dos_handle;
+    
+    /* check for STDIO devices */
+    dos_handle = BX_reg (context);
+    if (dos_handle==0 || dos_handle==1 || dos_handle ==2){
+        SET_DX( context, 0x80d3 );
+        return;        
+    }
+    
     status = wine_server_handle_to_fd( handle, 0, &fd, NULL, NULL );
     if (status)
     {
@@ -2731,7 +2739,8 @@
              * FIXME: Should check if file is on remote or removable drive.
              * FIXME: Should use drive file is located on (and not current).
              */
-            SET_DX( context, 0x0140 + INT21_GetCurrentDrive() );
+//            SET_DX( context, 0x0140 + INT21_GetCurrentDrive() );
+            SET_DX( context, 0x0 + INT21_GetCurrentDrive() );
         }
         break;
 
@@ -4450,7 +4459,6 @@
             SET_BH( context, 0xff ); /* OEM number => undefined */
         else
             SET_BH( context, 0x08 ); /* version flag => DOS is in ROM */
-
         SET_AL( context, HIBYTE(HIWORD(GetVersion16())) ); /* major version */
         SET_AH( context, LOBYTE(HIWORD(GetVersion16())) ); /* minor version */
 
@@ -4827,7 +4835,7 @@
                 selector = LOWORD( rv );
             }
             else
-                DOSMEM_GetBlock( bytes, &selector );
+                DOSMEM_GetBlock( BX_reg(context), &selector );
 
             if (selector)
             {
@@ -4838,7 +4846,7 @@
             {
                 SET_CFLAG(context);
                 SET_AX( context, 0x0008 ); /* insufficient memory */
-                SET_BX( context, DOSMEM_Available() >> 4 );
+                SET_BX( context, DOSMEM_Available() );
             }
         }
 	break;
@@ -4857,7 +4865,7 @@
                     context->SegEs = 0;
             }
             else
-                ok = DOSMEM_FreeBlock( (void*)((DWORD)context->SegEs << 4) );
+                ok = DOSMEM_FreeBlock( (void*)((DWORD)(context->SegEs-1) << 4) );
 
             if (!ok)
             {
@@ -4881,8 +4889,8 @@
             }
             else
             {
-                LPVOID address = (void*)((DWORD)context->SegEs << 4);
-                UINT blocksize = DOSMEM_ResizeBlock( address, newsize, FALSE );
+                LPVOID address = (void*)((DWORD)(context->SegEs-1) << 4);
+                UINT blocksize = DOSMEM_ResizeBlock( address, BX_reg(context), FALSE );
 
                 RESET_CFLAG(context);
                 if (blocksize == (UINT)-1)
@@ -4979,6 +4987,11 @@
             context->SegEs = SELECTOROF(ptr);
             SET_BX( context, OFFSETOF(ptr) );
         }
+        break;
+
+    case 0x53: /* TRANSLATE BPB to DPB */
+        FIXME("TRANSLATE BPB to DPB stub\n");
+	SET_AL( context, 0);
         break;
 
     case 0x54: /* Get Verify Flag */
Index: dlls/winedos/int2f.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int2f.c,v
retrieving revision 1.6
diff -u -r1.6 int2f.c
--- dlls/winedos/int2f.c	23 Jan 2004 01:51:33 -0000	1.6
+++ dlls/winedos/int2f.c	30 Jul 2004 15:14:17 -0000
@@ -193,6 +193,21 @@
            INT_BARF( context, 0x2f );
        }
        break;
+    case 0x55:  /* ROM COMMAND.COM */
+       switch(LOBYTE(context->Eax))
+       {
+       case 0x00:  /* COMMAND.COM INTERFACE */
+           FIXME("COMMAND.COM INTERFACE - not implemented\n");
+           SET_AX( context, 0 );
+           break;
+       case 0x01:  /* ROM COMMAND.COM INTERFACE */
+           FIXME("ROM COMMAND.COM INTERFACE - not implemented\n");
+           SET_AX( context, 0 );
+           break;
+       default:
+           INT_BARF( context, 0x2f );
+       }
+       break;
     case 0x56:  /* INTERLNK */
        switch(LOBYTE(context->Eax))
        {
Index: dlls/winedos/int31.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int31.c,v
retrieving revision 1.41
diff -u -r1.41 int31.c
--- dlls/winedos/int31.c	25 Nov 2003 00:42:27 -0000	1.41
+++ dlls/winedos/int31.c	30 Jul 2004 15:14:19 -0000
@@ -470,8 +470,11 @@
     if (!already) {
         if (!context->SegSs) {
             alloc = 1; /* allocate default stack */
-            stack16 = addr = DOSMEM_GetBlock( 64, (UINT16 *)&(context->SegSs) );
-            context->Esp = 64-2;
+            stack16 = addr = DOSMEM_GetBlock( 64/16, (UINT16 *)&(context->SegSs) );
+            stack16+=16;
+	    addr+=16;
+	    context->SegSs++;
+	    context->Esp = 64-2;
             stack16 += 32-1;
             if (!addr) {
                 ERR("could not allocate default stack\n");
@@ -511,7 +514,7 @@
         DOSVM_Enter( context );
         TRACE("returned from real-mode call\n");
     }
-    if (alloc) DOSMEM_FreeBlock( addr );
+    if (alloc) DOSMEM_FreeBlock( addr-16 );
     return 0;
 }
 
@@ -649,7 +652,9 @@
 
     if (NewRMCB)
     {
-	LPVOID RMCBmem = DOSMEM_GetBlock(4, &uParagraph);
+	LPVOID RMCBmem = DOSMEM_GetBlock(1, &uParagraph);
+	RMCBmem+=16;
+	uParagraph++;
 	LPBYTE p = RMCBmem;
 
 	*p++ = 0xcd; /* RMCB: */
@@ -697,7 +702,7 @@
 	PrevRMCB->next = CurrRMCB->next;
 	    else
 	FirstRMCB = CurrRMCB->next;
-	DOSMEM_FreeBlock(PTR_REAL_TO_LIN(SELECTOROF(CurrRMCB->address),OFFSETOF(CurrRMCB->address)));
+	DOSMEM_FreeBlock(PTR_REAL_TO_LIN(SELECTOROF(CurrRMCB->address),OFFSETOF(CurrRMCB->address))-16);
 	HeapFree(GetProcessHeap(), 0, CurrRMCB);
 	return 0;
     }
@@ -1042,7 +1047,7 @@
                 SET_DX( context, LOWORD(dw) );
             } else {
                 SET_AX( context, 0x0008 ); /* insufficient memory */
-                SET_BX( context, DOSMEM_Available() >> 4 );
+                SET_BX( context, DOSMEM_Available());
                 SET_CFLAG(context);
             }
             break;
Index: dlls/winedos/module.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/module.c,v
retrieving revision 1.42
diff -u -r1.42 module.c
--- dlls/winedos/module.c	20 Jan 2004 01:25:17 -0000	1.42
+++ dlls/winedos/module.c	30 Jul 2004 15:14:20 -0000
@@ -166,7 +166,9 @@
   while (env[sz++]) sz+=strlen(env+sz)+1;
  } else sz++;
  /* allocate it */
- envblk=DOSMEM_GetBlock(sz+sizeof(WORD)+strlen(name)+1,&seg);
+ envblk=DOSMEM_GetBlock( (sz+sizeof(WORD)+strlen(name)+1+15)/16 ,&seg);
+ seg++;
+ envblk+=16;
  /* fill it */
  if (env) {
   memcpy(envblk,env,sz);
@@ -253,20 +255,23 @@
     env_seg=MZ_InitEnvironment(oldenv, filename);
 
     /* allocate memory for the executable */
-    TRACE("Allocating DOS memory (min=%ld, max=%ld)\n",min_size,max_size);
-    avail=DOSMEM_Available();
+    ERR("Allocating DOS memory (min=%ld, max=%ld)\n",min_size,max_size);
+    avail=DOSMEM_Available()*16;
     if (avail<min_size) {
       ERR("insufficient DOS memory\n");
       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
       goto load_error;
     }
     if (avail>max_size) avail=max_size;
-    psp_start=DOSMEM_GetBlock(avail,&DOSVM_psp);
+    psp_start=DOSMEM_GetBlock(avail/16,&DOSVM_psp);
+    DOSVM_psp++;
+    ERR("DOSVM_psp=0x%04x\n");
     if (!psp_start) {
       ERR("error allocating DOS memory\n");
       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
       goto load_error;
     }
+    psp_start+=16;
     load_seg=DOSVM_psp+(old_com?0:PSP_SIZE);
     rel_seg=load_seg;
     load_start=psp_start+(PSP_SIZE<<4);
@@ -274,7 +279,7 @@
   }
 
  /* load executable image */
- TRACE("loading DOS %s image, %08lx bytes\n",old_com?"COM":"EXE",image_size);
+ ERR("loading DOS %s image, %08lx bytes\n",old_com?"COM":"EXE",image_size);
  SetFilePointer(hFile,image_start,NULL,FILE_BEGIN);
  if (!ReadFile(hFile,load_start,image_size,&len,NULL) || len != image_size) {
   /* check if this is due to the workaround for the pre-1.10 MS linker and we
@@ -287,7 +292,7 @@
 
  if (mz_header.e_crlc) {
   /* load relocation table */
-  TRACE("loading DOS EXE relocation table, %d entries\n",mz_header.e_crlc);
+  ERR("loading DOS EXE relocation table, %d entries\n",mz_header.e_crlc);
   /* FIXME: is this too slow without read buffering? */
   SetFilePointer(hFile,mz_header.e_lfarlc,NULL,FILE_BEGIN);
   for (x=0; x<mz_header.e_crlc; x++) {
@@ -305,7 +310,7 @@
     init_ss = load_seg+mz_header.e_ss;
     init_sp = mz_header.e_sp;
 
-    TRACE("entry point: %04x:%04x\n",init_cs,init_ip);
+    ERR("entry point: %04x:%04x\n",init_cs,init_ip);
   }
 
   if (alloc && !MZ_InitTask()) {
@@ -417,6 +422,11 @@
 
   BOOL ret = FALSE;
 
+  if (func!=0 && func!=1 && func!= 2 && func!=3){
+    SetLastError(ERROR_INVALID_FUNCTION);
+    return FALSE;  
+  }
+  
   if(!GetBinaryTypeA(filename, &binType))   /* determine what kind of binary this is */
   {
     return FALSE; /* binary is not an executable */
@@ -656,8 +666,8 @@
       /* FIXME: deallocate file handles etc */
       /* free process's associated memory
        * FIXME: walk memory and deallocate all blocks owned by process */
-      DOSMEM_FreeBlock( PTR_REAL_TO_LIN(psp->environment,0) );
-      DOSMEM_FreeBlock( PTR_REAL_TO_LIN(DOSVM_psp,0) );
+      DOSMEM_FreeBlock( PTR_REAL_TO_LIN(psp->environment,0)-16 );
+      DOSMEM_FreeBlock( PTR_REAL_TO_LIN(DOSVM_psp,0)-16 );
       /* switch to parent's PSP */
       DOSVM_psp = parpsp;
       psp_start = (LPBYTE)((DWORD)parpsp << 4);
Index: include/miscemu.h
===================================================================
RCS file: /home/wine/wine/include/miscemu.h,v
retrieving revision 1.77
diff -u -r1.77 miscemu.h
--- include/miscemu.h	9 Jan 2004 22:18:49 -0000	1.77
+++ include/miscemu.h	30 Jul 2004 15:14:21 -0000
@@ -93,15 +93,31 @@
 extern WORD DOSMEM_BiosSysSeg;
 
 /* msdos/dosmem.c */
+#define MCB_NORMAL      0x4d
+#define MCB_LAST        0x5a
+
+#define PSP_DOS         0x0060  
+#define PSP_FREE        0
+
+
+typedef struct {
+    BYTE type;
+    WORD psp;     /* segment of owner psp */
+    WORD size;    /* in paragraphs */
+    BYTE pad[3];
+    BYTE name[8];
+} MCB;
+
 extern BOOL DOSMEM_Init(BOOL);
 extern void   DOSMEM_Tick(WORD timer);
 extern WORD   DOSMEM_AllocSelector(WORD);
 extern LPVOID DOSMEM_GetBlock(UINT size, WORD* p);
-extern BOOL DOSMEM_FreeBlock(void* ptr);
-extern UINT DOSMEM_ResizeBlock(void* ptr, UINT size, BOOL exact);
+extern BOOL DOSMEM_FreeBlock(MCB* mcb);
+extern UINT DOSMEM_ResizeBlock(MCB* mcb, UINT size, BOOL exact);
 extern UINT DOSMEM_Available(void);
 extern LPVOID DOSMEM_MapRealToLinear(DWORD); /* real-mode to linear */
 extern LPVOID DOSMEM_MapDosToLinear(UINT); /* linear DOS to Wine */
 extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
+extern WORD   DOSMEM_SegFirstMCB(void);
 
 #endif /* __WINE_MISCEMU_H */
