[NTVDM]: Zero-fill memory with RtlZeroMemory (that exists also in NT mode), and use...
[reactos.git] / reactos / subsystems / ntvdm / dos / dos32krnl / dos.c
index 6925c26..f98ef75 100644 (file)
 #define NDEBUG
 
 #include "emulator.h"
-#include "callback.h"
+#include "cpu/cpu.h"
+#include "int32.h"
 
 #include "dos.h"
 #include "dos/dem.h"
 
 #include "bios/bios.h"
-#include "registers.h"
 
 /* PRIVATE VARIABLES **********************************************************/
 
@@ -419,6 +419,9 @@ static WORD DosCopyEnvironmentBlock(LPCVOID Environment, LPCSTR ProgramName)
     /* Add the string buffer size */
     TotalSize += strlen(ProgramName) + 1;
 
+    /* Add the two extra bytes */
+    TotalSize += 2;
+
     /* Allocate the memory for the environment block */
     DestSegment = DosAllocateMemory((WORD)((TotalSize + 0x0F) >> 4), NULL);
     if (!DestSegment) return 0;
@@ -442,6 +445,10 @@ static WORD DosCopyEnvironmentBlock(LPCVOID Environment, LPCSTR ProgramName)
     /* Set the final zero */
     *(DestBuffer++) = 0;
 
+    /* Store the special program name tag */
+    *(DestBuffer++) = LOBYTE(DOS_PROGRAM_NAME_TAG);
+    *(DestBuffer++) = HIBYTE(DOS_PROGRAM_NAME_TAG);
+
     /* Copy the program name after the environment block */
     strcpy(DestBuffer, ProgramName);
 
@@ -853,7 +860,7 @@ VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WOR
     PDOS_PSP PspBlock = SEGMENT_TO_PSP(PspSegment);
     LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
 
-    ZeroMemory(PspBlock, sizeof(DOS_PSP));
+    RtlZeroMemory(PspBlock, sizeof(*PspBlock));
 
     /* Set the exit interrupt */
     PspBlock->Exit[0] = 0xCD; // int 0x20
@@ -911,6 +918,7 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
     PIMAGE_DOS_HEADER Header;
     PDWORD RelocationTable;
     PWORD RelocWord;
+    LPSTR CmdLinePtr = (LPSTR)CommandLine;
 
     DPRINT1("DosLoadExecutable(%d, %s, %s, %s, 0x%08X, 0x%08X)\n",
             LoadType,
@@ -926,6 +934,10 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
         return ERROR_NOT_SUPPORTED;
     }
 
+    /* NULL-terminate the command line by removing the return carriage character */
+    while (*CmdLinePtr && *CmdLinePtr != '\r') CmdLinePtr++;
+    *CmdLinePtr = '\0';
+
     /* Open a handle to the executable */
     FileHandle = CreateFileA(ExecutablePath,
                              GENERIC_READ,
@@ -1003,7 +1015,7 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
         /* Check if at least the lowest allocation was successful */
         if (Segment == 0)
         {
-            Result = ERROR_NOT_ENOUGH_MEMORY;
+            Result = DosLastError;
             goto Cleanup;
         }
 
@@ -1044,14 +1056,14 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
             setES(Segment);
 
             /* Set the stack to the location from the header */
-            EmulatorSetStack(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss,
-                             Header->e_sp);
+            setSS(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss);
+            setSP(Header->e_sp);
 
             /* Execute */
             CurrentPsp = Segment;
             DiskTransferArea = MAKELONG(0x80, Segment);
-            EmulatorExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4),
-                            Header->e_ip);
+            CpuExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4),
+                       Header->e_ip);
         }
     }
     else
@@ -1072,7 +1084,7 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
         Segment = DosAllocateMemory(MaxAllocSize, NULL);
         if (Segment == 0)
         {
-            Result = ERROR_ARENA_TRASHED;
+            Result = DosLastError;
             goto Cleanup;
         }
 
@@ -1098,7 +1110,8 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
             setES(Segment);
 
             /* Set the stack to the last word of the segment */
-            EmulatorSetStack(Segment, 0xFFFE);
+            setSS(Segment);
+            setSP(0xFFFE);
 
             /*
              * Set the value on the stack to 0, so that a near return
@@ -1109,7 +1122,7 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
             /* Execute */
             CurrentPsp = Segment;
             DiskTransferArea = MAKELONG(0x80, Segment);
-            EmulatorExecute(Segment, 0x100);
+            CpuExecute(Segment, 0x100);
         }
     }
 
