mirror of
https://github.com/reactos/reactos.git
synced 2024-08-10 05:08:11 +00:00
[NTVDM]
Fix DOS character device I/O. Implement CON line buffering. Make sure INT 21h functions 01h, 06h, 07h, 08h, 0Ah and 3Fh work as expected for CON input. svn path=/trunk/; revision=69356
This commit is contained in:
parent
d8105a4366
commit
7f662fde76
|
@ -17,6 +17,7 @@
|
||||||
#include "../dem.h"
|
#include "../dem.h"
|
||||||
#include "dos.h"
|
#include "dos.h"
|
||||||
#include "dosfiles.h"
|
#include "dosfiles.h"
|
||||||
|
#include "handle.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "bios/bios.h"
|
#include "bios/bios.h"
|
||||||
|
|
||||||
|
@ -45,6 +46,16 @@ PBIOS_DATA BiosData;
|
||||||
CHAR DosReadCharacter(WORD FileHandle)
|
CHAR DosReadCharacter(WORD FileHandle)
|
||||||
{
|
{
|
||||||
WORD BytesRead;
|
WORD BytesRead;
|
||||||
|
PDOS_FILE_DESCRIPTOR Descriptor = NULL;
|
||||||
|
WORD OldDeviceInfo;
|
||||||
|
|
||||||
|
/* Find the standard input descriptor and switch it to binary mode */
|
||||||
|
Descriptor = DosGetHandleFileDescriptor(FileHandle);
|
||||||
|
if (Descriptor)
|
||||||
|
{
|
||||||
|
OldDeviceInfo = Descriptor->DeviceInfo;
|
||||||
|
Descriptor->DeviceInfo |= FILE_INFO_BINARY;
|
||||||
|
}
|
||||||
|
|
||||||
Sda->ByteBuffer = '\0';
|
Sda->ByteBuffer = '\0';
|
||||||
DPRINT("DosReadCharacter\n");
|
DPRINT("DosReadCharacter\n");
|
||||||
|
@ -55,6 +66,8 @@ CHAR DosReadCharacter(WORD FileHandle)
|
||||||
1,
|
1,
|
||||||
&BytesRead);
|
&BytesRead);
|
||||||
|
|
||||||
|
/* Restore the old mode and return the character */
|
||||||
|
if (Descriptor) Descriptor->DeviceInfo = OldDeviceInfo;
|
||||||
return Sda->ByteBuffer;
|
return Sda->ByteBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,15 +63,8 @@ WORD NTAPI ConDrvReadInput(PDOS_DEVICE_NODE Device, DWORD Buffer, PWORD Length)
|
||||||
|
|
||||||
Pointer[BytesRead++] = Character;
|
Pointer[BytesRead++] = Character;
|
||||||
|
|
||||||
if (Character != 0 && DoEcho)
|
|
||||||
DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
|
|
||||||
|
|
||||||
/* Stop on first carriage return */
|
/* Stop on first carriage return */
|
||||||
if (Character == '\r')
|
if (Character == '\r') break;
|
||||||
{
|
|
||||||
if (DoEcho) DosPrintCharacter(DOS_OUTPUT_HANDLE, '\n');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*Length = BytesRead;
|
*Length = BytesRead;
|
||||||
|
|
|
@ -45,9 +45,6 @@ PDOS_DATA DosData;
|
||||||
PDOS_SYSVARS SysVars;
|
PDOS_SYSVARS SysVars;
|
||||||
PDOS_SDA Sda;
|
PDOS_SDA Sda;
|
||||||
|
|
||||||
/* Echo state for INT 21h, AH = 01h and AH = 3Fh */
|
|
||||||
BOOLEAN DoEcho = FALSE;
|
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
static BOOLEAN DosChangeDrive(BYTE Drive)
|
static BOOLEAN DosChangeDrive(BYTE Drive)
|
||||||
|
@ -162,7 +159,54 @@ static BOOLEAN DosChangeDirectory(LPSTR Directory)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOLEAN DosControlBreak(VOID)
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
VOID DosEchoCharacter(CHAR Character)
|
||||||
|
{
|
||||||
|
switch (Character)
|
||||||
|
{
|
||||||
|
case '\0':
|
||||||
|
{
|
||||||
|
/* Nothing */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
{
|
||||||
|
/* Print both a carriage return and a newline */
|
||||||
|
DosPrintCharacter(DOS_OUTPUT_HANDLE, '\r');
|
||||||
|
DosPrintCharacter(DOS_OUTPUT_HANDLE, '\n');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '\b':
|
||||||
|
{
|
||||||
|
/* Erase the character */
|
||||||
|
DosPrintCharacter(DOS_OUTPUT_HANDLE, '\b');
|
||||||
|
DosPrintCharacter(DOS_OUTPUT_HANDLE, ' ');
|
||||||
|
DosPrintCharacter(DOS_OUTPUT_HANDLE, '\b');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
/* Check if this is a special character */
|
||||||
|
if (Character < 0x20)
|
||||||
|
{
|
||||||
|
DosPrintCharacter(DOS_OUTPUT_HANDLE, '^');
|
||||||
|
Character += 'A' - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Echo the character */
|
||||||
|
DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN DosControlBreak(VOID)
|
||||||
{
|
{
|
||||||
setCF(0);
|
setCF(0);
|
||||||
|
|
||||||
|
@ -178,8 +222,6 @@ static BOOLEAN DosControlBreak(VOID)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
|
||||||
|
|
||||||
VOID WINAPI DosInt20h(LPWORD Stack)
|
VOID WINAPI DosInt20h(LPWORD Stack)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -217,14 +259,9 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
{
|
{
|
||||||
DPRINT("INT 21h, AH = 01h\n");
|
DPRINT("INT 21h, AH = 01h\n");
|
||||||
|
|
||||||
// FIXME: Under DOS 2+, input / output handle may be redirected!!!!
|
|
||||||
DoEcho = TRUE;
|
|
||||||
Character = DosReadCharacter(DOS_INPUT_HANDLE);
|
Character = DosReadCharacter(DOS_INPUT_HANDLE);
|
||||||
DoEcho = FALSE;
|
DosEchoCharacter(Character);
|
||||||
|
if (Character == 0x03 && DosControlBreak()) 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);
|
setAL(Character);
|
||||||
break;
|
break;
|
||||||
|
@ -300,8 +337,11 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
/* Input */
|
/* Input */
|
||||||
if (DosCheckInput())
|
if (DosCheckInput())
|
||||||
{
|
{
|
||||||
|
CHAR Character = DosReadCharacter(DOS_INPUT_HANDLE);
|
||||||
|
DosEchoCharacter(Character);
|
||||||
|
|
||||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
|
||||||
setAL(DosReadCharacter(DOS_INPUT_HANDLE));
|
setAL(Character);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -314,17 +354,21 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Character Input without Echo */
|
/* Direct Character Input without Echo */
|
||||||
case 0x07:
|
case 0x07:
|
||||||
|
{
|
||||||
|
DPRINT("Direct char input without echo\n");
|
||||||
|
setAL(DosReadCharacter(DOS_INPUT_HANDLE));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Character Input without Echo */
|
||||||
case 0x08:
|
case 0x08:
|
||||||
{
|
{
|
||||||
DPRINT("Char input without echo\n");
|
DPRINT("Char input without echo\n");
|
||||||
|
|
||||||
Character = DosReadCharacter(DOS_INPUT_HANDLE);
|
Character = DosReadCharacter(DOS_INPUT_HANDLE);
|
||||||
|
if (Character == 0x03 && DosControlBreak()) break;
|
||||||
// FIXME: For 0x07, do not check Ctrl-C/Break.
|
|
||||||
// For 0x08, do check those control sequences and if needed,
|
|
||||||
// call INT 0x23.
|
|
||||||
|
|
||||||
setAL(Character);
|
setAL(Character);
|
||||||
break;
|
break;
|
||||||
|
@ -353,82 +397,19 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
/* Read Buffered Input */
|
/* Read Buffered Input */
|
||||||
case 0x0A:
|
case 0x0A:
|
||||||
{
|
{
|
||||||
WORD Count = 0;
|
WORD BytesRead;
|
||||||
PDOS_INPUT_BUFFER InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX());
|
PDOS_INPUT_BUFFER InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX());
|
||||||
|
|
||||||
DPRINT("Read Buffered Input\n");
|
DPRINT("Read Buffered Input\n");
|
||||||
|
if (InputBuffer->MaxLength == 0) break;
|
||||||
|
|
||||||
while (Count < InputBuffer->MaxLength)
|
/* Read from standard input */
|
||||||
{
|
DosReadFile(DOS_INPUT_HANDLE,
|
||||||
/* Try to read a character (wait) */
|
MAKELONG(getDX() + FIELD_OFFSET(DOS_INPUT_BUFFER, Buffer), getDS()),
|
||||||
Character = DosReadCharacter(DOS_INPUT_HANDLE);
|
InputBuffer->MaxLength,
|
||||||
|
&BytesRead);
|
||||||
switch (Character)
|
|
||||||
{
|
|
||||||
/* Extended character */
|
|
||||||
case '\0':
|
|
||||||
{
|
|
||||||
/* Read the scancode */
|
|
||||||
DosReadCharacter(DOS_INPUT_HANDLE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ctrl-C */
|
|
||||||
case 0x03:
|
|
||||||
{
|
|
||||||
DosPrintCharacter(DOS_OUTPUT_HANDLE, '^');
|
|
||||||
DosPrintCharacter(DOS_OUTPUT_HANDLE, 'C');
|
|
||||||
|
|
||||||
if (DosControlBreak())
|
|
||||||
{
|
|
||||||
/* Set the character to a newline to exit the loop */
|
|
||||||
Character = '\r';
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Backspace */
|
|
||||||
case '\b':
|
|
||||||
{
|
|
||||||
if (Count > 0)
|
|
||||||
{
|
|
||||||
Count--;
|
|
||||||
|
|
||||||
/* Erase the character */
|
|
||||||
DosPrintCharacter(DOS_OUTPUT_HANDLE, '\b');
|
|
||||||
DosPrintCharacter(DOS_OUTPUT_HANDLE, ' ');
|
|
||||||
DosPrintCharacter(DOS_OUTPUT_HANDLE, '\b');
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
/* Append it to the buffer */
|
|
||||||
InputBuffer->Buffer[Count] = Character;
|
|
||||||
|
|
||||||
/* Check if this is a special character */
|
|
||||||
if (Character < 0x20 && Character != 0x0A && Character != 0x0D)
|
|
||||||
{
|
|
||||||
DosPrintCharacter(DOS_OUTPUT_HANDLE, '^');
|
|
||||||
Character += 'A' - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Echo the character */
|
|
||||||
DosPrintCharacter(DOS_OUTPUT_HANDLE, Character);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Character == '\r') break;
|
|
||||||
if (Character == '\b') continue;
|
|
||||||
Count++; /* Carriage returns are NOT counted */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the length */
|
|
||||||
InputBuffer->Length = Count;
|
|
||||||
|
|
||||||
|
InputBuffer->Length = LOBYTE(BytesRead);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,12 +1035,10 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
|
|
||||||
DPRINT("DosReadFile(0x%04X)\n", getBX());
|
DPRINT("DosReadFile(0x%04X)\n", getBX());
|
||||||
|
|
||||||
DoEcho = TRUE;
|
|
||||||
ErrorCode = DosReadFile(getBX(),
|
ErrorCode = DosReadFile(getBX(),
|
||||||
MAKELONG(getDX(), getDS()),
|
MAKELONG(getDX(), getDS()),
|
||||||
getCX(),
|
getCX(),
|
||||||
&BytesRead);
|
&BytesRead);
|
||||||
DoEcho = FALSE;
|
|
||||||
|
|
||||||
if (ErrorCode == ERROR_SUCCESS)
|
if (ErrorCode == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
|
@ -246,6 +246,7 @@ typedef struct _DOS_DATA
|
||||||
WORD DosVersion; // DOS version to report to programs (can be different from the true one)
|
WORD DosVersion; // DOS version to report to programs (can be different from the true one)
|
||||||
DOS_SDA Sda;
|
DOS_SDA Sda;
|
||||||
CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
|
CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
|
||||||
|
BYTE UnreadConInputBuffer[128];
|
||||||
BYTE DosStack[384];
|
BYTE DosStack[384];
|
||||||
BYTE Sft[ANYSIZE_ARRAY];
|
BYTE Sft[ANYSIZE_ARRAY];
|
||||||
} DOS_DATA, *PDOS_DATA;
|
} DOS_DATA, *PDOS_DATA;
|
||||||
|
@ -293,7 +294,6 @@ C_ASSERT(sizeof(BIOS_DATA) == 0x100);
|
||||||
|
|
||||||
/* VARIABLES ******************************************************************/
|
/* VARIABLES ******************************************************************/
|
||||||
|
|
||||||
extern BOOLEAN DoEcho; // FIXME: Maybe move inside BiosData? (it's set by BIOS but used by CON driver in DOS BIOS)
|
|
||||||
extern PBIOS_DATA BiosData;
|
extern PBIOS_DATA BiosData;
|
||||||
extern PDOS_DATA DosData;
|
extern PDOS_DATA DosData;
|
||||||
extern PDOS_SYSVARS SysVars;
|
extern PDOS_SYSVARS SysVars;
|
||||||
|
@ -324,6 +324,9 @@ VOID DosPrintCharacter(WORD FileHandle, CHAR Character);
|
||||||
|
|
||||||
BOOLEAN DosBIOSInitialize(VOID);
|
BOOLEAN DosBIOSInitialize(VOID);
|
||||||
|
|
||||||
|
BOOLEAN DosControlBreak(VOID);
|
||||||
|
VOID DosEchoCharacter(CHAR Character);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DOS Kernel Functions
|
* DOS Kernel Functions
|
||||||
* See dos.c
|
* See dos.c
|
||||||
|
|
|
@ -691,9 +691,154 @@ WORD DosReadFile(WORD FileHandle,
|
||||||
PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
|
PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer);
|
||||||
if (!Node->ReadRoutine) return ERROR_INVALID_FUNCTION;
|
if (!Node->ReadRoutine) return ERROR_INVALID_FUNCTION;
|
||||||
|
|
||||||
/* Read the device */
|
if (Descriptor->DeviceInfo & FILE_INFO_BINARY)
|
||||||
Node->ReadRoutine(Node, Buffer, &Count);
|
{
|
||||||
*BytesRead = Count;
|
/* Read from the device directly */
|
||||||
|
Node->ReadRoutine(Node, Buffer, &Count);
|
||||||
|
*BytesRead = Count;
|
||||||
|
}
|
||||||
|
else if (Descriptor->DeviceInfo & FILE_INFO_STDIN)
|
||||||
|
{
|
||||||
|
/* Line-buffered CON input */
|
||||||
|
PCHAR ConBuffer = NULL;
|
||||||
|
PCHAR Pointer = FAR_POINTER(Buffer);
|
||||||
|
|
||||||
|
/* Check if the buffer is empty */
|
||||||
|
if (!SysVars->UnreadConInput)
|
||||||
|
{
|
||||||
|
ULONG LineSize = 0;
|
||||||
|
|
||||||
|
SysVars->UnreadConInput = FIELD_OFFSET(DOS_DATA, UnreadConInputBuffer);
|
||||||
|
ConBuffer = (PCHAR)SEG_OFF_TO_PTR(DOS_DATA_SEGMENT, SysVars->UnreadConInput);
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
USHORT Amount = 1;
|
||||||
|
CHAR Character;
|
||||||
|
|
||||||
|
/* Read a character from the CON device */
|
||||||
|
Node->ReadRoutine(Node,
|
||||||
|
MAKELONG(DOS_DATA_OFFSET(Sda.ByteBuffer),
|
||||||
|
DOS_DATA_SEGMENT),
|
||||||
|
&Amount);
|
||||||
|
if (Amount == 0) break;
|
||||||
|
|
||||||
|
Character = Sda->ByteBuffer;
|
||||||
|
|
||||||
|
if (LineSize == 127 && Character != '\r' && Character != '\b')
|
||||||
|
{
|
||||||
|
/* Line buffer full */
|
||||||
|
// TODO: Should we beep?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Character)
|
||||||
|
{
|
||||||
|
/* Extended character */
|
||||||
|
case '\0':
|
||||||
|
{
|
||||||
|
/* Read the scancode and discard it */
|
||||||
|
Amount = 1;
|
||||||
|
Node->ReadRoutine(Node,
|
||||||
|
MAKELONG(DOS_DATA_OFFSET(Sda.ByteBuffer),
|
||||||
|
DOS_DATA_SEGMENT),
|
||||||
|
&Amount);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ctrl-C */
|
||||||
|
case 0x03:
|
||||||
|
{
|
||||||
|
DosEchoCharacter(Character);
|
||||||
|
|
||||||
|
if (DosControlBreak())
|
||||||
|
{
|
||||||
|
/* Set the character to CR to end the loop */
|
||||||
|
Character = '\r';
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '\b':
|
||||||
|
{
|
||||||
|
if (LineSize > 0)
|
||||||
|
{
|
||||||
|
LineSize--;
|
||||||
|
if (ConBuffer[LineSize] == 0) LineSize--;
|
||||||
|
|
||||||
|
DosEchoCharacter(Character);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
/* Store the character in the buffer */
|
||||||
|
ConBuffer[LineSize++] = Character;
|
||||||
|
DosEchoCharacter(Character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop on a carriage return */
|
||||||
|
if (Character == '\r') break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*BytesRead = 0;
|
||||||
|
ConBuffer = (PCHAR)SEG_OFF_TO_PTR(DOS_DATA_SEGMENT, SysVars->UnreadConInput);
|
||||||
|
|
||||||
|
while (*BytesRead < Count)
|
||||||
|
{
|
||||||
|
Pointer[(*BytesRead)++] = *ConBuffer;
|
||||||
|
|
||||||
|
if (*ConBuffer == '\r')
|
||||||
|
{
|
||||||
|
/* A carriage return turns into a line feed */
|
||||||
|
*ConBuffer = '\n';
|
||||||
|
}
|
||||||
|
else if (*ConBuffer == '\n')
|
||||||
|
{
|
||||||
|
/* A line feed marks the true end of the line */
|
||||||
|
SysVars->UnreadConInput = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Move to the next character */
|
||||||
|
SysVars->UnreadConInput++;
|
||||||
|
ConBuffer++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Translated input from a character device that isn't CON */
|
||||||
|
PCHAR Pointer = FAR_POINTER(Buffer);
|
||||||
|
|
||||||
|
while (*BytesRead < Count)
|
||||||
|
{
|
||||||
|
USHORT Amount = 1;
|
||||||
|
CHAR Character;
|
||||||
|
|
||||||
|
/* Read a character from the device */
|
||||||
|
Node->ReadRoutine(Node,
|
||||||
|
MAKELONG(DOS_DATA_OFFSET(Sda.ByteBuffer),
|
||||||
|
DOS_DATA_SEGMENT),
|
||||||
|
&Amount);
|
||||||
|
if (Amount == 0) break;
|
||||||
|
|
||||||
|
Character = Sda->ByteBuffer;
|
||||||
|
// TODO: Process it somehow?
|
||||||
|
|
||||||
|
/* Store the character in the output buffer */
|
||||||
|
Pointer[(*BytesRead)++] = Character;
|
||||||
|
|
||||||
|
/* Check for EOF */
|
||||||
|
if (Character == 0x1A) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
|
|
||||||
/* DEFINES ********************************************************************/
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
|
#define FILE_INFO_STDIN (1 << 0)
|
||||||
|
#define FILE_INFO_STDOUT (1 << 1)
|
||||||
|
#define FILE_INFO_BINARY (1 << 5)
|
||||||
#define FILE_INFO_DEVICE (1 << 7)
|
#define FILE_INFO_DEVICE (1 << 7)
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
Loading…
Reference in a new issue