/* FIXME: Is there a way to create real aliasses with gcc? [CSH] */
#define ALIAS(Name, Target) typeof(Target) Name = Target
-
+extern VOID CsrConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData);
/* GLOBALS *******************************************************************/
static PCSRSS_CONSOLE ActiveConsole;
CRITICAL_SECTION ActiveConsoleLock;
static COORD PhysicalConsoleSize;
+static BOOL KeyReadInhibit = FALSE;
/* FUNCTIONS *****************************************************************/
+VOID CsrConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData)
+{
+ HANDLE Process, hThread;
+ NTSTATUS Status;
+ CLIENT_ID ClientId, ClientId1;
+
+ DPRINT1("CsrConsoleCtrlEvent Parent ProcessId = %x\n", ClientId.UniqueProcess);
+
+ if (ProcessData->CtrlDispatcher)
+ {
+ ClientId.UniqueProcess = (HANDLE) ProcessData->ProcessId;
+ Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
+ if( !NT_SUCCESS( Status ) )
+ {
+ DPRINT("CsrConsoleCtrlEvent: Failed for handle duplication\n");
+ return;
+ }
+
+ DPRINT1("CsrConsoleCtrlEvent Process Handle = %x\n", Process);
+
+
+ Status = RtlCreateUserThread(Process, NULL, FALSE, 0, NULL, NULL,
+ (PTHREAD_START_ROUTINE)ProcessData->CtrlDispatcher,
+ (PVOID) Event, &hThread, &ClientId1);
+ if( !NT_SUCCESS( Status ) )
+ {
+ DPRINT("CsrConsoleCtrlEvent: Failed Thread creation\n");
+ NtClose(Process);
+ return;
+ }
+ DPRINT1("CsrConsoleCtrlEvent Parent ProcessId = %x, ReturnPId = %x, hT = %x\n",
+ ClientId.UniqueProcess, ClientId1.UniqueProcess, hThread);
+ NtClose(hThread);
+ NtClose(Process);
+ }
+}
+
+
CSR_API(CsrAllocConsole)
{
PCSRSS_CONSOLE Console;
ProcessData->Console = 0;
return Reply->Status = Status;
}
+
ClientId.UniqueProcess = (HANDLE)ProcessData->ProcessId;
Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
if( !NT_SUCCESS( Status ) )
return Status;
}
NtClose( Process );
+ LOCK;
+ ProcessData->CtrlDispatcher = Request->Data.AllocConsoleRequest.CtrlDispatcher;
+ DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
+ InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ProcessEntry);
+ UNLOCK;
+
return STATUS_SUCCESS;
}
Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
Console->EarlyReturn = FALSE;
InitializeListHead(&Console->InputEvents);
+ InitializeListHead(&Console->ProcessList);
InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_INHERIT, NULL, NULL);
RtlFreeHeap( CsrssApiHeap, 0, Console->ActiveBuffer );
return Status;
}
+ /* Create the GDI Window to be used in windowed mode */
+ /* FIXME: create window; now write NULL */
+ Console->hWindow = (HWND) NULL;
/* add a reference count because the buffer is tied to the console */
Console->ActiveBuffer->Header.ReferenceCount++;
/* make console active, and insert into console list */
continue;
}
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
- Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb,
- &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 );
+ if( !KeyReadInhibit ) {
+ Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb,
+ &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 );
+ } else {
+ Status = STATUS_PENDING;
+ }
if( !NT_SUCCESS( Status ) )
{
DbgPrint( "CSR: ReadFile on keyboard device failed\n" );
UNLOCK;
}
- if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState &
+ /* process Ctrl-C and Ctrl-Break */
+ if (ActiveConsole->Mode & ENABLE_PROCESSED_INPUT &&
+ KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown &&
+ ((KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
+ (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
+ (KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)))
+ {
+ PCSRSS_PROCESS_DATA current;
+ PLIST_ENTRY current_entry;
+ DPRINT1("Console_Api Ctrl-C\n");
+ LOCK;
+ current_entry = ActiveConsole->ProcessList.Flink;
+ while (current_entry != &ActiveConsole->ProcessList)
+ {
+ current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
+ current_entry = current_entry->Flink;
+ CsrConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
+ }
+ UNLOCK;
+ RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
+ continue;
+ }
+ if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState &
( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) &&
( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP ||
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) )
KeyEventRecord->Echoed = TRUE;
}
}
+
+
ActiveConsole->WaitingChars++;
if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT) )
NtSetEvent( ActiveConsole->ActiveEvent, 0 );
BufferSize = Request->Data.ReadConsoleOutputRequest.BufferSize;
BufferCoord = Request->Data.ReadConsoleOutputRequest.BufferCoord;
Length = BufferSize.X * BufferSize.Y;
- Size = Length * sizeof(INPUT_RECORD);
+ Size = Length * sizeof(CHAR_INFO);
- if(((PVOID)CharInfo < ProcessData->CsrSectionViewBase)
+ if(((PVOID)CharInfo < ProcessData->CsrSectionViewBase)
|| (((PVOID)CharInfo + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
{
UNLOCK;
for(i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y)
{
- CurCharInfo = CharInfo + (i * BufferSize.Y);
+ CurCharInfo = CharInfo + (i * BufferSize.X);
Offset = (((Y + ScreenBuffer->ShowY) % ScreenBuffer->MaxY) * ScreenBuffer->MaxX + ReadRegion.Left) * 2;
for(X = ReadRegion.Left; X < ReadRegion.Right; ++X)
return Reply->Status;
}
+/**********************************************************************
+ * HardwareStateProperty
+ *
+ * DESCRIPTION
+ * Set/Get the value of the HardwareState and switch
+ * between direct video buffer ouput and GDI windowed
+ * output.
+ * ARGUMENTS
+ * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
+ * object. We use the same object to reply.
+ * NOTE
+ * ConsoleHwState has the correct size to be compatible
+ * with NT's, but values are not.
+ */
+static NTSTATUS FASTCALL SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
+{
+ DbgPrint( "Console Hardware State: %d\n", ConsoleHwState );
+
+ if ( (CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
+ ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
+ {
+ /* Inhibit keyboard input when hardware state ==
+ * CONSOLE_HARDWARE_STATE_GDI_MANAGED */
+ if (CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState) {
+ DbgPrint( "Keyboard Inhibited.\n" );
+ KeyReadInhibit = TRUE;
+ } else {
+ DbgPrint( "Keyboard Enabled.\n" );
+ KeyReadInhibit = FALSE;
+ }
+ if (Console->HardwareState != ConsoleHwState)
+ {
+ /* TODO: implement switching from full screen to windowed mode */
+ /* TODO: or back; now simply store the hardware state */
+ Console->HardwareState = ConsoleHwState;
+ }
+ return STATUS_SUCCESS;
+ }
+ return STATUS_INVALID_PARAMETER_3; // Client: (handle, set_get, [mode])
+}
+
+CSR_API(CsrHardwareStateProperty)
+{
+ PCSRSS_CONSOLE Console;
+ NTSTATUS Status;
+
+ Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
+ Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
+
+ LOCK;
+
+ Status = CsrGetObject (
+ ProcessData,
+ Request->Data.ConsoleHardwareStateRequest.ConsoleHandle,
+ (Object_t**) & Console
+ );
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint( "Failed to get console handle in SetConsoleHardwareState\n" );
+ Reply->Status = Status;
+ }
+ else
+ {
+ if(Console->Header.Type != CSRSS_CONSOLE_MAGIC)
+ {
+ DbgPrint( "Bad magic on Console: %08x\n", Console->Header.Type );
+ Reply->Status = STATUS_INVALID_HANDLE;
+ }
+ else
+ {
+ switch (Request->Data.ConsoleHardwareStateRequest.SetGet)
+ {
+ case CONSOLE_HARDWARE_STATE_GET:
+ Reply->Data.ConsoleHardwareStateReply.State = Console->HardwareState;
+ break;
+
+ case CONSOLE_HARDWARE_STATE_SET:
+ DbgPrint( "Setting console hardware state.\n" );
+ Reply->Status = SetConsoleHardwareState (Console, Request->Data.ConsoleHardwareStateRequest.State);
+ break;
+
+ default:
+ Reply->Status = STATUS_INVALID_PARAMETER_2; // Client: (handle, [set_get], mode)
+ break;
+ }
+ }
+ }
+
+ UNLOCK;
+
+ return Reply->Status;
+}
+
+CSR_API(CsrGetConsoleWindow)
+{
+ PCSRSS_CONSOLE Console;
+ NTSTATUS Status;
+
+ Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
+ Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
+
+ LOCK;
+
+ Status = CsrGetObject (
+ ProcessData,
+ Request->Data.ConsoleWindowRequest.ConsoleHandle,
+ (Object_t**) & Console
+ );
+ if (!NT_SUCCESS(Status))
+ {
+ Reply->Status = Status;
+ }
+ else
+ {
+ if(Console->Header.Type != CSRSS_CONSOLE_MAGIC)
+ {
+ Reply->Status = STATUS_INVALID_HANDLE;
+ }
+ else
+ {
+ // Is this GDI handle valid in the client's context?
+ Reply->Data.ConsoleWindowReply.WindowHandle = Console->hWindow;
+ }
+ }
+
+ UNLOCK;
+
+ return Reply->Status;
+}
+
/* EOF */