Whole new win32 console support, with multiple virtual consoles and scrollback support

svn path=/trunk/; revision=1128
This commit is contained in:
Phillip Susi 2000-04-23 17:44:53 +00:00
parent 4f6c860da3
commit cdd3a57119
7 changed files with 602 additions and 112 deletions

View file

@ -1,24 +1,49 @@
#include <ddk/ntddk.h>
#include <csrss/csrss.h>
#include <defines.h>
#include <structs.h>
typedef struct
/* Object type magic numbers */
#define CSRSS_CONSOLE_MAGIC 1
typedef struct Object_tt
{
BOOL TopLevel;
DWORD Type;
DWORD ReferenceCount;
CRITICAL_SECTION Lock;
} Object_t;
typedef struct ConsoleInput_t
{
LIST_ENTRY ListEntry;
INPUT_RECORD InputEvent;
} ConsoleInput;
typedef struct CSRSS_CONSOLE_t
{
DWORD Type;
DWORD ReferenceCount; /* Inherited from Object_t */
CRITICAL_SECTION Lock;
struct CSRSS_CONSOLE_t *Prev, *Next; /* Next and Prev consoles in console wheel */
HANDLE ActiveEvent;
BYTE Screen[80*25*2];
ULONG ReferenceCount;
HANDLE LockMutant;
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 */
} CSRSS_CONSOLE, *PCSRSS_CONSOLE;
typedef struct
{
PCSRSS_CONSOLE Console;
ULONG HandleTableSize;
PVOID* HandleTable;
Object_t ** HandleTable;
ULONG ProcessId;
HANDLE ConsoleEvent;
} CSRSS_PROCESS_DATA, *PCSRSS_PROCESS_DATA;
VOID CsrInitProcessData(VOID);
@ -57,24 +82,29 @@ VOID PrintString (char* fmt, ...);
/* api/wapi.c */
VOID Thread_Api(PVOID PortHandle);
VOID Console_Api( DWORD Ignored );
extern HANDLE CsrssApiHeap;
/* api/conio.c */
VOID CsrInitConsole(PCSRSS_PROCESS_DATA ProcessData,
NTSTATUS CsrInitConsole(PCSRSS_PROCESS_DATA ProcessData,
PCSRSS_CONSOLE Console);
VOID CsrDeleteConsole( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE Console );
VOID CsrInitConsoleSupport(VOID);
/* api/process.c */
PCSRSS_PROCESS_DATA CsrGetProcessData(ULONG ProcessId);
NTSTATUS CsrFreeProcessData( ULONG Pid );
/* api/handle.c */
NTSTATUS CsrInsertObject(PCSRSS_PROCESS_DATA ProcessData,
PHANDLE Handle,
PVOID Object);
NTSTATUS CsrGetObject(PCSRSS_PROCESS_DATA ProcessData,
HANDLE Handle,
PVOID* Object);
NTSTATUS CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Object_t *Object );
NTSTATUS CsrGetObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, Object_t **Object );
BOOL STDCALL CsrServerInitialization (ULONG ArgumentCount,
PWSTR *ArgumentArray);
NTSTATUS CsrReleaseObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Object );
VOID CsrUnlockObject( Object_t *Object );
VOID CsrDrawConsole( PCSRSS_CONSOLE Console );

View file

