Author: hbelusca Date: Sun May 11 19:25:09 2014 New Revision: 63238
URL: http://svn.reactos.org/svn/reactos?rev=63238&view=rev Log: [NTVDM] - 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).
Added: trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c (with props) Modified: trunk/reactos/subsystems/ntvdm/CMakeLists.txt trunk/reactos/subsystems/ntvdm/bios/bios32/kbdbios32.c trunk/reactos/subsystems/ntvdm/bios/kbdbios.h trunk/reactos/subsystems/ntvdm/bios/vidbios.c trunk/reactos/subsystems/ntvdm/bios/vidbios.h trunk/reactos/subsystems/ntvdm/callback.c trunk/reactos/subsystems/ntvdm/dos/dem.c trunk/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dos.c trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h trunk/reactos/subsystems/ntvdm/emulator.c trunk/reactos/subsystems/ntvdm/emulator.h trunk/reactos/subsystems/ntvdm/hardware/vga.c trunk/reactos/subsystems/ntvdm/int32.c trunk/reactos/subsystems/ntvdm/ntvdm.c trunk/reactos/subsystems/ntvdm/ntvdm.h
Modified: trunk/reactos/subsystems/ntvdm/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/CMakeLists... ============================================================================== --- trunk/reactos/subsystems/ntvdm/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/CMakeLists.txt [iso-8859-1] Sun May 11 19:25:09 2014 @@ -21,6 +21,7 @@ hardware/vga.c dos/dos32krnl/bios.c dos/dos32krnl/dos.c + dos/dos32krnl/dosfiles.c dos/dem.c bop.c callback.c
Modified: trunk/reactos/subsystems/ntvdm/bios/bios32/kbdbios32.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/bios/bios3... ============================================================================== --- trunk/reactos/subsystems/ntvdm/bios/bios32/kbdbios32.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/bios/bios32/kbdbios32.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -91,22 +91,13 @@ 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 @@ 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 @@ /* Get extended keystroke status */ case 0x11: // FIXME: Temporarily do the same as INT 16h, 01h { - WORD Data = BiosPeekCharacter(); - - if (Data != 0xFFFF) + WORD Character = BiosPeekCharacter(); + + if (Character != 0xFFFF) { /* There is a character, clear ZF and return it */ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF; - setAX(Data); + setAX(Character); } else {
Modified: trunk/reactos/subsystems/ntvdm/bios/kbdbios.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/bios/kbdbi... ============================================================================== --- trunk/reactos/subsystems/ntvdm/bios/kbdbios.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/bios/kbdbios.h [iso-8859-1] Sun May 11 19:25:09 2014 @@ -21,8 +21,6 @@
/* FUNCTIONS ******************************************************************/
-WORD BiosGetCharacter(VOID); - BOOLEAN KbdBiosInitialize(VOID); VOID KbdBiosCleanup(VOID);
Modified: trunk/reactos/subsystems/ntvdm/bios/vidbios.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/bios/vidbi... ============================================================================== --- trunk/reactos/subsystems/ntvdm/bios/vidbios.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/bios/vidbios.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -1532,6 +1532,37 @@ } }
+ +/* + * 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 @@ ((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);
Modified: trunk/reactos/subsystems/ntvdm/bios/vidbios.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/bios/vidbi... ============================================================================== --- trunk/reactos/subsystems/ntvdm/bios/vidbios.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/bios/vidbios.h [iso-8859-1] Sun May 11 19:25:09 2014 @@ -37,9 +37,12 @@
/* FUNCTIONS ******************************************************************/
+VOID VidBiosSyncCursorPosition(VOID); + VOID WINAPI VidBiosVideoService(LPWORD Stack);
-VOID VidBiosSyncCursorPosition(VOID); +VOID VidBiosDetachFromConsole(VOID); +VOID VidBiosAttachToConsole(VOID);
BOOLEAN VidBiosInitialize(VOID); VOID VidBiosCleanup(VOID);
Modified: trunk/reactos/subsystems/ntvdm/callback.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/callback.c... ============================================================================== --- trunk/reactos/subsystems/ntvdm/callback.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/callback.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -44,6 +44,13 @@ #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[] = { @@ -51,12 +58,6 @@
/* 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: @@ -74,7 +75,8 @@ 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 };
Modified: trunk/reactos/subsystems/ntvdm/dos/dem.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/dos/dem.c?... ============================================================================== --- trunk/reactos/subsystems/ntvdm/dos/dem.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/dos/dem.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -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 @@
StartupInfo.cb = sizeof(StartupInfo);
- VgaRefreshDisplay(); - VgaDetachFromConsole(FALSE); + VidBiosDetachFromConsole();
Result = CreateProcessA(NULL, CommandLine, @@ -171,9 +169,7 @@ dwExitCode = GetLastError(); }
- VgaAttachToConsole(); - VgaRefreshDisplay(); - VidBiosSyncCursorPosition(); + VidBiosAttachToConsole();
setAL((UCHAR)dwExitCode);
Modified: trunk/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/dos/dos32k... ============================================================================== --- trunk/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -24,65 +24,15 @@
/* 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 @@ } }
-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)
Modified: trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/dos/dos32k... ============================================================================== --- trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -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*/ 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; @@ -430,6 +435,11 @@
return DestSegment; } + + + + +
/* Taken from base/shell/cmd/console.c */ BOOL IsConsoleHandle(HANDLE hHandle) @@ -455,7 +465,7 @@ return GetConsoleMode(hHandle, &dwMode); }
-static WORD DosOpenHandle(HANDLE Handle) +WORD DosOpenHandle(HANDLE Handle) { BYTE i; WORD DosHandle; @@ -482,10 +492,10 @@ 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 @@ 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 @@ 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 @@ DestinationTable[i] = (BYTE)i;
/* Increase the reference count */ - DosSftRefCount[i]++; + DosSystemFileTable[i].RefCount++; }
/* Done */ @@ -570,7 +580,7 @@ DestinationTable[i] = SourceTable[i];
/* Increase the reference count */ - DosSftRefCount[SourceTable[i]]++; + DosSystemFileTable[SourceTable[i]].RefCount++; } }
@@ -594,16 +604,16 @@
/* 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 @@
/* 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 @@ 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 @@ 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 @@ 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 @@
return ERROR_SUCCESS; } +#endif
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode) { @@ -1400,7 +1193,6 @@ 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 @@ } }
+#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 @@ CommandInfo.VDMState = VDM_FLAG_DONT_WAIT; GetNextVDMCommand(&CommandInfo); } +#endif
/* Save the return code - Normal termination */ DosErrorLevel = MAKEWORD(ReturnCode, 0x00); @@ -1500,12 +1296,12 @@ * 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 @@ /* Read Character from STDIN with Echo */ case 0x01: { - Character = DosReadCharacter(); - DosPrintCharacter(Character); - - /* Let the BOP repeat if needed */ - if (getCF()) break; + // 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;
setAL(Character); break; @@ -1569,8 +1366,9 @@ /* 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 @@ { // 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 @@ { // 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 @@ { 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 @@ if (DosCheckInput()) { Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF; - setAL(DosReadCharacter()); + setAL(DosReadCharacter(DOS_INPUT_HANDLE)); } else { @@ -1651,10 +1451,15 @@ case 0x07: case 0x08: { - Character = DosReadCharacter(); - - /* Let the BOP repeat if needed */ - if (getCF()) break; + // FIXME: Under DOS 2+, input handle may be redirected!!!! + Character = DosReadCharacter(DOS_INPUT_HANDLE); + + // 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 @@
while (*String != '$') { - DosPrintCharacter(*String); + DosPrintCharacter(DOS_OUTPUT_HANDLE, *String); String++; }
@@ -1683,26 +1488,27 @@ /* 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(); - - /* If it's not ready yet, let the BOP repeat */ - if (getCF()) break; + DPRINT1("Read Buffered Input\n"); + + 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 @@ 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 @@ /* 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 @@ Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; setAX(ErrorCode); } + break; }
@@ -2358,7 +2129,7 @@ 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 @@ break; }
+#ifndef STANDALONE /* Execute */ case 0x4B: { @@ -2511,6 +2283,7 @@
break; } +#endif
/* Terminate With Return Code */ case 0x4C: @@ -2540,8 +2313,11 @@ 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 @@ 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; } @@ -2578,6 +2357,23 @@ * for more information. */ setBX(CurrentPsp); + 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; }
@@ -2666,32 +2462,6 @@ * 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 @@ /* 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 @@ /* 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
Modified: trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/dos/dos32k... ============================================================================== --- trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h [iso-8859-1] Sun May 11 19:25:09 2014 @@ -30,10 +30,12 @@ #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 @@ * 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 @@ * 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 @@ 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);
Added: trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/dos/dos32k... ============================================================================== --- trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c (added) +++ trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -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); +}
Propchange: trunk/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/subsystems/ntvdm/emulator.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/emulator.c... ============================================================================== --- trunk/reactos/subsystems/ntvdm/emulator.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/emulator.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -395,13 +395,22 @@ /* 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();
Modified: trunk/reactos/subsystems/ntvdm/emulator.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/emulator.h... ============================================================================== --- trunk/reactos/subsystems/ntvdm/emulator.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/emulator.h [iso-8859-1] Sun May 11 19:25:09 2014 @@ -34,13 +34,15 @@ #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 */
Modified: trunk/reactos/subsystems/ntvdm/hardware/vga.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/hardware/v... ============================================================================== --- trunk/reactos/subsystems/ntvdm/hardware/vga.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/hardware/vga.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -421,7 +421,7 @@ 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 @@ 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 @@ return FALSE; } } - else VgaUpdateCursorPosition(); + else + { + VgaUpdateCursorPosition(); + }
/* The active framebuffer is now the text framebuffer */ ConsoleFramebuffer = TextFramebuffer; @@ -1886,6 +1834,71 @@ 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 */
Modified: trunk/reactos/subsystems/ntvdm/int32.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/int32.c?re... ============================================================================== --- trunk/reactos/subsystems/ntvdm/int32.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/int32.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -58,6 +58,13 @@
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; @@ -73,15 +80,6 @@
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);
@@ -113,9 +111,11 @@ 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
Modified: trunk/reactos/subsystems/ntvdm/ntvdm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/ntvdm.c?re... ============================================================================== --- trunk/reactos/subsystems/ntvdm/ntvdm.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/ntvdm.c [iso-8859-1] Sun May 11 19:25:09 2014 @@ -21,12 +21,6 @@
#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 INT VdmMenuPos = -1; static BOOLEAN ShowPointer = FALSE;
+#ifndef STANDALONE ULONG SessionId = 0; +#endif + HANDLE VdmTaskEvent = NULL;
/* @@ -124,7 +121,7 @@ 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 @@
/* PUBLIC FUNCTIONS ***********************************************************/
-VOID DisplayMessage(LPCWSTR Format, ...) +VOID +DisplayMessage(LPCWSTR Format, ...) { WCHAR Buffer[256]; va_list Parameters; @@ -188,7 +186,9 @@ va_end(Parameters); }
-BOOL WINAPI ConsoleCtrlHandler(DWORD ControlType) +static BOOL +WINAPI +ConsoleCtrlHandler(DWORD ControlType) { switch (ControlType) { @@ -224,12 +224,14 @@ 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,72 +239,49 @@ DestroyVdmMenu(); }
-DWORD WINAPI PumpConsoleInput(LPVOID Parameter) -{ - HANDLE ConsoleInput = (HANDLE)Parameter; - INPUT_RECORD InputRecord; - DWORD Count; - - while (VdmRunning) - { - /* Make sure the task event is signaled */ - WaitForSingleObject(VdmTaskEvent, INFINITE); - - /* Wait for an input record */ - if (!ReadConsoleInput(ConsoleInput, &InputRecord, 1, &Count)) - { - DWORD LastError = GetLastError(); - DPRINT1("Error reading console input (0x%p, %lu) - Error %lu\n", ConsoleInput, Count, LastError); - return LastError; - } - - ASSERT(Count != 0); - - /* Check the event type */ - switch (InputRecord.EventType) - { - case KEY_EVENT: - case MOUSE_EVENT: - /* Send it to the PS/2 controller */ - PS2Dispatch(&InputRecord); - break; - - case MENU_EVENT: - { - switch (InputRecord.Event.MenuEvent.dwCommandId) - { - case ID_SHOWHIDE_MOUSE: - ShowHideMousePointer(ConsoleOutput, ShowPointer); - ShowPointer = !ShowPointer; - break; - - case ID_VDM_QUIT: - /* Stop the VDM */ - EmulatorTerminate(); - break; - - default: - break; - } - - break; - } - - default: - break; - } - } - - return 0; -} - -BOOL ConsoleInit(VOID) +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$", @@ -333,37 +312,86 @@ 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(); + /* 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 CommandThreadProc(LPVOID Parameter) +DWORD +WINAPI +PumpConsoleInput(LPVOID Parameter) +{ + HANDLE ConsoleInput = (HANDLE)Parameter; + INPUT_RECORD InputRecord; + DWORD Count; + + while (VdmRunning) + { + /* Make sure the task event is signaled */ + WaitForSingleObject(VdmTaskEvent, INFINITE); + + /* Wait for an input record */ + if (!ReadConsoleInput(ConsoleInput, &InputRecord, 1, &Count)) + { + DWORD LastError = GetLastError(); + DPRINT1("Error reading console input (0x%p, %lu) - Error %lu\n", ConsoleInput, Count, LastError); + return LastError; + } + + ASSERT(Count != 0); + + /* Check the event type */ + switch (InputRecord.EventType) + { + case KEY_EVENT: + case MOUSE_EVENT: + /* Send it to the PS/2 controller */ + PS2Dispatch(&InputRecord); + break; + + case MENU_EVENT: + { + switch (InputRecord.Event.MenuEvent.dwCommandId) + { + case ID_SHOWHIDE_MOUSE: + ShowHideMousePointer(ConsoleOutput, ShowPointer); + ShowPointer = !ShowPointer; + break; + + case ID_VDM_QUIT: + /* Stop the VDM */ + EmulatorTerminate(); + break; + + default: + break; + } + + break; + } + + default: + break; + } + } + + return 0; +} + +#ifndef STANDALONE +static DWORD +WINAPI +CommandThreadProc(LPVOID Parameter) { BOOLEAN First = TRUE; DWORD Result; @@ -404,30 +432,14 @@ 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; - } - - /* 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); + // break; + continue; + }
First = FALSE; } @@ -435,8 +447,10 @@
return 0; } - -INT wmain(INT argc, WCHAR *argv[]) +#endif + +INT +wmain(INT argc, WCHAR *argv[]) { #ifdef STANDALONE
@@ -459,6 +473,7 @@ }
#else + INT i; WCHAR *endptr;
@@ -530,26 +545,15 @@ #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
Modified: trunk/reactos/subsystems/ntvdm/ntvdm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/ntvdm.h?re... ============================================================================== --- trunk/reactos/subsystems/ntvdm/ntvdm.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/ntvdm/ntvdm.h [iso-8859-1] Sun May 11 19:25:09 2014 @@ -28,13 +28,22 @@
#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, ...);