[NTVDM]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 11 May 2014 19:25:09 +0000 (19:25 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 11 May 2014 19:25:09 +0000 (19:25 +0000)
- Continue to work on VGA attach/detach from console;
- Stick more #if(n)def STANDALONE to portions of code that are useful (or not) in standalone (i.e. not in OS-integrated) mode;
- Isolate the Dos***File functions in a new source file;
- Get rid of STACK_COUNTER, STACK_VAR_A and STACK_VAR_B since we now use 32-->16 bit callbacks (and therefore adjust the callback/INT32 trampoline stubs accordingly).

svn path=/trunk/; revision=63238

17 files changed:
reactos/subsystems/ntvdm/CMakeLists.txt
reactos/subsystems/ntvdm/bios/bios32/kbdbios32.c
reactos/subsystems/ntvdm/bios/kbdbios.h
reactos/subsystems/ntvdm/bios/vidbios.c
reactos/subsystems/ntvdm/bios/vidbios.h
reactos/subsystems/ntvdm/callback.c
reactos/subsystems/ntvdm/dos/dem.c
reactos/subsystems/ntvdm/dos/dos32krnl/bios.c
reactos/subsystems/ntvdm/dos/dos32krnl/dos.c
reactos/subsystems/ntvdm/dos/dos32krnl/dos.h
reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c [new file with mode: 0644]
reactos/subsystems/ntvdm/emulator.c
reactos/subsystems/ntvdm/emulator.h
reactos/subsystems/ntvdm/hardware/vga.c
reactos/subsystems/ntvdm/int32.c
reactos/subsystems/ntvdm/ntvdm.c
reactos/subsystems/ntvdm/ntvdm.h

index 80ab3e9..2ee9f55 100644 (file)
@@ -21,6 +21,7 @@ list(APPEND SOURCE
     hardware/vga.c
     dos/dos32krnl/bios.c
     dos/dos32krnl/dos.c
+    dos/dos32krnl/dosfiles.c
     dos/dem.c
     bop.c
     callback.c
index 9d95ccd..716af1f 100644 (file)
@@ -91,22 +91,13 @@ static WORD BiosPeekCharacter(VOID)
     else return 0xFFFF;
 }
 
-WORD BiosGetCharacter(VOID)
+static WORD BiosGetCharacter(VOID)
 {
     WORD CharacterData = 0;
 
-    /* Check if there is a key available */
-    if (BiosKbdBufferTop(&CharacterData))
-    {
-        /* A key was available, remove it from the queue */
-        BiosKbdBufferPop();
-    }
-    else
-    {
-        /* No key available. Set the handler CF to repeat the BOP */
-        setCF(1);
-        // CharacterData = 0xFFFF;
-    }
+    /* Check if there is a key available, and if so, remove it from the queue */
+    if (BiosKbdBufferTop(&CharacterData)) BiosKbdBufferPop();
+    else CharacterData = 0xFFFF;
 
     return CharacterData;
 }
@@ -121,7 +112,17 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
         case 0x10:  // FIXME: Temporarily do the same as INT 16h, 00h
         {
             /* Read the character (and wait if necessary) */
-            setAX(BiosGetCharacter());
+            WORD Character = BiosGetCharacter();
+
+            if (Character == 0xFFFF)
+            {
+                /* No key available. Set the handler CF to repeat the BOP */
+                setCF(1);
+                break;
+            }
+
+            setAX(Character);
+
             break;
         }
 
@@ -130,13 +131,13 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
         /* Get extended keystroke status */
         case 0x11:  // FIXME: Temporarily do the same as INT 16h, 01h
         {
-            WORD Data = BiosPeekCharacter();
+            WORD Character = BiosPeekCharacter();
 
-            if (Data != 0xFFFF)
+            if (Character != 0xFFFF)
             {
                 /* There is a character, clear ZF and return it */
                 Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
-                setAX(Data);
+                setAX(Character);
             }
             else
             {
index 4648678..1d8798a 100644 (file)
@@ -21,8 +21,6 @@
 
 /* FUNCTIONS ******************************************************************/
 
-WORD BiosGetCharacter(VOID);
-
 BOOLEAN KbdBiosInitialize(VOID);
 VOID KbdBiosCleanup(VOID);
 
index cec5a70..41d22d3 100644 (file)
@@ -1532,6 +1532,37 @@ VOID WINAPI VidBiosVideoService(LPWORD Stack)
     }
 }
 
+
+/*
+ * Those attach / detach functions are work-in-progress
+ */
+
+static BOOL Attached = TRUE;
+
+VOID VidBiosAttachToConsole(VOID)
+{
+    // VgaRefreshDisplay();
+    if (!Attached)
+    {
+        VgaAttachToConsole();
+        Attached = TRUE;
+    }
+
+    VgaRefreshDisplay();
+    VidBiosSyncCursorPosition();
+}
+
+VOID VidBiosDetachFromConsole(VOID)
+{
+    /* Perform another screen refresh */
+    VgaRefreshDisplay();
+
+    /* Detach from the console */
+    VgaDetachFromConsole(FALSE);
+    Attached = FALSE;
+}
+
+
 BOOLEAN VidBiosInitialize(VOID)
 {
     /* Some interrupts are in fact addresses to tables */
@@ -1541,6 +1572,15 @@ BOOLEAN VidBiosInitialize(VOID)
     ((PULONG)BaseAddress)[0x43] = (ULONG)NULL;
     ((PULONG)BaseAddress)[0x44] = (ULONG)NULL;
 
+    //
+    // FIXME: At the moment we always set a VGA mode. In the future,
+    // we should set this mode **only** when:
+    // - an app starts to use directly the video memory
+    //   (that should be done in emulator.c)
+    // - or starts to use non-stream I/O interrupts
+    //   (that should be done here, or maybe in VGA ??)
+    //
+
     /* Set the default video mode */
     VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
 
index 70b3e54..5e29147 100644 (file)
@@ -37,9 +37,12 @@ enum
 
 /* FUNCTIONS ******************************************************************/
 
+VOID VidBiosSyncCursorPosition(VOID);
+
 VOID WINAPI VidBiosVideoService(LPWORD Stack);
 
-VOID VidBiosSyncCursorPosition(VOID);
+VOID VidBiosDetachFromConsole(VOID);
+VOID VidBiosAttachToConsole(VOID);
 
 BOOLEAN VidBiosInitialize(VOID);
 VOID VidBiosCleanup(VOID);
index 34c0bcc..feed3d8 100644 (file)
@@ -44,6 +44,13 @@ do {                                 \
 #define CALL16_TRAMPOLINE_SIZE  (1 * sizeof(ULONGLONG))
 #define  INT16_TRAMPOLINE_SIZE  (1 * sizeof(ULONGLONG))
 
+//
+// WARNING WARNING!!
+//
+// If you modify the code stubs here, think also
+// about updating them in int32.c too!!
+//
+
 /* 16-bit generic interrupt code for calling a 32-bit interrupt handler */
 BYTE Int16To32[] =
 {
@@ -52,12 +59,6 @@ BYTE Int16To32[] =
     /* Push the value of the interrupt to be called */
     0x6A, 0xFF,         // push i (patchable to 0x6A, 0xIntNum)
 
-    /* The counter variable (initialized to 0) */
-    0x6A, 0x00,         // push 0
-
-    /* Stack variables */
-    0x83, 0xEC, 0x04,   // sub sp, 4
-
     /* The BOP Sequence */
 // BOP_SEQ:
     0xF8,               // clc
@@ -74,7 +75,8 @@ BYTE Int16To32[] =
     0xEB, 0xF5,         // jmp BOP_SEQ (offset -11)
 
 // EXIT:
-    0x83, 0xC4, 0x08,   // add sp, 8
+    // 0x44, 0x44,         // inc sp, inc sp
+    0x83, 0xC4, 0x02,   // add sp, 2
     0xCF,               // iret
 };
 
index f78dab8..f0b251d 100644 (file)
@@ -21,7 +21,6 @@
 #include "bop.h"
 
 #include "bios/bios.h"
-#include "hardware/vga.h"
 
 /* Extra PSDK/NDK Headers */
 #include <ndk/obtypes.h>
@@ -138,8 +137,7 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
 
             StartupInfo.cb = sizeof(StartupInfo);
 
-            VgaRefreshDisplay();
-            VgaDetachFromConsole(FALSE);
+            VidBiosDetachFromConsole();
 
             Result = CreateProcessA(NULL,
                                     CommandLine,
@@ -171,9 +169,7 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
                 dwExitCode = GetLastError();
             }
 
-            VgaAttachToConsole();
-            VgaRefreshDisplay();
-            VidBiosSyncCursorPosition();
+            VidBiosAttachToConsole();
 
             setAL((UCHAR)dwExitCode);
 
index b7ce9d3..32057e5 100644 (file)
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
-#if 0
-static WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten)
-{
-    WORD Result = ERROR_SUCCESS;
-    DWORD BytesWritten32 = 0;
-    HANDLE Handle = DosGetRealHandle(FileHandle);
-    WORD i;
-
-    DPRINT("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n",
-           FileHandle,
-           Count);
-
-    /* Make sure the handle is valid */
-    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
-
-    if (IsConsoleHandle(Handle))
-    {
-        for (i = 0; i < Count; i++)
-        {
-            /* Call the BIOS to print the character */
-            VidBiosPrintCharacter(((LPBYTE)Buffer)[i], DOS_CHAR_ATTRIBUTE, Bda->VideoPage);
-            BytesWritten32++;
-        }
-    }
-    else
-    {
-        /* Write the file */
-        if (!WriteFile(Handle, Buffer, Count, &BytesWritten32, NULL))
-        {
-            /* Store the error code */
-            Result = (WORD)GetLastError();
-        }
-    }
-
-    /* The number of bytes written is always 16-bit */
-    *BytesWritten = LOWORD(BytesWritten32);
-
-    /* Return the error code */
-    return Result;
-}
-#endif
-
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-CHAR DosReadCharacter(VOID)
+CHAR DosReadCharacter(WORD FileHandle)
 {
     CHAR Character = '\0';
     WORD BytesRead;
 
-    if (IsConsoleHandle(DosGetRealHandle(DOS_INPUT_HANDLE)))
-    {
-        /* Call the BIOS */
-        Character = LOBYTE(BiosGetCharacter());
-    }
-    else
-    {
-        /* Use the file reading function */
-        DosReadFile(DOS_INPUT_HANDLE, &Character, sizeof(CHAR), &BytesRead);
-    }
+    /* Use the file reading function */
+    DosReadFile(FileHandle, &Character, 1, &BytesRead);
 
     return Character;
 }
@@ -117,12 +67,12 @@ BOOLEAN DosCheckInput(VOID)
     }
 }
 
