Reworked console code to use frame buffers and input queues

svn path=/trunk/; revision=1552
This commit is contained in:
Phillip Susi 2001-01-21 00:11:54 +00:00
parent 5d6f1d7dfa
commit f353289fba
7 changed files with 594 additions and 336 deletions

View file

@ -27,7 +27,8 @@ typedef struct
typedef struct
{
HANDLE ConsoleHandle;
HANDLE InputHandle;
HANDLE OutputHandle;
} CSRSS_CREATE_PROCESS_REPLY, *PCSRSS_CREATE_PROCESS_REPLY;
typedef struct
@ -45,7 +46,8 @@ typedef struct
typedef struct
{
HANDLE ConsoleHandle;
ULONG NrCharactersToRead;
WORD NrCharactersToRead;
WORD nCharsCanBeDeleted; // number of chars already in buffer that can be backspaced
} CSRSS_READ_CONSOLE_REQUEST, *PCSRSS_READ_CONSOLE_REQUEST;
typedef struct
@ -57,7 +59,8 @@ typedef struct
typedef struct
{
HANDLE ConsoleHandle;
HANDLE InputHandle;
HANDLE OutputHandle;
} CSRSS_ALLOC_CONSOLE_REPLY, *PCSRSS_ALLOC_CONSOLE_REPLY;
typedef struct
@ -168,6 +171,21 @@ typedef struct
DWORD ConsoleMode;
} CSRSS_GET_CONSOLE_MODE_REPLY, *PCSRSS_GET_CONSOLE_MODE_REPLY;
typedef struct
{
/* may want to add some parameters here someday */
} CSRSS_CREATE_SCREEN_BUFFER_REQUEST, *PCSRSS_CREATE_SCREEN_BUFFER_REQUEST;
typedef struct
{
HANDLE OutputHandle; /* handle to newly created screen buffer */
} CSRSS_CREATE_SCREEN_BUFFER_REPLY, *PCSRSS_CREATE_SCREEN_BUFFER_REPLY;
typedef struct
{
HANDLE OutputHandle; /* handle to screen buffer to switch to */
} CSRSS_SET_ACTIVE_SCREEN_BUFFER_REQUEST, *PCSRSS_SET_ACTIVE_SCREEN_BUFFER_REQUEST;
#define CSRSS_MAX_WRITE_CONSOLE_REQUEST (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_REQUEST))
#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST ))
@ -194,6 +212,8 @@ typedef struct
#define CSRSS_SET_ATTRIB (0x10)
#define CSRSS_GET_MODE (0x11)
#define CSRSS_SET_MODE (0x12)
#define CSRSS_CREATE_SCREEN_BUFFER (0x13)
#define CSRSS_SET_SCREEN_BUFFER (0x14)
typedef struct
{
@ -217,6 +237,8 @@ typedef struct
CSRSS_SET_ATTRIB_REQUEST SetAttribRequest;
CSRSS_SET_CONSOLE_MODE_REQUEST SetConsoleModeRequest;
CSRSS_GET_CONSOLE_MODE_REQUEST GetConsoleModeRequest;
CSRSS_CREATE_SCREEN_BUFFER_REQUEST CreateScreenBufferRequest;
CSRSS_SET_ACTIVE_SCREEN_BUFFER_REQUEST SetActiveScreenBufferRequest;
} Data;
} CSRSS_API_REQUEST, *PCSRSS_API_REQUEST;
@ -237,6 +259,7 @@ typedef struct
CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REPLY WriteConsoleOutputAttribReply;
CSRSS_GET_CURSOR_INFO_REPLY GetCursorInfoReply;
CSRSS_GET_CONSOLE_MODE_REPLY GetConsoleModeReply;
CSRSS_CREATE_SCREEN_BUFFER_REPLY CreateScreenBufferReply;
} Data;
} CSRSS_API_REPLY, *PCSRSS_API_REPLY;

View file

@ -19,9 +19,10 @@
#define ENABLE_PROCESSED_INPUT (0x01)
#define ENABLE_WINDOW_INPUT (0x08)
#define ENABLE_MOUSE_INPUT (0x0f)
#define CONSOLE_MODE_VALID (0x1f)
#define CONSOLE_INPUT_MODE_VALID (0x0f)
#define ENABLE_PROCESSED_OUTPUT (0x01)
#define ENABLE_WRAP_AT_EOL_OUTPUT (0x02)
#define CONSOLE_OUTPUT_MODE_VALID (0x03)
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize;

