- 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 * COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine * PROJECT: ReactOS Virtual DOS Machine
* FILE: dos.c * FILE: dos/dos32krnl/bios.c
* PURPOSE: VDM DOS Kernel * PURPOSE: DOS32 Bios
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/ */
@ -31,6 +31,8 @@ CHAR DosReadCharacter(WORD FileHandle)
CHAR Character = '\0'; CHAR Character = '\0';
WORD BytesRead; WORD BytesRead;
DPRINT("DosReadCharacter\n");
/* Use the file reading function */ /* Use the file reading function */
DosReadFile(FileHandle, &Character, 1, &BytesRead); DosReadFile(FileHandle, &Character, 1, &BytesRead);

View file

@ -2,8 +2,9 @@
* COPYRIGHT: GPL - See COPYING in the top level directory * COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine * PROJECT: ReactOS Virtual DOS Machine
* FILE: dos/dos32krnl/dos.c * FILE: dos/dos32krnl/dos.c
* PURPOSE: VDM DOS Kernel * PURPOSE: DOS32 Kernel
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/ */
/* INCLUDES *******************************************************************/ /* INCLUDES *******************************************************************/
@ -1436,13 +1437,16 @@ VOID WINAPI DosInt21h(LPWORD Stack)
/* Read Character from STDIN with Echo */ /* Read Character from STDIN with Echo */
case 0x01: case 0x01:
{ {
DPRINT("INT 21h, AH = 01h\n");
// FIXME: Under DOS 2+, input / output handle may be redirected!!!! // FIXME: Under DOS 2+, input / output handle may be redirected!!!!
DoEcho = TRUE; DoEcho = TRUE;
Character = DosReadCharacter(DOS_INPUT_HANDLE); Character = DosReadCharacter(DOS_INPUT_HANDLE);
DoEcho = FALSE; DoEcho = FALSE;
// /* Let the BOP repeat if needed */ // FIXME: Check whether Ctrl-C / Ctrl-Break is pressed, and call INT 23h if so.
// if (getCF()) break; // Check also Ctrl-P and set echo-to-printer flag.
// Ctrl-Z is not interpreted.
setAL(Character); setAL(Character);
break; break;
@ -1536,6 +1540,8 @@ VOID WINAPI DosInt21h(LPWORD Stack)
case 0x07: case 0x07:
case 0x08: case 0x08:
{ {
DPRINT("Char input without echo\n");
// FIXME: Under DOS 2+, input handle may be redirected!!!! // FIXME: Under DOS 2+, input handle may be redirected!!!!
Character = DosReadCharacter(DOS_INPUT_HANDLE); 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 * See Ralf Brown: http://www.ctyme.com/intr/rb-2562.htm
* for more information. * for more information.
*/ */
setAL('$'); setAL('$'); // *String
break; break;
} }
@ -1576,7 +1582,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
WORD Count = 0; WORD Count = 0;
InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX()); InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX());
DPRINT1("Read Buffered Input\n"); DPRINT("Read Buffered Input\n");
while (Count < InputBuffer->MaxLength) while (Count < InputBuffer->MaxLength)
{ {
@ -1585,12 +1591,15 @@ VOID WINAPI DosInt21h(LPWORD Stack)
/* Try to read a character (wait) */ /* Try to read a character (wait) */
Character = DosReadCharacter(DOS_INPUT_HANDLE); 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 */ /* Echo the character and append it to the buffer */
DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
InputBuffer->Buffer[Count] = Character; InputBuffer->Buffer[Count] = Character;
Count++; /* Carriage returns are also counted */
if (Character == '\r') break; if (Character == '\r') break;
Count++;
} }
/* Update the length */ /* Update the length */
@ -1623,13 +1632,9 @@ VOID WINAPI DosInt21h(LPWORD Stack)
InputFunction == 0x07 || InputFunction == 0x08 || InputFunction == 0x07 || InputFunction == 0x08 ||
InputFunction == 0x0A) InputFunction == 0x0A)
{ {
/* Call ourselves recursively */
setAH(InputFunction); setAH(InputFunction);
/* DosInt21h(Stack);
* Instead of calling ourselves really recursively as in:
* DosInt21h(Stack);
* prefer resetting the CF flag to let the BOP repeat.
*/
setCF(1);
} }
break; break;
} }
@ -1737,7 +1742,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
/* Create New PSP */ /* Create New PSP */
case 0x26: case 0x26:
{ {
DPRINT1("INT 21h, 26h - Create New PSP is UNIMPLEMENTED\n"); DPRINT1("INT 21h, AH = 26h - Create New PSP is UNIMPLEMENTED\n");
break; break;
} }
@ -1993,15 +1998,16 @@ VOID WINAPI DosInt21h(LPWORD Stack)
break; break;
} }
/* Create File */ /* Create or Truncate File */
case 0x3C: case 0x3C:
{ {
WORD FileHandle; WORD FileHandle;
WORD ErrorCode = DosCreateFile(&FileHandle, WORD ErrorCode = DosCreateFile(&FileHandle,
(LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()), (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()),
CREATE_ALWAYS,
getCX()); getCX());
if (ErrorCode == 0) if (ErrorCode == ERROR_SUCCESS)
{ {
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
setAX(FileHandle); setAX(FileHandle);
@ -2023,7 +2029,7 @@ VOID WINAPI DosInt21h(LPWORD Stack)
(LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()), (LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()),
getAL()); getAL());
if (ErrorCode == 0) if (ErrorCode == ERROR_SUCCESS)
{ {
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
setAX(FileHandle); setAX(FileHandle);
@ -2059,6 +2065,8 @@ VOID WINAPI DosInt21h(LPWORD Stack)
WORD BytesRead = 0; WORD BytesRead = 0;
WORD ErrorCode; WORD ErrorCode;
DPRINT("INT 21h, AH = 3Fh\n");
DoEcho = TRUE; DoEcho = TRUE;
ErrorCode = DosReadFile(getBX(), ErrorCode = DosReadFile(getBX(),
SEG_OFF_TO_PTR(getDS(), getDX()), SEG_OFF_TO_PTR(getDS(), getDX()),
@ -2468,6 +2476,30 @@ VOID WINAPI DosInt21h(LPWORD Stack)
break; 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 */ /* Get/Set Memory Management Options */
case 0x58: case 0x58:
{ {
@ -2524,6 +2556,79 @@ VOID WINAPI DosInt21h(LPWORD Stack)
break; 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 */ /* Set Handle Count */
case 0x67: case 0x67:
{ {
@ -2537,6 +2642,50 @@ VOID WINAPI DosInt21h(LPWORD Stack)
break; 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 */ /* Unsupported */
default: default:
{ {
@ -2562,6 +2711,8 @@ VOID WINAPI DosFastConOut(LPWORD Stack)
{ {
/* /*
* This is the DOS 2+ Fast Console Output Interrupt. * 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 * See Ralf Brown: http://www.ctyme.com/intr/rb-4124.htm
* for more information. * for more information.
*/ */
@ -2570,7 +2721,12 @@ VOID WINAPI DosFastConOut(LPWORD Stack)
USHORT AX = getAX(); USHORT AX = getAX();
USHORT BX = getBX(); 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); setBL(DOS_CHAR_ATTRIBUTE);
setBH(Bda->VideoPage); setBH(Bda->VideoPage);

View file

@ -1,8 +1,8 @@
/* /*
* COPYRIGHT: GPL - See COPYING in the top level directory * COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine * PROJECT: ReactOS Virtual DOS Machine
* FILE: dos.h * FILE: dos/dos32krnl/dos.h
* PURPOSE: VDM DOS Kernel * PURPOSE: DOS32 Kernel
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/ */
@ -191,8 +191,8 @@ BOOL IsConsoleHandle(HANDLE hHandle);
WORD DosOpenHandle(HANDLE Handle); WORD DosOpenHandle(HANDLE Handle);
HANDLE DosGetRealHandle(WORD DosHandle); HANDLE DosGetRealHandle(WORD DosHandle);
WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes); WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD CreationFlags, WORD Attributes);
WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode); WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes);
WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead); WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead);
WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten); WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten);
WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset); 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 * COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine * PROJECT: ReactOS Virtual DOS Machine
* FILE: dos/dos32krnl/dosfiles.c * FILE: dos/dos32krnl/dosfiles.c
* PURPOSE: DOS Files * PURPOSE: DOS32 Files Support
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/ */
/* INCLUDES *******************************************************************/ /* INCLUDES *******************************************************************/
@ -22,13 +23,14 @@
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes) WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD CreationFlags, WORD Attributes)
{ {
HANDLE FileHandle; HANDLE FileHandle;
WORD DosHandle; WORD DosHandle;
DPRINT("DosCreateFile: FilePath \"%s\", Attributes 0x%04X\n", DPRINT("DosCreateFile: FilePath \"%s\", CreationFlags 0x%04X, Attributes 0x%04X\n",
FilePath, FilePath,
CreationFlags,
Attributes); Attributes);
/* Create the file */ /* Create the file */
@ -36,7 +38,7 @@ WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes)
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, NULL,
CREATE_ALWAYS, CreationFlags,
Attributes, Attributes,
NULL); NULL);
@ -63,37 +65,40 @@ WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode) WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessShareModes)
{ {
HANDLE FileHandle; HANDLE FileHandle;
ACCESS_MASK Access = 0; ACCESS_MASK AccessMode = 0;
DWORD ShareMode = 0;
BOOL InheritableFile = FALSE;
SECURITY_ATTRIBUTES SecurityAttributes;
WORD DosHandle; WORD DosHandle;
DPRINT("DosOpenFile: FilePath \"%s\", AccessMode 0x%04X\n", DPRINT("DosOpenFile: FilePath \"%s\", AccessShareModes 0x%04X\n",
FilePath, FilePath,
AccessMode); AccessShareModes);
/* Parse the access mode */ /* Parse the access mode */
switch (AccessMode & 3) switch (AccessShareModes & 0x03)
{ {
case 0: case 0:
{ {
/* Read-only */ /* Read-only */
Access = GENERIC_READ; AccessMode = GENERIC_READ;
break; break;
} }
case 1: case 1:
{ {
/* Write only */ /* Write only */
Access = GENERIC_WRITE; AccessMode = GENERIC_WRITE;
break; break;
} }
case 2: case 2:
{ {
/* Read and write */ /* Read and write */
Access = GENERIC_READ | GENERIC_WRITE; AccessMode = GENERIC_READ | GENERIC_WRITE;
break; 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 */ /* Open the file */
FileHandle = CreateFileA(FilePath, FileHandle = CreateFileA(FilePath,
Access, AccessMode,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, ShareMode,
NULL, &SecurityAttributes,
OPEN_EXISTING, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,
NULL); NULL);
@ -142,7 +200,7 @@ WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead)
DWORD BytesRead32 = 0; DWORD BytesRead32 = 0;
HANDLE Handle = DosGetRealHandle(FileHandle); 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 */ /* Make sure the handle is valid */
if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; 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; DWORD BytesWritten32 = 0;
HANDLE Handle = DosGetRealHandle(FileHandle); HANDLE Handle = DosGetRealHandle(FileHandle);
DPRINT1("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n", DPRINT("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count);
FileHandle,
Count);
/* Make sure the handle is valid */ /* Make sure the handle is valid */
if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; 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; return ERROR_SUCCESS;
} }
// This function is almost exclusively used as a DosFlushInputBuffer
BOOL DosFlushFileBuffers(WORD FileHandle) BOOL DosFlushFileBuffers(WORD FileHandle)
{ {
HANDLE Handle = DosGetRealHandle(FileHandle); HANDLE Handle = DosGetRealHandle(FileHandle);
@ -322,9 +377,11 @@ BOOL DosFlushFileBuffers(WORD FileHandle)
if (Handle == INVALID_HANDLE_VALUE) return FALSE; if (Handle == INVALID_HANDLE_VALUE) return FALSE;
/* /*
* No need to check whether the handle is a console handle since * This function can either flush files back to disks, or flush
* FlushFileBuffers() automatically does this check and calls * console input buffers, in which case there is no need to check
* FlushConsoleInputBuffer() for us. * whether the handle is a console handle. FlushFileBuffers()
* automatically does this check and calls FlushConsoleInputBuffer()
* if needed.
*/ */
return FlushFileBuffers(Handle); return FlushFileBuffers(Handle);
} }