-VOID DosPrintCharacter(CHAR Character)
+VOID DosPrintCharacter(WORD FileHandle, CHAR Character)
 {
     WORD BytesWritten;
 
     /* Use the file writing function */
-    DosWriteFile(DOS_OUTPUT_HANDLE, &Character, sizeof(CHAR), &BytesWritten);
+    DosWriteFile(FileHandle, &Character, 1, &BytesWritten);
 }
 
 BOOLEAN DosBIOSInitialize(VOID)
index f1f9fff..6ce7e3f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * COPYRIGHT:       GPL - See COPYING in the top level directory
  * PROJECT:         ReactOS Virtual DOS Machine
- * FILE:            dos.c
+ * FILE:            dos/dos32krnl/dos.c
  * PURPOSE:         VDM DOS Kernel
  * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
  */
@@ -29,8 +29,13 @@ static DWORD DiskTransferArea;
 /*static*/ BYTE CurrentDrive;
 static CHAR LastDrive = 'E';
 static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
-static HANDLE DosSystemFileTable[DOS_SFT_SIZE];
-static WORD DosSftRefCount[DOS_SFT_SIZE];
+
+static struct
+{
+    HANDLE Handle;
+    WORD   RefCount;
+} DosSystemFileTable[DOS_SFT_SIZE];
+
 static BYTE DosAllocStrategy = DOS_ALLOC_BEST_FIT;
 static BOOLEAN DosUmbLinked = FALSE;
 static WORD DosErrorLevel = 0x0000;
@@ -431,6 +436,11 @@ static WORD DosCopyEnvironmentBlock(LPCVOID Environment, LPCSTR ProgramName)
     return DestSegment;
 }
 
+
+
+
+
+
 /* Taken from base/shell/cmd/console.c */
 BOOL IsConsoleHandle(HANDLE hHandle)
 {
@@ -455,7 +465,7 @@ BOOL IsConsoleHandle(HANDLE hHandle)
     return GetConsoleMode(hHandle, &dwMode);
 }
 
-static WORD DosOpenHandle(HANDLE Handle)
+WORD DosOpenHandle(HANDLE Handle)
 {
     BYTE i;
     WORD DosHandle;
@@ -482,10 +492,10 @@ static WORD DosOpenHandle(HANDLE Handle)
     for (i = 0; i < DOS_SFT_SIZE; i++)
     {
         /* Check if this is the same handle */
-        if (DosSystemFileTable[i] != Handle) continue;
+        if (DosSystemFileTable[i].Handle != Handle) continue;
 
         /* Already in the table, reference it */
-        DosSftRefCount[i]++;
+        DosSystemFileTable[i].RefCount++;
 
         /* Set the JFT entry to that SFT index */
         HandleTable[DosHandle] = i;
@@ -498,11 +508,11 @@ static WORD DosOpenHandle(HANDLE Handle)
     for (i = 0; i < DOS_SFT_SIZE; i++)
     {
         /* Make sure this is an empty table entry */
-        if (DosSystemFileTable[i] != INVALID_HANDLE_VALUE) continue;
+        if (DosSystemFileTable[i].Handle != INVALID_HANDLE_VALUE) continue;
 
         /* Initialize the empty table entry */
-        DosSystemFileTable[i] = Handle;
-        DosSftRefCount[i] = 1;
+        DosSystemFileTable[i].Handle   = Handle;
+        DosSystemFileTable[i].RefCount = 1;
 
         /* Set the JFT entry to that SFT index */
         HandleTable[DosHandle] = i;
@@ -531,7 +541,7 @@ HANDLE DosGetRealHandle(WORD DosHandle)
     if (HandleTable[DosHandle] == 0xFF) return INVALID_HANDLE_VALUE;
 
     /* Return the Win32 handle */
-    return DosSystemFileTable[HandleTable[DosHandle]];
+    return DosSystemFileTable[HandleTable[DosHandle]].Handle;
 }
 
 static VOID DosCopyHandleTable(LPBYTE DestinationTable)
@@ -553,7 +563,7 @@ static VOID DosCopyHandleTable(LPBYTE DestinationTable)
             DestinationTable[i] = (BYTE)i;
 
             /* Increase the reference count */
-            DosSftRefCount[i]++;
+            DosSystemFileTable[i].RefCount++;
         }
 
         /* Done */
@@ -570,7 +580,7 @@ static VOID DosCopyHandleTable(LPBYTE DestinationTable)
         DestinationTable[i] = SourceTable[i];
 
         /* Increase the reference count */
-        DosSftRefCount[SourceTable[i]]++;
+        DosSystemFileTable[SourceTable[i]].RefCount++;
     }
 }
 
@@ -594,16 +604,16 @@ static BOOLEAN DosCloseHandle(WORD DosHandle)
 
     /* Decrement the reference count of the SFT entry */
     SftIndex = HandleTable[DosHandle];
-    DosSftRefCount[SftIndex]--;
+    DosSystemFileTable[SftIndex].RefCount--;
 
     /* Check if the reference count fell to zero */
-    if (!DosSftRefCount[SftIndex])
+    if (!DosSystemFileTable[SftIndex].RefCount)
     {
         /* Close the file, it's no longer needed */
-        CloseHandle(DosSystemFileTable[SftIndex]);
+        CloseHandle(DosSystemFileTable[SftIndex].Handle);
 
         /* Clear the handle */
-        DosSystemFileTable[SftIndex] = INVALID_HANDLE_VALUE;
+        DosSystemFileTable[SftIndex].Handle = INVALID_HANDLE_VALUE;
     }
 
     /* Clear the entry in the JFT */
@@ -641,7 +651,7 @@ static BOOLEAN DosDuplicateHandle(WORD OldHandle, WORD NewHandle)
 
     /* Increment the reference count of the SFT entry */
     SftIndex = HandleTable[OldHandle];
-    DosSftRefCount[SftIndex]++;
+    DosSystemFileTable[SftIndex].RefCount++;
 
     /* Make the new handle point to that SFT entry */
     HandleTable[NewHandle] = SftIndex;
@@ -650,260 +660,11 @@ static BOOLEAN DosDuplicateHandle(WORD OldHandle, WORD NewHandle)
     return TRUE;
 }
 