View file

@ -4,37 +4,64 @@
/* Object type magic numbers */
#define CSRSS_CONSOLE_MAGIC 1
#define CSRSS_CONSOLE_MAGIC 1
#define CSRSS_SCREEN_BUFFER_MAGIC 2
typedef struct Object_tt
{
DWORD Type;
DWORD ReferenceCount;
LONG Type;
LONG ReferenceCount;
} Object_t;
typedef struct ConsoleInput_t
{
LIST_ENTRY ListEntry;
INPUT_RECORD InputEvent;
BOOLEAN Echoed; // already been echoed or not
} ConsoleInput;
/************************************************************************
* Screen buffer structure represents the win32 screen buffer object. *
* Internally, the portion of the buffer being shown CAN loop past the *
* bottom of the virtual buffer and wrap around to the top. Win32 does *
* not do this. I decided to do this because it eliminates the need to *
* do a massive memcpy() to scroll the contents of the buffer up to *
* scroll the screen on output, instead I just shift down the position *
* to be displayed, and let it wrap around to the top again. *
* The VirtualX member keeps track of the top X coord that win32 *
* clients THINK is currently being displayed, because they think that *
* when the display reaches the bottom of the buffer and another line *
* being printed causes another line to scroll down, that the buffer IS *
* memcpy()'s up, and the bottom of the buffer is still displayed, but *
* internally, I just wrap back to the top of the buffer. *
***********************************************************************/
typedef struct CSRSS_SCREEN_BUFFER_t
{
Object_t Header; /* Object header */
BYTE *Buffer; /* pointer to screen buffer */
USHORT MaxX, MaxY; /* size of the entire scrollback buffer */
USHORT ShowX, ShowY; /* beginning offset for the actual display area */
ULONG CurrentX; /* Current X cursor position */
ULONG CurrentY; /* Current Y cursor position */
BYTE DefaultAttrib; /* default char attribute */
USHORT VirtualX; /* top row of buffer being displayed, reported to callers */
CONSOLE_CURSOR_INFO CursorInfo;
USHORT Mode;
} CSRSS_SCREEN_BUFFER, *PCSRSS_SCREEN_BUFFER;
typedef struct CSRSS_CONSOLE_t
{
DWORD Type;
DWORD ReferenceCount; /* Inherited from Object_t */
struct CSRSS_CONSOLE_t *Prev, *Next; /* Next and Prev consoles in console wheel */
Object_t Header; /* Object header */
struct CSRSS_CONSOLE_t *Prev, *Next; /* Next and Prev consoles in console wheel */
HANDLE ActiveEvent;
BYTE *Buffer;
USHORT MaxX, MaxY; /* size of the entire scrollback buffer */
USHORT ShowX, ShowY; /* beginning offset for the actual display area */
ULONG CurrentX;
ULONG CurrentY;
BYTE DefaultAttrib; /* default char attribute */
LIST_ENTRY InputEvents; /* List head for input event queue */
CONSOLE_CURSOR_INFO CursorInfo;
DWORD ConsoleMode;
LIST_ENTRY InputEvents; /* List head for input event queue */
WORD WaitingChars;
WORD WaitingLines; /* number of chars and lines in input queue */
WORD WaitingLines; /* number of chars and lines in input queue */
PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */
WORD Mode; /* Console mode flags */
WORD EchoCount; /* count of chars to echo, in line buffered mode */
} CSRSS_CONSOLE, *PCSRSS_CONSOLE;
typedef struct
@ -101,6 +128,10 @@ NTSTATUS CsrSetConsoleMode( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST
NTSTATUS CsrGetConsoleMode( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply );
NTSTATUS CsrCreateScreenBuffer( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply );
NTSTATUS CsrSetScreenBuffer( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply );
/* print.c */
VOID DisplayString(LPCWSTR lpwString);
VOID PrintString (char* fmt, ...);
@ -112,9 +143,10 @@ VOID Console_Api( DWORD Ignored );
extern HANDLE CsrssApiHeap;
/* api/conio.c */
NTSTATUS CsrInitConsole(PCSRSS_PROCESS_DATA ProcessData,
PCSRSS_CONSOLE Console);
VOID CsrDeleteConsole( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE Console );
NTSTATUS CsrInitConsole(PCSRSS_CONSOLE Console);
VOID CsrDeleteConsole( PCSRSS_CONSOLE Console );
VOID CsrDeleteScreenBuffer( PCSRSS_SCREEN_BUFFER Buffer );
NTSTATUS CsrInitConsoleScreenBuffer( PCSRSS_SCREEN_BUFFER Console );
VOID CsrInitConsoleSupport(VOID);
/* api/process.c */
@ -127,8 +159,5 @@ NTSTATUS CsrGetObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, Object_t
BOOL STDCALL CsrServerInitialization (ULONG ArgumentCount,
PWSTR *ArgumentArray);
NTSTATUS CsrReleaseObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Object );
VOID CsrDrawConsole( PCSRSS_CONSOLE Console );
VOID CsrDrawConsole( PCSRSS_SCREEN_BUFFER Console );
NTSTATUS CsrpWriteConsole( PCSRSS_SCREEN_BUFFER Buff, CHAR *Buffer, DWORD Length, BOOL Attrib );

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
/* $Id: handle.c,v 1.7 2000/05/26 05:40:20 phreak Exp $
/* $Id: handle.c,v 1.8 2001/01/21 00:11:54 phreak Exp $
*
* reactos/subsys/csrss/api/handle.c
*
@ -35,15 +35,16 @@ NTSTATUS CsrReleaseObject(PCSRSS_PROCESS_DATA ProcessData,
HANDLE Handle)
{
Object_t *Object;
// DbgPrint( "CsrReleaseObject\n" );
if( (((ULONG)Handle) >> 2) - 1 > ProcessData->HandleTableSize || ProcessData->HandleTable[(((ULONG)Handle) >> 2) - 1] == 0 )
return STATUS_INVALID_HANDLE;
/* dec ref count */
Object = ProcessData->HandleTable[(((ULONG)Handle) >> 2) - 1];
if( --Object->ReferenceCount == 0 )
if( InterlockedDecrement( &Object->ReferenceCount ) == 0 )
switch( Object->Type )
{
case CSRSS_CONSOLE_MAGIC: CsrDeleteConsole( ProcessData, (PCSRSS_CONSOLE) Object );
case CSRSS_CONSOLE_MAGIC: CsrDeleteConsole( (PCSRSS_CONSOLE) Object );
break;
case CSRSS_SCREEN_BUFFER_MAGIC: CsrDeleteScreenBuffer( (PCSRSS_SCREEN_BUFFER) Object );
break;
default: DbgPrint( "CSR: Error: releaseing unknown object type" );
}
@ -56,14 +57,13 @@ NTSTATUS CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Objec
ULONG i;
PVOID* NewBlock;
// DbgPrint( "CsrInsertObject\n" );
for (i = 0; i < ProcessData->HandleTableSize; i++)
{
if (ProcessData->HandleTable[i] == NULL)
{
ProcessData->HandleTable[i] = Object;
*Handle = (HANDLE)(((i + 1) << 2) | 0x3);
Object->ReferenceCount++;
InterlockedIncrement( &Object->ReferenceCount );
return(STATUS_SUCCESS);
}
}
@ -82,7 +82,7 @@ NTSTATUS CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Objec
ProcessData->HandleTable = (Object_t **)NewBlock;
ProcessData->HandleTable[i] = Object;
*Handle = (HANDLE)(((i + 1) << 2) | 0x3);
Object->ReferenceCount++;
InterlockedIncrement( &Object->ReferenceCount );
ProcessData->HandleTableSize = ProcessData->HandleTableSize + 64;
return(STATUS_SUCCESS);
}

