From 325729ca4a9fc911c2259339977380b1f4108080 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 15 May 2014 23:13:06 +0000 Subject: [PATCH] [NTVDM] - Add some diagnostic DPRINTs (they are off by default), and fix few of them. - Fix/complete few comments. - Implement INT 21h, AH=56h (rename file), 5Ah (create temporary file), 5Bh (create new file), 68h and 6Ah ("commit" aka. flush file; they are the same function). - Stubplement INT 21h, AH=60h (canonicalize file name or path) and 6Ch (extended open or create file). For this latest one I will merge DosCreateFile and DosOpenFile into the same function (in fact a wrapper around CreateFileA, that is used both for creating and opening files). svn path=/trunk/; revision=63309 --- reactos/subsystems/ntvdm/dos/dos32krnl/bios.c | 6 +- reactos/subsystems/ntvdm/dos/dos32krnl/dos.c | 190 ++++++++++++++++-- reactos/subsystems/ntvdm/dos/dos32krnl/dos.h | 8 +- .../subsystems/ntvdm/dos/dos32krnl/dosfiles.c | 103 +++++++--- 4 files changed, 261 insertions(+), 46 deletions(-) diff --git a/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c b/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c index 32057e51f4b..b70be3b2be7 100644 --- a/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c +++ b/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c @@ -1,8 +1,8 @@ /* * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine - * FILE: dos.c - * PURPOSE: VDM DOS Kernel + * FILE: dos/dos32krnl/bios.c + * PURPOSE: DOS32 Bios * PROGRAMMERS: Aleksandar Andrejevic */ @@ -31,6 +31,8 @@ CHAR DosReadCharacter(WORD FileHandle) CHAR Character = '\0'; WORD BytesRead; + DPRINT("DosReadCharacter\n"); + /* Use the file reading function */ DosReadFile(FileHandle, &Character, 1, &BytesRead); diff --git a/reactos/subsystems/ntvdm/dos/dos32krnl/dos.c b/reactos/subsystems/ntvdm/dos/dos32krnl/dos.c index bfdef07dc1c..4928ca443fe 100644 --- a/reactos/subsystems/ntvdm/dos/dos32krnl/dos.c +++ b/reactos/subsystems/ntvdm/dos/dos32krnl/dos.c @@ -2,8 +2,9 @@ * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine * FILE: dos/dos32krnl/dos.c - * PURPOSE: VDM DOS Kernel + * PURPOSE: DOS32 Kernel * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ /* INCLUDES *******************************************************************/ @@ -1436,13 +1437,16 @@ VOID WINAPI DosInt21h(LPWORD Stack) /* Read Character from STDIN with Echo */ case 0x01: { + DPRINT("INT 21h, AH = 01h\n"); + // FIXME: Under DOS 2+, input / output handle may be redirected!!!! DoEcho = TRUE; Character = DosReadCharacter(DOS_INPUT_HANDLE); DoEcho = FALSE; - // /* Let the BOP repeat if needed */ - // if (getCF()) break; + // FIXME: Check whether Ctrl-C / Ctrl-Break is pressed, and call INT 23h if so. + // Check also Ctrl-P and set echo-to-printer flag. + // Ctrl-Z is not interpreted. setAL(Character); break; @@ -1536,6 +1540,8 @@ VOID WINAPI DosInt21h(LPWORD Stack) case 0x07: case 0x08: { + DPRINT("Char input without echo\n"); + // FIXME: Under DOS 2+, input handle may be redirected!!!! Character = DosReadCharacter(DOS_INPUT_HANDLE); @@ -1566,7 +1572,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) * See Ralf Brown: http://www.ctyme.com/intr/rb-2562.htm * for more information. */ - setAL('$'); + setAL('$'); // *String break; } @@ -1576,7 +1582,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) WORD Count = 0; InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX()); - DPRINT1("Read Buffered Input\n"); + DPRINT("Read Buffered Input\n"); while (Count < InputBuffer->MaxLength) { @@ -1585,12 +1591,15 @@ VOID WINAPI DosInt21h(LPWORD Stack) /* Try to read a character (wait) */ Character = DosReadCharacter(DOS_INPUT_HANDLE); + // FIXME: Check whether Ctrl-C / Ctrl-Break is pressed, and call INT 23h if so. + /* Echo the character and append it to the buffer */ DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); InputBuffer->Buffer[Count] = Character; + Count++; /* Carriage returns are also counted */ + if (Character == '\r') break; - Count++; } /* Update the length */ @@ -1623,13 +1632,9 @@ VOID WINAPI DosInt21h(LPWORD Stack) InputFunction == 0x07 || InputFunction == 0x08 || InputFunction == 0x0A) { + /* Call ourselves recursively */ setAH(InputFunction); - /* - * Instead of calling ourselves really recursively as in: - * DosInt21h(Stack); - * prefer resetting the CF flag to let the BOP repeat. - */ - setCF(1); + DosInt21h(Stack); } break; } @@ -1737,7 +1742,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) /* Create New PSP */ case 0x26: { - DPRINT1("INT 21h, 26h - Create New PSP is UNIMPLEMENTED\n"); + DPRINT1("INT 21h, AH = 26h - Create New PSP is UNIMPLEMENTED\n"); break; } @@ -1993,15 +1998,16 @@ VOID WINAPI DosInt21h(LPWORD Stack) break; } - /* Create File */ + /* Create or Truncate File */ case 0x3C: { WORD FileHandle; WORD ErrorCode = DosCreateFile(&FileHandle, (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()), + CREATE_ALWAYS, getCX()); - if (ErrorCode == 0) + if (ErrorCode == ERROR_SUCCESS) { Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; setAX(FileHandle); @@ -2023,7 +2029,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()), getAL()); - if (ErrorCode == 0) + if (ErrorCode == ERROR_SUCCESS) { Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; setAX(FileHandle); @@ -2059,6 +2065,8 @@ VOID WINAPI DosInt21h(LPWORD Stack) WORD BytesRead = 0; WORD ErrorCode; + DPRINT("INT 21h, AH = 3Fh\n"); + DoEcho = TRUE; ErrorCode = DosReadFile(getBX(), SEG_OFF_TO_PTR(getDS(), getDX()), @@ -2468,6 +2476,30 @@ VOID WINAPI DosInt21h(LPWORD Stack) break; } + /* Rename File */ + case 0x56: + { + LPSTR ExistingFileName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX()); + LPSTR NewFileName = (LPSTR)SEG_OFF_TO_PTR(getES(), getDI()); + + /* + * See Ralf Brown: http://www.ctyme.com/intr/rb-2990.htm + * for more information. + */ + + if (MoveFileA(ExistingFileName, NewFileName)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(GetLastError()); + } + + break; + } + /* Get/Set Memory Management Options */ case 0x58: { @@ -2524,6 +2556,79 @@ VOID WINAPI DosInt21h(LPWORD Stack) break; } + /* Create Temporary File */ + case 0x5A: + { + LPSTR PathName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX()); + LPSTR FileName = PathName; // The buffer for the path and the full file name is the same. + UINT uRetVal; + WORD FileHandle; + WORD ErrorCode; + + /* + * See Ralf Brown: http://www.ctyme.com/intr/rb-3014.htm + * for more information. + */ + + // FIXME: Check for buffer validity? + // It should be a ASCIZ path ending with a '\' + 13 zero bytes + // to receive the generated filename. + + /* First create the temporary file */ + uRetVal = GetTempFileNameA(PathName, NULL, 0, FileName); + if (uRetVal == 0) + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(GetLastError()); + break; + } + + /* Now try to open it in read/write access */ + ErrorCode = DosOpenFile(&FileHandle, FileName, 2); + if (ErrorCode == ERROR_SUCCESS) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(FileHandle); + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ErrorCode); + } + + break; + } + + /* Create New File */ + case 0x5B: + { + WORD FileHandle; + WORD ErrorCode = DosCreateFile(&FileHandle, + (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()), + CREATE_NEW, + getCX()); + + if (ErrorCode == ERROR_SUCCESS) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(FileHandle); + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ErrorCode); + } + + break; + } + + /* Canonicalize File Name or Path */ + case 0x60: + { + // TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + break; + } + /* Set Handle Count */ case 0x67: { @@ -2537,6 +2642,50 @@ VOID WINAPI DosInt21h(LPWORD Stack) break; } + /* Commit File */ + case 0x68: + case 0x6A: + { + /* + * Function 6Ah is identical to function 68h, + * and sets AH to 68h if success. + * See Ralf Brown: http://www.ctyme.com/intr/rb-3176.htm + * for more information. + */ + setAH(0x68); + + if (DosFlushFileBuffers(getBX())) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(GetLastError()); + } + + break; + } + + /* Extended Open/Create */ + case 0x6C: + { + /* Check for AL == 00 */ + if (getAL() != 0x00) + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_FUNCTION); + break; + } + + // TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // FIXME: Extend and merge DosOpenFile and DosCreateFile into + // a single wrapper around CreateFileA, which acts as: + // http://www.ctyme.com/intr/rb-3179.htm + + break; + } + /* Unsupported */ default: { @@ -2562,6 +2711,8 @@ VOID WINAPI DosFastConOut(LPWORD Stack) { /* * This is the DOS 2+ Fast Console Output Interrupt. + * The default handler under DOS 2.x and 3.x simply calls INT 10h/AH=0Eh. + * * See Ralf Brown: http://www.ctyme.com/intr/rb-4124.htm * for more information. */ @@ -2570,7 +2721,12 @@ VOID WINAPI DosFastConOut(LPWORD Stack) USHORT AX = getAX(); USHORT BX = getBX(); - /* Set the parameters (AL = character, already set) */ + /* + * Set the parameters: + * AL contains the character to print (already set), + * BL contains the character attribute, + * BH contains the video page to use. + */ setBL(DOS_CHAR_ATTRIBUTE); setBH(Bda->VideoPage); diff --git a/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h b/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h index ead1344d29b..e2f0cef368c 100644 --- a/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h +++ b/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h @@ -1,8 +1,8 @@ /* * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine - * FILE: dos.h - * PURPOSE: VDM DOS Kernel + * FILE: dos/dos32krnl/dos.h + * PURPOSE: DOS32 Kernel * PROGRAMMERS: Aleksandar Andrejevic */ @@ -191,8 +191,8 @@ 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 DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD CreationFlags, WORD Attributes); +WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes); 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); diff --git a/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c b/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c index 51c57d3c2c0..e5560b2264d 100644 --- a/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c +++ b/reactos/subsystems/ntvdm/dos/dos32krnl/dosfiles.c @@ -2,8 +2,9 @@ * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine * FILE: dos/dos32krnl/dosfiles.c - * PURPOSE: DOS Files + * PURPOSE: DOS32 Files Support * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ /* INCLUDES *******************************************************************/ @@ -22,13 +23,14 @@ /* PUBLIC FUNCTIONS ***********************************************************/ -WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes) +WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD CreationFlags, WORD Attributes) { HANDLE FileHandle; WORD DosHandle; - DPRINT("DosCreateFile: FilePath \"%s\", Attributes 0x%04X\n", + DPRINT("DosCreateFile: FilePath \"%s\", CreationFlags 0x%04X, Attributes 0x%04X\n", FilePath, + CreationFlags, Attributes); /* Create the file */ @@ -36,7 +38,7 @@ WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes) GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - CREATE_ALWAYS, + CreationFlags, Attributes, NULL); @@ -63,37 +65,40 @@ WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes) return ERROR_SUCCESS; } -WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode) +WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes) { HANDLE FileHandle; - ACCESS_MASK Access = 0; + ACCESS_MASK AccessMode = 0; + DWORD ShareMode = 0; + BOOL InheritableFile = FALSE; + SECURITY_ATTRIBUTES SecurityAttributes; WORD DosHandle; - DPRINT("DosOpenFile: FilePath \"%s\", AccessMode 0x%04X\n", + DPRINT("DosOpenFile: FilePath \"%s\", AccessShareModes 0x%04X\n", FilePath, - AccessMode); + AccessShareModes); /* Parse the access mode */ - switch (AccessMode & 3) + switch (AccessShareModes & 0x03) { case 0: { /* Read-only */ - Access = GENERIC_READ; + AccessMode = GENERIC_READ; break; } case 1: { /* Write only */ - Access = GENERIC_WRITE; + AccessMode = GENERIC_WRITE; break; } case 2: { /* Read and write */ - Access = GENERIC_READ | GENERIC_WRITE; + AccessMode = GENERIC_READ | GENERIC_WRITE; break; } @@ -104,11 +109,64 @@ WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode) } } + /* Parse the share mode */ + switch ((AccessShareModes >> 4) & 0x07) + { + case 0: + { + /* Compatibility mode */ + ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + break; + } + + case 1: + { + /* No sharing "DenyAll" */ + ShareMode = 0; + break; + } + + case 2: + { + /* No write share "DenyWrite" */ + ShareMode = FILE_SHARE_READ; + break; + } + + case 3: + { + /* No read share "DenyRead" */ + ShareMode = FILE_SHARE_WRITE; + break; + } + + case 4: + { + /* Full share "DenyNone" */ + ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + break; + } + + default: + { + /* Invalid */ + return ERROR_INVALID_PARAMETER; + } + } + + /* Check for inheritance */ + InheritableFile = ((AccessShareModes & 0x80) == 0); + + /* Assign default security attributes to the file, and set the inheritance flag */ + SecurityAttributes.nLength = sizeof(SecurityAttributes); + SecurityAttributes.lpSecurityDescriptor = NULL; + SecurityAttributes.bInheritHandle = InheritableFile; + /* Open the file */ FileHandle = CreateFileA(FilePath, - Access, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, + AccessMode, + ShareMode, + &SecurityAttributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); @@ -142,7 +200,7 @@ WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead) DWORD BytesRead32 = 0; HANDLE Handle = DosGetRealHandle(FileHandle); - DPRINT1("DosReadFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count); + 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; @@ -207,9 +265,7 @@ WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritte DWORD BytesWritten32 = 0; HANDLE Handle = DosGetRealHandle(FileHandle); - DPRINT1("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n", - FileHandle, - Count); + 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; @@ -313,7 +369,6 @@ WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset) return ERROR_SUCCESS; } -// This function is almost exclusively used as a DosFlushInputBuffer BOOL DosFlushFileBuffers(WORD FileHandle) { HANDLE Handle = DosGetRealHandle(FileHandle); @@ -322,9 +377,11 @@ BOOL DosFlushFileBuffers(WORD FileHandle) 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. + * This function can either flush files back to disks, or flush + * console input buffers, in which case there is no need to check + * whether the handle is a console handle. FlushFileBuffers() + * automatically does this check and calls FlushConsoleInputBuffer() + * if needed. */ return FlushFileBuffers(Handle); } -- 2.17.1