-static WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes)
-{
-    HANDLE FileHandle;
-    WORD DosHandle;
-
-    DPRINT("DosCreateFile: FilePath \"%s\", Attributes 0x%04X\n",
-            FilePath,
-            Attributes);
-
-    /* Create the file */
-    FileHandle = CreateFileA(FilePath,
-                             GENERIC_READ | GENERIC_WRITE,
-                             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                             NULL,
-                             CREATE_ALWAYS,
-                             Attributes,
-                             NULL);
-
-    if (FileHandle == INVALID_HANDLE_VALUE)
-    {
-        /* Return the error code */
-        return (WORD)GetLastError();
-    }
-
-    /* Open the DOS handle */
-    DosHandle = DosOpenHandle(FileHandle);
-
-    if (DosHandle == INVALID_DOS_HANDLE)
-    {
-        /* Close the handle */
-        CloseHandle(FileHandle);
-
-        /* Return the error code */
-        return ERROR_TOO_MANY_OPEN_FILES;
-    }
-
-    /* It was successful */
-    *Handle = DosHandle;
-    return ERROR_SUCCESS;
-}
-
-static WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode)
-{
-    HANDLE FileHandle;
-    ACCESS_MASK Access = 0;
-    WORD DosHandle;
-
-    DPRINT("DosOpenFile: FilePath \"%s\", AccessMode 0x%04X\n",
-            FilePath,
-            AccessMode);
-
-    /* Parse the access mode */
-    switch (AccessMode & 3)
-    {
-        case 0:
-        {
-            /* Read-only */
-            Access = GENERIC_READ;
-            break;
-        }
-
-        case 1:
-        {
-            /* Write only */
-            Access = GENERIC_WRITE;
-            break;
-        }
-
-        case 2:
-        {
-            /* Read and write */
-            Access = GENERIC_READ | GENERIC_WRITE;
-            break;
-        }
-
-        default:
-        {
-            /* Invalid */
-            return ERROR_INVALID_PARAMETER;
-        }
-    }
-
-    /* Open the file */
-    FileHandle = CreateFileA(FilePath,
-                             Access,
-                             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                             NULL,
-                             OPEN_EXISTING,
-                             FILE_ATTRIBUTE_NORMAL,
-                             NULL);
-
-    if (FileHandle == INVALID_HANDLE_VALUE)
-    {
-        /* Return the error code */
-        return (WORD)GetLastError();
-    }
-
-    /* Open the DOS handle */
-    DosHandle = DosOpenHandle(FileHandle);
-
-    if (DosHandle == INVALID_DOS_HANDLE)
-    {
-        /* Close the handle */
-        CloseHandle(FileHandle);
-
-        /* Return the error code */
-        return ERROR_TOO_MANY_OPEN_FILES;
-    }
-
-    /* It was successful */
-    *Handle = DosHandle;
-    return ERROR_SUCCESS;
-}
-
-WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead)
-{
-    WORD Result = ERROR_SUCCESS;
-    DWORD BytesRead32 = 0;
-    HANDLE Handle = DosGetRealHandle(FileHandle);
-
-    DPRINT("DosReadFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count);
-
-    /* Make sure the handle is valid */
-    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
-
-    /* Read the file */
-    if (!ReadFile(Handle, Buffer, Count, &BytesRead32, NULL))
-    {
-        /* Store the error code */
-        Result = (WORD)GetLastError();
-    }
-
-    /* The number of bytes read is always 16-bit */
-    *BytesRead = LOWORD(BytesRead32);
-
-    /* Return the error code */
-    return Result;
-}
-
-WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten)
-{
-    WORD Result = ERROR_SUCCESS;
-    DWORD BytesWritten32 = 0;
-    HANDLE Handle = DosGetRealHandle(FileHandle);
-    WORD i;
-
-    DPRINT("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n",
-           FileHandle,
-           Count);
-
-    /* Make sure the handle is valid */
-    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
-
-    if (IsConsoleHandle(Handle))
-    {
-        for (i = 0; i < Count; i++)
-        {
-            /* Save AX and BX */
-            USHORT AX = getAX();
-            USHORT BX = getBX();
-
-            /* Set the parameters */
-            setAL(((PCHAR)Buffer)[i]);
-            setBL(DOS_CHAR_ATTRIBUTE);
-            setBH(Bda->VideoPage);
-
-            /* Call the BIOS INT 10h, AH=0Eh "Teletype Output" */
-            setAH(0x0E);
-            Int32Call(&DosContext, BIOS_VIDEO_INTERRUPT);
-
-            /* Restore AX and BX */
-            setBX(BX);
-            setAX(AX);
-
-            BytesWritten32++;
-        }
-    }
-    else
-    {
-        /* Write the file */
-        if (!WriteFile(Handle, Buffer, Count, &BytesWritten32, NULL))
-        {
-            /* Store the error code */
-            Result = (WORD)GetLastError();
-        }
-    }
-
-    /* The number of bytes written is always 16-bit */
-    *BytesWritten = LOWORD(BytesWritten32);
-
-    /* Return the error code */
-    return Result;
-}
-
-static WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset)
-{
-    WORD Result = ERROR_SUCCESS;
-    DWORD FilePointer;
-    HANDLE Handle = DosGetRealHandle(FileHandle);
-
-    DPRINT("DosSeekFile: FileHandle 0x%04X, Offset 0x%08X, Origin 0x%02X\n",
-           FileHandle,
-           Offset,
-           Origin);
-
-    /* Make sure the handle is valid */
-    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
 
-    /* Check if the origin is valid */
-    if (Origin != FILE_BEGIN && Origin != FILE_CURRENT && Origin != FILE_END)
-    {
-        return ERROR_INVALID_FUNCTION;
-    }
 
-    /* Move the file pointer */
-    FilePointer = SetFilePointer(Handle, Offset, NULL, Origin);
 
-    /* Check if there's a possibility the operation failed */
-    if (FilePointer == INVALID_SET_FILE_POINTER)
-    {
-        /* Get the real error code */
-        Result = (WORD)GetLastError();
-    }
 
-    if (Result != ERROR_SUCCESS)
-    {
-        /* The operation did fail */
-        return Result;
-    }
 
-    /* Return the file pointer, if requested */
-    if (NewOffset) *NewOffset = FilePointer;
-
-    /* Return success */
-    return ERROR_SUCCESS;
-}
-
-static BOOLEAN DosFlushFileBuffers(WORD FileHandle)
-{
-    HANDLE Handle = DosGetRealHandle(FileHandle);
-
-    /* Make sure the handle is valid */
-    if (Handle == INVALID_HANDLE_VALUE) return FALSE;
-
-    /*
-     * No need to check whether the handle is a console handle since
-     * FlushFileBuffers() automatically does this check and calls
-     * FlushConsoleInputBuffer() for us.
-     */
-    // if (IsConsoleHandle(Handle))
-    //    return (BOOLEAN)FlushConsoleInputBuffer(Handle);
-    // else
-    return (BOOLEAN)FlushFileBuffers(Handle);
-}
 
 static BOOLEAN DosChangeDrive(BYTE Drive)
 {
@@ -1279,6 +1040,36 @@ Cleanup:
     return Result;
 }
 
+DWORD DosStartProcess(IN LPCSTR ExecutablePath,
+                      IN LPCSTR CommandLine,
+                      IN PVOID Environment)
+{
+    DWORD Result;
+
+    Result = DosLoadExecutable(DOS_LOAD_AND_EXECUTE,
+                               ExecutablePath,
+                               CommandLine,
+                               Environment,
+                               NULL,
+                               NULL);
+
+    if (Result != ERROR_SUCCESS) goto Quit;
+
+    /* Attach to the console */
+    VidBiosAttachToConsole(); // FIXME: And in fact, attach the full NTVDM UI to the console
+
+    /* Start simulation */
+    SetEvent(VdmTaskEvent);
+    EmulatorSimulate();
+
+    /* Detach from the console */
+    VidBiosDetachFromConsole(); // FIXME: And in fact, detach the full NTVDM UI from the console
+
+Quit:
+    return Result;
+}
+
+#ifndef STANDALONE
 WORD DosCreateProcess(DOS_EXEC_TYPE LoadType,
                       LPCSTR ProgramName,
                       PDOS_EXEC_PARAM_BLOCK Parameters)
@@ -1363,16 +1154,17 @@ WORD DosCreateProcess(DOS_EXEC_TYPE LoadType,
             GetNextVDMCommand(&CommandInfo);
 
             /* Load the executable */
-            Result= DosLoadExecutable(LoadType,
-                                      AppName,
-                                      CmdLine,
-                                      Env,
-                                      &Parameters->StackLocation,
-                                      &Parameters->EntryPoint);
+            Result = DosLoadExecutable(LoadType,
+                                       AppName,
+                                       CmdLine,
+                                       Env,
+                                       &Parameters->StackLocation,
+                                       &Parameters->EntryPoint);
             if (Result != ERROR_SUCCESS)
             {
                 DisplayMessage(L"Could not load '%S'. Error: %u", AppName, Result);
-                break;
+                // FIXME: Decrement the reenter count. Or, instead, just increment
+                // the VDM reenter count *only* if this call succeeds...
             }
 
             break;
@@ -1392,6 +1184,7 @@ WORD DosCreateProcess(DOS_EXEC_TYPE LoadType,
 
     return ERROR_SUCCESS;
 }
+#endif
 
 VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode)
 {
@@ -1400,7 +1193,6 @@ VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode)
     PDOS_MCB CurrentMcb;
     LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
     PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp);