@ -1,4 +1,4 @@
/* $Id: conio.c,v 1.4 2000/04/03 21:54:41 dwelch Exp $
/* $Id: conio.c,v 1.5 2000/04/23 17:44:53 phreak Exp $
*
* reactos/subsys/csrss/api/conio.c
*
@ -13,11 +13,16 @@
#include <csrss/csrss.h>
#include "api.h"
#include <ntdll/rtl.h>
#include <ddk/ntddblue.h>
/* GLOBALS *******************************************************************/
static HANDLE ConsoleDeviceHandle;
static HANDLE KeyboardDeviceHandle;
static PCSRSS_CONSOLE ActiveConsole;
CRITICAL_SECTION ActiveConsoleLock;
static COORD PhysicalConsoleSize;
/* FUNCTIONS *****************************************************************/
@ -25,13 +30,59 @@ NTSTATUS CsrAllocConsole(PCSRSS_PROCESS_DATA ProcessData,
PCSRSS_API_REQUEST LpcMessage,
PCSRSS_API_REPLY LpcReply)
{
PCSRSS_CONSOLE Console;
HANDLE Process;
NTSTATUS Status;
CLIENT_ID ClientId;
LpcReply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
LpcReply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
sizeof(LPC_MESSAGE_HEADER);
LpcReply->Status = STATUS_NOT_IMPLEMENTED;
return(STATUS_NOT_IMPLEMENTED);
if( ProcessData->Console )
{
LpcReply->Status = STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
}
LpcReply->Status = STATUS_SUCCESS;
Console = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( CSRSS_CONSOLE ) );
if( Console == 0 )
{
LpcReply->Status = STATUS_INSUFFICIENT_RESOURCES;
return STATUS_INSUFFICIENT_RESOURCES;
}
LpcReply->Status = CsrInitConsole( ProcessData, Console );
if( !NT_SUCCESS( LpcReply->Status ) )
{
RtlFreeHeap( CsrssApiHeap, 0, Console );
return LpcReply->Status;
}
ProcessData->Console = Console;
Console->ReferenceCount++;
CsrInsertObject( ProcessData, &LpcReply->Data.AllocConsoleReply.ConsoleHandle, (Object_t *)Console );
ClientId.UniqueProcess = (HANDLE)ProcessData->ProcessId;
Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" );
Console->ReferenceCount--;
ProcessData->Console = 0;
CsrReleaseObject( ProcessData, LpcReply->Data.AllocConsoleReply.ConsoleHandle );
LpcReply->Status = Status;
return Status;
}
Status = NtDuplicateObject( NtCurrentProcess(), &ProcessData->Console->ActiveEvent, Process, &ProcessData->ConsoleEvent, SYNCHRONIZE, FALSE, 0 );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: NtDuplicateObject() failed\n" );
NtClose( Process );
Console->ReferenceCount--;
CsrReleaseObject( ProcessData, LpcReply->Data.AllocConsoleReply.ConsoleHandle );
ProcessData->Console = 0;
LpcReply->Status = Status;
return Status;
}
NtClose( Process );
return STATUS_SUCCESS;
}
NTSTATUS CsrFreeConsole(PCSRSS_PROCESS_DATA ProcessData,
@ -51,14 +102,12 @@ NTSTATUS CsrReadConsole(PCSRSS_PROCESS_DATA ProcessData,
PCSRSS_API_REQUEST LpcMessage,
PCSRSS_API_REPLY LpcReply)
{
KEY_EVENT_RECORD KeyEventRecord;
PINPUT_RECORD Input;
PCHAR Buffer;
int i;
ULONG nNumberOfCharsToRead;
PCSRSS_CONSOLE Console;
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
// DbgPrint("CSR: CsrReadConsole()\n");
nNumberOfCharsToRead =
LpcMessage->Data.ReadConsoleRequest.NrCharactersToRead;
@ -70,79 +119,296 @@ NTSTATUS CsrReadConsole(PCSRSS_PROCESS_DATA ProcessData,
LpcReply->Header.DataSize = LpcReply->Header.MessageSize -
sizeof(LPC_MESSAGE_HEADER);
Buffer = LpcReply->Data.ReadConsoleReply.Buffer;
LpcReply->Data.ReadConsoleReply.EventHandle = ProcessData->ConsoleEvent;
Status = STATUS_SUCCESS;
for (i=0; (NT_SUCCESS(Status) && i<nNumberOfCharsToRead);)
Status = CsrGetObject( ProcessData, LpcMessage->Data.ReadConsoleRequest.ConsoleHandle, (Object_t **)&Console );
if( !NT_SUCCESS( Status ) )
{
LpcReply->Status = Status;
return Status;
}
for (i=0; i<nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++ )
{
// DbgPrint("CSR: Doing read file (KeyboardDeviceHandle %x)\n",
// KeyboardDeviceHandle);
Status = NtReadFile(KeyboardDeviceHandle,
NULL,
NULL,
NULL,
&Iosb,
&KeyEventRecord,
sizeof(KEY_EVENT_RECORD),
NULL,
0);
if (!NT_SUCCESS(Status))
{
// DbgPrint("CSR: Read failed, bailing\n");
}
if (KeyEventRecord.bKeyDown && KeyEventRecord.uChar.AsciiChar != 0)
{
Buffer[i] = KeyEventRecord.uChar.AsciiChar;
// DbgPrint("CSR: Read '%c'\n", Buffer[i]);
i++;
}
Input = &((ConsoleInput *)Console->InputEvents.Flink)->InputEvent;
Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
Console->InputEvents.Flink->Blink = &Console->InputEvents;
Buffer[i] = Input->Event.KeyEvent.uChar.AsciiChar;
RtlFreeHeap( CsrssApiHeap, 0, Input );
}
CsrUnlockObject( (Object_t *)Console );
LpcReply->Data.ReadConsoleReply.NrCharactersRead = i;
LpcReply->Status = Status;
LpcReply->Status = i ? STATUS_SUCCESS : STATUS_PENDING;
return(Status);
}
NTSTATUS CsrWriteConsole(PCSRSS_PROCESS_DATA ProcessData,
PCSRSS_API_REQUEST Message,
PCSRSS_API_REPLY LpcReply)
{
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
int i;
BYTE *Buffer = Message->Data.WriteConsoleRequest.Buffer;
PCSRSS_CONSOLE Console;
LpcReply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
LpcReply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
sizeof(LPC_MESSAGE_HEADER);
// DbgPrint("CSR: CsrWriteConsole()\n");
// DbgPrint("CSR: ConsoleDeviceHandle %x\n", ConsoleDeviceHandle);
// DbgPrint("CSR: NrCharactersToWrite %d\n",
// Message->Data.WriteConsoleRequest.NrCharactersToWrite);
// DbgPrint("CSR: Buffer %s\n",
// Message->Data.WriteConsoleRequest.Buffer);
Status = NtWriteFile(ConsoleDeviceHandle,
NULL,
NULL,
NULL,
&Iosb,
Message->Data.WriteConsoleRequest.Buffer,
Message->Data.WriteConsoleRequest.NrCharactersToWrite,
NULL,
0);
if (!NT_SUCCESS(Status))
{
// DbgPrint("CSR: Write failed\n");
return(Status);
}
LpcReply->Data.WriteConsoleReply.NrCharactersWritten = Iosb.Information;
if( !NT_SUCCESS( CsrGetObject( ProcessData, Message->Data.WriteConsoleRequest.ConsoleHandle, (Object_t **)&Console ) ) )
return LpcReply->Status = STATUS_INVALID_HANDLE;
for( i = 0; i < Message->Data.WriteConsoleRequest.NrCharactersToWrite; i++ )
{
switch( Buffer[ i ] )
{
case '\n': {
int c;
Console->CurrentX = 0;
/* slide the viewable screen */
if( ((PhysicalConsoleSize.Y + Console->ShowY) % Console->MaxY) == (Console->CurrentY + 1) )
if( ++Console->ShowY == (Console->MaxY - 1) )
Console->ShowY = 0;
if( ++Console->CurrentY == Console->MaxY )
{
Console->CurrentY = 0;
for( c = 0; c < Console->MaxX; c++ )
{
/* clear new line */
Console->Buffer[ c * 2 ] = ' ';
Console->Buffer[ (c * 2) + 1 ] = Console->DefaultAttrib;
}
}
else for( c = 0; c < Console->MaxX; c++ )
{
/* clear new line */
Console->Buffer[ 2 * ((Console->CurrentY * Console->MaxX) + c) ] = ' ';
Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + c)) + 1 ] = Console->DefaultAttrib;
}
break;
}
case '\b': {
if( Console->CurrentX == 0 )
{
/* slide viewable screen up */
if( Console->ShowY == Console->CurrentY )
if( Console->ShowY == 0 )
Console->ShowY = Console->MaxY;
else Console->ShowY--;
/* slide virtual position up */
Console->CurrentX = Console->MaxX;
if( Console->CurrentY == 0 )
Console->CurrentY = Console->MaxY;
else Console->CurrentY--;
}
else Console->CurrentX--;
Console->Buffer[ 2 * ((Console->CurrentY * Console->MaxX) + Console->CurrentX) ] = ' ';
Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + Console->CurrentX)) + 1 ] = Console->DefaultAttrib;
break;
}
default: {
int c;
Console->Buffer[ 2 * (((Console->CurrentY * Console->MaxX)) + Console->CurrentX) ] = Buffer[ i ];
Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + Console->CurrentX)) + 1 ] = Console->DefaultAttrib;
Console->CurrentX++;
if( Console->CurrentX == Console->MaxX )
{
/* if end of line, go to next */
Console->CurrentX = 0;
if( ++Console->CurrentY == Console->MaxY )
{
/* if end of buffer, wrap back to beginning */
Console->CurrentY = 0;
/* clear new line */
for( c = 0; c < Console->MaxX; c++ )
{
Console->Buffer[ 2 * ((Console->CurrentY * Console->MaxX) + c) ] = ' ';
Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + c)) + 1 ] = Console->DefaultAttrib;
}
}
else {
/* clear new line */
for( c = 0; c < Console->MaxX; c += 2 )
{
Console->Buffer[ 2 * ((Console->CurrentY * Console->MaxX) + c) ] = ' ';
Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + c)) + 1 ] = Console->DefaultAttrib;
}
}
/* slide the viewable screen */
if( (Console->CurrentY - Console->ShowY) == PhysicalConsoleSize.Y )
if( ++Console->ShowY == Console->MaxY )
Console->ShowY = 0;
}
}
}
}
CsrUnlockObject( (Object_t *)Console );
RtlEnterCriticalSection( &ActiveConsoleLock );
if( Console == ActiveConsole )
{ /* only write to screen if Console is Active, and not scrolled up */
Status = NtWriteFile(ConsoleDeviceHandle,
NULL,
NULL,
NULL,
&Iosb,
Message->Data.WriteConsoleRequest.Buffer,
Message->Data.WriteConsoleRequest.NrCharactersToWrite,
NULL,
0);
if (!NT_SUCCESS(Status))
DbgPrint("CSR: Write failed\n");
}
RtlLeaveCriticalSection( &ActiveConsoleLock );
LpcReply->Data.WriteConsoleReply.NrCharactersWritten = i;
LpcReply->Status = STATUS_SUCCESS;
return(STATUS_SUCCESS);
}
VOID CsrInitConsole(PCSRSS_PROCESS_DATA ProcessData,
NTSTATUS CsrInitConsole(PCSRSS_PROCESS_DATA ProcessData,
PCSRSS_CONSOLE Console)
{
NTSTATUS Status;
Console->MaxX = PhysicalConsoleSize.X;
Console->MaxY = PhysicalConsoleSize.Y * 2;
Console->ShowX = 0;
Console->ShowY = 0;
Console->CurrentX = 0;
Console->CurrentY = 0;
Console->ReferenceCount = 0;
Console->Type = CSRSS_CONSOLE_MAGIC;
RtlInitializeCriticalSection( &Console->Lock );
Console->Buffer = RtlAllocateHeap( CsrssApiHeap, 0, Console->MaxX * Console->MaxY * 2 );
if( Console->Buffer == 0 )
return STATUS_INSUFFICIENT_RESOURCES;
Console->InputEvents.Flink = Console->InputEvents.Blink = &Console->InputEvents;
Status = NtCreateEvent( &Console->ActiveEvent, STANDARD_RIGHTS_ALL, 0, FALSE, FALSE );
if( !NT_SUCCESS( Status ) )
{
RtlFreeHeap( CsrssApiHeap, 0, Console->Buffer );
return Status;
}
Console->DefaultAttrib = 0x17;
/* initialize buffer to be empty with default attributes */
for( ; Console->CurrentY < Console->MaxY; Console->CurrentY++ )
{
for( ; Console->CurrentX < Console->MaxX; Console->CurrentX++ )
{
Console->Buffer[ (Console->CurrentX * 2) + (Console->CurrentY * Console->MaxX * 2) ] = ' ';
Console->Buffer[ (Console->CurrentX * 2) + (Console->CurrentY * Console->MaxX * 2)+ 1 ] = Console->DefaultAttrib;
}
Console->CurrentX = 0;
}
/* make console active, and insert into console list */
RtlEnterCriticalSection( &ActiveConsoleLock );
if( ActiveConsole )
{
Console->Prev = ActiveConsole;
Console->Next = ActiveConsole->Next;
ActiveConsole->Next->Prev = Console;
ActiveConsole->Next = Console;
}
else {
Console->Prev = Console;
Console->Next = Console;
}
Console->CurrentX = 0;
Console->CurrentY = 0;
ActiveConsole = Console;
/* copy buffer contents to screen */
CsrDrawConsole( Console );
RtlLeaveCriticalSection( &ActiveConsoleLock );
return STATUS_SUCCESS;
}
/***************************************************************
* CsrDrawConsole blasts the console buffer onto the screen *
* must be called while holding the active console lock *
**************************************************************/
VOID CsrDrawConsole( PCSRSS_CONSOLE Console )
{
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
CONSOLE_MODE Mode;
int i, y;
/* first set position to 0,0 */
ScrInfo.dwCursorPosition.X = 0;
ScrInfo.dwCursorPosition.Y = 0;
ScrInfo.wAttributes = Console->DefaultAttrib;
Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: Failed to set console info\n" );
return;
}
Mode.dwMode = 0; /* clear ENABLE_PROCESSED_OUTPUT mode */
Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: Failed to set console mode\n" );
return;
}
/* blast out buffer */
for( i = 0, y = Console->ShowY; i < PhysicalConsoleSize.Y; i++ )
{
Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, &Console->Buffer[ (Console->ShowX * 2) + (y * Console->MaxX * 2) ], PhysicalConsoleSize.X * 2, 0, 0 );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: Write to console failed\n" );
return;
}
/* wrap back around the end of the buffer */
if( ++y == Console->MaxY )
y = 0;
}
Mode.dwMode = ENABLE_PROCESSED_OUTPUT;
Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: Failed to set console mode\n" );
return;
}
ScrInfo.dwCursorPosition.X = Console->CurrentX - Console->ShowX;
ScrInfo.dwCursorPosition.Y = ((Console->CurrentY + Console->MaxY) - Console->ShowY) % Console->MaxY;
Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: Failed to set console info\n" );
return;
}
}
VOID CsrDeleteConsole( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE Console )
{
ConsoleInput *Event;
RtlFreeHeap( CsrssApiHeap, 0, Console->Buffer );
while( Console->InputEvents.Flink != &Console->InputEvents )
{
Event = (ConsoleInput *)Console->InputEvents.Flink;
Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents;
RtlFreeHeap( CsrssApiHeap, 0, Event );
}
RtlEnterCriticalSection( &ActiveConsoleLock );
if( ActiveConsole == Console )
{
if( Console->Next != Console )
{
ActiveConsole = Console->Next;
Console->Prev->Next = Console->Next;
Console->Next->Prev = Console->Prev;
}
else ActiveConsole = 0;
}
if( ActiveConsole )
CsrDrawConsole( ActiveConsole );
RtlLeaveCriticalSection( &ActiveConsoleLock );
NtClose( Console->ActiveEvent );
RtlDeleteCriticalSection( &Console->Lock );
}
VOID CsrInitConsoleSupport(VOID)
@ -151,6 +417,7 @@ VOID CsrInitConsoleSupport(VOID)
UNICODE_STRING DeviceName;
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
DbgPrint("CSR: CsrInitConsoleSupport()\n");
@ -189,7 +456,99 @@ VOID CsrInitConsoleSupport(VOID)
DbgPrint("CSR: Failed to open keyboard. Expect problems.\n");
}
DbgPrint("CSR: KeyboardDeviceHandle %x\n", KeyboardDeviceHandle);
ActiveConsole = 0;
RtlInitializeCriticalSection( &ActiveConsoleLock );
Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, &ScrInfo, sizeof( ScrInfo ) );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
return;
}
PhysicalConsoleSize = ScrInfo.dwSize;
}
VOID Console_Api( DWORD Ignored )
{
/* keep reading events from the keyboard and stuffing them into the current
console's input queue */
ConsoleInput *KeyEventRecord;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
while( 1 )
{
KeyEventRecord = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( ConsoleInput ) );
if( KeyEventRecord == 0 )
{
DbgPrint( "CSR: Memory allocation failure!" );
continue;
}
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
Status = NtReadFile( KeyboardDeviceHandle, NULL, NULL, NULL, &Iosb, &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: ReadFile on keyboard device failed\n" );
continue;
}
// DbgPrint( "Char: %c\n", KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar );
if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) && KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
{
if( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == 'q' )
{
/* alt-tab, swap consoles */
RtlEnterCriticalSection( &ActiveConsoleLock );
if( ActiveConsole->Next != ActiveConsole )
ActiveConsole = ActiveConsole->Next;
CsrDrawConsole( ActiveConsole );
RtlLeaveCriticalSection( &ActiveConsoleLock );
continue;
}
else if( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP || KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN )
{
/* scroll up or down */
RtlEnterCriticalSection( &ActiveConsoleLock );
if( ActiveConsole == 0 )
{
DbgPrint( "CSR: No Active Console!\n" );
continue;
}
RtlEnterCriticalSection( &ActiveConsole->Lock );
if( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP )
{
/* only scroll up if there is room to scroll up into */
if( ActiveConsole->ShowY != ((ActiveConsole->CurrentY + 1) % ActiveConsole->MaxY) )
ActiveConsole->ShowY = (ActiveConsole->ShowY + ActiveConsole->MaxY - 1) % ActiveConsole->MaxY;
}
else if( ActiveConsole->ShowY != ActiveConsole->CurrentY )
/* only scroll down if there is room to scroll down into */
if( ActiveConsole->ShowY % ActiveConsole->MaxY != ActiveConsole->CurrentY )
if( ((ActiveConsole->CurrentY + 1) % ActiveConsole->MaxY) != (ActiveConsole->ShowY + PhysicalConsoleSize.Y) % ActiveConsole->MaxY )
ActiveConsole->ShowY = (ActiveConsole->ShowY + 1) % ActiveConsole->MaxY;
CsrDrawConsole( ActiveConsole );
RtlLeaveCriticalSection( &ActiveConsole->Lock );
RtlLeaveCriticalSection( &ActiveConsoleLock );
}
}
if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
continue;
/* ignore dead keys */
if( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == 0 )
continue;
RtlEnterCriticalSection( &ActiveConsoleLock );
if( ActiveConsole == 0 )
{
DbgPrint( "CSR: No Active Console!\n" );
continue;
}
RtlEnterCriticalSection( &ActiveConsole->Lock );
KeyEventRecord->ListEntry.Flink = &ActiveConsole->InputEvents;
KeyEventRecord->ListEntry.Blink = ActiveConsole->InputEvents.Blink;
ActiveConsole->InputEvents.Blink->Flink = &KeyEventRecord->ListEntry;
ActiveConsole->InputEvents.Blink = &KeyEventRecord->ListEntry;
NtSetEvent( ActiveConsole->ActiveEvent, 0 );
}
RtlLeaveCriticalSection( &ActiveConsoleLock );
}
/* EOF */

