3 * reactos/subsys/csrss/api/conio.c
5 * Console I/O functions
7 * ReactOS Operating System
10 /* INCLUDES ******************************************************************/
12 #include <ddk/ntddk.h>
14 #include <csrss/csrss.h>
16 #include <ntdll/rtl.h>
17 #include <ddk/ntddblue.h>
22 #define LOCK RtlEnterCriticalSection(&ActiveConsoleLock)
23 #define UNLOCK RtlLeaveCriticalSection(&ActiveConsoleLock)
25 /* FIXME: Is there a way to create real aliasses with gcc? [CSH] */
26 #define ALIAS(Name, Target) typeof(Target) Name = Target
27 extern VOID CsrConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData);
29 /* GLOBALS *******************************************************************/
31 static HANDLE ConsoleDeviceHandle;
32 static HANDLE KeyboardDeviceHandle;
33 static PCSRSS_CONSOLE ActiveConsole;
34 CRITICAL_SECTION ActiveConsoleLock;
35 static COORD PhysicalConsoleSize;
36 static BOOL KeyReadInhibit = FALSE;
38 /* FUNCTIONS *****************************************************************/
40 VOID CsrConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData)
42 HANDLE Process, hThread;
44 CLIENT_ID ClientId, ClientId1;
46 DPRINT1("CsrConsoleCtrlEvent Parent ProcessId = %x\n", ClientId.UniqueProcess);
48 if (ProcessData->CtrlDispatcher)
50 ClientId.UniqueProcess = (HANDLE) ProcessData->ProcessId;
51 Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
52 if( !NT_SUCCESS( Status ) )
54 DPRINT("CsrConsoleCtrlEvent: Failed for handle duplication\n");
58 DPRINT1("CsrConsoleCtrlEvent Process Handle = %x\n", Process);
61 Status = RtlCreateUserThread(Process, NULL, FALSE, 0, NULL, NULL,
62 (PTHREAD_START_ROUTINE)ProcessData->CtrlDispatcher,
63 (PVOID) Event, &hThread, &ClientId1);
64 if( !NT_SUCCESS( Status ) )
66 DPRINT("CsrConsoleCtrlEvent: Failed Thread creation\n");
70 DPRINT1("CsrConsoleCtrlEvent Parent ProcessId = %x, ReturnPId = %x, hT = %x\n",
71 ClientId.UniqueProcess, ClientId1.UniqueProcess, hThread);
78 CSR_API(CsrAllocConsole)
80 PCSRSS_CONSOLE Console;
85 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
86 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
89 if (ProcessData == NULL)
91 return(Reply->Status = STATUS_INVALID_PARAMETER);
94 if( ProcessData->Console )
96 Reply->Status = STATUS_INVALID_PARAMETER;
97 return STATUS_INVALID_PARAMETER;
99 Reply->Status = STATUS_SUCCESS;
100 Console = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( CSRSS_CONSOLE ) );
103 Reply->Status = STATUS_INSUFFICIENT_RESOURCES;
104 return STATUS_INSUFFICIENT_RESOURCES;
106 Reply->Status = CsrInitConsole( Console );
107 if( !NT_SUCCESS( Reply->Status ) )
109 RtlFreeHeap( CsrssApiHeap, 0, Console );
110 return Reply->Status;
112 ProcessData->Console = Console;
113 /* add a reference count because the process is tied to the console */
114 Console->Header.ReferenceCount++;
115 Status = CsrInsertObject( ProcessData, &Reply->Data.AllocConsoleReply.InputHandle, &Console->Header );
116 if( !NT_SUCCESS( Status ) )
118 CsrDeleteConsole( Console );
119 ProcessData->Console = 0;
120 return Reply->Status = Status;
122 Status = CsrInsertObject( ProcessData, &Reply->Data.AllocConsoleReply.OutputHandle, &Console->ActiveBuffer->Header );
123 if( !NT_SUCCESS( Status ) )
125 Console->Header.ReferenceCount--;
126 CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.InputHandle );
127 ProcessData->Console = 0;
128 return Reply->Status = Status;
131 ClientId.UniqueProcess = (HANDLE)ProcessData->ProcessId;
132 Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
133 if( !NT_SUCCESS( Status ) )
135 DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" );
136 Console->Header.ReferenceCount--;
137 ProcessData->Console = 0;
138 CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.OutputHandle );
139 CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.InputHandle );
140 Reply->Status = Status;
143 Status = NtDuplicateObject( NtCurrentProcess(), ProcessData->Console->ActiveEvent, Process, &ProcessData->ConsoleEvent, SYNCHRONIZE, FALSE, 0 );
144 if( !NT_SUCCESS( Status ) )
146 DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status );
148 Console->Header.ReferenceCount--;
149 CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.OutputHandle );
150 CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.InputHandle );
151 ProcessData->Console = 0;
152 Reply->Status = Status;
157 ProcessData->CtrlDispatcher = Request->Data.AllocConsoleRequest.CtrlDispatcher;
158 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
159 InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ProcessEntry);
162 return STATUS_SUCCESS;
165 CSR_API(CsrFreeConsole)
167 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
168 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
171 if (ProcessData == NULL)
173 return(Reply->Status = STATUS_INVALID_PARAMETER);
176 Reply->Status = STATUS_NOT_IMPLEMENTED;
178 return(STATUS_NOT_IMPLEMENTED);
181 CSR_API(CsrReadConsole)
183 PLIST_ENTRY CurrentEntry;
187 ULONG nNumberOfCharsToRead;
188 PCSRSS_CONSOLE Console;
191 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
192 nNumberOfCharsToRead = Request->Data.ReadConsoleRequest.NrCharactersToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : Request->Data.ReadConsoleRequest.NrCharactersToRead;
193 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
194 Reply->Header.DataSize = Reply->Header.MessageSize -
197 Buffer = Reply->Data.ReadConsoleReply.Buffer;
199 Status = CsrGetObject( ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle, (Object_t **)&Console );
200 if( !NT_SUCCESS( Status ) )
202 Reply->Status = Status;
206 if( Console->Header.Type != CSRSS_CONSOLE_MAGIC )
208 Reply->Status = STATUS_INVALID_HANDLE;
210 return STATUS_INVALID_HANDLE;
212 Reply->Data.ReadConsoleReply.EventHandle = ProcessData->ConsoleEvent;
213 for (; i<nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++ )
215 // remove input event from queue
216 CurrentEntry = RemoveHeadList(&Console->InputEvents);
217 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
219 // only pay attention to valid ascii chars, on key down
220 if( Input->InputEvent.EventType == KEY_EVENT &&
221 Input->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
222 Input->InputEvent.Event.KeyEvent.uChar.AsciiChar )
224 // backspace handling
225 if( Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' )
227 // echo if it has not already been done, and either we or the client has chars to be deleted
228 if( !Input->Echoed && ( i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted ) )
229 CsrpWriteConsole( Console->ActiveBuffer, &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
231 i-=2; // if we already have something to return, just back it up by 2
233 { // otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer
234 Reply->Data.ReadConsoleReply.NrCharactersRead = 0;
235 Reply->Status = STATUS_NOTIFY_CLEANUP;
236 Console->WaitingChars--;
237 RtlFreeHeap( CsrssApiHeap, 0, Input );
239 return STATUS_NOTIFY_CLEANUP;
241 Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--;
242 Input->Echoed = TRUE; // mark as echoed so we don't echo it below
244 // do not copy backspace to buffer
245 else Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
246 // echo to screen if enabled and we did not already echo the char
247 if( Console->Mode & ENABLE_ECHO_INPUT &&
249 Input->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\r' )
250 CsrpWriteConsole( Console->ActiveBuffer, &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
253 Console->WaitingChars--;
254 RtlFreeHeap( CsrssApiHeap, 0, Input );
256 Reply->Data.ReadConsoleReply.NrCharactersRead = i;
258 Reply->Status = STATUS_PENDING; // we didn't read anything
259 else if( Console->Mode & ENABLE_LINE_INPUT )
260 if( !Console->WaitingLines || Buffer[i-1] != '\n' )
262 Reply->Status = STATUS_PENDING; // line buffered, didn't get a complete line
265 Console->WaitingLines--;
266 Reply->Status = STATUS_SUCCESS; // line buffered, did get a complete line
268 else Reply->Status = STATUS_SUCCESS; // not line buffered, did read something
269 if( Reply->Status == STATUS_PENDING )
271 Console->EchoCount = nNumberOfCharsToRead - i;
274 Console->EchoCount = 0; // if the client is no longer waiting on input, do not echo
276 Reply->Header.MessageSize += i;
278 return Reply->Status;
281 #define GET_CELL_BUFFER(b,o)\
284 #define SET_CELL_BUFFER(b,o,c,a)\
285 (b)->Buffer[(o)++]=(c);\
286 (b)->Buffer[(o)++]=(a);
290 PCSRSS_SCREEN_BUFFER Buff,
294 DWORD Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + StartX);
296 for ( ; StartX < Buff->MaxX; StartX ++ )
298 /* Fill the cell: Offset is incremented by the macro */
299 SET_CELL_BUFFER(Buff,Offset,' ',Buff->DefaultAttrib)
303 NTSTATUS STDCALL CsrpWriteConsole( PCSRSS_SCREEN_BUFFER Buff, CHAR *Buffer, DWORD Length, BOOL Attrib )
305 IO_STATUS_BLOCK Iosb;
310 for( i = 0; i < Length; i++ )
312 switch( Buffer[ i ] )
317 /* slide the viewable screen */
318 if (((Buff->CurrentY-Buff->ShowY + Buff->MaxY) % Buff->MaxY) == PhysicalConsoleSize.Y - 1)
319 if (++Buff->ShowY == Buff->MaxY)
321 if( ++Buff->CurrentY == Buff->MaxY )
325 ClearLineBuffer (Buff, 0);
329 if( Buff->CurrentX == 0 )
331 /* slide viewable screen up */
332 if( Buff->ShowY == Buff->CurrentY )
334 if( Buff->ShowY == 0 )
335 Buff->ShowY = Buff->MaxY;
339 /* slide virtual position up */
340 Buff->CurrentX = Buff->MaxX;
341 if( Buff->CurrentY == 0 )
342 Buff->CurrentY = Buff->MaxY;
348 Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + Buff->CurrentX);
349 SET_CELL_BUFFER(Buff,Offset,' ',Buff->DefaultAttrib);
357 CsrpWriteConsole(Buff, " ", (8 - (Buff->CurrentX % 8)), FALSE);
361 Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX);
362 Buff->Buffer[Offset ++] = Buffer[ i ];
364 Buff->Buffer[Offset] = Buff->DefaultAttrib;
366 if( Buff->CurrentX == Buff->MaxX )
368 /* if end of line, go to next */
370 if( ++Buff->CurrentY == Buff->MaxY )
372 /* if end of buffer, wrap back to beginning */
376 ClearLineBuffer (Buff, 0);
377 /* slide the viewable screen */
378 if( (Buff->CurrentY - Buff->ShowY + Buff->MaxY - 1) % Buff->MaxY == PhysicalConsoleSize.Y -1)
379 if( ++Buff->ShowY == Buff->MaxY )
384 if( Buff == ActiveConsole->ActiveBuffer )
385 { /* only write to screen if Console is Active, and not scrolled up */
388 Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, Buffer, Length, NULL, 0);
389 if (!NT_SUCCESS(Status))
390 DbgPrint("CSR: Write failed\n");
393 return(STATUS_SUCCESS);
396 #define CsrpInitRect(_Rect, _Top, _Left, _Bottom, _Right) \
398 ((_Rect).Top) = _Top; \
399 ((_Rect).Left) = _Left; \
400 ((_Rect).Bottom) = _Bottom; \
401 ((_Rect).Right) = _Right; \
404 #define CsrpRectHeight(Rect) \
405 ((Rect.Top) > (Rect.Bottom) ? 0 : (Rect.Bottom) - (Rect.Top) + 1)
407 #define CsrpRectWidth(Rect) \
408 ((Rect.Left) > (Rect.Right) ? 0 : (Rect.Right) - (Rect.Left) + 1)
410 #define CsrpIsRectEmpty(Rect) \
411 ((Rect.Left > Rect.Right) || (Rect.Top > Rect.Bottom))
414 inline BOOLEAN CsrpIsEqualRect(
418 return ((Rect1.Left == Rect2.Left) && (Rect1.Right == Rect2.Right) &&
419 (Rect1.Top == Rect2.Top) && (Rect1.Bottom == Rect2.Bottom));
422 inline BOOLEAN CsrpGetIntersection(
423 PSMALL_RECT Intersection,
427 if (CsrpIsRectEmpty(Rect1) ||
428 (CsrpIsRectEmpty(Rect2)) ||
429 (Rect1.Top > Rect2.Bottom) ||
430 (Rect1.Left > Rect2.Right) ||
431 (Rect1.Bottom < Rect2.Top) ||
432 (Rect1.Right < Rect2.Left))
434 /* The rectangles do not intersect */
435 CsrpInitRect(*Intersection, 0, -1, 0, -1)
441 RtlMax(Rect1.Top, Rect2.Top),
442 RtlMax(Rect1.Left, Rect2.Left),
443 RtlMin(Rect1.Bottom, Rect2.Bottom),
444 RtlMin(Rect1.Right, Rect2.Right));
448 inline BOOLEAN CsrpGetUnion(
453 if (CsrpIsRectEmpty(Rect1))
455 if (CsrpIsRectEmpty(Rect2))
457 CsrpInitRect(*Union, 0, -1, 0, -1);
465 if (CsrpIsRectEmpty(Rect2))
473 RtlMin(Rect1.Top, Rect2.Top),
474 RtlMin(Rect1.Left, Rect2.Left),
475 RtlMax(Rect1.Bottom, Rect2.Bottom),
476 RtlMax(Rect1.Right, Rect2.Right));
482 inline BOOLEAN CsrpSubtractRect(
483 PSMALL_RECT Subtraction,
489 if (CsrpIsRectEmpty(Rect1))
491 CsrpInitRect(*Subtraction, 0, -1, 0, -1);
494 *Subtraction = Rect1;
495 if (CsrpGetIntersection(&tmp, Rect1, Rect2))
497 if (CsrpIsEqualRect(tmp, *Subtraction))
499 CsrpInitRect(*Subtraction, 0, -1, 0, -1);
502 if ((tmp.Top == Subtraction->Top) && (tmp.Bottom == Subtraction->Bottom))
504 if (tmp.Left == Subtraction->Left)
505 Subtraction->Left = tmp.Right;
506 else if (tmp.Right == Subtraction->Right)
507 Subtraction->Right = tmp.Left;
509 else if ((tmp.Left == Subtraction->Left) && (tmp.Right == Subtraction->Right))
511 if (tmp.Top == Subtraction->Top)
512 Subtraction->Top = tmp.Bottom;
513 else if (tmp.Bottom == Subtraction->Bottom)
514 Subtraction->Bottom = tmp.Top;
521 * Screen buffer must be locked when this function is called
523 static VOID CsrpCopyRegion(
524 PCSRSS_SCREEN_BUFFER ScreenBuffer,
525 SMALL_RECT SrcRegion,
526 SMALL_RECT DstRegion)
534 DstY = DstRegion.Top;
535 BytesPerLine = CsrpRectWidth(DstRegion) * 2;
537 SrcY = (SrcRegion.Top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
538 DstY = (DstRegion.Top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
539 SrcOffset = (SrcY * ScreenBuffer->MaxX + SrcRegion.Left + ScreenBuffer->ShowX) * 2;
540 DstOffset = (DstY * ScreenBuffer->MaxX + DstRegion.Left + ScreenBuffer->ShowX) * 2;
542 for (i = SrcRegion.Top; i <= SrcRegion.Bottom; i++)
545 &ScreenBuffer->Buffer[DstOffset],
546 &ScreenBuffer->Buffer[SrcOffset],
549 if (++DstY == ScreenBuffer->MaxY)
552 DstOffset = (DstRegion.Left + ScreenBuffer->ShowX) * 2;
556 DstOffset += ScreenBuffer->MaxX * 2;
559 if (++SrcY == ScreenBuffer->MaxY)
562 SrcOffset = (SrcRegion.Left + ScreenBuffer->ShowX) * 2;
566 SrcOffset += ScreenBuffer->MaxX * 2;
572 * Screen buffer must be locked when this function is called
574 static VOID CsrpFillRegion(
575 PCSRSS_SCREEN_BUFFER ScreenBuffer,
584 Y = (Region.Top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
585 Offset = (Y * ScreenBuffer->MaxX + Region.Left + ScreenBuffer->ShowX) * 2;
586 Delta = (ScreenBuffer->MaxX - CsrpRectWidth(Region)) * 2;
588 for (i = Region.Top; i <= Region.Bottom; i++)
590 for (X = Region.Left; X <= Region.Right; X++)
592 SET_CELL_BUFFER(ScreenBuffer, Offset, CharInfo.Char.AsciiChar, CharInfo.Attributes);
594 if (++Y == ScreenBuffer->MaxY)
597 Offset = (Region.Left + ScreenBuffer->ShowX) * 2;
607 * Screen buffer must be locked when this function is called
609 inline NTSTATUS CsrpSetConsoleDeviceCursor(PCSRSS_SCREEN_BUFFER ScreenBuffer, SHORT X, SHORT Y)
611 CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
612 IO_STATUS_BLOCK Iosb;
614 ScrInfo.dwCursorPosition.X = X;
615 ScrInfo.dwCursorPosition.Y = Y;
616 ScrInfo.wAttributes = ScreenBuffer->DefaultAttrib;
618 return NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
619 IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
623 * Region - Region of virtual screen buffer to draw onto the physical console
624 * Screen buffer must be locked when this function is called
626 static VOID CsrpDrawRegion(
627 PCSRSS_SCREEN_BUFFER ScreenBuffer,
630 IO_STATUS_BLOCK Iosb;
632 CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
639 Mode.dwMode = 0; /* clear ENABLE_PROCESSED_OUTPUT mode */
640 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
641 IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
642 if( !NT_SUCCESS( Status ) )
644 DbgPrint( "CSR: Failed to set console mode\n" );
648 /* blast out buffer */
649 BytesPerLine = CsrpRectWidth(Region) * 2;
650 SrcOffset = (((Region.Top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY) * ScreenBuffer->MaxX + Region.Left + ScreenBuffer->ShowX) * 2;
651 SrcDelta = ScreenBuffer->MaxX * 2;
652 for( i = Region.Top, y = ScreenBuffer->ShowY; i <= Region.Bottom; i++ )
654 /* Position the cursor correctly */
655 Status = CsrpSetConsoleDeviceCursor(ScreenBuffer, Region.Left, i);
656 if( !NT_SUCCESS( Status ) )
658 DbgPrint( "CSR: Failed to set console info\n" );
662 Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
663 &ScreenBuffer->Buffer[ SrcOffset ],
664 BytesPerLine, 0, 0 );
665 if( !NT_SUCCESS( Status ) )
667 DbgPrint( "CSR: Write to console failed\n" );
671 /* wrap back around the end of the buffer */
672 if( ++y == ScreenBuffer->MaxY )
675 SrcOffset = (Region.Left + ScreenBuffer->ShowX) * 2;
679 SrcOffset += SrcDelta;
682 Mode.dwMode = ENABLE_PROCESSED_OUTPUT;
683 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
684 IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
685 if( !NT_SUCCESS( Status ) )
687 DbgPrint( "CSR: Failed to set console mode\n" );
690 Status = CsrpSetConsoleDeviceCursor(
692 ScreenBuffer->CurrentX - ScreenBuffer->ShowX,
693 ((ScreenBuffer->CurrentY + ScreenBuffer->MaxY) - ScreenBuffer->ShowY) % ScreenBuffer->MaxY);
694 if( !NT_SUCCESS( Status ) )
696 DbgPrint( "CSR: Failed to set console info\n" );
699 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
700 IOCTL_CONSOLE_SET_CURSOR_INFO, &ScreenBuffer->CursorInfo,
701 sizeof( ScreenBuffer->CursorInfo ), 0, 0 );
702 if( !NT_SUCCESS( Status ) )
704 DbgPrint( "CSR: Failed to set cursor info\n" );
710 CSR_API(CsrWriteConsole)
712 BYTE *Buffer = Request->Data.WriteConsoleRequest.Buffer;
713 PCSRSS_SCREEN_BUFFER Buff;
715 DPRINT("CsrWriteConsole\n");
717 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
718 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
722 if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle,
723 (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
726 return Reply->Status = STATUS_INVALID_HANDLE;
728 CsrpWriteConsole( Buff, Buffer, Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE );
730 return Reply->Status = STATUS_SUCCESS;
734 NTSTATUS STDCALL CsrInitConsoleScreenBuffer( PCSRSS_SCREEN_BUFFER Console )
736 Console->Header.Type = CSRSS_SCREEN_BUFFER_MAGIC;
737 Console->Header.ReferenceCount = 0;
738 Console->MaxX = PhysicalConsoleSize.X;
739 Console->MaxY = PhysicalConsoleSize.Y;
742 Console->CurrentX = 0;
743 Console->CurrentY = 0;
744 Console->Buffer = RtlAllocateHeap( CsrssApiHeap, 0, Console->MaxX * Console->MaxY * 2 );
745 if( Console->Buffer == 0 )
746 return STATUS_INSUFFICIENT_RESOURCES;
747 Console->DefaultAttrib = 0x17;
748 /* initialize buffer to be empty with default attributes */
749 for( ; Console->CurrentY < Console->MaxY; Console->CurrentY++ )
751 ClearLineBuffer (Console, 0);
753 Console->CursorInfo.bVisible = TRUE;
754 Console->CursorInfo.dwSize = 5;
755 Console->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
756 Console->CurrentX = 0;
757 Console->CurrentY = 0;
758 return STATUS_SUCCESS;
761 VOID STDCALL CsrDeleteScreenBuffer( PCSRSS_SCREEN_BUFFER Buffer )
763 RtlFreeHeap( CsrssApiHeap, 0, Buffer->Buffer );
764 RtlFreeHeap( CsrssApiHeap, 0, Buffer );
767 NTSTATUS STDCALL CsrInitConsole(PCSRSS_CONSOLE Console)
770 OBJECT_ATTRIBUTES ObjectAttributes;
772 Console->Title.MaximumLength = Console->Title.Length = 0;
773 Console->Title.Buffer = 0;
775 RtlCreateUnicodeString( &Console->Title, L"Command Prompt" );
777 Console->Header.ReferenceCount = 0;
778 Console->WaitingChars = 0;
779 Console->WaitingLines = 0;
780 Console->EchoCount = 0;
781 Console->Header.Type = CSRSS_CONSOLE_MAGIC;
782 Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
783 Console->EarlyReturn = FALSE;
784 InitializeListHead(&Console->InputEvents);
785 InitializeListHead(&Console->ProcessList);
787 InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_INHERIT, NULL, NULL);
789 Status = NtCreateEvent( &Console->ActiveEvent, STANDARD_RIGHTS_ALL, &ObjectAttributes, FALSE, FALSE );
790 if( !NT_SUCCESS( Status ) )
794 Console->ActiveBuffer = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( CSRSS_SCREEN_BUFFER ) );
795 if( !Console->ActiveBuffer )
797 NtClose( Console->ActiveEvent );
798 return STATUS_INSUFFICIENT_RESOURCES;
800 Status = CsrInitConsoleScreenBuffer( Console->ActiveBuffer );
801 if( !NT_SUCCESS( Status ) )
803 NtClose( Console->ActiveEvent );
804 RtlFreeHeap( CsrssApiHeap, 0, Console->ActiveBuffer );
807 /* Create the GDI Window to be used in windowed mode */
808 /* FIXME: create window; now write NULL */
809 Console->hWindow = (HWND) NULL;
810 /* add a reference count because the buffer is tied to the console */
811 Console->ActiveBuffer->Header.ReferenceCount++;
812 /* make console active, and insert into console list */
816 Console->Prev = ActiveConsole;
817 Console->Next = ActiveConsole->Next;
818 ActiveConsole->Next->Prev = Console;
819 ActiveConsole->Next = Console;
822 Console->Prev = Console;
823 Console->Next = Console;
825 ActiveConsole = Console;
826 /* copy buffer contents to screen */
827 CsrDrawConsole( Console->ActiveBuffer );
829 return STATUS_SUCCESS;
832 /***************************************************************
833 * CsrDrawConsole blasts the console buffer onto the screen *
834 * must be called while holding the active console lock *
835 **************************************************************/
836 VOID STDCALL CsrDrawConsole( PCSRSS_SCREEN_BUFFER Buff )
844 PhysicalConsoleSize.Y - 1,
845 PhysicalConsoleSize.X - 1);
847 CsrpDrawRegion(Buff, Region);
851 VOID STDCALL CsrDeleteConsole( PCSRSS_CONSOLE Console )
854 DPRINT( "CsrDeleteConsole\n" );
856 /* Drain input event queue */
857 while( Console->InputEvents.Flink != &Console->InputEvents )
859 Event = (ConsoleInput *)Console->InputEvents.Flink;
860 Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
861 Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents;
862 RtlFreeHeap( CsrssApiHeap, 0, Event );
864 /* Switch to next console */
865 if( ActiveConsole == Console )
867 if( Console->Next != Console )
869 ActiveConsole = Console->Next;
871 else ActiveConsole = 0;
873 if (Console->Next != Console)
875 Console->Prev->Next = Console->Next;
876 Console->Next->Prev = Console->Prev;
880 CsrDrawConsole( ActiveConsole->ActiveBuffer );
881 if( !--Console->ActiveBuffer->Header.ReferenceCount )
882 CsrDeleteScreenBuffer( Console->ActiveBuffer );
884 NtClose( Console->ActiveEvent );
885 RtlFreeUnicodeString( &Console->Title );
886 RtlFreeHeap( CsrssApiHeap, 0, Console );
889 VOID STDCALL CsrInitConsoleSupport(VOID)
891 OBJECT_ATTRIBUTES ObjectAttributes;
892 UNICODE_STRING DeviceName;
894 IO_STATUS_BLOCK Iosb;
895 CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
897 DPRINT("CSR: CsrInitConsoleSupport()\n");
899 RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\BlueScreen");
900 InitializeObjectAttributes(&ObjectAttributes,
905 Status = NtOpenFile(&ConsoleDeviceHandle,
910 FILE_SYNCHRONOUS_IO_ALERT);
911 if (!NT_SUCCESS(Status))
913 DbgPrint("CSR: Failed to open console. Expect problems.\n");
916 RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\Keyboard");
917 InitializeObjectAttributes(&ObjectAttributes,
922 Status = NtOpenFile(&KeyboardDeviceHandle,
928 if (!NT_SUCCESS(Status))
930 DbgPrint("CSR: Failed to open keyboard. Expect problems.\n");
934 RtlInitializeCriticalSection( &ActiveConsoleLock );
935 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, &ScrInfo, sizeof( ScrInfo ) );
936 if( !NT_SUCCESS( Status ) )
938 DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
941 PhysicalConsoleSize = ScrInfo.dwSize;
944 VOID Console_Api( DWORD RefreshEvent )
946 /* keep reading events from the keyboard and stuffing them into the current
947 console's input queue */
948 ConsoleInput *KeyEventRecord;
949 ConsoleInput *TempInput;
950 IO_STATUS_BLOCK Iosb;
952 HANDLE Events[2]; // 0 = keyboard, 1 = refresh
955 PCSRSS_CONSOLE SwapConsole = 0; // console we are thinking about swapping with
958 Status = NtCreateEvent( &Events[0], STANDARD_RIGHTS_ALL, NULL, FALSE, FALSE );
959 if( !NT_SUCCESS( Status ) )
961 DbgPrint( "CSR: NtCreateEvent failed: %x\n", Status );
962 NtTerminateProcess( NtCurrentProcess(), Status );
964 Events[1] = (HANDLE)RefreshEvent;
967 KeyEventRecord = RtlAllocateHeap(CsrssApiHeap,
969 sizeof(ConsoleInput));
970 if ( KeyEventRecord == 0 )
972 DbgPrint( "CSR: Memory allocation failure!" );
975 KeyEventRecord->InputEvent.EventType = KEY_EVENT;
976 if( !KeyReadInhibit ) {
977 Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb,
978 &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 );
980 Status = STATUS_PENDING;
982 if( !NT_SUCCESS( Status ) )
984 DbgPrint( "CSR: ReadFile on keyboard device failed\n" );
985 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
988 if( Status == STATUS_PENDING )
992 Status = NtWaitForMultipleObjects( 2, Events, WaitAny, FALSE, NULL );
993 if( Status == STATUS_WAIT_0 + 1 )
996 CsrDrawConsole( ActiveConsole->ActiveBuffer );
1000 else if( Status != STATUS_WAIT_0 )
1002 DbgPrint( "CSR: NtWaitForMultipleObjects failed: %x, exiting\n", Status );
1003 NtTerminateProcess( NtCurrentProcess(), Status );
1008 if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState &
1009 ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&&
1010 KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_TAB )
1011 if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
1017 /* alt-tab, swap consoles */
1018 // move SwapConsole to next console, and print its title
1021 SwapConsole = ActiveConsole;
1023 if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED )
1024 SwapConsole = SwapConsole->Prev;
1025 else SwapConsole = SwapConsole->Next;
1026 Title.MaximumLength = RtlUnicodeStringToAnsiSize( &SwapConsole->Title );
1028 Buffer = RtlAllocateHeap( CsrssApiHeap,
1030 sizeof( COORD ) + Title.MaximumLength);
1031 pos = (COORD *)Buffer;
1032 Title.Buffer = Buffer + sizeof( COORD );
1034 RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Title, FALSE);
1035 pos->Y = PhysicalConsoleSize.Y / 2;
1036 pos->X = ( PhysicalConsoleSize.X - Title.Length ) / 2;
1037 // redraw the console to clear off old title
1038 CsrDrawConsole( ActiveConsole->ActiveBuffer );
1039 Status = NtDeviceIoControlFile( ConsoleDeviceHandle,
1044 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
1046 sizeof (COORD) + Title.Length,
1049 if( !NT_SUCCESS( Status ) )
1051 DPRINT1( "Error writing to console\n" );
1053 RtlFreeHeap( CsrssApiHeap, 0, Buffer );
1056 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
1060 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
1063 else if( SwapConsole &&
1064 KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_MENU &&
1065 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == FALSE )
1067 // alt key released, swap consoles
1071 if( SwapConsole != ActiveConsole )
1073 // first remove swapconsole from the list
1074 SwapConsole->Prev->Next = SwapConsole->Next;
1075 SwapConsole->Next->Prev = SwapConsole->Prev;
1076 // now insert before activeconsole
1077 SwapConsole->Next = ActiveConsole;
1078 SwapConsole->Prev = ActiveConsole->Prev;
1079 ActiveConsole->Prev->Next = SwapConsole;
1080 ActiveConsole->Prev = SwapConsole;
1082 ActiveConsole = SwapConsole;
1084 CsrDrawConsole( ActiveConsole->ActiveBuffer );
1088 /* process Ctrl-C and Ctrl-Break */
1089 if (ActiveConsole->Mode & ENABLE_PROCESSED_INPUT &&
1090 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown &&
1091 ((KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
1092 (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
1093 (KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)))
1095 PCSRSS_PROCESS_DATA current;
1096 PLIST_ENTRY current_entry;
1097 DPRINT1("Console_Api Ctrl-C\n");
1099 current_entry = ActiveConsole->ProcessList.Flink;
1100 while (current_entry != &ActiveConsole->ProcessList)
1102 current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
1103 current_entry = current_entry->Flink;
1104 CsrConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
1107 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
1110 if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState &
1111 ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) &&
1112 ( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP ||
1113 KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) )
1115 if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
1117 /* scroll up or down */
1119 if( ActiveConsole == 0 )
1121 DbgPrint( "CSR: No Active Console!\n" );
1123 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
1126 if( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP )
1128 /* only scroll up if there is room to scroll up into */
1129 if( ActiveConsole->ActiveBuffer->ShowY != ((ActiveConsole->ActiveBuffer->CurrentY + 1) %
1130 ActiveConsole->ActiveBuffer->MaxY) )
1131 ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY +
1132 ActiveConsole->ActiveBuffer->MaxY - 1) % ActiveConsole->ActiveBuffer->MaxY;
1134 else if( ActiveConsole->ActiveBuffer->ShowY != ActiveConsole->ActiveBuffer->CurrentY )
1135 /* only scroll down if there is room to scroll down into */
1136 if( ActiveConsole->ActiveBuffer->ShowY % ActiveConsole->ActiveBuffer->MaxY !=
1137 ActiveConsole->ActiveBuffer->CurrentY )
1139 if( ((ActiveConsole->ActiveBuffer->CurrentY + 1) % ActiveConsole->ActiveBuffer->MaxY) !=
1140 (ActiveConsole->ActiveBuffer->ShowY + PhysicalConsoleSize.Y) % ActiveConsole->ActiveBuffer->MaxY )
1141 ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY + 1) %
1142 ActiveConsole->ActiveBuffer->MaxY;
1143 CsrDrawConsole( ActiveConsole->ActiveBuffer );
1146 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
1150 if( ActiveConsole == 0 )
1152 DbgPrint( "CSR: No Active Console!\n" );
1154 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
1157 // process special keys if enabled
1158 if( ActiveConsole->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) )
1159 switch( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar )
1162 // add a \n to the queue as well
1164 updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown;
1165 KeyEventRecord->Echoed = FALSE;
1166 KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\r';
1167 InsertTailList(&ActiveConsole->InputEvents, &KeyEventRecord->ListEntry);
1168 ActiveConsole->WaitingChars++;
1169 KeyEventRecord = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( ConsoleInput ) );
1170 if( !KeyEventRecord )
1172 DbgPrint( "CSR: Failed to allocate KeyEventRecord\n" );
1176 KeyEventRecord->InputEvent.EventType = KEY_EVENT;
1177 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown = updown;
1178 KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = 0;
1179 KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualScanCode = 0;
1180 KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\n';
1182 // add event to the queue
1183 InsertTailList(&ActiveConsole->InputEvents, &KeyEventRecord->ListEntry);
1184 // if line input mode is enabled, only wake the client on enter key down
1185 if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT ) ||
1186 ActiveConsole->EarlyReturn ||
1187 ( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' &&
1188 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE ) )
1190 NtSetEvent( ActiveConsole->ActiveEvent, 0 );
1191 if( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
1192 ActiveConsole->WaitingLines++;
1194 KeyEventRecord->Echoed = FALSE;
1195 if( ActiveConsole->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) &&
1196 KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' &&
1197 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown )
1199 // walk the input queue looking for a char to backspace
1200 for( TempInput = (ConsoleInput *)ActiveConsole->InputEvents.Blink;
1201 TempInput != (ConsoleInput *)&ActiveConsole->InputEvents &&
1202 (TempInput->InputEvent.EventType != KEY_EVENT ||
1203 TempInput->InputEvent.Event.KeyEvent.bKeyDown == FALSE ||
1204 TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' );
1205 TempInput = (ConsoleInput *)TempInput->ListEntry.Blink );
1206 // if we found one, delete it, otherwise, wake the client
1207 if( TempInput != (ConsoleInput *)&ActiveConsole->InputEvents )
1209 // delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue
1210 RemoveEntryList(&TempInput->ListEntry);
1211 if( TempInput->Echoed )
1212 CsrpWriteConsole( ActiveConsole->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
1213 RtlFreeHeap( CsrssApiHeap, 0, TempInput );
1214 RemoveEntryList(&KeyEventRecord->ListEntry);
1215 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
1216 ActiveConsole->WaitingChars -= 2;
1218 else NtSetEvent( ActiveConsole->ActiveEvent, 0 );
1221 // echo chars if we are supposed to and client is waiting for some
1222 if( ( ActiveConsole->Mode & ENABLE_ECHO_INPUT ) && ActiveConsole->EchoCount &&
1223 KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar &&
1224 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
1225 KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\r' )
1227 // mark the char as already echoed
1228 CsrpWriteConsole( ActiveConsole->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
1229 ActiveConsole->EchoCount--;
1230 KeyEventRecord->Echoed = TRUE;
1235 ActiveConsole->WaitingChars++;
1236 if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT) )
1237 NtSetEvent( ActiveConsole->ActiveEvent, 0 );
1242 CSR_API(CsrGetScreenBufferInfo)
1245 PCSRSS_SCREEN_BUFFER Buff;
1246 PCONSOLE_SCREEN_BUFFER_INFO pInfo;
1247 IO_STATUS_BLOCK Iosb;
1249 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1250 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1251 sizeof(LPC_MESSAGE);
1254 if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle,
1255 (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
1258 return Reply->Status = STATUS_INVALID_HANDLE;
1260 pInfo = &Reply->Data.ScreenBufferInfoReply.Info;
1261 if( Buff == ActiveConsole->ActiveBuffer )
1263 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
1264 IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, pInfo, sizeof( *pInfo ) );
1265 if( !NT_SUCCESS( Status ) )
1266 DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
1267 Reply->Status = Status;
1270 pInfo->dwSize.X = PhysicalConsoleSize.X;
1271 pInfo->dwSize.Y = PhysicalConsoleSize.Y;
1272 pInfo->dwCursorPosition.X = Buff->CurrentX - Buff->ShowX;
1273 pInfo->dwCursorPosition.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY;
1274 pInfo->wAttributes = Buff->DefaultAttrib;
1275 pInfo->srWindow.Left = 0;
1276 pInfo->srWindow.Right = PhysicalConsoleSize.X - 1;
1277 pInfo->srWindow.Top = 0;
1278 pInfo->srWindow.Bottom = PhysicalConsoleSize.Y - 1;
1279 Reply->Status = STATUS_SUCCESS;
1282 return Reply->Status;
1285 CSR_API(CsrSetCursor)
1288 PCSRSS_SCREEN_BUFFER Buff;
1289 CONSOLE_SCREEN_BUFFER_INFO Info;
1290 IO_STATUS_BLOCK Iosb;
1292 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1293 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1294 sizeof(LPC_MESSAGE);
1297 if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.SetCursorRequest.ConsoleHandle,
1298 (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
1301 return Reply->Status = STATUS_INVALID_HANDLE;
1303 Info.dwCursorPosition = Request->Data.SetCursorRequest.Position;
1304 Info.wAttributes = Buff->DefaultAttrib;
1305 if( Buff == ActiveConsole->ActiveBuffer )
1307 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb,
1308 IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &Info, sizeof( Info ), 0, 0 );
1309 if( !NT_SUCCESS( Status ) )
1310 DbgPrint( "CSR: Failed to set console info, expect trouble\n" );
1313 Buff->CurrentX = Info.dwCursorPosition.X + Buff->ShowX;
1314 Buff->CurrentY = (Info.dwCursorPosition.Y + Buff->ShowY) % Buff->MaxY;
1316 return Reply->Status = Status;
1319 CSR_API(CsrWriteConsoleOutputChar)
1321 PBYTE String = Request->Data.WriteConsoleOutputCharRequest.String;
1323 PCSRSS_SCREEN_BUFFER Buff;
1326 IO_STATUS_BLOCK Iosb;
1328 DPRINT("CsrWriteConsoleOutputChar\n");
1330 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1331 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1332 sizeof(LPC_MESSAGE);
1334 if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle, (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
1337 return Reply->Status = STATUS_INVALID_HANDLE;
1341 X = Request->Data.WriteConsoleOutputCharRequest.Coord.X + Buff->ShowX;
1342 Y = (Request->Data.WriteConsoleOutputCharRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
1343 Length = Request->Data.WriteConsoleOutputCharRequest.Length;
1344 Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
1347 *Buffer = *String++;
1349 if (++X == Buff->MaxX)
1351 if (++Y == Buff->MaxY)
1354 Buffer = Buff->Buffer;
1359 if( ActiveConsole->ActiveBuffer == Buff )
1361 Status = NtDeviceIoControlFile( ConsoleDeviceHandle,
1366 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
1367 &Request->Data.WriteConsoleOutputCharRequest.Coord,
1368 sizeof (COORD) + Request->Data.WriteConsoleOutputCharRequest.Length,
1371 if( !NT_SUCCESS( Status ) )
1372 DPRINT1( "Failed to write output chars: %x\n", Status );
1374 Reply->Data.WriteConsoleOutputCharReply.EndCoord.X = X - Buff->ShowX;
1375 Reply->Data.WriteConsoleOutputCharReply.EndCoord.Y = (Y + Buff->MaxY - Buff->ShowY) % Buff->MaxY;
1377 return Reply->Status = STATUS_SUCCESS;
1380 CSR_API(CsrFillOutputChar)
1382 PCSRSS_SCREEN_BUFFER Buff;
1385 OUTPUT_CHARACTER Character;
1388 IO_STATUS_BLOCK Iosb;
1390 DPRINT("CsrFillOutputChar\n");
1392 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1393 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1394 sizeof(LPC_MESSAGE);
1397 if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC )
1400 return Reply->Status = STATUS_INVALID_HANDLE;
1402 X = Request->Data.FillOutputRequest.Position.X + Buff->ShowX;
1403 Y = (Request->Data.FillOutputRequest.Position.Y + Buff->ShowY) % Buff->MaxY;
1404 Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
1405 Char = Request->Data.FillOutputRequest.Char;
1406 Length = Request->Data.FillOutputRequest.Length;
1411 if( ++X == Buff->MaxX )
1413 if( ++Y == Buff->MaxY )
1416 Buffer = Buff->Buffer;
1421 if( Buff == ActiveConsole->ActiveBuffer )
1423 Character.dwCoord = Request->Data.FillOutputRequest.Position;
1424 Character.cCharacter = Char;
1425 Character.nLength = Request->Data.FillOutputRequest.Length;
1426 Status = NtDeviceIoControlFile( ConsoleDeviceHandle,
1431 IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER,
1436 if (!NT_SUCCESS(Status))
1437 DPRINT1( "Failed to write output characters to console\n" );
1440 return Reply->Status;
1443 CSR_API(CsrReadInputEvent)
1445 PLIST_ENTRY CurrentEntry;
1446 PCSRSS_CONSOLE Console;
1448 ConsoleInput *Input;
1450 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1451 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1452 sizeof(LPC_MESSAGE);
1453 Reply->Data.ReadInputReply.Event = ProcessData->ConsoleEvent;
1456 Status = CsrGetObject( ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, (Object_t **)&Console );
1457 if( !NT_SUCCESS( Status ) || (Status = Console->Header.Type == CSRSS_CONSOLE_MAGIC ? 0 : STATUS_INVALID_HANDLE))
1459 Reply->Status = Status;
1464 // only get input if there is any
1465 if( Console->InputEvents.Flink != &Console->InputEvents )
1467 CurrentEntry = RemoveHeadList(&Console->InputEvents);
1468 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
1469 Reply->Data.ReadInputReply.Input = Input->InputEvent;
1471 if( Input->InputEvent.EventType == KEY_EVENT )
1473 if( Console->Mode & ENABLE_LINE_INPUT &&
1474 Input->InputEvent.Event.KeyEvent.bKeyDown == FALSE &&
1475 Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
1476 Console->WaitingLines--;
1477 Console->WaitingChars--;
1479 RtlFreeHeap( CsrssApiHeap, 0, Input );
1481 if (Console->InputEvents.Flink != &Console->InputEvents &&
1482 Reply->Data.ReadInputReply.Input.EventType == KEY_EVENT &&
1483 Reply->Data.ReadInputReply.Input.Event.KeyEvent.uChar.AsciiChar == '\r')
1485 Input = CONTAINING_RECORD(Console->InputEvents.Flink, ConsoleInput, ListEntry);
1486 if (Input->InputEvent.EventType == KEY_EVENT &&
1487 Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' &&
1488 ((Input->InputEvent.Event.KeyEvent.bKeyDown && Reply->Data.ReadInputReply.Input.Event.KeyEvent.bKeyDown) ||
1489 (Input->InputEvent.Event.KeyEvent.bKeyDown==FALSE && Reply->Data.ReadInputReply.Input.Event.KeyEvent.bKeyDown==FALSE)))
1491 if(Console->Mode & ENABLE_LINE_INPUT &&
1492 Input->InputEvent.Event.KeyEvent.bKeyDown == FALSE &&
1493 Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
1494 Console->WaitingLines--;
1495 Console->WaitingChars--;
1496 RemoveHeadList(&Console->InputEvents);
1497 RtlFreeHeap( CsrssApiHeap, 0, Input );
1501 Reply->Data.ReadInputReply.MoreEvents = (Console->InputEvents.Flink != &Console->InputEvents) ? TRUE : FALSE;
1502 Status = STATUS_SUCCESS;
1503 Console->EarlyReturn = FALSE; // clear early return
1506 Status = STATUS_PENDING;
1507 Console->EarlyReturn = TRUE; // mark for early return
1510 return Reply->Status = Status;
1513 CSR_API(CsrWriteConsoleOutputAttrib)
1515 PCSRSS_SCREEN_BUFFER Buff;
1516 PUCHAR Buffer, Attribute;
1519 IO_STATUS_BLOCK Iosb;
1521 DPRINT("CsrWriteConsoleOutputAttrib\n");
1523 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1524 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1525 sizeof(LPC_MESSAGE);
1527 Status = CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle, (Object_t **)&Buff );
1528 if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE ))
1530 Reply->Status = Status;
1534 X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X + Buff->ShowX;
1535 Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
1536 Length = Request->Data.WriteConsoleOutputAttribRequest.Length;
1537 Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + 1];
1538 Attribute = Request->Data.WriteConsoleOutputAttribRequest.String;
1541 *Buffer = *Attribute++;
1543 if( ++X == Buff->MaxX )
1546 if( ++Y == Buff->MaxY )
1549 Buffer = Buff->Buffer + 1;
1553 if( Buff == ActiveConsole->ActiveBuffer )
1555 Status = NtDeviceIoControlFile( ConsoleDeviceHandle,
1560 IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE,
1561 &Request->Data.WriteConsoleOutputAttribRequest.Coord,
1562 Request->Data.WriteConsoleOutputAttribRequest.Length +
1566 if( !NT_SUCCESS( Status ) )
1567 DPRINT1( "Failed to write output attributes to console\n" );
1569 Reply->Data.WriteConsoleOutputAttribReply.EndCoord.X = Buff->CurrentX - Buff->ShowX;
1570 Reply->Data.WriteConsoleOutputAttribReply.EndCoord.Y = ( Buff->CurrentY + Buff->MaxY - Buff->ShowY ) % Buff->MaxY;
1572 return Reply->Status = STATUS_SUCCESS;
1575 CSR_API(CsrFillOutputAttrib)
1577 OUTPUT_ATTRIBUTE Attribute;
1578 PCSRSS_SCREEN_BUFFER Buff;
1582 IO_STATUS_BLOCK Iosb;
1585 DPRINT("CsrFillOutputAttrib\n");
1587 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1588 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1589 sizeof(LPC_MESSAGE);
1591 Status = CsrGetObject( ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, (Object_t **)&Buff );
1592 if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE ))
1594 Reply->Status = Status;
1598 X = Request->Data.FillOutputAttribRequest.Coord.X + Buff->ShowX;
1599 Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
1600 Length = Request->Data.FillOutputAttribRequest.Length;
1601 Attr = Request->Data.FillOutputAttribRequest.Attribute;
1602 Buffer = &Buff->Buffer[(Y * Buff->MaxX * 2) + (X * 2) + 1];
1607 if( ++X == Buff->MaxX )
1610 if( ++Y == Buff->MaxY )
1613 Buffer = Buff->Buffer + 1;
1617 if( Buff == ActiveConsole->ActiveBuffer )
1619 Attribute.wAttribute = Attr;
1620 Attribute.nLength = Request->Data.FillOutputAttribRequest.Length;
1621 Attribute.dwCoord = Request->Data.FillOutputAttribRequest.Coord;
1622 Status = NtDeviceIoControlFile( ConsoleDeviceHandle,
1627 IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE,
1629 sizeof(OUTPUT_ATTRIBUTE),
1632 if( !NT_SUCCESS( Status ) )
1633 DPRINT1( "Failed to fill output attributes to console\n" );
1636 return Reply->Status = STATUS_SUCCESS;
1640 CSR_API(CsrGetCursorInfo)
1642 PCSRSS_SCREEN_BUFFER Buff;
1645 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1646 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1647 sizeof(LPC_MESSAGE);
1649 Status = CsrGetObject( ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, (Object_t **)&Buff );
1650 if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE ))
1652 Reply->Status = Status;
1656 Reply->Data.GetCursorInfoReply.Info = Buff->CursorInfo;
1658 return Reply->Status = STATUS_SUCCESS;
1661 CSR_API(CsrSetCursorInfo)
1663 PCSRSS_SCREEN_BUFFER Buff;
1665 IO_STATUS_BLOCK Iosb;
1667 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1668 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1669 sizeof(LPC_MESSAGE);
1671 Status = CsrGetObject( ProcessData,
1672 Request->Data.SetCursorInfoRequest.ConsoleHandle, (Object_t **)&Buff );
1674 if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE ))
1676 Reply->Status = Status;
1680 Buff->CursorInfo = Request->Data.SetCursorInfoRequest.Info;
1681 if( Buff == ActiveConsole->ActiveBuffer )
1683 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_CURSOR_INFO, &Buff->CursorInfo, sizeof( Buff->CursorInfo ), 0, 0 );
1684 if( !NT_SUCCESS( Status ) )
1686 DbgPrint( "CSR: Failed to set cursor info\n" );
1687 return Reply->Status = Status;
1691 return Reply->Status = STATUS_SUCCESS;
1694 CSR_API(CsrSetTextAttrib)
1697 CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
1698 IO_STATUS_BLOCK Iosb;
1699 PCSRSS_SCREEN_BUFFER Buff;
1701 DPRINT("CsrSetTextAttrib\n");
1703 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1704 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
1705 sizeof(LPC_MESSAGE);
1707 Status = CsrGetObject( ProcessData, Request->Data.SetAttribRequest.ConsoleHandle, (Object_t **)&Buff );
1708 if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE ))
1710 Reply->Status = Status;
1714 Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib;
1715 if( Buff == ActiveConsole->ActiveBuffer )
1717 ScrInfo.wAttributes = Buff->DefaultAttrib;
1718 ScrInfo.dwCursorPosition.X = Buff->CurrentX - Buff->ShowX;
1719 ScrInfo.dwCursorPosition.Y = ((Buff->CurrentY + Buff->MaxY) - Buff->ShowY) % Buff->MaxY;
1720 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
1721 if( !NT_SUCCESS( Status ) )
1723 DbgPrint( "CSR: Failed to set console info\n" );
1725 return Reply->Status = Status;
1729 return Reply->Status = STATUS_SUCCESS;
1732 CSR_API(CsrSetConsoleMode)
1735 PCSRSS_CONSOLE Console;
1736 PCSRSS_SCREEN_BUFFER Buff;
1738 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1739 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
1741 Status = CsrGetObject( ProcessData,
1742 Request->Data.SetConsoleModeRequest.ConsoleHandle,
1743 (Object_t **)&Console );
1744 if( !NT_SUCCESS( Status ) )
1746 Reply->Status = Status;
1751 Buff = (PCSRSS_SCREEN_BUFFER)Console;
1752 if( Console->Header.Type == CSRSS_CONSOLE_MAGIC )
1753 Console->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_INPUT_MODE_VALID;
1754 else if( Console->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC )
1755 Buff->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_OUTPUT_MODE_VALID;
1757 Reply->Status = STATUS_INVALID_HANDLE;
1762 Reply->Status = STATUS_SUCCESS;
1763 return Reply->Status;
1766 CSR_API(CsrGetConsoleMode)
1769 PCSRSS_CONSOLE Console;
1770 PCSRSS_SCREEN_BUFFER Buff; /* gee, I really wish I could use an anonymous union here */
1772 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1773 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
1775 Status = CsrGetObject( ProcessData,
1776 Request->Data.GetConsoleModeRequest.ConsoleHandle,
1777 (Object_t **)&Console );
1778 if( !NT_SUCCESS( Status ) )
1780 Reply->Status = Status;
1784 Reply->Status = STATUS_SUCCESS;
1785 Buff = (PCSRSS_SCREEN_BUFFER)Console;
1786 if( Console->Header.Type == CSRSS_CONSOLE_MAGIC )
1787 Reply->Data.GetConsoleModeReply.ConsoleMode = Console->Mode;
1788 else if( Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC )
1789 Reply->Data.GetConsoleModeReply.ConsoleMode = Buff->Mode;
1790 else Status = STATUS_INVALID_HANDLE;
1792 return Reply->Status;
1795 CSR_API(CsrCreateScreenBuffer)
1797 PCSRSS_SCREEN_BUFFER Buff;
1800 Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY );
1801 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
1803 if (ProcessData == NULL)
1805 return(Reply->Status = STATUS_INVALID_PARAMETER);
1808 Buff = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( CSRSS_SCREEN_BUFFER ) );
1810 Reply->Status = STATUS_INSUFFICIENT_RESOURCES;
1812 Status = CsrInitConsoleScreenBuffer( Buff );
1813 if( !NT_SUCCESS( Status ) )
1814 Reply->Status = Status;
1816 Status = CsrInsertObject( ProcessData, &Reply->Data.CreateScreenBufferReply.OutputHandle, &Buff->Header );
1817 if( !NT_SUCCESS( Status ) )
1818 Reply->Status = Status;
1819 else Reply->Status = STATUS_SUCCESS;
1822 return Reply->Status;
1825 CSR_API(CsrSetScreenBuffer)
1828 PCSRSS_SCREEN_BUFFER Buff;
1830 Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY );
1831 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
1833 Status = CsrGetObject( ProcessData, Request->Data.SetActiveScreenBufferRequest.OutputHandle, (Object_t **)&Buff );
1834 if( !NT_SUCCESS( Status ) )
1835 Reply->Status = Status;
1837 // drop reference to old buffer, maybe delete
1838 if( !InterlockedDecrement( &ProcessData->Console->ActiveBuffer->Header.ReferenceCount ) )
1839 CsrDeleteScreenBuffer( ProcessData->Console->ActiveBuffer );
1840 // tie console to new buffer
1841 ProcessData->Console->ActiveBuffer = Buff;
1842 // inc ref count on new buffer
1843 InterlockedIncrement( &Buff->Header.ReferenceCount );
1844 // if the console is active, redraw it
1845 if( ActiveConsole == ProcessData->Console )
1846 CsrDrawConsole( Buff );
1847 Reply->Status = STATUS_SUCCESS;
1850 return Reply->Status;
1853 CSR_API(CsrSetTitle)
1856 PCSRSS_CONSOLE Console;
1858 Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY );
1859 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
1861 Status = CsrGetObject( ProcessData, Request->Data.SetTitleRequest.Console, (Object_t **)&Console );
1862 if( !NT_SUCCESS( Status ) )
1863 Reply->Status = Status;
1865 // copy title to console
1866 RtlFreeUnicodeString( &Console->Title );
1867 RtlCreateUnicodeString( &Console->Title, Request->Data.SetTitleRequest.Title );
1868 Reply->Status = STATUS_SUCCESS;
1871 return Reply->Status;
1874 CSR_API(CsrGetTitle)
1877 PCSRSS_CONSOLE Console;
1879 Reply->Header.MessageSize = sizeof (CSRSS_API_REPLY);
1880 Reply->Header.DataSize =
1881 sizeof (CSRSS_API_REPLY)
1882 - sizeof(LPC_MESSAGE);
1884 Status = CsrGetObject (
1886 Request->Data.GetTitleRequest.ConsoleHandle,
1887 (Object_t **) & Console
1889 if ( !NT_SUCCESS( Status ) )
1891 Reply->Status = Status;
1895 HANDLE ConsoleHandle = Request->Data.GetTitleRequest.ConsoleHandle;
1897 /* Copy title of the console to the user title buffer */
1899 & Reply->Data.GetTitleReply,
1900 sizeof (CSRSS_GET_TITLE_REPLY)
1902 Reply->Data.GetTitleReply.ConsoleHandle = ConsoleHandle;
1903 Reply->Data.GetTitleReply.Length = Console->Title.Length;
1904 wcscpy (Reply->Data.GetTitleReply.Title, Console->Title.Buffer);
1905 Reply->Header.MessageSize += Console->Title.Length;
1906 Reply->Header.DataSize += Console->Title.Length;
1907 Reply->Status = STATUS_SUCCESS;
1910 return Reply->Status;
1913 CSR_API(CsrWriteConsoleOutput)
1915 SHORT i, X, Y, SizeX, SizeY;
1916 PCSRSS_SCREEN_BUFFER Buff;
1917 SMALL_RECT ScreenBuffer;
1918 CHAR_INFO* CurCharInfo;
1919 SMALL_RECT WriteRegion;
1920 CHAR_INFO* CharInfo;
1927 DPRINT("CsrWriteConsoleOutput\n");
1929 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1930 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
1932 Status = CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputRequest.ConsoleHandle, (Object_t **)&Buff );
1933 if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE ))
1935 Reply->Status = Status;
1940 BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize;
1941 PSize = BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO);
1942 BufferCoord = Request->Data.WriteConsoleOutputRequest.BufferCoord;
1943 CharInfo = Request->Data.WriteConsoleOutputRequest.CharInfo;
1944 if (((PVOID)CharInfo < ProcessData->CsrSectionViewBase) ||
1945 (((PVOID)CharInfo + PSize) >
1946 (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
1949 Reply->Status = STATUS_ACCESS_VIOLATION;
1950 return(Reply->Status);
1952 WriteRegion = Request->Data.WriteConsoleOutputRequest.WriteRegion;
1954 SizeY = RtlMin(BufferSize.Y - BufferCoord.Y, CsrpRectHeight(WriteRegion));
1955 SizeX = RtlMin(BufferSize.X - BufferCoord.X, CsrpRectWidth(WriteRegion));
1956 WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
1957 WriteRegion.Right = WriteRegion.Left + SizeX - 1;
1959 /* Make sure WriteRegion is inside the screen buffer */
1960 CsrpInitRect(ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
1961 if (!CsrpGetIntersection(&WriteRegion, ScreenBuffer, WriteRegion))
1964 /* It is okay to have a WriteRegion completely outside the screen buffer.
1965 No data is written then. */
1966 return (Reply->Status = STATUS_SUCCESS);
1969 for ( i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++ )
1971 CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
1972 Offset = (((Y + Buff->ShowY) % Buff->MaxY) * Buff->MaxX + WriteRegion.Left) * 2;
1973 for ( X = WriteRegion.Left; X <= WriteRegion.Right; X++ )
1975 SET_CELL_BUFFER(Buff, Offset, CurCharInfo->Char.AsciiChar, CurCharInfo->Attributes);
1980 if( Buff == ActiveConsole->ActiveBuffer )
1982 CsrpDrawRegion( ActiveConsole->ActiveBuffer, WriteRegion );
1986 Reply->Data.WriteConsoleOutputReply.WriteRegion.Right = WriteRegion.Left + SizeX - 1;
1987 Reply->Data.WriteConsoleOutputReply.WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
1988 Reply->Data.WriteConsoleOutputReply.WriteRegion.Left = WriteRegion.Left;
1989 Reply->Data.WriteConsoleOutputReply.WriteRegion.Top = WriteRegion.Top;
1990 return (Reply->Status = STATUS_SUCCESS);
1993 CSR_API(CsrFlushInputBuffer)
1995 PLIST_ENTRY CurrentEntry;
1996 PLIST_ENTRY NextEntry;
1997 PCSRSS_CONSOLE Console;
1998 ConsoleInput* Input;
2001 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2002 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
2004 Status = CsrGetObject( ProcessData, Request->Data.FlushInputBufferRequest.ConsoleInput, (Object_t **)&Console );
2005 if( !NT_SUCCESS( Status ) || (Status = Console->Header.Type == CSRSS_CONSOLE_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE ))
2007 Reply->Status = Status;
2012 /* Discard all entries in the input event queue */
2013 while (!IsListEmpty(&Console->InputEvents))
2015 CurrentEntry = RemoveHeadList(&Console->InputEvents);
2016 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
2017 /* Destroy the event */
2018 RtlFreeHeap( CsrssApiHeap, 0, Input );
2020 Console->WaitingChars=0;
2023 return (Reply->Status = STATUS_SUCCESS);
2026 CSR_API(CsrScrollConsoleScreenBuffer)
2028 SHORT i, X, Y, SizeX, SizeY;
2029 PCSRSS_SCREEN_BUFFER Buff;
2030 SMALL_RECT ScreenBuffer;
2031 SMALL_RECT SrcRegion;
2032 SMALL_RECT DstRegion;
2033 SMALL_RECT FillRegion;
2034 IO_STATUS_BLOCK Iosb;
2035 CHAR_INFO* CharInfo;
2041 ALIAS(ConsoleHandle,Request->Data.ScrollConsoleScreenBufferRequest.ConsoleHandle);
2042 ALIAS(ScrollRectangle,Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle);
2043 ALIAS(UseClipRectangle,Request->Data.ScrollConsoleScreenBufferRequest.UseClipRectangle);
2044 ALIAS(ClipRectangle,Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle);
2045 ALIAS(DestinationOrigin,Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin);
2046 ALIAS(Fill,Request->Data.ScrollConsoleScreenBufferRequest.Fill);
2048 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2049 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
2051 Status = CsrGetObject( ProcessData, ConsoleHandle, (Object_t **)&Buff );
2052 if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE ))
2054 Reply->Status = Status;
2059 /* Make sure source rectangle is inside the screen buffer */
2060 CsrpInitRect(ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
2061 if (!CsrpGetIntersection(&SrcRegion, ScreenBuffer, ScrollRectangle))
2064 return (Reply->Status = STATUS_INVALID_PARAMETER);
2067 if (UseClipRectangle)
2069 if (!CsrpGetIntersection(&SrcRegion, SrcRegion, ClipRectangle))
2072 return (Reply->Status = STATUS_SUCCESS);
2079 DestinationOrigin.Y,
2080 DestinationOrigin.X,
2081 DestinationOrigin.Y + CsrpRectHeight(ScrollRectangle) - 1,
2082 DestinationOrigin.X + CsrpRectWidth(ScrollRectangle) - 1)
2084 /* Make sure destination rectangle is inside the screen buffer */
2085 if (!CsrpGetIntersection(&DstRegion, DstRegion, ScreenBuffer))
2088 return (Reply->Status = STATUS_INVALID_PARAMETER);
2091 CsrpCopyRegion(Buff, SrcRegion, DstRegion);
2094 /* Get the region that should be filled with the specified character and attributes */
2098 CsrpGetUnion(&FillRegion, SrcRegion, DstRegion);
2100 if (CsrpSubtractRect(&FillRegion, FillRegion, DstRegion))
2102 /* FIXME: The subtracted rectangle is off by one line */
2103 FillRegion.Top += 1;
2105 CsrpFillRegion(Buff, FillRegion, Fill);
2109 if (Buff == ActiveConsole->ActiveBuffer)
2111 /* Draw destination region */
2112 CsrpDrawRegion(ActiveConsole->ActiveBuffer, DstRegion);
2116 /* Draw filled region */
2117 CsrpDrawRegion(ActiveConsole->ActiveBuffer, FillRegion);
2122 return(Reply->Status = STATUS_SUCCESS);
2126 CSR_API(CsrReadConsoleOutputChar)
2129 PCSRSS_SCREEN_BUFFER ScreenBuffer;
2134 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2135 Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE);
2136 ReadBuffer = Reply->Data.ReadConsoleOutputCharReply.String;
2140 Status = CsrGetObject(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, (Object_t**)&ScreenBuffer);
2141 if (!NT_SUCCESS(Status))
2143 Reply->Status = Status;
2145 return(Reply->Status);
2148 if (ScreenBuffer->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC)
2150 Reply->Status = STATUS_INVALID_HANDLE;
2152 return(Reply->Status);
2155 Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X + ScreenBuffer->ShowX;
2156 Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
2158 for (i = 0; i < Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; ++i)
2160 *ReadBuffer = ScreenBuffer->Buffer[(Xpos * 2) + (Ypos * 2 * ScreenBuffer->MaxX)];
2165 if (Xpos == ScreenBuffer->MaxX)
2170 if (Ypos == ScreenBuffer->MaxY)
2177 Reply->Status = STATUS_SUCCESS;
2178 Reply->Data.ReadConsoleOutputCharReply.EndCoord.X = Xpos - ScreenBuffer->ShowX;
2179 Reply->Data.ReadConsoleOutputCharReply.EndCoord.Y = (Ypos - ScreenBuffer->ShowY + ScreenBuffer->MaxY) % ScreenBuffer->MaxY;
2180 Reply->Header.MessageSize += Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead;
2181 Reply->Header.DataSize += Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead;
2185 return(Reply->Status);
2189 CSR_API(CsrReadConsoleOutputAttrib)
2192 PCSRSS_SCREEN_BUFFER ScreenBuffer;
2197 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2198 Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE);
2199 ReadBuffer = Reply->Data.ReadConsoleOutputAttribReply.String;
2203 Status = CsrGetObject(ProcessData, Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle, (Object_t**)&ScreenBuffer);
2204 if (!NT_SUCCESS(Status))
2206 Reply->Status = Status;
2208 return(Reply->Status);
2211 if (ScreenBuffer->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC)
2213 Reply->Status = STATUS_INVALID_HANDLE;
2215 return(Reply->Status);
2218 Xpos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.X + ScreenBuffer->ShowX;
2219 Ypos = (Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.Y + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
2221 for (i = 0; i < Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; ++i)
2223 *ReadBuffer = ScreenBuffer->Buffer[(Xpos * 2) + (Ypos * 2 * ScreenBuffer->MaxX) + 1];
2228 if (Xpos == ScreenBuffer->MaxX)
2233 if (Ypos == ScreenBuffer->MaxY)
2240 Reply->Status = STATUS_SUCCESS;
2241 Reply->Data.ReadConsoleOutputAttribReply.EndCoord.X = Xpos - ScreenBuffer->ShowX;
2242 Reply->Data.ReadConsoleOutputAttribReply.EndCoord.Y = (Ypos - ScreenBuffer->ShowY + ScreenBuffer->MaxY) % ScreenBuffer->MaxY;
2243 Reply->Header.MessageSize += Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead;
2244 Reply->Header.DataSize += Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead;
2248 return(Reply->Status);
2252 CSR_API(CsrGetNumberOfConsoleInputEvents)
2255 PCSRSS_CONSOLE Console;
2256 PLIST_ENTRY CurrentItem;
2259 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2260 Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE);
2264 Status = CsrGetObject(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, (Object_t**)&Console);
2265 if (!NT_SUCCESS(Status))
2267 Reply->Status = Status;
2269 return(Reply->Status);
2272 if (Console->Header.Type != CSRSS_CONSOLE_MAGIC)
2274 Reply->Status = STATUS_INVALID_HANDLE;
2276 return(Reply->Status);
2279 CurrentItem = &Console->InputEvents;
2282 // If there are any events ...
2283 if(CurrentItem->Flink != CurrentItem)
2287 CurrentItem = CurrentItem->Flink;
2289 }while(CurrentItem != &Console->InputEvents);
2294 Reply->Status = STATUS_SUCCESS;
2295 Reply->Data.GetNumInputEventsReply.NumInputEvents = NumEvents;
2297 return Reply->Status;
2301 CSR_API(CsrPeekConsoleInput)
2304 PCSRSS_CONSOLE Console;
2307 PLIST_ENTRY CurrentItem;
2308 PLIST_ENTRY NextItem;
2309 PINPUT_RECORD InputRecord;
2313 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2314 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
2318 Status = CsrGetObject(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, (Object_t**)&Console);
2319 if(!NT_SUCCESS(Status))
2321 Reply->Status = Status;
2323 return Reply->Status;
2326 if(Console->Header.Type != CSRSS_CONSOLE_MAGIC)
2328 Reply->Status = STATUS_INVALID_HANDLE;
2330 return Reply->Status;
2333 InputRecord = Request->Data.PeekConsoleInputRequest.InputRecord;
2334 Length = Request->Data.PeekConsoleInputRequest.Length;
2335 Size = Length * sizeof(INPUT_RECORD);
2337 if(((PVOID)InputRecord < ProcessData->CsrSectionViewBase)
2338 || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
2341 Reply->Status = STATUS_ACCESS_VIOLATION;
2342 return Reply->Status ;
2347 if(!IsListEmpty(&Console->InputEvents))
2349 CurrentItem = &Console->InputEvents;
2351 while(NumItems < Length)
2354 Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
2355 *InputRecord++ = Item->InputEvent;
2357 if(CurrentItem->Flink == &Console->InputEvents)
2360 CurrentItem = CurrentItem->Flink;
2366 Reply->Status = STATUS_SUCCESS;
2367 Reply->Data.PeekConsoleInputReply.Length = NumItems;
2368 return Reply->Status;
2372 CSR_API(CsrReadConsoleOutput)
2374 PCHAR_INFO CharInfo;
2375 PCHAR_INFO CurCharInfo;
2376 PCSRSS_SCREEN_BUFFER ScreenBuffer;
2383 SMALL_RECT ReadRegion;
2384 SMALL_RECT ScreenRect;
2385 DWORD i, Y, X, Offset;
2387 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2388 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
2392 Status = CsrGetObject(ProcessData, Request->Data.ReadConsoleOutputRequest.ConsoleHandle, (Object_t**)&ScreenBuffer);
2393 if(!NT_SUCCESS(Status))
2395 Reply->Status = Status;
2397 return Reply->Status;
2400 if(ScreenBuffer->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC)
2402 Reply->Status = STATUS_INVALID_HANDLE;
2404 return Reply->Status;
2407 CharInfo = Request->Data.ReadConsoleOutputRequest.CharInfo;
2408 ReadRegion = Request->Data.ReadConsoleOutputRequest.ReadRegion;
2409 BufferSize = Request->Data.ReadConsoleOutputRequest.BufferSize;
2410 BufferCoord = Request->Data.ReadConsoleOutputRequest.BufferCoord;
2411 Length = BufferSize.X * BufferSize.Y;
2412 Size = Length * sizeof(CHAR_INFO);
2414 if(((PVOID)CharInfo < ProcessData->CsrSectionViewBase)
2415 || (((PVOID)CharInfo + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
2418 Reply->Status = STATUS_ACCESS_VIOLATION;
2419 return Reply->Status ;
2422 SizeY = RtlMin(BufferSize.Y - BufferCoord.Y, CsrpRectHeight(ReadRegion));
2423 SizeX = RtlMin(BufferSize.X - BufferCoord.X, CsrpRectWidth(ReadRegion));
2424 ReadRegion.Bottom = ReadRegion.Top + SizeY;
2425 ReadRegion.Right = ReadRegion.Left + SizeX;
2427 CsrpInitRect(ScreenRect, 0, 0, ScreenBuffer->MaxY - 1, ScreenBuffer->MaxX - 1);
2428 if (!CsrpGetIntersection(&ReadRegion, ScreenRect, ReadRegion))
2431 Reply->Status = STATUS_SUCCESS;
2432 return Reply->Status;
2435 for(i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y)
2437 CurCharInfo = CharInfo + (i * BufferSize.X);
2439 Offset = (((Y + ScreenBuffer->ShowY) % ScreenBuffer->MaxY) * ScreenBuffer->MaxX + ReadRegion.Left) * 2;
2440 for(X = ReadRegion.Left; X < ReadRegion.Right; ++X)
2442 CurCharInfo->Char.AsciiChar = GET_CELL_BUFFER(ScreenBuffer, Offset);
2443 CurCharInfo->Attributes = GET_CELL_BUFFER(ScreenBuffer, Offset);
2450 Reply->Status = STATUS_SUCCESS;
2451 Reply->Data.ReadConsoleOutputReply.ReadRegion.Right = ReadRegion.Left + SizeX - 1;
2452 Reply->Data.ReadConsoleOutputReply.ReadRegion.Bottom = ReadRegion.Top + SizeY - 1;
2453 Reply->Data.ReadConsoleOutputReply.ReadRegion.Left = ReadRegion.Left;
2454 Reply->Data.ReadConsoleOutputReply.ReadRegion.Top = ReadRegion.Top;
2456 return Reply->Status;
2460 CSR_API(CsrWriteConsoleInput)
2462 PINPUT_RECORD InputRecord;
2463 PCSRSS_CONSOLE Console;
2468 PLIST_ENTRY NextItem;
2469 ConsoleInput* Record;
2471 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2472 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
2476 Status = CsrGetObject(ProcessData, Request->Data.WriteConsoleInputRequest.ConsoleHandle, (Object_t**)&Console);
2477 if(!NT_SUCCESS(Status))
2479 Reply->Status = Status;
2481 return Reply->Status;
2484 if(Console->Header.Type != CSRSS_CONSOLE_MAGIC)
2486 Reply->Status = STATUS_INVALID_HANDLE;
2488 return Reply->Status;
2491 InputRecord = Request->Data.WriteConsoleInputRequest.InputRecord;
2492 Length = Request->Data.WriteConsoleInputRequest.Length;
2493 Size = Length * sizeof(INPUT_RECORD);
2495 if(((PVOID)InputRecord < ProcessData->CsrSectionViewBase)
2496 || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
2499 Reply->Status = STATUS_ACCESS_VIOLATION;
2500 return Reply->Status ;
2503 for(i = 0; i < Length; ++i)
2505 Record = RtlAllocateHeap(CsrssApiHeap, 0, sizeof(ConsoleInput));
2509 Reply->Status = STATUS_INSUFFICIENT_RESOURCES;
2510 return Reply->Status;
2513 Record->InputEvent = *InputRecord++;
2514 InsertTailList(&Console->InputEvents, &Record->ListEntry);
2519 Reply->Status = STATUS_SUCCESS;
2520 Reply->Data.WriteConsoleInputReply.Length = i;
2521 return Reply->Status;
2524 /**********************************************************************
2525 * HardwareStateProperty
2528 * Set/Get the value of the HardwareState and switch
2529 * between direct video buffer ouput and GDI windowed
2532 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2533 * object. We use the same object to reply.
2535 * ConsoleHwState has the correct size to be compatible
2536 * with NT's, but values are not.
2538 static NTSTATUS FASTCALL SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
2540 DbgPrint( "Console Hardware State: %d\n", ConsoleHwState );
2542 if ( (CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
2543 ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
2545 /* Inhibit keyboard input when hardware state ==
2546 * CONSOLE_HARDWARE_STATE_GDI_MANAGED */
2547 if (CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState) {
2548 DbgPrint( "Keyboard Inhibited.\n" );
2549 KeyReadInhibit = TRUE;
2551 DbgPrint( "Keyboard Enabled.\n" );
2552 KeyReadInhibit = FALSE;
2554 if (Console->HardwareState != ConsoleHwState)
2556 /* TODO: implement switching from full screen to windowed mode */
2557 /* TODO: or back; now simply store the hardware state */
2558 Console->HardwareState = ConsoleHwState;
2560 return STATUS_SUCCESS;
2562 return STATUS_INVALID_PARAMETER_3; // Client: (handle, set_get, [mode])
2565 CSR_API(CsrHardwareStateProperty)
2567 PCSRSS_CONSOLE Console;
2570 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2571 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
2575 Status = CsrGetObject (
2577 Request->Data.ConsoleHardwareStateRequest.ConsoleHandle,
2578 (Object_t**) & Console
2580 if (!NT_SUCCESS(Status))
2582 DbgPrint( "Failed to get console handle in SetConsoleHardwareState\n" );
2583 Reply->Status = Status;
2587 if(Console->Header.Type != CSRSS_CONSOLE_MAGIC)
2589 DbgPrint( "Bad magic on Console: %08x\n", Console->Header.Type );
2590 Reply->Status = STATUS_INVALID_HANDLE;
2594 switch (Request->Data.ConsoleHardwareStateRequest.SetGet)
2596 case CONSOLE_HARDWARE_STATE_GET:
2597 Reply->Data.ConsoleHardwareStateReply.State = Console->HardwareState;
2600 case CONSOLE_HARDWARE_STATE_SET:
2601 DbgPrint( "Setting console hardware state.\n" );
2602 Reply->Status = SetConsoleHardwareState (Console, Request->Data.ConsoleHardwareStateRequest.State);
2606 Reply->Status = STATUS_INVALID_PARAMETER_2; // Client: (handle, [set_get], mode)
2614 return Reply->Status;
2617 CSR_API(CsrGetConsoleWindow)
2619 PCSRSS_CONSOLE Console;
2622 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
2623 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE);
2627 Status = CsrGetObject (
2629 Request->Data.ConsoleWindowRequest.ConsoleHandle,
2630 (Object_t**) & Console
2632 if (!NT_SUCCESS(Status))
2634 Reply->Status = Status;
2638 if(Console->Header.Type != CSRSS_CONSOLE_MAGIC)
2640 Reply->Status = STATUS_INVALID_HANDLE;
2644 // Is this GDI handle valid in the client's context?
2645 Reply->Data.ConsoleWindowReply.WindowHandle = Console->hWindow;
2651 return Reply->Status;