-    VDM_COMMAND_INFO CommandInfo;
 
     DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X\n",
            Psp,
@@ -1451,10 +1243,13 @@ Done:
         }
     }
 
+#ifndef STANDALONE
     // FIXME: This is probably not the best way to do it
     /* Check if this was a nested DOS task */
     if (CurrentPsp != SYSTEM_PSP)
     {
+        VDM_COMMAND_INFO CommandInfo;
+
         /* Decrement the re-entry count */
         CommandInfo.TaskId = SessionId;
         CommandInfo.VDMState = VDM_DEC_REENTER_COUNT;
@@ -1468,6 +1263,7 @@ Done:
         CommandInfo.VDMState = VDM_FLAG_DONT_WAIT;
         GetNextVDMCommand(&CommandInfo);
     }
+#endif
 
     /* Save the return code - Normal termination */
     DosErrorLevel = MAKEWORD(ReturnCode, 0x00);
@@ -1500,12 +1296,12 @@ BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle)
              * for a list of possible flags.
              */
 
-            if (Handle == DosSystemFileTable[0])
+            if (Handle == DosSystemFileTable[DOS_INPUT_HANDLE].Handle)
             {
                 /* Console input */
                 InfoWord |= 1 << 0;
             }
-            else if (Handle == DosSystemFileTable[1])
+            else if (Handle == DosSystemFileTable[DOS_OUTPUT_HANDLE].Handle)
             {
                 /* Console output */
                 InfoWord |= 1 << 1;
@@ -1556,11 +1352,12 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         /* Read Character from STDIN with Echo */
         case 0x01:
         {
-            Character = DosReadCharacter();
-            DosPrintCharacter(Character);
+            // FIXME: Under DOS 2+, input / output handle may be redirected!!!!
+            Character = DosReadCharacter(DOS_INPUT_HANDLE);
+            DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
 
-            /* Let the BOP repeat if needed */
-            if (getCF()) break;
+            // /* Let the BOP repeat if needed */
+            // if (getCF()) break;
 
             setAL(Character);
             break;
@@ -1569,8 +1366,9 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         /* Write Character to STDOUT */
         case 0x02:
         {
+            // FIXME: Under DOS 2+, output handle may be redirected!!!!
             Character = getDL();
-            DosPrintCharacter(Character);
+            DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
 
             /*
              * We return the output character (DOS 2.1+).
@@ -1588,7 +1386,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         {
             // FIXME: Really read it from STDAUX!
             DPRINT1("INT 16h, 03h: Read character from STDAUX is HALFPLEMENTED\n");
-            setAL(DosReadCharacter());
+            // setAL(DosReadCharacter());
             break;
         }
 
@@ -1597,7 +1395,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         {
             // FIXME: Really write it to STDAUX!
             DPRINT1("INT 16h, 04h: Write character to STDAUX is HALFPLEMENTED\n");
-            DosPrintCharacter(getDL());
+            // DosPrintCharacter(getDL());
             break;
         }
 
@@ -1616,10 +1414,12 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         {
             Character = getDL();
 
+            // FIXME: Under DOS 2+, output handle may be redirected!!!!
+
             if (Character != 0xFF)
             {
                 /* Output */
-                DosPrintCharacter(Character);
+                DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
 
                 /*
                  * We return the output character (DOS 2.1+).
@@ -1634,7 +1434,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
                 if (DosCheckInput())
                 {
                     Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
-                    setAL(DosReadCharacter());
+                    setAL(DosReadCharacter(DOS_INPUT_HANDLE));
                 }
                 else
                 {
@@ -1651,10 +1451,15 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         case 0x07:
         case 0x08:
         {
-            Character = DosReadCharacter();
+            // FIXME: Under DOS 2+, input handle may be redirected!!!!
+            Character = DosReadCharacter(DOS_INPUT_HANDLE);
 
-            /* Let the BOP repeat if needed */
-            if (getCF()) break;
+            // FIXME: For 0x07, do not check Ctrl-C/Break.
+            //        For 0x08, do check those control sequences and if needed,
+            //        call INT 0x23.
+
+            // /* Let the BOP repeat if needed */
+            // if (getCF()) break;
 
             setAL(Character);
             break;
@@ -1667,7 +1472,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
 
             while (*String != '$')
             {
-                DosPrintCharacter(*String);
+                DosPrintCharacter(DOS_OUTPUT_HANDLE, *String);
                 String++;
             }
 
@@ -1683,26 +1488,27 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         /* Read Buffered Input */
         case 0x0A:
         {
+            WORD Count = 0;
             InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX());
 
-            while (Stack[STACK_COUNTER] < InputBuffer->MaxLength)
-            {
-                /* Try to read a character */
-                Character = DosReadCharacter();
+            DPRINT1("Read Buffered Input\n");
 
-                /* If it's not ready yet, let the BOP repeat */
-                if (getCF()) break;
+            while (Count < InputBuffer->MaxLength)
+            {
+                /* Try to read a character (wait) */
+                Character = DosReadCharacter(DOS_INPUT_HANDLE);
 
                 /* Echo the character and append it to the buffer */
-                DosPrintCharacter(Character);
-                InputBuffer->Buffer[Stack[STACK_COUNTER]] = Character;
+                DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
+                InputBuffer->Buffer[Count] = Character;
 
                 if (Character == '\r') break;
-                Stack[STACK_COUNTER]++;
+                Count++;
             }
 
             /* Update the length */
-            InputBuffer->Length = Stack[STACK_COUNTER];
+            InputBuffer->Length = Count;
+
             break;
         }
 
@@ -1719,7 +1525,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             BYTE InputFunction = getAL();
 
             /* Flush STDIN buffer */
-            DosFlushFileBuffers(DOS_INPUT_HANDLE); // Maybe just create a DosFlushInputBuffer...
+            DosFlushFileBuffers(DOS_INPUT_HANDLE);
 
             /*
              * If the input function number contained in AL is valid, i.e.
@@ -2163,47 +1969,11 @@ VOID WINAPI DosInt21h(LPWORD Stack)
         /* Read from File or Device */
         case 0x3F:
         {
-            WORD Handle    = getBX();
-            LPBYTE Buffer  = (LPBYTE)SEG_OFF_TO_PTR(getDS(), getDX());
-            WORD Count     = getCX();
             WORD BytesRead = 0;
-            WORD ErrorCode = ERROR_SUCCESS;
-            CHAR Character;
-
-            if (IsConsoleHandle(DosGetRealHandle(Handle)))
-            {
-                while (Stack[STACK_COUNTER] < Count)
-                {
-                    /* Read a character from the BIOS */
-                    Character = LOBYTE(BiosGetCharacter());
-
-                    /* Stop if the BOP needs to be repeated */
-                    if (getCF()) break;
-
-                    // FIXME: Security checks!
-                    DosPrintCharacter(Character);
-                    Buffer[Stack[STACK_COUNTER]++] = Character;
-
-                    if (Character == '\r')
-                    {
-                        /* Stop on first carriage return */
-                        DosPrintCharacter('\n');
-                        break;
-                    }
-                }
-
-                if (Character != '\r')
-                {
-                    if (Stack[STACK_COUNTER] < Count) ErrorCode = ERROR_NOT_READY;
-                    else BytesRead = Count;
-                }
-                else BytesRead = Stack[STACK_COUNTER];
-            }
-            else
-            {
-                /* Use the file reading function */
-                ErrorCode = DosReadFile(Handle, Buffer, Count, &BytesRead);
-            }
+            WORD ErrorCode = DosReadFile(getBX(),
+                                         SEG_OFF_TO_PTR(getDS(), getDX()),
+                                         getCX(),
+                                         &BytesRead);
 
             if (ErrorCode == ERROR_SUCCESS)
             {
@@ -2215,6 +1985,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
                 Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
                 setAX(ErrorCode);
             }
+
             break;
         }
 
@@ -2358,7 +2129,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             WORD NewHandle;
             HANDLE Handle = DosGetRealHandle(getBX());
 
-            if (Handle != INVALID_HANDLE_VALUE)
+            if (Handle == INVALID_HANDLE_VALUE)
             {
                 /* The handle is invalid */
                 Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
@@ -2491,6 +2262,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             break;
         }
 
+#ifndef STANDALONE
         /* Execute */
         case 0x4B:
         {
@@ -2511,6 +2283,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
 
             break;
         }
+#endif
 
         /* Terminate With Return Code */
         case 0x4C:
@@ -2540,8 +2313,11 @@ VOID WINAPI DosInt21h(LPWORD Stack)
                                                  getCX());
 
             setAX(Result);
-            if (Result == ERROR_SUCCESS) Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
-            else Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+
+            if (Result == ERROR_SUCCESS)
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            else
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
 
             break;
         }
@@ -2552,8 +2328,11 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             WORD Result = (WORD)demFileFindNext(FAR_POINTER(DiskTransferArea));
 
             setAX(Result);
-            if (Result == ERROR_SUCCESS) Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
-            else Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+
+            if (Result == ERROR_SUCCESS)
+                Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            else
+                Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
 
             break;
         }