View file

@ -1,4 +1,4 @@
/* $Id: handle.c,v 1.5 2000/03/26 22:00:10 dwelch Exp $
/* $Id: handle.c,v 1.6 2000/04/23 17:44:53 phreak Exp $
*
* reactos/subsys/csrss/api/handle.c
*
@ -13,35 +13,66 @@
#include <csrss/csrss.h>
#include "api.h"
#include <ntdll/rtl.h>
/* FUNCTIONS *****************************************************************/
NTSTATUS CsrGetObject(PCSRSS_PROCESS_DATA ProcessData,
HANDLE Handle,
PVOID* Object)
NTSTATUS CsrGetObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, Object_t **Object )
{
// DbgPrint( "CsrGetObject, Object: %x, %x, %x\n", Object, Handle, ProcessData->HandleTableSize );
if( (((ULONG)Handle) >> 2) - 1 > ProcessData->HandleTableSize )
{
DbgPrint( "CsrGetObject returning invalid handle\n" );
return STATUS_INVALID_HANDLE;
}
*Object = ProcessData->HandleTable[(((ULONG)Handle) >> 2) - 1];
return(STATUS_SUCCESS);
RtlEnterCriticalSection( &(*Object)->Lock );
// DbgPrint( "CsrGetObject returning\n" );
return *Object ? STATUS_SUCCESS : STATUS_INVALID_HANDLE;
}
VOID CsrUnlockObject( Object_t *Object )
{
RtlLeaveCriticalSection( &Object->Lock );
}
NTSTATUS CsrReleaseObject(PCSRSS_PROCESS_DATA ProcessData,
PVOID Object)
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];
RtlEnterCriticalSection( &Object->Lock );
if( --Object->ReferenceCount == 0 )
switch( Object->Type )
{
case CSRSS_CONSOLE_MAGIC: CsrDeleteConsole( ProcessData, (PCSRSS_CONSOLE) Object );
DbgPrint( "Deleting Console\n" );
break;
default: DbgPrint( "CSR: Error: releaseing unknown object type" );
}
DbgPrint( "Deleting object, refcount: %d\n", Object->ReferenceCount );
ProcessData->HandleTable[(((ULONG)Handle) >> 2) - 1] = 0;
RtlLeaveCriticalSection( &Object->Lock );
return STATUS_SUCCESS;
}
NTSTATUS CsrInsertObject(PCSRSS_PROCESS_DATA ProcessData,
PHANDLE Handle,
PVOID Object)
NTSTATUS CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Object_t *Object )
{
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++;
return(STATUS_SUCCESS);
}
}
@ -56,10 +87,14 @@ NTSTATUS CsrInsertObject(PCSRSS_PROCESS_DATA ProcessData,
RtlCopyMemory(NewBlock,
ProcessData->HandleTable,
ProcessData->HandleTableSize * sizeof(HANDLE));
ProcessData->HandleTable = NewBlock;
RtlFreeHeap( CsrssApiHeap, 0, ProcessData->HandleTable );
ProcessData->HandleTable = (Object_t **)NewBlock;
ProcessData->HandleTable[i] = Object;
*Handle = (HANDLE)(((i + 1) << 2) | 0x3);
Object->ReferenceCount++;
ProcessData->HandleTableSize = ProcessData->HandleTableSize + 64;
return(STATUS_SUCCESS);
}