@@ -1153,7 +1166,7 @@ DWORD DosStartProcess(IN LPCSTR ExecutablePath,
 
     /* Start simulation */
     SetEvent(VdmTaskEvent);
-    EmulatorSimulate();
+    CpuSimulate();
 
     /* Detach from the console */
     VidBiosDetachFromConsole(); // FIXME: And in fact, detach the full NTVDM UI from the console
@@ -1191,8 +1204,8 @@ WORD DosCreateProcess(DOS_EXEC_TYPE LoadType,
     }
 
     /* Set up the startup info structure */
-    ZeroMemory(&StartupInfo, sizeof(STARTUPINFOA));
-    StartupInfo.cb = sizeof(STARTUPINFOA);
+    RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
+    StartupInfo.cb = sizeof(StartupInfo);
 
     /* Create the process */
     if (!CreateProcessA(ProgramName,
@@ -1217,7 +1230,7 @@ WORD DosCreateProcess(DOS_EXEC_TYPE LoadType,
         case SCS_WOW_BINARY:
         {
             /* Clear the structure */
-            ZeroMemory(&CommandInfo, sizeof(CommandInfo));
+            RtlZeroMemory(&CommandInfo, sizeof(CommandInfo));
 
             /* Initialize the structure members */
             CommandInfo.TaskId = SessionId;
@@ -1332,7 +1345,7 @@ Done:
         if (CurrentPsp == SYSTEM_PSP)
         {
             ResetEvent(VdmTaskEvent);
-            EmulatorUnsimulate();
+            CpuUnsimulate();
         }
     }
 
@@ -1349,7 +1362,7 @@ Done:
         GetNextVDMCommand(&CommandInfo);
 
         /* Clear the structure */
-        ZeroMemory(&CommandInfo, sizeof(CommandInfo));
+        RtlZeroMemory(&CommandInfo, sizeof(CommandInfo));
 
         /* Update the VDM state of the task */
         CommandInfo.TaskId = SessionId;
@@ -1362,8 +1375,8 @@ Done:
     DosErrorLevel = MAKEWORD(ReturnCode, 0x00);
 
     /* Return control to the parent process */
-    EmulatorExecute(HIWORD(PspBlock->TerminateAddress),
-                    LOWORD(PspBlock->TerminateAddress));
+    CpuExecute(HIWORD(PspBlock->TerminateAddress),
+               LOWORD(PspBlock->TerminateAddress));
 }
 
 BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle)
@@ -1393,15 +1406,18 @@ BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle)
             {
                 /* Console input */
                 InfoWord |= 1 << 0;
+
+                /* It is a device */
+                InfoWord |= 1 << 7;
             }
             else if (Handle == DosSystemFileTable[DOS_OUTPUT_HANDLE].Handle)
             {
                 /* Console output */
                 InfoWord |= 1 << 1;
-            }
 
-            /* It is a device */
-            InfoWord |= 1 << 7;
+                /* It is a device */
+                InfoWord |= 1 << 7;
+            }
 
             /* Return the device information word */
             setDX(InfoWord);
@@ -1740,7 +1756,8 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         case 0x25:
         {
             ULONG FarPointer = MAKELONG(getDX(), getDS());
-            DPRINT1("Setting interrupt 0x%x ...\n", getAL());
+            DPRINT1("Setting interrupt 0x%02X to %04X:%04X ...\n",
+                    getAL(), HIWORD(FarPointer), LOWORD(FarPointer));
 
             /* Write the new far pointer to the IDT */
             ((PULONG)BaseAddress)[getAL()] = FarPointer;
@@ -1825,8 +1842,9 @@ VOID WINAPI DosInt21h(LPWORD Stack)
                  * Return DOS OEM number:
                  * 0x00 for IBM PC-DOS
                  * 0x02 for packaged MS-DOS
+                 * 0xFF for NT DOS
                  */
-                setBH(0x02);
+                setBH(0xFF);
             }
 
             if (LOBYTE(PspBlock->DosVersion) >= 5 && getAL() == 0x01)
@@ -2564,6 +2582,14 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             break;
         }
 
+        /* Get Extended Error Information */
+        case 0x59:
+        {
+            DPRINT1("INT 21h, AH = 59h, BX = %04Xh - Get Extended Error Information is UNIMPLEMENTED\n",
+                    getBX());
+            break;
+        }
+
         /* Create Temporary File */
         case 0x5A:
         {
@@ -2760,6 +2786,10 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         /* Extended Open/Create */
         case 0x6C:
         {
+            WORD FileHandle;
+            WORD CreationStatus;
+            WORD ErrorCode;
+
             /* Check for AL == 00 */
             if (getAL() != 0x00)
             {
@@ -2768,10 +2798,31 @@ VOID WINAPI DosInt21h(LPWORD Stack)
                 break;
             }
 
-            // TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-            // FIXME: Extend and merge DosOpenFile and DosCreateFile into
-            // a single wrapper around CreateFileA, which acts as:
-            // http://www.ctyme.com/intr/rb-3179.htm
+            /*
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-3179.htm
+             * for the full detailed description.
+             *
+             * WARNING: BH contains some extended flags that are NOT SUPPORTED.
+             */
+
+            ErrorCode = DosCreateFileEx(&FileHandle,
+                                        &CreationStatus,
+                                        (LPCSTR)SEG_OFF_TO_PTR(getDS(), getSI()),
+                                        getBL(),
+                                        getDL(),
+                                        getCX());
+
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+                setCX(CreationStatus);
+                setAX(FileHandle);
+            }
+            else
+            {
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+                setAX(ErrorCode);
+            }
 
             break;
         }
@@ -2794,7 +2845,7 @@ VOID WINAPI DosBreakInterrupt(LPWORD Stack)
 
     /* Stop the VDM task */
     ResetEvent(VdmTaskEvent);
-    EmulatorUnsimulate();
+    CpuUnsimulate();
 }
 
 VOID WINAPI DosFastConOut(LPWORD Stack)
@@ -2850,7 +2901,7 @@ BOOLEAN DosKRNLInitialize(VOID)
     WCHAR Buffer[256];
 
     /* Clear the current directory buffer */
-    ZeroMemory(CurrentDirectories, sizeof(CurrentDirectories));
+    RtlZeroMemory(CurrentDirectories, sizeof(CurrentDirectories));
 
     /* Get the current directory */
     if (!GetCurrentDirectoryA(MAX_PATH, CurrentDirectory))