@@ -2581,6 +2360,23 @@ VOID WINAPI DosInt21h(LPWORD Stack)
             break;
         }
 
+        /* Internal - Get "List of lists" (SYSVARS) */
+        case 0x52:
+        {
+            /*
+             * On return, ES points at the DOS data segment (see also INT 2F/AX=1203h).
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-2983.htm
+             * for more information.
+             */
+
+            /* Return the DOS "list of lists" in ES:BX */
+            setES(0x0000);
+            setBX(0x0000);
+
+            DisplayMessage(L"Required for AARD code, do you remember? :P");
+            break;
+        }
+
         /* Get/Set Memory Management Options */
         case 0x58:
         {
@@ -2666,32 +2462,6 @@ VOID WINAPI DosFastConOut(LPWORD Stack)
      * for more information.
      */
 
-#if 0
-    if (Stack[STACK_COUNTER] == 0)
-    {
-        Stack[STACK_COUNTER]++;
-
-        /* Save AX and BX */
-        Stack[STACK_VAR_A] = getAX();
-        Stack[STACK_VAR_B] = getBX();
-
-        /* Rewind the BOP manually, we can't use CF because the interrupt could modify it */
-        EmulatorExecute(getCS(), getIP() - 4);
-
-        /* Call INT 0x10, AH = 0x0E */
-        setAH(0x0E);
-        setBL(DOS_CHAR_ATTRIBUTE);
-        setBH(Bda->VideoPage);
-
-        EmulatorInterrupt(0x10);
-    }
-    else
-    {
-        /* Restore AX and BX */
-        setAX(Stack[STACK_VAR_A]);
-        setBX(Stack[STACK_VAR_B]);
-    }
-#else
     /* Save AX and BX */
     USHORT AX = getAX();
     USHORT BX = getBX();
@@ -2707,12 +2477,11 @@ VOID WINAPI DosFastConOut(LPWORD Stack)
     /* Restore AX and BX */
     setBX(BX);
     setAX(AX);
-#endif
 }
 
 VOID WINAPI DosInt2Fh(LPWORD Stack)
 {
-    DPRINT1("DOS System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
+    DPRINT1("DOS Internal System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
             getAH(), getAL());
     Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
 }
@@ -2778,17 +2547,19 @@ BOOLEAN DosKRNLInitialize(VOID)
     /* Initialize the SFT */
     for (i = 0; i < DOS_SFT_SIZE; i++)
     {
-        DosSystemFileTable[i] = INVALID_HANDLE_VALUE;
-        DosSftRefCount[i] = 0;
+        DosSystemFileTable[i].Handle   = INVALID_HANDLE_VALUE;
+        DosSystemFileTable[i].RefCount = 0;
     }
 
     /* Get handles to standard I/O devices */
-    DosSystemFileTable[0] = GetStdHandle(STD_INPUT_HANDLE);
-    DosSystemFileTable[1] = GetStdHandle(STD_OUTPUT_HANDLE);
-    DosSystemFileTable[2] = GetStdHandle(STD_ERROR_HANDLE);
+    DosSystemFileTable[0].Handle = GetStdHandle(STD_INPUT_HANDLE);
+    DosSystemFileTable[1].Handle = GetStdHandle(STD_OUTPUT_HANDLE);
+    DosSystemFileTable[2].Handle = GetStdHandle(STD_ERROR_HANDLE);
 
     /* Initialize the reference counts */
-    DosSftRefCount[0] = DosSftRefCount[1] = DosSftRefCount[2] = 1;
+    DosSystemFileTable[0].RefCount =
+    DosSystemFileTable[1].RefCount =
+    DosSystemFileTable[2].RefCount = 1;
 
 #endif
 
index 18e0b14..f3e9140 100644 (file)
 #define USER_MEMORY_SIZE 0x8FFE
 #define SYSTEM_PSP 0x08
 #define SYSTEM_ENV_BLOCK 0x800
-#define INVALID_DOS_HANDLE 0xFFFF
-#define DOS_INPUT_HANDLE 0
-#define DOS_OUTPUT_HANDLE 1
-#define DOS_ERROR_HANDLE 2
+
+#define INVALID_DOS_HANDLE  0xFFFF
+#define DOS_INPUT_HANDLE    0
+#define DOS_OUTPUT_HANDLE   1
+#define DOS_ERROR_HANDLE    2
+
 #define DOS_SFT_SIZE 255
 #define SEGMENT_TO_MCB(seg) ((PDOS_MCB)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
 #define SEGMENT_TO_PSP(seg) ((PDOS_PSP)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
@@ -172,9 +174,9 @@ do { \
  * DOS BIOS Functions
  * See bios.c
  */
-CHAR DosReadCharacter(VOID);
+CHAR DosReadCharacter(WORD FileHandle);
 BOOLEAN DosCheckInput(VOID);
-VOID DosPrintCharacter(CHAR Character);
+VOID DosPrintCharacter(WORD FileHandle, CHAR Character);
 
 BOOLEAN DosBIOSInitialize(VOID);
 
@@ -184,9 +186,15 @@ BOOLEAN DosBIOSInitialize(VOID);
  * See dos.c
  */
 BOOL IsConsoleHandle(HANDLE hHandle);
+WORD DosOpenHandle(HANDLE Handle);
 HANDLE DosGetRealHandle(WORD DosHandle);
+
+WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes);
+WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode);
 WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead);
 WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten);
+WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset);
+BOOL DosFlushFileBuffers(WORD FileHandle);
 
 VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment);
 DWORD DosLoadExecutable(
@@ -202,6 +210,9 @@ WORD DosCreateProcess(
     LPCSTR ProgramName,
     PDOS_EXEC_PARAM_BLOCK Parameters
 );
+DWORD DosStartProcess(IN LPCSTR ExecutablePath,
+                      IN LPCSTR CommandLine,
+                      IN PVOID Environment);
 VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode);
 BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle);
 