View file

@ -1,4 +1,4 @@
/* $Id: process.c,v 1.7 2000/04/03 21:54:41 dwelch Exp $
/* $Id: process.c,v 1.8 2000/04/23 17:44:53 phreak Exp $
*
* reactos/subsys/csrss/api/process.c
*
@ -12,7 +12,7 @@
#include <ddk/ntddk.h>
#include <csrss/csrss.h>
#include <ntdll/rtl.h>
#include "api.h"
/* GLOBALS *******************************************************************/
@ -64,13 +64,48 @@ PCSRSS_PROCESS_DATA CsrGetProcessData(ULONG ProcessId)
return(NULL);
}
NTSTATUS CsrFreeProcessData( ULONG Pid )
{
int i;
for( i = 0; i < NrProcess; i++ )
{
if( ProcessData[i] && ProcessData[i]->ProcessId == Pid )
{
if( ProcessData[i]->HandleTable )
{
int c;
for( c = 0; c < ProcessData[i]->HandleTableSize; c++ )
if( ProcessData[i]->HandleTable[c] )
CsrReleaseObject( ProcessData[i], (HANDLE)((c + 1) << 2) );
RtlFreeHeap( CsrssApiHeap, 0, ProcessData[i]->HandleTable );
}
if( ProcessData[i]->Console )
{
RtlEnterCriticalSection( &ProcessData[i]->Console->Lock );
if( --ProcessData[i]->Console->ReferenceCount == 0 )
{
RtlLeaveCriticalSection( &ProcessData[i]->Console->Lock );
CsrDeleteConsole( ProcessData[i], ProcessData[i]->Console );
}
RtlLeaveCriticalSection( &ProcessData[i]->Console->Lock );
}
RtlFreeHeap( CsrssApiHeap, 0, ProcessData[i] );
ProcessData[i] = 0;
return STATUS_SUCCESS;
}
}
return STATUS_INVALID_PARAMETER;
}
NTSTATUS CsrCreateProcess (PCSRSS_PROCESS_DATA ProcessData,
PCSRSS_CREATE_PROCESS_REQUEST Request,
PCSRSS_API_REPLY Reply)
{
PCSRSS_PROCESS_DATA NewProcessData;
NTSTATUS Status;
HANDLE Process;
Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
sizeof(LPC_MESSAGE_HEADER);
Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
@ -97,18 +132,43 @@ NTSTATUS CsrCreateProcess (PCSRSS_PROCESS_DATA ProcessData,
CsrInitConsole(ProcessData,
Console);
NewProcessData->Console = Console;
Console->ReferenceCount++;
}
else
{
NewProcessData->Console = ProcessData->Console;
RtlEnterCriticalSection( &ProcessData->Console->Lock );
ProcessData->Console->ReferenceCount++;
RtlLeaveCriticalSection( &ProcessData->Console->Lock );
}
CsrInsertObject(NewProcessData,
&Reply->Data.CreateProcessReply.ConsoleHandle,
NewProcessData->Console);
// DbgPrint("CSR: ConsoleHandle %x\n",
// Reply->Data.CreateProcessReply.ConsoleHandle);
if( NewProcessData->Console )
{
CLIENT_ID ClientId;
CsrInsertObject(NewProcessData,
&Reply->Data.CreateProcessReply.ConsoleHandle,
(Object_t *)NewProcessData->Console);
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" );
CsrFreeProcessData( NewProcessData->ProcessId );
Reply->Status = Status;
return Status;
}
Status = NtDuplicateObject( NtCurrentProcess(), &NewProcessData->Console->ActiveEvent, Process, &NewProcessData->ConsoleEvent, SYNCHRONIZE, FALSE, 0 );
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: NtDuplicateObject() failed\n" );
NtClose( Process );
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);