View file

@ -1,4 +1,4 @@
/* $Id: process.c,v 1.10 2000/07/04 11:11:06 dwelch Exp $
/* $Id: process.c,v 1.11 2001/01/21 00:11:54 phreak Exp $
*
* reactos/subsys/csrss/api/process.c
*
@ -90,13 +90,8 @@ NTSTATUS CsrFreeProcessData( ULONG Pid )
}
if( ProcessData[i]->Console )
{
RtlEnterCriticalSection( &ActiveConsoleLock );
if( --ProcessData[i]->Console->ReferenceCount == 0 )
{
RtlLeaveCriticalSection( &ActiveConsoleLock );
CsrDeleteConsole( ProcessData[i], ProcessData[i]->Console );
}
RtlLeaveCriticalSection( &ActiveConsoleLock );
if( InterlockedDecrement( &(ProcessData[i]->Console->Header.ReferenceCount) ) == 0 )
CsrDeleteConsole( ProcessData[i]->Console );
}
RtlFreeHeap( CsrssApiHeap, 0, ProcessData[i] );
ProcessData[i] = 0;
@ -139,30 +134,37 @@ NTSTATUS CsrCreateProcess (PCSRSS_PROCESS_DATA ProcessData,
Console = RtlAllocateHeap(CsrssApiHeap,
HEAP_ZERO_MEMORY,
sizeof(CSRSS_CONSOLE));
CsrInitConsole(ProcessData,
Console);
Status = CsrInitConsole(Console);
if( !NT_SUCCESS( Status ) )
{
CsrFreeProcessData( NewProcessData->ProcessId );
Reply->Status = Status;
return Status;
}
NewProcessData->Console = Console;
Console->ReferenceCount++;
Console->Header.ReferenceCount++;
}
else
{
NewProcessData->Console = ProcessData->Console;
RtlEnterCriticalSection( &ActiveConsoleLock );
ProcessData->Console->ReferenceCount++;
RtlLeaveCriticalSection( &ActiveConsoleLock );
InterlockedIncrement( &(ProcessData->Console->Header.ReferenceCount) );
}
if( NewProcessData->Console )
{
CLIENT_ID ClientId;
CsrInsertObject(NewProcessData,
&Reply->Data.CreateProcessReply.ConsoleHandle,
&Reply->Data.CreateProcessReply.InputHandle,
(Object_t *)NewProcessData->Console);
RtlEnterCriticalSection( &ActiveConsoleLock );
CsrInsertObject( NewProcessData, &Reply->Data.CreateProcessReply.OutputHandle, &(NewProcessData->Console->ActiveBuffer->Header) );
RtlLeaveCriticalSection( &ActiveConsoleLock );
ClientId.UniqueProcess = (HANDLE)NewProcessData->ProcessId;
Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" );
InterlockedDecrement( &(NewProcessData->Console->Header.ReferenceCount) );
CsrFreeProcessData( NewProcessData->ProcessId );
Reply->Status = Status;
return Status;
@ -172,15 +174,14 @@ NTSTATUS CsrCreateProcess (PCSRSS_PROCESS_DATA ProcessData,
{
DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status );
NtClose( Process );
InterlockedDecrement( &(NewProcessData->Console->Header.ReferenceCount) );
CsrFreeProcessData( NewProcessData->ProcessId );
Reply->Status = Status;
return Status;
}
NtClose( Process );
}
else Reply->Data.CreateProcessReply.ConsoleHandle = INVALID_HANDLE_VALUE;
// DisplayString(L"CSR: Did CreateProcess successfully\n");
// DbgPrint("Reply->Header.MessageSize %d\n", Reply->Header.MessageSize);
else Reply->Data.CreateProcessReply.OutputHandle = Reply->Data.CreateProcessReply.InputHandle = INVALID_HANDLE_VALUE;
return(STATUS_SUCCESS);
}

View file

@ -1,4 +1,4 @@
/* $Id: wapi.c,v 1.10 2001/01/18 15:00:09 dwelch Exp $
/* $Id: wapi.c,v 1.11 2001/01/21 00:11:54 phreak Exp $
*
* reactos/subsys/csrss/api/wapi.c
*
@ -44,6 +44,8 @@ static const CsrFunc CsrFuncs[] = {
CsrSetTextAttrib,
CsrGetConsoleMode,
CsrSetConsoleMode,
CsrCreateScreenBuffer,
CsrSetScreenBuffer,
0 };
static void Thread_Api2(HANDLE ServerPort)