diff --git a/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c b/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c
new file mode 100644 (file)
index 0000000..03a5df8
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            dos/dos32krnl/dosfiles.c
+ * PURPOSE:         DOS Files
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+// #include "callback.h"
+
+#include "dos.h"
+#include "dos/dem.h"
+
+#include "bios/bios.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes)
+{
+    HANDLE FileHandle;
+    WORD DosHandle;
+
+    DPRINT("DosCreateFile: FilePath \"%s\", Attributes 0x%04X\n",
+            FilePath,
+            Attributes);
+
+    /* Create the file */
+    FileHandle = CreateFileA(FilePath,
+                             GENERIC_READ | GENERIC_WRITE,
+                             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                             NULL,
+                             CREATE_ALWAYS,
+                             Attributes,
+                             NULL);
+
+    if (FileHandle == INVALID_HANDLE_VALUE)
+    {
+        /* Return the error code */
+        return (WORD)GetLastError();
+    }
+
+    /* Open the DOS handle */
+    DosHandle = DosOpenHandle(FileHandle);
+
+    if (DosHandle == INVALID_DOS_HANDLE)
+    {
+        /* Close the handle */
+        CloseHandle(FileHandle);
+
+        /* Return the error code */
+        return ERROR_TOO_MANY_OPEN_FILES;
+    }
+
+    /* It was successful */
+    *Handle = DosHandle;
+    return ERROR_SUCCESS;
+}
+
+WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode)
+{
+    HANDLE FileHandle;
+    ACCESS_MASK Access = 0;
+    WORD DosHandle;
+
+    DPRINT("DosOpenFile: FilePath \"%s\", AccessMode 0x%04X\n",
+            FilePath,
+            AccessMode);
+
+    /* Parse the access mode */
+    switch (AccessMode & 3)
+    {
+        case 0:
+        {
+            /* Read-only */
+            Access = GENERIC_READ;
+            break;
+        }
+
+        case 1:
+        {
+            /* Write only */
+            Access = GENERIC_WRITE;
+            break;
+        }
+
+        case 2:
+        {
+            /* Read and write */
+            Access = GENERIC_READ | GENERIC_WRITE;
+            break;
+        }
+
+        default:
+        {
+            /* Invalid */
+            return ERROR_INVALID_PARAMETER;
+        }
+    }
+
+    /* Open the file */
+    FileHandle = CreateFileA(FilePath,
+                             Access,
+                             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                             NULL,
+                             OPEN_EXISTING,
+                             FILE_ATTRIBUTE_NORMAL,
+                             NULL);
+
+    if (FileHandle == INVALID_HANDLE_VALUE)
+    {
+        /* Return the error code */
+        return (WORD)GetLastError();
+    }
+
+    /* Open the DOS handle */
+    DosHandle = DosOpenHandle(FileHandle);
+
+    if (DosHandle == INVALID_DOS_HANDLE)
+    {
+        /* Close the handle */
+        CloseHandle(FileHandle);
+
+        /* Return the error code */
+        return ERROR_TOO_MANY_OPEN_FILES;
+    }
+
+    /* It was successful */
+    *Handle = DosHandle;
+    return ERROR_SUCCESS;
+}
+
+WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead)
+{
+    WORD Result = ERROR_SUCCESS;
+    DWORD BytesRead32 = 0;
+    HANDLE Handle = DosGetRealHandle(FileHandle);
+
+    DPRINT1("DosReadFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count);
+
+    /* Make sure the handle is valid */
+    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
+
+    if (IsConsoleHandle(Handle))
+    {
+        CHAR Character;
+
+        /*
+         * Use BIOS Get Keystroke function
+         */
+
+        /* Save AX */
+        USHORT AX = getAX();
+
+        for (BytesRead32 = 0; BytesRead32 < Count; BytesRead32++)
+        {
+            /* Call the BIOS INT 16h, AH=00h "Get Keystroke" */
+            setAH(0x00);
+            Int32Call(&DosContext, BIOS_KBD_INTERRUPT);
+
+            /* Retrieve the character in AL (scan code is in AH) */
+            Character = getAL();
+
+            // FIXME: Sometimes we need echo, some other times not.
+            // DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
+
+            ((PCHAR)Buffer)[BytesRead32] = Character;
+
+            /* Stop on first carriage return */
+            if (Character == '\r')
+            {
+                // DosPrintCharacter(DOS_OUTPUT_HANDLE, '\n');
+                break;
+            }
+
+            // BytesRead32++;
+        }
+
+        /* Restore AX */
+        setAX(AX);
+    }
+    else
+    {
+        /* Read the file */
+        if (!ReadFile(Handle, Buffer, Count /* * sizeof(CHAR) */, &BytesRead32, NULL))
+        {
+            /* Store the error code */
+            Result = (WORD)GetLastError();
+        }
+    }
+
+    /* The number of bytes read is always 16-bit */
+    *BytesRead = LOWORD(BytesRead32);
+
+    /* Return the error code */
+    return Result;
+}
+
+WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten)
+{
+    WORD Result = ERROR_SUCCESS;
+    DWORD BytesWritten32 = 0;
+    HANDLE Handle = DosGetRealHandle(FileHandle);
+
+    DPRINT1("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n",
+           FileHandle,
+           Count);
+
+    /* Make sure the handle is valid */
+    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
+
+    if (IsConsoleHandle(Handle))
+    {
+        /*
+         * Use BIOS Teletype function
+         */
+
+        /* Save AX and BX */
+        USHORT AX = getAX();
+        USHORT BX = getBX();
+
+        // FIXME: Use BIOS Write String function INT 10h, AH=13h ??
+
+        for (BytesWritten32 = 0; BytesWritten32 < Count; BytesWritten32++)
+        {
+            /* Set the parameters */
+            setAL(((PCHAR)Buffer)[BytesWritten32]);
+            setBL(DOS_CHAR_ATTRIBUTE);
+            setBH(Bda->VideoPage);
+
+            /* Call the BIOS INT 10h, AH=0Eh "Teletype Output" */
+            setAH(0x0E);
+            Int32Call(&DosContext, BIOS_VIDEO_INTERRUPT);
+
+            // BytesWritten32++;
+        }
+
+        /* Restore AX and BX */
+        setBX(BX);
+        setAX(AX);
+    }
+    else
+    {
+        /* Write the file */
+        if (!WriteFile(Handle, Buffer, Count /* * sizeof(CHAR) */, &BytesWritten32, NULL))
+        {
+            /* Store the error code */
+            Result = (WORD)GetLastError();
+        }
+    }
+
+    /* The number of bytes written is always 16-bit */
+    *BytesWritten = LOWORD(BytesWritten32);
+
+    /* Return the error code */
+    return Result;
+}
+
+WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset)
+{
+    WORD Result = ERROR_SUCCESS;
+    DWORD FilePointer;
+    HANDLE Handle = DosGetRealHandle(FileHandle);
+
+    DPRINT("DosSeekFile: FileHandle 0x%04X, Offset 0x%08X, Origin 0x%02X\n",
+           FileHandle,
+           Offset,
+           Origin);
+
+    /* Make sure the handle is valid */
+    if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
+
+    /* Check if the origin is valid */
+    if (Origin != FILE_BEGIN && Origin != FILE_CURRENT && Origin != FILE_END)
+    {
+        return ERROR_INVALID_FUNCTION;
+    }
+
+    /* Move the file pointer */
+    if (IsConsoleHandle(Handle))
+    {
+        /* Always succeeds when seeking a console handle */
+        FilePointer = 0;
+        Result = ERROR_SUCCESS;
+    }
+    else
+    {
+        FilePointer = SetFilePointer(Handle, Offset, NULL, Origin);
+    }
+
+    /* Check if there's a possibility the operation failed */
+    if (FilePointer == INVALID_SET_FILE_POINTER)
+    {
+        /* Get the real error code */
+        Result = (WORD)GetLastError();
+    }
+
+    if (Result != ERROR_SUCCESS)
+    {
+        /* The operation did fail */
+        return Result;
+    }
+
+    /* Return the file pointer, if requested */
+    if (NewOffset) *NewOffset = FilePointer;
+
+    /* Return success */
+    return ERROR_SUCCESS;
+}
+
+// This function is almost exclusively used as a DosFlushInputBuffer
+BOOL DosFlushFileBuffers(WORD FileHandle)
+{
+    HANDLE Handle = DosGetRealHandle(FileHandle);
+
+    /* Make sure the handle is valid */
+    if (Handle == INVALID_HANDLE_VALUE) return FALSE;
+
+    /*
+     * No need to check whether the handle is a console handle since
+     * FlushFileBuffers() automatically does this check and calls
+     * FlushConsoleInputBuffer() for us.
+     */
+    return FlushFileBuffers(Handle);
+}
index cbe3e1e..094d156 100644 (file)
@@ -395,13 +395,22 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
     /* Initialize the PS2 port */
     PS2Initialize(ConsoleInput);
 
+    /**************** ATTACH INPUT WITH CONSOLE *****************/
     /* Start the input thread */
     InputThread = CreateThread(NULL, 0, &PumpConsoleInput, ConsoleInput, 0, NULL);
-    // if (InputThread == NULL) return FALSE;
+    if (InputThread == NULL)
+    {
+        DisplayMessage(L"Failed to create the console input thread.");
+        return FALSE;
+    }
+    /************************************************************/
 
     /* Initialize the VGA */
-    // if (!VgaInitialize(ConsoleOutput)) return FALSE;
-    VgaInitialize(ConsoleOutput);
+    if (!VgaInitialize(ConsoleOutput))
+    {
+        DisplayMessage(L"Failed to initialize VGA support.");
+        return FALSE;
+    }
 
     /* Initialize the software callback system and register the emulator BOPs */
     InitializeCallbacks();
index 20e9a07..1b1337f 100644 (file)
 #define EMULATOR_FLAG_VIP (1 << 20)
 #define EMULATOR_FLAG_ID (1 << 21)
 
-#define STACK_VAR_B     0
-#define STACK_VAR_A     1
-#define STACK_COUNTER   2
-#define STACK_INT_NUM   3
-#define STACK_IP        4
-#define STACK_CS        5
-#define STACK_FLAGS     6
+//
+// WARNING WARNING!!
+// If you're changing the indices here, you then need to
+// also fix the BOP code in callback.c !!!!!!!!!!!!!!!!!
+//
+#define STACK_INT_NUM   0
+#define STACK_IP        1
+#define STACK_CS        2
+#define STACK_FLAGS     3
 
 
 /* Basic Memory Management */
index 7c4665d..590ff05 100644 (file)
@@ -421,7 +421,7 @@ static VOID VgaUpdateCursorPosition(VOID)
     VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG]  = LOBYTE(Offset);
     VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG] = HIBYTE(Offset);
 
-    VidBiosSyncCursorPosition();
+    // VidBiosSyncCursorPosition();
     VgaUpdateTextCursor();
 }
 
@@ -538,61 +538,6 @@ static BOOL VgaAttachToConsoleInternal(PCOORD Resolution)
     return TRUE;
 }
 
