- 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
This commit is contained in:
Hermès Bélusca-Maïto 2014-05-15 23:13:06 +00:00
parent 480e3ae350
commit 325729ca4a
4 changed files with 261 additions and 46 deletions

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
*/
@ -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);

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
* 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);

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
*/
@ -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);

View file

@ -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 <theflash AT sdf DOT lonestar DOT org>
* 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);
}