View file

@ -1,4 +1,4 @@
/* $Id: wapi.c,v 1.6 2000/04/03 21:54:41 dwelch Exp $
/* $Id: wapi.c,v 1.7 2000/04/23 17:44:53 phreak Exp $
*
* reactos/subsys/csrss/api/wapi.c
*
@ -46,7 +46,8 @@ static void Thread_Api2(HANDLE ServerPort)
if (LpcRequest.Header.MessageType == LPC_PORT_CLOSED)
{
// DbgPrint("Client closed port\n");
DbgPrint("Client closed port\n");
CsrFreeProcessData( LpcRequest.Header.Cid.UniqueProcess );
NtClose(ServerPort);
NtTerminateThread(NtCurrentThread(), STATUS_SUCCESS);
}
@ -127,20 +128,7 @@ void Thread_Api(PVOID PortHandle)
HANDLE ServerPort;
HANDLE ServerThread;
CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE,
NULL,
65536,
65536,
NULL,
NULL);
if (CsrssApiHeap == NULL)
{
PrintString("CSR: Failed to create private heap, aborting\n");
return;
}
CsrInitProcessData();
CsrInitConsoleSupport();
for (;;)
{

View file

@ -1,4 +1,4 @@
/* $Id: csrss.c,v 1.6 2000/03/22 18:35:58 dwelch Exp $
/* $Id: csrss.c,v 1.7 2000/04/23 17:44:53 phreak Exp $
*
* csrss.c - Client/Server Runtime subsystem
*
@ -106,7 +106,7 @@ VOID NtProcessStartup(PPEB Peb)
{
DbgPrint("CSR: Failed to open csrss notification event\n");
}
DbgPrint( "foof\n" );
if (CsrServerInitialization (argc, argv) == TRUE)
{
DisplayString( L"CSR: Subsystem initialized.\n" );

View file

@ -1,4 +1,4 @@
/* $Id: init.c,v 1.7 2000/03/22 18:35:58 dwelch Exp $
/* $Id: init.c,v 1.8 2000/04/23 17:44:53 phreak Exp $
*
* reactos/subsys/csrss/init.c
*
@ -33,6 +33,7 @@ HANDLE CsrSbApiPort = INVALID_HANDLE_VALUE;
UNICODE_STRING CsrDirectoryName;
extern HANDLE CsrssApiHeap;
static NTSTATUS
CsrParseCommandLine (
@ -120,7 +121,19 @@ CsrServerInitialization (
PrintString("CSR: Unable to create \\ApiPort (Status %x)\n", Status);
return(FALSE);
}
CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE,
NULL,
65536,
65536,
NULL,
NULL);
if (CsrssApiHeap == NULL)
{
PrintString("CSR: Failed to create private heap, aborting\n");
return FALSE;
}
CsrInitConsoleSupport();
Status = RtlCreateUserThread(NtCurrentProcess(),
NULL,
FALSE,
@ -137,7 +150,12 @@ CsrServerInitialization (
NtClose(ApiPortHandle);
return FALSE;
}
Status = RtlCreateUserThread( NtCurrentProcess(), NULL, FALSE, 0, NULL, NULL, (PTHREAD_START_ROUTINE)Console_Api, 0, NULL, NULL );
if( !NT_SUCCESS( Status ) )
{
PrintString( "CSR: Unable to create console thread\n" );
return FALSE;
}
return TRUE;
}