-BOOL VgaAttachToConsole(VOID)
-{
-    if (TextResolution.X == 0 || TextResolution.Y == 0)
-        DPRINT1("VgaAttachToConsole -- TextResolution uninitialized\n");
-
-    if (TextResolution.X == 0) TextResolution.X = 80;
-    if (TextResolution.Y == 0) TextResolution.Y = 25;
-
-    return VgaAttachToConsoleInternal(&TextResolution);
-}
-
-VOID VgaDetachFromConsole(BOOL ChangingMode)
-{
-    ULONG dummyLength;
-    PVOID dummyPtr;
-    COORD dummySize = {0};
-
-    __RegisterConsoleVDM(0,
-                         NULL,
-                         NULL,
-                         NULL,
-                         0,
-                         &dummyLength,
-                         &dummyPtr,
-                         NULL,
-                         0,
-                         dummySize,
-                         (PCHAR*)&dummyPtr);
-
-    TextFramebuffer = NULL;
-
-    if (!ChangingMode)
-    {
-        SMALL_RECT ConRect;
-
-        /* Restore the old screen buffer */
-        SetConsoleActiveScreenBuffer(TextConsoleBuffer);
-
-        /* Restore the original console size */
-        ConRect.Left   = 0;
-        ConRect.Top    = 0;
-        ConRect.Right  = ConRect.Left + OrgConsoleBufferInfo.srWindow.Right  - OrgConsoleBufferInfo.srWindow.Left;
-        ConRect.Bottom = ConRect.Top  + OrgConsoleBufferInfo.srWindow.Bottom - OrgConsoleBufferInfo.srWindow.Top ;
-        /*
-         * See the following trick explanation in VgaAttachToConsoleInternal.
-         */
-        SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize);
-        SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect);
-        SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize);
-
-        /* Restore the original cursor shape */
-        SetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo);
-    }
-}
-
 static BOOL IsConsoleHandle(HANDLE hHandle)
 {
     DWORD dwMode;
@@ -1038,7 +983,10 @@ static BOOL VgaEnterTextMode(PCOORD Resolution)
             return FALSE;
         }
     }
-    else VgaUpdateCursorPosition();
+    else
+    {
+        VgaUpdateCursorPosition();
+    }
 
     /* The active framebuffer is now the text framebuffer */
     ConsoleFramebuffer = TextFramebuffer;
@@ -1886,6 +1834,71 @@ VOID VgaResetPalette(VOID)
     PaletteChanged = TRUE;
 }
 
+
+
+
+BOOL VgaAttachToConsole(VOID)
+{
+    //
+    // FIXME: We should go back to the saved screen state
+    //
+    if (TextResolution.X == 0 || TextResolution.Y == 0)
+        DPRINT1("VgaAttachToConsole -- TextResolution uninitialized\n");
+
+    if (TextResolution.X == 0) TextResolution.X = 80;
+    if (TextResolution.Y == 0) TextResolution.Y = 25;
+
+    return VgaAttachToConsoleInternal(&TextResolution);
+}
+
+VOID VgaDetachFromConsole(BOOL ChangingMode)
+{
+    ULONG dummyLength;
+    PVOID dummyPtr;
+    COORD dummySize = {0};
+
+    //
+    // FIXME: We should save the screen state
+    //
+
+    __RegisterConsoleVDM(0,
+                         NULL,
+                         NULL,
+                         NULL,
+                         0,
+                         &dummyLength,
+                         &dummyPtr,
+                         NULL,
+                         0,
+                         dummySize,
+                         (PCHAR*)&dummyPtr);
+
+    TextFramebuffer = NULL;
+
+    if (!ChangingMode)
+    {
+        SMALL_RECT ConRect;
+
+        /* Restore the old screen buffer */
+        SetConsoleActiveScreenBuffer(TextConsoleBuffer);
+
+        /* Restore the original console size */
+        ConRect.Left   = 0;
+        ConRect.Top    = 0;
+        ConRect.Right  = ConRect.Left + OrgConsoleBufferInfo.srWindow.Right  - OrgConsoleBufferInfo.srWindow.Left;
+        ConRect.Bottom = ConRect.Top  + OrgConsoleBufferInfo.srWindow.Bottom - OrgConsoleBufferInfo.srWindow.Top ;
+        /*
+         * See the following trick explanation in VgaAttachToConsoleInternal.
+         */
+        SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize);
+        SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect);
+        SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize);
+
+        /* Restore the original cursor shape */
+        SetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo);
+    }
+}
+
 BOOLEAN VgaInitialize(HANDLE TextHandle)
 {
     /* Save the default text-mode console output handle */
index b89eb13..2e9631d 100644 (file)
@@ -58,6 +58,13 @@ VOID WINAPI ControlBop(LPWORD Stack)
 
 VOID InitializeInt32(WORD BiosSegment)
 {
+    //
+    // WARNING WARNING!!
+    //
+    // If you modify the code stubs here, think also
+    // about updating them in callback.c too!!
+    //
+
     LPDWORD IntVecTable = (LPDWORD)BaseAddress;
     LPBYTE  BiosCode    = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0);
     USHORT i;
@@ -74,15 +81,6 @@ VOID InitializeInt32(WORD BiosSegment)
         BiosCode[Offset++] = 0x6A; // push i
         BiosCode[Offset++] = (UCHAR)i;
 
-        /* The counter variable (initialized to 0) */
-        BiosCode[Offset++] = 0x6A; // push 0
-        BiosCode[Offset++] = 0x00;
-
-        /* Stack variables */
-        BiosCode[Offset++] = 0x83; // sub sp, 4
-        BiosCode[Offset++] = 0xEC;
-        BiosCode[Offset++] = 0x04;
-
         BopSeqOffset = COMMON_STUB_OFFSET - (Offset + 3);
 
         BiosCode[Offset++] = 0xE9; // jmp near BOP_SEQ
@@ -113,9 +111,11 @@ VOID InitializeInt32(WORD BiosSegment)
     BiosCode[Offset++] = 0xF5;
 
 // EXIT:
-    BiosCode[Offset++] = 0x83; // add sp, 8
+    // BiosCode[Offset++] = 0x44; // inc sp
+    // BiosCode[Offset++] = 0x44; // inc sp
+    BiosCode[Offset++] = 0x83; // add sp, 2
     BiosCode[Offset++] = 0xC4;
-    BiosCode[Offset++] = 0x08;
+    BiosCode[Offset++] = 0x02;
 
     BiosCode[Offset++] = 0xCF; // iret
 
index 813a885..1239def 100644 (file)
 
 #include "resource.h"
 
-/*
- * Activate this line if you want to run NTVDM in standalone mode with:
- * ntvdm.exe <program>
- */
-// #define STANDALONE
-
 /* VARIABLES ******************************************************************/
 
 static HANDLE ConsoleInput  = INVALID_HANDLE_VALUE;
@@ -39,7 +33,10 @@ static HMENU hConsoleMenu  = NULL;
 static INT   VdmMenuPos    = -1;
 static BOOLEAN ShowPointer = FALSE;
 
+#ifndef STANDALONE
 ULONG SessionId = 0;
+#endif
+
 HANDLE VdmTaskEvent = NULL;
 
 /*
@@ -124,7 +121,7 @@ AppendMenuItems(HMENU hMenu,
 static VOID
 CreateVdmMenu(HANDLE ConOutHandle)
 {
-    hConsoleMenu = ConsoleMenuControl(ConsoleOutput,
+    hConsoleMenu = ConsoleMenuControl(ConOutHandle,
                                       ID_SHOWHIDE_MOUSE,
                                       ID_VDM_QUIT);
     if (hConsoleMenu == NULL) return;
@@ -176,7 +173,8 @@ static VOID ShowHideMousePointer(HANDLE ConOutHandle, BOOLEAN ShowPtr)
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-VOID DisplayMessage(LPCWSTR Format, ...)
+VOID
+DisplayMessage(LPCWSTR Format, ...)
 {
     WCHAR Buffer[256];
     va_list Parameters;
@@ -188,7 +186,9 @@ VOID DisplayMessage(LPCWSTR Format, ...)
     va_end(Parameters);
 }
 
-BOOL WINAPI ConsoleCtrlHandler(DWORD ControlType)
+static BOOL
+WINAPI
+ConsoleCtrlHandler(DWORD ControlType)
 {
     switch (ControlType)
     {
@@ -224,12 +224,14 @@ BOOL WINAPI ConsoleCtrlHandler(DWORD ControlType)
     return TRUE;
 }
 
-VOID ConsoleInitUI(VOID)
+static VOID
+ConsoleInitUI(VOID)
 {
     CreateVdmMenu(ConsoleOutput);
 }
 
-VOID ConsoleCleanupUI(VOID)
+static VOID
+ConsoleCleanupUI(VOID)
 {
     /* Display again properly the mouse pointer */
     if (ShowPointer) ShowHideMousePointer(ConsoleOutput, ShowPointer);
@@ -237,7 +239,97 @@ VOID ConsoleCleanupUI(VOID)
     DestroyVdmMenu();
 }
 
-DWORD WINAPI PumpConsoleInput(LPVOID Parameter)
+static BOOL
+ConsoleAttach(VOID)
+{
+    /* Save the original input and output console modes */
+    if (!GetConsoleMode(ConsoleInput , &OrgConsoleInputMode ) ||
+        !GetConsoleMode(ConsoleOutput, &OrgConsoleOutputMode))
+    {
+        CloseHandle(ConsoleOutput);
+        CloseHandle(ConsoleInput);
+        wprintf(L"FATAL: Cannot save console in/out modes\n");
+        // return FALSE;
+    }
+
+    /* Initialize the UI */
+    ConsoleInitUI();
+
+    return TRUE;
+}
+
+static VOID
+ConsoleDetach(VOID)
+{
+    /* Restore the original input and output console modes */
+    SetConsoleMode(ConsoleOutput, OrgConsoleOutputMode);
+    SetConsoleMode(ConsoleInput , OrgConsoleInputMode );
+
+    /* Cleanup the UI */
+    ConsoleCleanupUI();
+}
+
+static BOOL
+ConsoleInit(VOID)
+{
+    /* Set the handler routine */
+    SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
+
+    /* Enable the CTRL_LAST_CLOSE_EVENT */
+    SetLastConsoleEventActive();
+
+    /*
+     * NOTE: The CONIN$ and CONOUT$ "virtual" files
+     * always point to non-redirected console handles.
+     */
+
+    /* Get the input handle to the real console, and check for success */
+    ConsoleInput = CreateFileW(L"CONIN$",
+                               GENERIC_READ | GENERIC_WRITE,
+                               FILE_SHARE_READ | FILE_SHARE_WRITE,
+                               NULL,
+                               OPEN_EXISTING,
+                               0,
+                               NULL);
+    if (ConsoleInput == INVALID_HANDLE_VALUE)
+    {
+        wprintf(L"FATAL: Cannot retrieve a handle to the console input\n");
+        return FALSE;
+    }
+
+    /* Get the output handle to the real console, and check for success */
+    ConsoleOutput = CreateFileW(L"CONOUT$",
+                                GENERIC_READ | GENERIC_WRITE,
+                                FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                NULL,
+                                OPEN_EXISTING,
+                                0,
+                                NULL);
+    if (ConsoleOutput == INVALID_HANDLE_VALUE)
+    {
+        CloseHandle(ConsoleInput);
+        wprintf(L"FATAL: Cannot retrieve a handle to the console output\n");
+        return FALSE;
+    }
+
+    /* Effectively attach to the console */
+    return ConsoleAttach();
+}
+
+static VOID
+ConsoleCleanup(VOID)
+{
+    /* Detach from the console */
+    ConsoleDetach();
+
+    /* Close the console handles */
+    if (ConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleOutput);
+    if (ConsoleInput  != INVALID_HANDLE_VALUE) CloseHandle(ConsoleInput);
+}
+
+DWORD
+WINAPI
+PumpConsoleInput(LPVOID Parameter)
 {
     HANDLE ConsoleInput = (HANDLE)Parameter;
     INPUT_RECORD InputRecord;
@@ -296,74 +388,10 @@ DWORD WINAPI PumpConsoleInput(LPVOID Parameter)
     return 0;
 }
 
-BOOL ConsoleInit(VOID)
-{
-    /* Set the handler routine */
-    SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
-
-    /* Enable the CTRL_LAST_CLOSE_EVENT */
-    SetLastConsoleEventActive();
-
-    /* Get the input handle to the real console, and check for success */
-    ConsoleInput = CreateFileW(L"CONIN$",
-                               GENERIC_READ | GENERIC_WRITE,
-                               FILE_SHARE_READ | FILE_SHARE_WRITE,
-                               NULL,
-                               OPEN_EXISTING,
-                               0,
-                               NULL);
-    if (ConsoleInput == INVALID_HANDLE_VALUE)
-    {
-        wprintf(L"FATAL: Cannot retrieve a handle to the console input\n");
-        return FALSE;
-    }
-
-    /* Get the output handle to the real console, and check for success */
-    ConsoleOutput = CreateFileW(L"CONOUT$",
-                                GENERIC_READ | GENERIC_WRITE,
-                                FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                NULL,
-                                OPEN_EXISTING,
-                                0,
-                                NULL);
-    if (ConsoleOutput == INVALID_HANDLE_VALUE)
-    {
-        CloseHandle(ConsoleInput);
-        wprintf(L"FATAL: Cannot retrieve a handle to the console output\n");
-        return FALSE;
-    }
-
-    /* Save the original input and output console modes */
-    if (!GetConsoleMode(ConsoleInput , &OrgConsoleInputMode ) ||
-        !GetConsoleMode(ConsoleOutput, &OrgConsoleOutputMode))
-    {
-        CloseHandle(ConsoleOutput);
-        CloseHandle(ConsoleInput);
-        wprintf(L"FATAL: Cannot save console in/out modes\n");
-        return FALSE;
-    }
-
-    /* Initialize the UI */
-    ConsoleInitUI();
-
-    return TRUE;
-}
-
-VOID ConsoleCleanup(VOID)
-{
-    /* Restore the original input and output console modes */
-    SetConsoleMode(ConsoleOutput, OrgConsoleOutputMode);
-    SetConsoleMode(ConsoleInput , OrgConsoleInputMode );
-
-    /* Cleanup the UI */
-    ConsoleCleanupUI();
-
-    /* Close the console handles */
-    if (ConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(ConsoleOutput);
-    if (ConsoleInput  != INVALID_HANDLE_VALUE) CloseHandle(ConsoleInput);
-}
-
-DWORD WINAPI CommandThreadProc(LPVOID Parameter)
+#ifndef STANDALONE
+static DWORD
+WINAPI
+CommandThreadProc(LPVOID Parameter)
 {
     BOOLEAN First = TRUE;
     DWORD Result;
@@ -404,39 +432,25 @@ DWORD WINAPI CommandThreadProc(LPVOID Parameter)
         if (!GetNextVDMCommand(&CommandInfo)) break;
 
         /* Start the process from the command line */
-        DPRINT1("Starting '%s'...\n", AppName);
-
-        Result = DosLoadExecutable(DOS_LOAD_AND_EXECUTE, AppName, CmdLine, Env, NULL, NULL);
+        DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine);
+        Result = DosStartProcess(AppName, CmdLine, Env);
         if (Result != ERROR_SUCCESS)
         {
             DisplayMessage(L"Could not start '%S'. Error: %u", AppName, Result);
-            break;
+            // break;
+            continue;
         }
 
-        /* Attach to the console */
-        if (!First) VgaAttachToConsole();
-
-        /* Perform a screen refresh */
-        VgaRefreshDisplay();
-
-        /* Start simulation */
-        SetEvent(VdmTaskEvent);
-        EmulatorSimulate();
-
-        /* Perform another screen refresh */
-        VgaRefreshDisplay();
-
-        /* Detach from the console */
-        VgaDetachFromConsole(FALSE);
-
         First = FALSE;
     }
     while (AcceptCommands);
 
     return 0;
 }
+#endif
 
-INT wmain(INT argc, WCHAR *argv[])
+INT
+wmain(INT argc, WCHAR *argv[])
 {
 #ifdef STANDALONE
 
@@ -459,6 +473,7 @@ INT wmain(INT argc, WCHAR *argv[])
     }
 
 #else
+
     INT i;
     WCHAR *endptr;
 
@@ -530,27 +545,16 @@ INT wmain(INT argc, WCHAR *argv[])
 #else
 
     /* Start the process from the command line */
-    DPRINT1("Starting '%s'...\n", ApplicationName);
-
-    Result = DosLoadExecutable(DOS_LOAD_AND_EXECUTE,
-                               ApplicationName,
-                               CommandLine,
-                               GetEnvironmentStrings(),
-                               NULL,
-                               NULL);
+    DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine);
+    Result = DosStartProcess(ApplicationName,
+                             CommandLine,
+                             GetEnvironmentStrings());
     if (Result != ERROR_SUCCESS)
     {
         DisplayMessage(L"Could not start '%S'. Error: %u", ApplicationName, Result);
         goto Cleanup;
     }
 
-    /* Start simulation */
-    SetEvent(VdmTaskEvent);
-    EmulatorSimulate();
-
-    /* Perform another screen refresh */
-    VgaRefreshDisplay();
-
 #endif
 
 Cleanup:
index 3555ce4..d6a2569 100644 (file)
 
 #include <vddsvc.h>
 
+DWORD WINAPI SetLastConsoleEventActive(VOID);
+
 #include <debug.h>
 
-DWORD WINAPI SetLastConsoleEventActive(VOID);
+/*
+ * Activate this line if you want to run NTVDM in standalone mode with:
+ * ntvdm.exe <program>
+ */
+#define STANDALONE
 
 /* FUNCTIONS ******************************************************************/
 
+#ifndef STANDALONE
 extern ULONG SessionId;
+#endif
+
 extern HANDLE VdmTaskEvent;
 
 VOID DisplayMessage(LPCWSTR Format, ...);