1 /* $Id: conio.c,v 1.48 2003/06/19 19:38:26 ea Exp $
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
29 /* GLOBALS *******************************************************************/
31 static HANDLE ConsoleDeviceHandle
;
32 static HANDLE KeyboardDeviceHandle
;
33 static PCSRSS_CONSOLE ActiveConsole
;
34 CRITICAL_SECTION ActiveConsoleLock
;
35 static COORD PhysicalConsoleSize
;
37 /* FUNCTIONS *****************************************************************/
39 CSR_API(CsrAllocConsole
)
41 PCSRSS_CONSOLE Console
;
46 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
47 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
50 if (ProcessData
== NULL
)
52 return(Reply
->Status
= STATUS_INVALID_PARAMETER
);
55 if( ProcessData
->Console
)
57 Reply
->Status
= STATUS_INVALID_PARAMETER
;
58 return STATUS_INVALID_PARAMETER
;
60 Reply
->Status
= STATUS_SUCCESS
;
61 Console
= RtlAllocateHeap( CsrssApiHeap
, 0, sizeof( CSRSS_CONSOLE
) );
64 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
65 return STATUS_INSUFFICIENT_RESOURCES
;
67 Reply
->Status
= CsrInitConsole( Console
);
68 if( !NT_SUCCESS( Reply
->Status
) )
70 RtlFreeHeap( CsrssApiHeap
, 0, Console
);
73 ProcessData
->Console
= Console
;
74 /* add a reference count because the process is tied to the console */
75 Console
->Header
.ReferenceCount
++;
76 Status
= CsrInsertObject( ProcessData
, &Reply
->Data
.AllocConsoleReply
.InputHandle
, &Console
->Header
);
77 if( !NT_SUCCESS( Status
) )
79 CsrDeleteConsole( Console
);
80 ProcessData
->Console
= 0;
81 return Reply
->Status
= Status
;
83 Status
= CsrInsertObject( ProcessData
, &Reply
->Data
.AllocConsoleReply
.OutputHandle
, &Console
->ActiveBuffer
->Header
);
84 if( !NT_SUCCESS( Status
) )
86 Console
->Header
.ReferenceCount
--;
87 CsrReleaseObject( ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
88 ProcessData
->Console
= 0;
89 return Reply
->Status
= Status
;
91 ClientId
.UniqueProcess
= (HANDLE
)ProcessData
->ProcessId
;
92 Status
= NtOpenProcess( &Process
, PROCESS_DUP_HANDLE
, 0, &ClientId
);
93 if( !NT_SUCCESS( Status
) )
95 DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" );
96 Console
->Header
.ReferenceCount
--;
97 ProcessData
->Console
= 0;
98 CsrReleaseObject( ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
99 CsrReleaseObject( ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
100 Reply
->Status
= Status
;
103 Status
= NtDuplicateObject( NtCurrentProcess(), ProcessData
->Console
->ActiveEvent
, Process
, &ProcessData
->ConsoleEvent
, SYNCHRONIZE
, FALSE
, 0 );
104 if( !NT_SUCCESS( Status
) )
106 DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status
);
108 Console
->Header
.ReferenceCount
--;
109 CsrReleaseObject( ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
110 CsrReleaseObject( ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
111 ProcessData
->Console
= 0;
112 Reply
->Status
= Status
;
116 return STATUS_SUCCESS
;
119 CSR_API(CsrFreeConsole
)
121 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
122 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
125 if (ProcessData
== NULL
)
127 return(Reply
->Status
= STATUS_INVALID_PARAMETER
);
130 Reply
->Status
= STATUS_NOT_IMPLEMENTED
;
132 return(STATUS_NOT_IMPLEMENTED
);
135 CSR_API(CsrReadConsole
)
137 PLIST_ENTRY CurrentEntry
;
141 ULONG nNumberOfCharsToRead
;
142 PCSRSS_CONSOLE Console
;
145 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
146 nNumberOfCharsToRead
= Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
> CSRSS_MAX_READ_CONSOLE_REQUEST
? CSRSS_MAX_READ_CONSOLE_REQUEST
: Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
;
147 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
148 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
-
151 Buffer
= Reply
->Data
.ReadConsoleReply
.Buffer
;
153 Status
= CsrGetObject( ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
, (Object_t
**)&Console
);
154 if( !NT_SUCCESS( Status
) )
156 Reply
->Status
= Status
;
160 if( Console
->Header
.Type
!= CSRSS_CONSOLE_MAGIC
)
162 Reply
->Status
= STATUS_INVALID_HANDLE
;
164 return STATUS_INVALID_HANDLE
;
166 Reply
->Data
.ReadConsoleReply
.EventHandle
= ProcessData
->ConsoleEvent
;
167 for (; i
<nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++ )
169 // remove input event from queue
170 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
171 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
173 // only pay attention to valid ascii chars, on key down
174 if( Input
->InputEvent
.EventType
== KEY_EVENT
&&
175 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
&&
176 Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
178 // backspace handling
179 if( Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\b' )
181 // echo if it has not already been done, and either we or the client has chars to be deleted
182 if( !Input
->Echoed
&& ( i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
) )
183 CsrpWriteConsole( Console
->ActiveBuffer
, &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
185 i
-=2; // if we already have something to return, just back it up by 2
187 { // otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer
188 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= 0;
189 Reply
->Status
= STATUS_NOTIFY_CLEANUP
;
190 Console
->WaitingChars
--;
191 RtlFreeHeap( CsrssApiHeap
, 0, Input
);
193 return STATUS_NOTIFY_CLEANUP
;
195 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
196 Input
->Echoed
= TRUE
; // mark as echoed so we don't echo it below
198 // do not copy backspace to buffer
199 else Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
200 // echo to screen if enabled and we did not already echo the char
201 if( Console
->Mode
& ENABLE_ECHO_INPUT
&&
203 Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\r' )
204 CsrpWriteConsole( Console
->ActiveBuffer
, &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
207 Console
->WaitingChars
--;
208 RtlFreeHeap( CsrssApiHeap
, 0, Input
);
210 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= i
;
212 Reply
->Status
= STATUS_PENDING
; // we didn't read anything
213 else if( Console
->Mode
& ENABLE_LINE_INPUT
)
214 if( !Console
->WaitingLines
|| Buffer
[i
-1] != '\n' )
216 Reply
->Status
= STATUS_PENDING
; // line buffered, didn't get a complete line
219 Console
->WaitingLines
--;
220 Reply
->Status
= STATUS_SUCCESS
; // line buffered, did get a complete line
222 else Reply
->Status
= STATUS_SUCCESS
; // not line buffered, did read something
223 if( Reply
->Status
== STATUS_PENDING
)
225 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
228 Console
->EchoCount
= 0; // if the client is no longer waiting on input, do not echo
230 Reply
->Header
.MessageSize
+= i
;
232 return Reply
->Status
;
235 #define GET_CELL_BUFFER(b,o)\
238 #define SET_CELL_BUFFER(b,o,c,a)\
239 (b)->Buffer[(o)++]=(c);\
240 (b)->Buffer[(o)++]=(a);
244 PCSRSS_SCREEN_BUFFER Buff
,
248 DWORD Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + StartX
);
250 for ( ; StartX
< Buff
->MaxX
; StartX
++ )
252 /* Fill the cell: Offset is incremented by the macro */
253 SET_CELL_BUFFER(Buff
,Offset
,' ',Buff
->DefaultAttrib
)
257 NTSTATUS STDCALL
CsrpWriteConsole( PCSRSS_SCREEN_BUFFER Buff
, CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
259 IO_STATUS_BLOCK Iosb
;
264 for( i
= 0; i
< Length
; i
++ )
266 switch( Buffer
[ i
] )
271 /* slide the viewable screen */
272 if (((Buff
->CurrentY
-Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == PhysicalConsoleSize
.Y
- 1)
273 if (++Buff
->ShowY
== Buff
->MaxY
)
275 if( ++Buff
->CurrentY
== Buff
->MaxY
)
279 ClearLineBuffer (Buff
, 0);
283 if( Buff
->CurrentX
== 0 )
285 /* slide viewable screen up */
286 if( Buff
->ShowY
== Buff
->CurrentY
)
288 if( Buff
->ShowY
== 0 )
289 Buff
->ShowY
= Buff
->MaxY
;
293 /* slide virtual position up */
294 Buff
->CurrentX
= Buff
->MaxX
;
295 if( Buff
->CurrentY
== 0 )
296 Buff
->CurrentY
= Buff
->MaxY
;
302 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
303 SET_CELL_BUFFER(Buff
,Offset
,' ',Buff
->DefaultAttrib
);
311 CsrpWriteConsole(Buff
, " ", (8 - (Buff
->CurrentX
% 8)), FALSE
);
315 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
316 Buff
->Buffer
[Offset
++] = Buffer
[ i
];
318 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
320 if( Buff
->CurrentX
== Buff
->MaxX
)
322 /* if end of line, go to next */
324 if( ++Buff
->CurrentY
== Buff
->MaxY
)
326 /* if end of buffer, wrap back to beginning */
330 ClearLineBuffer (Buff
, 0);
331 /* slide the viewable screen */
332 if( (Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
- 1) % Buff
->MaxY
== PhysicalConsoleSize
.Y
-1)
333 if( ++Buff
->ShowY
== Buff
->MaxY
)
338 if( Buff
== ActiveConsole
->ActiveBuffer
)
339 { /* only write to screen if Console is Active, and not scrolled up */
342 Status
= NtWriteFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, Buffer
, Length
, NULL
, 0);
343 if (!NT_SUCCESS(Status
))
344 DbgPrint("CSR: Write failed\n");
347 return(STATUS_SUCCESS
);
350 #define CsrpInitRect(_Rect, _Top, _Left, _Bottom, _Right) \
352 ((_Rect).Top) = _Top; \
353 ((_Rect).Left) = _Left; \
354 ((_Rect).Bottom) = _Bottom; \
355 ((_Rect).Right) = _Right; \
358 #define CsrpRectHeight(Rect) \
359 ((Rect.Top) > (Rect.Bottom) ? 0 : (Rect.Bottom) - (Rect.Top) + 1)
361 #define CsrpRectWidth(Rect) \
362 ((Rect.Left) > (Rect.Right) ? 0 : (Rect.Right) - (Rect.Left) + 1)
364 #define CsrpIsRectEmpty(Rect) \
365 ((Rect.Left > Rect.Right) || (Rect.Top > Rect.Bottom))
368 inline BOOLEAN
CsrpIsEqualRect(
372 return ((Rect1
.Left
== Rect2
.Left
) && (Rect1
.Right
== Rect2
.Right
) &&
373 (Rect1
.Top
== Rect2
.Top
) && (Rect1
.Bottom
== Rect2
.Bottom
));
376 inline BOOLEAN
CsrpGetIntersection(
377 PSMALL_RECT Intersection
,
381 if (CsrpIsRectEmpty(Rect1
) ||
382 (CsrpIsRectEmpty(Rect2
)) ||
383 (Rect1
.Top
> Rect2
.Bottom
) ||
384 (Rect1
.Left
> Rect2
.Right
) ||
385 (Rect1
.Bottom
< Rect2
.Top
) ||
386 (Rect1
.Right
< Rect2
.Left
))
388 /* The rectangles do not intersect */
389 CsrpInitRect(*Intersection
, 0, -1, 0, -1)
395 RtlMax(Rect1
.Top
, Rect2
.Top
),
396 RtlMax(Rect1
.Left
, Rect2
.Left
),
397 RtlMin(Rect1
.Bottom
, Rect2
.Bottom
),
398 RtlMin(Rect1
.Right
, Rect2
.Right
));
402 inline BOOLEAN
CsrpGetUnion(
407 if (CsrpIsRectEmpty(Rect1
))
409 if (CsrpIsRectEmpty(Rect2
))
411 CsrpInitRect(*Union
, 0, -1, 0, -1);
419 if (CsrpIsRectEmpty(Rect2
))
427 RtlMin(Rect1
.Top
, Rect2
.Top
),
428 RtlMin(Rect1
.Left
, Rect2
.Left
),
429 RtlMax(Rect1
.Bottom
, Rect2
.Bottom
),
430 RtlMax(Rect1
.Right
, Rect2
.Right
));
436 inline BOOLEAN
CsrpSubtractRect(
437 PSMALL_RECT Subtraction
,
443 if (CsrpIsRectEmpty(Rect1
))
445 CsrpInitRect(*Subtraction
, 0, -1, 0, -1);
448 *Subtraction
= Rect1
;
449 if (CsrpGetIntersection(&tmp
, Rect1
, Rect2
))
451 if (CsrpIsEqualRect(tmp
, *Subtraction
))
453 CsrpInitRect(*Subtraction
, 0, -1, 0, -1);
456 if ((tmp
.Top
== Subtraction
->Top
) && (tmp
.Bottom
== Subtraction
->Bottom
))
458 if (tmp
.Left
== Subtraction
->Left
)
459 Subtraction
->Left
= tmp
.Right
;
460 else if (tmp
.Right
== Subtraction
->Right
)
461 Subtraction
->Right
= tmp
.Left
;
463 else if ((tmp
.Left
== Subtraction
->Left
) && (tmp
.Right
== Subtraction
->Right
))
465 if (tmp
.Top
== Subtraction
->Top
)
466 Subtraction
->Top
= tmp
.Bottom
;
467 else if (tmp
.Bottom
== Subtraction
->Bottom
)
468 Subtraction
->Bottom
= tmp
.Top
;
475 * Screen buffer must be locked when this function is called
477 static VOID
CsrpCopyRegion(
478 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
479 SMALL_RECT SrcRegion
,
480 SMALL_RECT DstRegion
)
488 DstY
= DstRegion
.Top
;
489 BytesPerLine
= CsrpRectWidth(DstRegion
) * 2;
491 SrcY
= (SrcRegion
.Top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
492 DstY
= (DstRegion
.Top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
493 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
.Left
+ ScreenBuffer
->ShowX
) * 2;
494 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
.Left
+ ScreenBuffer
->ShowX
) * 2;
496 for (i
= SrcRegion
.Top
; i
<= SrcRegion
.Bottom
; i
++)
499 &ScreenBuffer
->Buffer
[DstOffset
],
500 &ScreenBuffer
->Buffer
[SrcOffset
],
503 if (++DstY
== ScreenBuffer
->MaxY
)
506 DstOffset
= (DstRegion
.Left
+ ScreenBuffer
->ShowX
) * 2;
510 DstOffset
+= ScreenBuffer
->MaxX
* 2;
513 if (++SrcY
== ScreenBuffer
->MaxY
)
516 SrcOffset
= (SrcRegion
.Left
+ ScreenBuffer
->ShowX
) * 2;
520 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
526 * Screen buffer must be locked when this function is called
528 static VOID
CsrpFillRegion(
529 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
538 Y
= (Region
.Top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
539 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
.Left
+ ScreenBuffer
->ShowX
) * 2;
540 Delta
= (ScreenBuffer
->MaxX
- CsrpRectWidth(Region
)) * 2;
542 for (i
= Region
.Top
; i
<= Region
.Bottom
; i
++)
544 for (X
= Region
.Left
; X
<= Region
.Right
; X
++)
546 SET_CELL_BUFFER(ScreenBuffer
, Offset
, CharInfo
.Char
.AsciiChar
, CharInfo
.Attributes
);
548 if (++Y
== ScreenBuffer
->MaxY
)
551 Offset
= (Region
.Left
+ ScreenBuffer
->ShowX
) * 2;
561 * Screen buffer must be locked when this function is called
563 inline NTSTATUS
CsrpSetConsoleDeviceCursor(PCSRSS_SCREEN_BUFFER ScreenBuffer
, SHORT X
, SHORT Y
)
565 CONSOLE_SCREEN_BUFFER_INFO ScrInfo
;
566 IO_STATUS_BLOCK Iosb
;
568 ScrInfo
.dwCursorPosition
.X
= X
;
569 ScrInfo
.dwCursorPosition
.Y
= Y
;
570 ScrInfo
.wAttributes
= ScreenBuffer
->DefaultAttrib
;
572 return NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
,
573 IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
, &ScrInfo
, sizeof( ScrInfo
), 0, 0 );
577 * Region - Region of virtual screen buffer to draw onto the physical console
578 * Screen buffer must be locked when this function is called
580 static VOID
CsrpDrawRegion(
581 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
584 IO_STATUS_BLOCK Iosb
;
586 CONSOLE_SCREEN_BUFFER_INFO ScrInfo
;
593 Mode
.dwMode
= 0; /* clear ENABLE_PROCESSED_OUTPUT mode */
594 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
,
595 IOCTL_CONSOLE_SET_MODE
, &Mode
, sizeof( Mode
), 0, 0 );
596 if( !NT_SUCCESS( Status
) )
598 DbgPrint( "CSR: Failed to set console mode\n" );
602 /* blast out buffer */
603 BytesPerLine
= CsrpRectWidth(Region
) * 2;
604 SrcOffset
= (((Region
.Top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
) * ScreenBuffer
->MaxX
+ Region
.Left
+ ScreenBuffer
->ShowX
) * 2;
605 SrcDelta
= ScreenBuffer
->MaxX
* 2;
606 for( i
= Region
.Top
, y
= ScreenBuffer
->ShowY
; i
<= Region
.Bottom
; i
++ )
608 /* Position the cursor correctly */
609 Status
= CsrpSetConsoleDeviceCursor(ScreenBuffer
, Region
.Left
, i
);
610 if( !NT_SUCCESS( Status
) )
612 DbgPrint( "CSR: Failed to set console info\n" );
616 Status
= NtWriteFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
,
617 &ScreenBuffer
->Buffer
[ SrcOffset
],
618 BytesPerLine
, 0, 0 );
619 if( !NT_SUCCESS( Status
) )
621 DbgPrint( "CSR: Write to console failed\n" );
625 /* wrap back around the end of the buffer */
626 if( ++y
== ScreenBuffer
->MaxY
)
629 SrcOffset
= (Region
.Left
+ ScreenBuffer
->ShowX
) * 2;
633 SrcOffset
+= SrcDelta
;
636 Mode
.dwMode
= ENABLE_PROCESSED_OUTPUT
;
637 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
,
638 IOCTL_CONSOLE_SET_MODE
, &Mode
, sizeof( Mode
), 0, 0 );
639 if( !NT_SUCCESS( Status
) )
641 DbgPrint( "CSR: Failed to set console mode\n" );
644 Status
= CsrpSetConsoleDeviceCursor(
646 ScreenBuffer
->CurrentX
- ScreenBuffer
->ShowX
,
647 ((ScreenBuffer
->CurrentY
+ ScreenBuffer
->MaxY
) - ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
);
648 if( !NT_SUCCESS( Status
) )
650 DbgPrint( "CSR: Failed to set console info\n" );
653 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
,
654 IOCTL_CONSOLE_SET_CURSOR_INFO
, &ScreenBuffer
->CursorInfo
,
655 sizeof( ScreenBuffer
->CursorInfo
), 0, 0 );
656 if( !NT_SUCCESS( Status
) )
658 DbgPrint( "CSR: Failed to set cursor info\n" );
664 CSR_API(CsrWriteConsole
)
666 BYTE
*Buffer
= Request
->Data
.WriteConsoleRequest
.Buffer
;
667 PCSRSS_SCREEN_BUFFER Buff
;
669 DPRINT("CsrWriteConsole\n");
671 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
672 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
676 if( !NT_SUCCESS( CsrGetObject( ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
,
677 (Object_t
**)&Buff
) ) || Buff
->Header
.Type
!= CSRSS_SCREEN_BUFFER_MAGIC
)
680 return Reply
->Status
= STATUS_INVALID_HANDLE
;
682 CsrpWriteConsole( Buff
, Buffer
, Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
684 return Reply
->Status
= STATUS_SUCCESS
;
688 NTSTATUS STDCALL
CsrInitConsoleScreenBuffer( PCSRSS_SCREEN_BUFFER Console
)
690 Console
->Header
.Type
= CSRSS_SCREEN_BUFFER_MAGIC
;
691 Console
->Header
.ReferenceCount
= 0;
692 Console
->MaxX
= PhysicalConsoleSize
.X
;
693 Console
->MaxY
= PhysicalConsoleSize
.Y
;
696 Console
->CurrentX
= 0;
697 Console
->CurrentY
= 0;
698 Console
->Buffer
= RtlAllocateHeap( CsrssApiHeap
, 0, Console
->MaxX
* Console
->MaxY
* 2 );
699 if( Console
->Buffer
== 0 )
700 return STATUS_INSUFFICIENT_RESOURCES
;
701 Console
->DefaultAttrib
= 0x17;
702 /* initialize buffer to be empty with default attributes */
703 for( ; Console
->CurrentY
< Console
->MaxY
; Console
->CurrentY
++ )
705 ClearLineBuffer (Console
, 0);
707 Console
->CursorInfo
.bVisible
= TRUE
;
708 Console
->CursorInfo
.dwSize
= 5;
709 Console
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
710 Console
->CurrentX
= 0;
711 Console
->CurrentY
= 0;
712 return STATUS_SUCCESS
;
715 VOID STDCALL
CsrDeleteScreenBuffer( PCSRSS_SCREEN_BUFFER Buffer
)
717 RtlFreeHeap( CsrssApiHeap
, 0, Buffer
->Buffer
);
718 RtlFreeHeap( CsrssApiHeap
, 0, Buffer
);
721 NTSTATUS STDCALL
CsrInitConsole(PCSRSS_CONSOLE Console
)
724 OBJECT_ATTRIBUTES ObjectAttributes
;
726 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
727 Console
->Title
.Buffer
= 0;
729 RtlCreateUnicodeString( &Console
->Title
, L
"Command Prompt" );
731 Console
->Header
.ReferenceCount
= 0;
732 Console
->WaitingChars
= 0;
733 Console
->WaitingLines
= 0;
734 Console
->EchoCount
= 0;
735 Console
->Header
.Type
= CSRSS_CONSOLE_MAGIC
;
736 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
737 Console
->EarlyReturn
= FALSE
;
738 InitializeListHead(&Console
->InputEvents
);
740 InitializeObjectAttributes(&ObjectAttributes
, NULL
, OBJ_INHERIT
, NULL
, NULL
);
742 Status
= NtCreateEvent( &Console
->ActiveEvent
, STANDARD_RIGHTS_ALL
, &ObjectAttributes
, FALSE
, FALSE
);
743 if( !NT_SUCCESS( Status
) )
747 Console
->ActiveBuffer
= RtlAllocateHeap( CsrssApiHeap
, 0, sizeof( CSRSS_SCREEN_BUFFER
) );
748 if( !Console
->ActiveBuffer
)
750 NtClose( Console
->ActiveEvent
);
751 return STATUS_INSUFFICIENT_RESOURCES
;
753 Status
= CsrInitConsoleScreenBuffer( Console
->ActiveBuffer
);
754 if( !NT_SUCCESS( Status
) )
756 NtClose( Console
->ActiveEvent
);
757 RtlFreeHeap( CsrssApiHeap
, 0, Console
->ActiveBuffer
);
760 /* Create the GDI Window to be used in windowed mode */
761 /* FIXME: create window; now write NULL */
762 Console
->hWindow
= (HWND
) NULL
;
763 /* add a reference count because the buffer is tied to the console */
764 Console
->ActiveBuffer
->Header
.ReferenceCount
++;
765 /* make console active, and insert into console list */
769 Console
->Prev
= ActiveConsole
;
770 Console
->Next
= ActiveConsole
->Next
;
771 ActiveConsole
->Next
->Prev
= Console
;
772 ActiveConsole
->Next
= Console
;
775 Console
->Prev
= Console
;
776 Console
->Next
= Console
;
778 ActiveConsole
= Console
;
779 /* copy buffer contents to screen */
780 CsrDrawConsole( Console
->ActiveBuffer
);
782 return STATUS_SUCCESS
;
785 /***************************************************************
786 * CsrDrawConsole blasts the console buffer onto the screen *
787 * must be called while holding the active console lock *
788 **************************************************************/
789 VOID STDCALL
CsrDrawConsole( PCSRSS_SCREEN_BUFFER Buff
)
797 PhysicalConsoleSize
.Y
- 1,
798 PhysicalConsoleSize
.X
- 1);
800 CsrpDrawRegion(Buff
, Region
);
804 VOID STDCALL
CsrDeleteConsole( PCSRSS_CONSOLE Console
)
807 DPRINT( "CsrDeleteConsole\n" );
809 /* Drain input event queue */
810 while( Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
812 Event
= (ConsoleInput
*)Console
->InputEvents
.Flink
;
813 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
814 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
815 RtlFreeHeap( CsrssApiHeap
, 0, Event
);
817 /* Switch to next console */
818 if( ActiveConsole
== Console
)
820 if( Console
->Next
!= Console
)
822 ActiveConsole
= Console
->Next
;
824 else ActiveConsole
= 0;
826 if (Console
->Next
!= Console
)
828 Console
->Prev
->Next
= Console
->Next
;
829 Console
->Next
->Prev
= Console
->Prev
;
833 CsrDrawConsole( ActiveConsole
->ActiveBuffer
);
834 if( !--Console
->ActiveBuffer
->Header
.ReferenceCount
)
835 CsrDeleteScreenBuffer( Console
->ActiveBuffer
);
837 NtClose( Console
->ActiveEvent
);
838 RtlFreeUnicodeString( &Console
->Title
);
839 RtlFreeHeap( CsrssApiHeap
, 0, Console
);
842 VOID STDCALL
CsrInitConsoleSupport(VOID
)
844 OBJECT_ATTRIBUTES ObjectAttributes
;
845 UNICODE_STRING DeviceName
;
847 IO_STATUS_BLOCK Iosb
;
848 CONSOLE_SCREEN_BUFFER_INFO ScrInfo
;
850 DPRINT("CSR: CsrInitConsoleSupport()\n");
852 RtlInitUnicodeStringFromLiteral(&DeviceName
, L
"\\??\\BlueScreen");
853 InitializeObjectAttributes(&ObjectAttributes
,
858 Status
= NtOpenFile(&ConsoleDeviceHandle
,
863 FILE_SYNCHRONOUS_IO_ALERT
);
864 if (!NT_SUCCESS(Status
))
866 DbgPrint("CSR: Failed to open console. Expect problems.\n");
869 RtlInitUnicodeStringFromLiteral(&DeviceName
, L
"\\??\\Keyboard");
870 InitializeObjectAttributes(&ObjectAttributes
,
875 Status
= NtOpenFile(&KeyboardDeviceHandle
,
881 if (!NT_SUCCESS(Status
))
883 DbgPrint("CSR: Failed to open keyboard. Expect problems.\n");
887 RtlInitializeCriticalSection( &ActiveConsoleLock
);
888 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
, 0, 0, &ScrInfo
, sizeof( ScrInfo
) );
889 if( !NT_SUCCESS( Status
) )
891 DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
894 PhysicalConsoleSize
= ScrInfo
.dwSize
;
897 VOID
Console_Api( DWORD RefreshEvent
)
899 /* keep reading events from the keyboard and stuffing them into the current
900 console's input queue */
901 ConsoleInput
*KeyEventRecord
;
902 ConsoleInput
*TempInput
;
903 IO_STATUS_BLOCK Iosb
;
905 HANDLE Events
[2]; // 0 = keyboard, 1 = refresh
908 PCSRSS_CONSOLE SwapConsole
= 0; // console we are thinking about swapping with
911 Status
= NtCreateEvent( &Events
[0], STANDARD_RIGHTS_ALL
, NULL
, FALSE
, FALSE
);
912 if( !NT_SUCCESS( Status
) )
914 DbgPrint( "CSR: NtCreateEvent failed: %x\n", Status
);
915 NtTerminateProcess( NtCurrentProcess(), Status
);
917 Events
[1] = (HANDLE
)RefreshEvent
;
920 KeyEventRecord
= RtlAllocateHeap(CsrssApiHeap
,
922 sizeof(ConsoleInput
));
923 if ( KeyEventRecord
== 0 )
925 DbgPrint( "CSR: Memory allocation failure!" );
928 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
929 Status
= NtReadFile( KeyboardDeviceHandle
, Events
[0], NULL
, NULL
, &Iosb
,
930 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
, sizeof( KEY_EVENT_RECORD
), NULL
, 0 );
931 if( !NT_SUCCESS( Status
) )
933 DbgPrint( "CSR: ReadFile on keyboard device failed\n" );
934 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
937 if( Status
== STATUS_PENDING
)
941 Status
= NtWaitForMultipleObjects( 2, Events
, WaitAny
, FALSE
, NULL
);
942 if( Status
== STATUS_WAIT_0
+ 1 )
945 CsrDrawConsole( ActiveConsole
->ActiveBuffer
);
949 else if( Status
!= STATUS_WAIT_0
)
951 DbgPrint( "CSR: NtWaitForMultipleObjects failed: %x, exiting\n", Status
);
952 NtTerminateProcess( NtCurrentProcess(), Status
);
957 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
&
958 ( RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
)&&
959 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_TAB
)
960 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
)
966 /* alt-tab, swap consoles */
967 // move SwapConsole to next console, and print its title
970 SwapConsole
= ActiveConsole
;
972 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
)
973 SwapConsole
= SwapConsole
->Prev
;
974 else SwapConsole
= SwapConsole
->Next
;
975 Title
.MaximumLength
= RtlUnicodeStringToAnsiSize( &SwapConsole
->Title
);
977 Buffer
= RtlAllocateHeap( CsrssApiHeap
,
979 sizeof( COORD
) + Title
.MaximumLength
);
980 pos
= (COORD
*)Buffer
;
981 Title
.Buffer
= Buffer
+ sizeof( COORD
);
983 RtlUnicodeStringToAnsiString(&Title
, &SwapConsole
->Title
, FALSE
);
984 pos
->Y
= PhysicalConsoleSize
.Y
/ 2;
985 pos
->X
= ( PhysicalConsoleSize
.X
- Title
.Length
) / 2;
986 // redraw the console to clear off old title
987 CsrDrawConsole( ActiveConsole
->ActiveBuffer
);
988 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
,
993 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
,
995 sizeof (COORD
) + Title
.Length
,
998 if( !NT_SUCCESS( Status
) )
1000 DPRINT1( "Error writing to console\n" );
1002 RtlFreeHeap( CsrssApiHeap
, 0, Buffer
);
1005 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
1009 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
1012 else if( SwapConsole
&&
1013 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_MENU
&&
1014 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== FALSE
)
1016 // alt key released, swap consoles
1020 if( SwapConsole
!= ActiveConsole
)
1022 // first remove swapconsole from the list
1023 SwapConsole
->Prev
->Next
= SwapConsole
->Next
;
1024 SwapConsole
->Next
->Prev
= SwapConsole
->Prev
;
1025 // now insert before activeconsole
1026 SwapConsole
->Next
= ActiveConsole
;
1027 SwapConsole
->Prev
= ActiveConsole
->Prev
;
1028 ActiveConsole
->Prev
->Next
= SwapConsole
;
1029 ActiveConsole
->Prev
= SwapConsole
;
1031 ActiveConsole
= SwapConsole
;
1033 CsrDrawConsole( ActiveConsole
->ActiveBuffer
);
1037 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
&
1038 ( RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
) &&
1039 ( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
||
1040 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
) )
1042 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
)
1044 /* scroll up or down */
1046 if( ActiveConsole
== 0 )
1048 DbgPrint( "CSR: No Active Console!\n" );
1050 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
1053 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)
1055 /* only scroll up if there is room to scroll up into */
1056 if( ActiveConsole
->ActiveBuffer
->ShowY
!= ((ActiveConsole
->ActiveBuffer
->CurrentY
+ 1) %
1057 ActiveConsole
->ActiveBuffer
->MaxY
) )
1058 ActiveConsole
->ActiveBuffer
->ShowY
= (ActiveConsole
->ActiveBuffer
->ShowY
+
1059 ActiveConsole
->ActiveBuffer
->MaxY
- 1) % ActiveConsole
->ActiveBuffer
->MaxY
;
1061 else if( ActiveConsole
->ActiveBuffer
->ShowY
!= ActiveConsole
->ActiveBuffer
->CurrentY
)
1062 /* only scroll down if there is room to scroll down into */
1063 if( ActiveConsole
->ActiveBuffer
->ShowY
% ActiveConsole
->ActiveBuffer
->MaxY
!=
1064 ActiveConsole
->ActiveBuffer
->CurrentY
)
1066 if( ((ActiveConsole
->ActiveBuffer
->CurrentY
+ 1) % ActiveConsole
->ActiveBuffer
->MaxY
) !=
1067 (ActiveConsole
->ActiveBuffer
->ShowY
+ PhysicalConsoleSize
.Y
) % ActiveConsole
->ActiveBuffer
->MaxY
)
1068 ActiveConsole
->ActiveBuffer
->ShowY
= (ActiveConsole
->ActiveBuffer
->ShowY
+ 1) %
1069 ActiveConsole
->ActiveBuffer
->MaxY
;
1070 CsrDrawConsole( ActiveConsole
->ActiveBuffer
);
1073 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
1077 if( ActiveConsole
== 0 )
1079 DbgPrint( "CSR: No Active Console!\n" );
1081 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
1084 // process special keys if enabled
1085 if( ActiveConsole
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
) )
1086 switch( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1089 // add a \n to the queue as well
1091 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1092 KeyEventRecord
->Echoed
= FALSE
;
1093 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1094 InsertTailList(&ActiveConsole
->InputEvents
, &KeyEventRecord
->ListEntry
);
1095 ActiveConsole
->WaitingChars
++;
1096 KeyEventRecord
= RtlAllocateHeap( CsrssApiHeap
, 0, sizeof( ConsoleInput
) );
1097 if( !KeyEventRecord
)
1099 DbgPrint( "CSR: Failed to allocate KeyEventRecord\n" );
1103 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1104 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1105 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1106 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1107 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1109 // add event to the queue
1110 InsertTailList(&ActiveConsole
->InputEvents
, &KeyEventRecord
->ListEntry
);
1111 // if line input mode is enabled, only wake the client on enter key down
1112 if( !(ActiveConsole
->Mode
& ENABLE_LINE_INPUT
) ||
1113 ActiveConsole
->EarlyReturn
||
1114 ( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\n' &&
1115 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
) )
1117 NtSetEvent( ActiveConsole
->ActiveEvent
, 0 );
1118 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\n' )
1119 ActiveConsole
->WaitingLines
++;
1121 KeyEventRecord
->Echoed
= FALSE
;
1122 if( ActiveConsole
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
) &&
1123 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\b' &&
1124 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1126 // walk the input queue looking for a char to backspace
1127 for( TempInput
= (ConsoleInput
*)ActiveConsole
->InputEvents
.Blink
;
1128 TempInput
!= (ConsoleInput
*)&ActiveConsole
->InputEvents
&&
1129 (TempInput
->InputEvent
.EventType
!= KEY_EVENT
||
1130 TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
== FALSE
||
1131 TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\b' );
1132 TempInput
= (ConsoleInput
*)TempInput
->ListEntry
.Blink
);
1133 // if we found one, delete it, otherwise, wake the client
1134 if( TempInput
!= (ConsoleInput
*)&ActiveConsole
->InputEvents
)
1136 // delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue
1137 RemoveEntryList(&TempInput
->ListEntry
);
1138 if( TempInput
->Echoed
)
1139 CsrpWriteConsole( ActiveConsole
->ActiveBuffer
, &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
1140 RtlFreeHeap( CsrssApiHeap
, 0, TempInput
);
1141 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1142 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
1143 ActiveConsole
->WaitingChars
-= 2;
1145 else NtSetEvent( ActiveConsole
->ActiveEvent
, 0 );
1148 // echo chars if we are supposed to and client is waiting for some
1149 if( ( ActiveConsole
->Mode
& ENABLE_ECHO_INPUT
) && ActiveConsole
->EchoCount
&&
1150 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&&
1151 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
&&
1152 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\r' )
1154 // mark the char as already echoed
1155 CsrpWriteConsole( ActiveConsole
->ActiveBuffer
, &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
1156 ActiveConsole
->EchoCount
--;
1157 KeyEventRecord
->Echoed
= TRUE
;
1160 ActiveConsole
->WaitingChars
++;
1161 if( !(ActiveConsole
->Mode
& ENABLE_LINE_INPUT
) )
1162 NtSetEvent( ActiveConsole
->ActiveEvent
, 0 );
1167 CSR_API(CsrGetScreenBufferInfo
)
1170 PCSRSS_SCREEN_BUFFER Buff
;
1171 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1172 IO_STATUS_BLOCK Iosb
;
1174 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1175 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1176 sizeof(LPC_MESSAGE
);
1179 if( !NT_SUCCESS( CsrGetObject( ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
,
1180 (Object_t
**)&Buff
) ) || Buff
->Header
.Type
!= CSRSS_SCREEN_BUFFER_MAGIC
)
1183 return Reply
->Status
= STATUS_INVALID_HANDLE
;
1185 pInfo
= &Reply
->Data
.ScreenBufferInfoReply
.Info
;
1186 if( Buff
== ActiveConsole
->ActiveBuffer
)
1188 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
,
1189 IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
, 0, 0, pInfo
, sizeof( *pInfo
) );
1190 if( !NT_SUCCESS( Status
) )
1191 DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
1192 Reply
->Status
= Status
;
1195 pInfo
->dwSize
.X
= PhysicalConsoleSize
.X
;
1196 pInfo
->dwSize
.Y
= PhysicalConsoleSize
.Y
;
1197 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1198 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1199 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1200 pInfo
->srWindow
.Left
= 0;
1201 pInfo
->srWindow
.Right
= PhysicalConsoleSize
.X
- 1;
1202 pInfo
->srWindow
.Top
= 0;
1203 pInfo
->srWindow
.Bottom
= PhysicalConsoleSize
.Y
- 1;
1204 Reply
->Status
= STATUS_SUCCESS
;
1207 return Reply
->Status
;
1210 CSR_API(CsrSetCursor
)
1213 PCSRSS_SCREEN_BUFFER Buff
;
1214 CONSOLE_SCREEN_BUFFER_INFO Info
;
1215 IO_STATUS_BLOCK Iosb
;
1217 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1218 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1219 sizeof(LPC_MESSAGE
);
1222 if( !NT_SUCCESS( CsrGetObject( ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
,
1223 (Object_t
**)&Buff
) ) || Buff
->Header
.Type
!= CSRSS_SCREEN_BUFFER_MAGIC
)
1226 return Reply
->Status
= STATUS_INVALID_HANDLE
;
1228 Info
.dwCursorPosition
= Request
->Data
.SetCursorRequest
.Position
;
1229 Info
.wAttributes
= Buff
->DefaultAttrib
;
1230 if( Buff
== ActiveConsole
->ActiveBuffer
)
1232 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
,
1233 IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
, &Info
, sizeof( Info
), 0, 0 );
1234 if( !NT_SUCCESS( Status
) )
1235 DbgPrint( "CSR: Failed to set console info, expect trouble\n" );
1238 Buff
->CurrentX
= Info
.dwCursorPosition
.X
+ Buff
->ShowX
;
1239 Buff
->CurrentY
= (Info
.dwCursorPosition
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1241 return Reply
->Status
= Status
;
1244 CSR_API(CsrWriteConsoleOutputChar
)
1246 PBYTE String
= Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1248 PCSRSS_SCREEN_BUFFER Buff
;
1251 IO_STATUS_BLOCK Iosb
;
1253 DPRINT("CsrWriteConsoleOutputChar\n");
1255 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1256 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1257 sizeof(LPC_MESSAGE
);
1259 if( !NT_SUCCESS( CsrGetObject( ProcessData
, Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
, (Object_t
**)&Buff
) ) || Buff
->Header
.Type
!= CSRSS_SCREEN_BUFFER_MAGIC
)
1262 return Reply
->Status
= STATUS_INVALID_HANDLE
;
1266 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1267 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1268 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1269 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1272 *Buffer
= *String
++;
1274 if (++X
== Buff
->MaxX
)
1276 if (++Y
== Buff
->MaxY
)
1279 Buffer
= Buff
->Buffer
;
1284 if( ActiveConsole
->ActiveBuffer
== Buff
)
1286 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
,
1291 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
,
1292 &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1293 sizeof (COORD
) + Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1296 if( !NT_SUCCESS( Status
) )
1297 DPRINT1( "Failed to write output chars: %x\n", Status
);
1299 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.X
= X
- Buff
->ShowX
;
1300 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1302 return Reply
->Status
= STATUS_SUCCESS
;
1305 CSR_API(CsrFillOutputChar
)
1307 PCSRSS_SCREEN_BUFFER Buff
;
1310 OUTPUT_CHARACTER Character
;
1313 IO_STATUS_BLOCK Iosb
;
1315 DPRINT("CsrFillOutputChar\n");
1317 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1318 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1319 sizeof(LPC_MESSAGE
);
1322 if( !NT_SUCCESS( CsrGetObject( ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, (Object_t
**)&Buff
) ) || Buff
->Header
.Type
!= CSRSS_SCREEN_BUFFER_MAGIC
)
1325 return Reply
->Status
= STATUS_INVALID_HANDLE
;
1327 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1328 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1329 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1330 Char
= Request
->Data
.FillOutputRequest
.Char
;
1331 Length
= Request
->Data
.FillOutputRequest
.Length
;
1336 if( ++X
== Buff
->MaxX
)
1338 if( ++Y
== Buff
->MaxY
)
1341 Buffer
= Buff
->Buffer
;
1346 if( Buff
== ActiveConsole
->ActiveBuffer
)
1348 Character
.dwCoord
= Request
->Data
.FillOutputRequest
.Position
;
1349 Character
.cCharacter
= Char
;
1350 Character
.nLength
= Request
->Data
.FillOutputRequest
.Length
;
1351 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
,
1356 IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER
,
1361 if (!NT_SUCCESS(Status
))
1362 DPRINT1( "Failed to write output characters to console\n" );
1365 return Reply
->Status
;
1368 CSR_API(CsrReadInputEvent
)
1370 PLIST_ENTRY CurrentEntry
;
1371 PCSRSS_CONSOLE Console
;
1373 ConsoleInput
*Input
;
1375 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1376 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1377 sizeof(LPC_MESSAGE
);
1378 Reply
->Data
.ReadInputReply
.Event
= ProcessData
->ConsoleEvent
;
1381 Status
= CsrGetObject( ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, (Object_t
**)&Console
);
1382 if( !NT_SUCCESS( Status
) || (Status
= Console
->Header
.Type
== CSRSS_CONSOLE_MAGIC
? 0 : STATUS_INVALID_HANDLE
))
1384 Reply
->Status
= Status
;
1389 // only get input if there is any
1390 if( Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
1392 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
1393 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1394 Reply
->Data
.ReadInputReply
.Input
= Input
->InputEvent
;
1396 if( Input
->InputEvent
.EventType
== KEY_EVENT
)
1398 if( Console
->Mode
& ENABLE_LINE_INPUT
&&
1399 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
== FALSE
&&
1400 Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\n' )
1401 Console
->WaitingLines
--;
1402 Console
->WaitingChars
--;
1404 RtlFreeHeap( CsrssApiHeap
, 0, Input
);
1406 if (Console
->InputEvents
.Flink
!= &Console
->InputEvents
&&
1407 Reply
->Data
.ReadInputReply
.Input
.EventType
== KEY_EVENT
&&
1408 Reply
->Data
.ReadInputReply
.Input
.Event
.KeyEvent
.uChar
.AsciiChar
== '\r')
1410 Input
= CONTAINING_RECORD(Console
->InputEvents
.Flink
, ConsoleInput
, ListEntry
);
1411 if (Input
->InputEvent
.EventType
== KEY_EVENT
&&
1412 Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\n' &&
1413 ((Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
&& Reply
->Data
.ReadInputReply
.Input
.Event
.KeyEvent
.bKeyDown
) ||
1414 (Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
==FALSE
&& Reply
->Data
.ReadInputReply
.Input
.Event
.KeyEvent
.bKeyDown
==FALSE
)))
1416 if(Console
->Mode
& ENABLE_LINE_INPUT
&&
1417 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
== FALSE
&&
1418 Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\n' )
1419 Console
->WaitingLines
--;
1420 Console
->WaitingChars
--;
1421 RemoveHeadList(&Console
->InputEvents
);
1422 RtlFreeHeap( CsrssApiHeap
, 0, Input
);
1426 Reply
->Data
.ReadInputReply
.MoreEvents
= (Console
->InputEvents
.Flink
!= &Console
->InputEvents
) ? TRUE
: FALSE
;
1427 Status
= STATUS_SUCCESS
;
1428 Console
->EarlyReturn
= FALSE
; // clear early return
1431 Status
= STATUS_PENDING
;
1432 Console
->EarlyReturn
= TRUE
; // mark for early return
1435 return Reply
->Status
= Status
;
1438 CSR_API(CsrWriteConsoleOutputAttrib
)
1440 PCSRSS_SCREEN_BUFFER Buff
;
1441 PUCHAR Buffer
, Attribute
;
1444 IO_STATUS_BLOCK Iosb
;
1446 DPRINT("CsrWriteConsoleOutputAttrib\n");
1448 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1449 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1450 sizeof(LPC_MESSAGE
);
1452 Status
= CsrGetObject( ProcessData
, Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
, (Object_t
**)&Buff
);
1453 if( !NT_SUCCESS( Status
) || (Status
= Buff
->Header
.Type
== CSRSS_SCREEN_BUFFER_MAGIC
? 0 : STATUS_INVALID_HANDLE
))
1455 Reply
->Status
= Status
;
1459 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1460 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1461 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1462 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1463 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1466 *Buffer
= *Attribute
++;
1468 if( ++X
== Buff
->MaxX
)
1471 if( ++Y
== Buff
->MaxY
)
1474 Buffer
= Buff
->Buffer
+ 1;
1478 if( Buff
== ActiveConsole
->ActiveBuffer
)
1480 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
,
1485 IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE
,
1486 &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1487 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
+
1491 if( !NT_SUCCESS( Status
) )
1492 DPRINT1( "Failed to write output attributes to console\n" );
1494 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1495 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.Y
= ( Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1497 return Reply
->Status
= STATUS_SUCCESS
;
1500 CSR_API(CsrFillOutputAttrib
)
1502 OUTPUT_ATTRIBUTE Attribute
;
1503 PCSRSS_SCREEN_BUFFER Buff
;
1507 IO_STATUS_BLOCK Iosb
;
1510 DPRINT("CsrFillOutputAttrib\n");
1512 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1513 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1514 sizeof(LPC_MESSAGE
);
1516 Status
= CsrGetObject( ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, (Object_t
**)&Buff
);
1517 if( !NT_SUCCESS( Status
) || (Status
= Buff
->Header
.Type
== CSRSS_SCREEN_BUFFER_MAGIC
? 0 : STATUS_INVALID_HANDLE
))
1519 Reply
->Status
= Status
;
1523 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1524 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1525 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1526 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1527 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1532 if( ++X
== Buff
->MaxX
)
1535 if( ++Y
== Buff
->MaxY
)
1538 Buffer
= Buff
->Buffer
+ 1;
1542 if( Buff
== ActiveConsole
->ActiveBuffer
)
1544 Attribute
.wAttribute
= Attr
;
1545 Attribute
.nLength
= Request
->Data
.FillOutputAttribRequest
.Length
;
1546 Attribute
.dwCoord
= Request
->Data
.FillOutputAttribRequest
.Coord
;
1547 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
,
1552 IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE
,
1554 sizeof(OUTPUT_ATTRIBUTE
),
1557 if( !NT_SUCCESS( Status
) )
1558 DPRINT1( "Failed to fill output attributes to console\n" );
1561 return Reply
->Status
= STATUS_SUCCESS
;
1565 CSR_API(CsrGetCursorInfo
)
1567 PCSRSS_SCREEN_BUFFER Buff
;
1570 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1571 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1572 sizeof(LPC_MESSAGE
);
1574 Status
= CsrGetObject( ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, (Object_t
**)&Buff
);
1575 if( !NT_SUCCESS( Status
) || (Status
= Buff
->Header
.Type
== CSRSS_SCREEN_BUFFER_MAGIC
? 0 : STATUS_INVALID_HANDLE
))
1577 Reply
->Status
= Status
;
1581 Reply
->Data
.GetCursorInfoReply
.Info
= Buff
->CursorInfo
;
1583 return Reply
->Status
= STATUS_SUCCESS
;
1586 CSR_API(CsrSetCursorInfo
)
1588 PCSRSS_SCREEN_BUFFER Buff
;
1590 IO_STATUS_BLOCK Iosb
;
1592 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1593 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1594 sizeof(LPC_MESSAGE
);
1596 Status
= CsrGetObject( ProcessData
,
1597 Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, (Object_t
**)&Buff
);
1599 if( !NT_SUCCESS( Status
) || (Status
= Buff
->Header
.Type
== CSRSS_SCREEN_BUFFER_MAGIC
? 0 : STATUS_INVALID_HANDLE
))
1601 Reply
->Status
= Status
;
1605 Buff
->CursorInfo
= Request
->Data
.SetCursorInfoRequest
.Info
;
1606 if( Buff
== ActiveConsole
->ActiveBuffer
)
1608 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_CURSOR_INFO
, &Buff
->CursorInfo
, sizeof( Buff
->CursorInfo
), 0, 0 );
1609 if( !NT_SUCCESS( Status
) )
1611 DbgPrint( "CSR: Failed to set cursor info\n" );
1612 return Reply
->Status
= Status
;
1616 return Reply
->Status
= STATUS_SUCCESS
;
1619 CSR_API(CsrSetTextAttrib
)
1622 CONSOLE_SCREEN_BUFFER_INFO ScrInfo
;
1623 IO_STATUS_BLOCK Iosb
;
1624 PCSRSS_SCREEN_BUFFER Buff
;
1626 DPRINT("CsrSetTextAttrib\n");
1628 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1629 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1630 sizeof(LPC_MESSAGE
);
1632 Status
= CsrGetObject( ProcessData
, Request
->Data
.SetAttribRequest
.ConsoleHandle
, (Object_t
**)&Buff
);
1633 if( !NT_SUCCESS( Status
) || (Status
= Buff
->Header
.Type
== CSRSS_SCREEN_BUFFER_MAGIC
? 0 : STATUS_INVALID_HANDLE
))
1635 Reply
->Status
= Status
;
1639 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1640 if( Buff
== ActiveConsole
->ActiveBuffer
)
1642 ScrInfo
.wAttributes
= Buff
->DefaultAttrib
;
1643 ScrInfo
.dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1644 ScrInfo
.dwCursorPosition
.Y
= ((Buff
->CurrentY
+ Buff
->MaxY
) - Buff
->ShowY
) % Buff
->MaxY
;
1645 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
, &ScrInfo
, sizeof( ScrInfo
), 0, 0 );
1646 if( !NT_SUCCESS( Status
) )
1648 DbgPrint( "CSR: Failed to set console info\n" );
1650 return Reply
->Status
= Status
;
1654 return Reply
->Status
= STATUS_SUCCESS
;
1657 CSR_API(CsrSetConsoleMode
)
1660 PCSRSS_CONSOLE Console
;
1661 PCSRSS_SCREEN_BUFFER Buff
;
1663 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1664 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1666 Status
= CsrGetObject( ProcessData
,
1667 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
1668 (Object_t
**)&Console
);
1669 if( !NT_SUCCESS( Status
) )
1671 Reply
->Status
= Status
;
1676 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1677 if( Console
->Header
.Type
== CSRSS_CONSOLE_MAGIC
)
1678 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
1679 else if( Console
->Header
.Type
== CSRSS_SCREEN_BUFFER_MAGIC
)
1680 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
1682 Reply
->Status
= STATUS_INVALID_HANDLE
;
1687 Reply
->Status
= STATUS_SUCCESS
;
1688 return Reply
->Status
;
1691 CSR_API(CsrGetConsoleMode
)
1694 PCSRSS_CONSOLE Console
;
1695 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
1697 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1698 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1700 Status
= CsrGetObject( ProcessData
,
1701 Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
1702 (Object_t
**)&Console
);
1703 if( !NT_SUCCESS( Status
) )
1705 Reply
->Status
= Status
;
1709 Reply
->Status
= STATUS_SUCCESS
;
1710 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1711 if( Console
->Header
.Type
== CSRSS_CONSOLE_MAGIC
)
1712 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Console
->Mode
;
1713 else if( Buff
->Header
.Type
== CSRSS_SCREEN_BUFFER_MAGIC
)
1714 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Buff
->Mode
;
1715 else Status
= STATUS_INVALID_HANDLE
;
1717 return Reply
->Status
;
1720 CSR_API(CsrCreateScreenBuffer
)
1722 PCSRSS_SCREEN_BUFFER Buff
;
1725 Reply
->Header
.MessageSize
= sizeof( CSRSS_API_REPLY
);
1726 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1728 if (ProcessData
== NULL
)
1730 return(Reply
->Status
= STATUS_INVALID_PARAMETER
);
1733 Buff
= RtlAllocateHeap( CsrssApiHeap
, 0, sizeof( CSRSS_SCREEN_BUFFER
) );
1735 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
1737 Status
= CsrInitConsoleScreenBuffer( Buff
);
1738 if( !NT_SUCCESS( Status
) )
1739 Reply
->Status
= Status
;
1741 Status
= CsrInsertObject( ProcessData
, &Reply
->Data
.CreateScreenBufferReply
.OutputHandle
, &Buff
->Header
);
1742 if( !NT_SUCCESS( Status
) )
1743 Reply
->Status
= Status
;
1744 else Reply
->Status
= STATUS_SUCCESS
;
1747 return Reply
->Status
;
1750 CSR_API(CsrSetScreenBuffer
)
1753 PCSRSS_SCREEN_BUFFER Buff
;
1755 Reply
->Header
.MessageSize
= sizeof( CSRSS_API_REPLY
);
1756 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1758 Status
= CsrGetObject( ProcessData
, Request
->Data
.SetActiveScreenBufferRequest
.OutputHandle
, (Object_t
**)&Buff
);
1759 if( !NT_SUCCESS( Status
) )
1760 Reply
->Status
= Status
;
1762 // drop reference to old buffer, maybe delete
1763 if( !InterlockedDecrement( &ProcessData
->Console
->ActiveBuffer
->Header
.ReferenceCount
) )
1764 CsrDeleteScreenBuffer( ProcessData
->Console
->ActiveBuffer
);
1765 // tie console to new buffer
1766 ProcessData
->Console
->ActiveBuffer
= Buff
;
1767 // inc ref count on new buffer
1768 InterlockedIncrement( &Buff
->Header
.ReferenceCount
);
1769 // if the console is active, redraw it
1770 if( ActiveConsole
== ProcessData
->Console
)
1771 CsrDrawConsole( Buff
);
1772 Reply
->Status
= STATUS_SUCCESS
;
1775 return Reply
->Status
;
1778 CSR_API(CsrSetTitle
)
1781 PCSRSS_CONSOLE Console
;
1783 Reply
->Header
.MessageSize
= sizeof( CSRSS_API_REPLY
);
1784 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1786 Status
= CsrGetObject( ProcessData
, Request
->Data
.SetTitleRequest
.Console
, (Object_t
**)&Console
);
1787 if( !NT_SUCCESS( Status
) )
1788 Reply
->Status
= Status
;
1790 // copy title to console
1791 RtlFreeUnicodeString( &Console
->Title
);
1792 RtlCreateUnicodeString( &Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
1793 Reply
->Status
= STATUS_SUCCESS
;
1796 return Reply
->Status
;
1799 CSR_API(CsrGetTitle
)
1802 PCSRSS_CONSOLE Console
;
1804 Reply
->Header
.MessageSize
= sizeof (CSRSS_API_REPLY
);
1805 Reply
->Header
.DataSize
=
1806 sizeof (CSRSS_API_REPLY
)
1807 - sizeof(LPC_MESSAGE
);
1809 Status
= CsrGetObject (
1811 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
1812 (Object_t
**) & Console
1814 if ( !NT_SUCCESS( Status
) )
1816 Reply
->Status
= Status
;
1820 HANDLE ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
1822 /* Copy title of the console to the user title buffer */
1824 & Reply
->Data
.GetTitleReply
,
1825 sizeof (CSRSS_GET_TITLE_REPLY
)
1827 Reply
->Data
.GetTitleReply
.ConsoleHandle
= ConsoleHandle
;
1828 Reply
->Data
.GetTitleReply
.Length
= Console
->Title
.Length
;
1829 wcscpy (Reply
->Data
.GetTitleReply
.Title
, Console
->Title
.Buffer
);
1830 Reply
->Header
.MessageSize
+= Console
->Title
.Length
;
1831 Reply
->Header
.DataSize
+= Console
->Title
.Length
;
1832 Reply
->Status
= STATUS_SUCCESS
;
1835 return Reply
->Status
;
1838 CSR_API(CsrWriteConsoleOutput
)
1840 SHORT i
, X
, Y
, SizeX
, SizeY
;
1841 PCSRSS_SCREEN_BUFFER Buff
;
1842 SMALL_RECT ScreenBuffer
;
1843 CHAR_INFO
* CurCharInfo
;
1844 SMALL_RECT WriteRegion
;
1845 CHAR_INFO
* CharInfo
;
1852 DPRINT("CsrWriteConsoleOutput\n");
1854 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1855 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1857 Status
= CsrGetObject( ProcessData
, Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
, (Object_t
**)&Buff
);
1858 if( !NT_SUCCESS( Status
) || (Status
= Buff
->Header
.Type
== CSRSS_SCREEN_BUFFER_MAGIC
? STATUS_SUCCESS
: STATUS_INVALID_HANDLE
))
1860 Reply
->Status
= Status
;
1865 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
1866 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
1867 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
1868 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
1869 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
1870 (((PVOID
)CharInfo
+ PSize
) >
1871 (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
1874 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
1875 return(Reply
->Status
);
1877 WriteRegion
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
;
1879 SizeY
= RtlMin(BufferSize
.Y
- BufferCoord
.Y
, CsrpRectHeight(WriteRegion
));
1880 SizeX
= RtlMin(BufferSize
.X
- BufferCoord
.X
, CsrpRectWidth(WriteRegion
));
1881 WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
1882 WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
1884 /* Make sure WriteRegion is inside the screen buffer */
1885 CsrpInitRect(ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1886 if (!CsrpGetIntersection(&WriteRegion
, ScreenBuffer
, WriteRegion
))
1889 /* It is okay to have a WriteRegion completely outside the screen buffer.
1890 No data is written then. */
1891 return (Reply
->Status
= STATUS_SUCCESS
);
1894 for ( i
= 0, Y
= WriteRegion
.Top
; Y
<= WriteRegion
.Bottom
; i
++, Y
++ )
1896 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
1897 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.Left
) * 2;
1898 for ( X
= WriteRegion
.Left
; X
<= WriteRegion
.Right
; X
++ )
1900 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
1905 if( Buff
== ActiveConsole
->ActiveBuffer
)
1907 CsrpDrawRegion( ActiveConsole
->ActiveBuffer
, WriteRegion
);
1911 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
1912 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
1913 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Left
= WriteRegion
.Left
;
1914 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Top
= WriteRegion
.Top
;
1915 return (Reply
->Status
= STATUS_SUCCESS
);
1918 CSR_API(CsrFlushInputBuffer
)
1920 PLIST_ENTRY CurrentEntry
;
1921 PLIST_ENTRY NextEntry
;
1922 PCSRSS_CONSOLE Console
;
1923 ConsoleInput
* Input
;
1926 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1927 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1929 Status
= CsrGetObject( ProcessData
, Request
->Data
.FlushInputBufferRequest
.ConsoleInput
, (Object_t
**)&Console
);
1930 if( !NT_SUCCESS( Status
) || (Status
= Console
->Header
.Type
== CSRSS_CONSOLE_MAGIC
? STATUS_SUCCESS
: STATUS_INVALID_HANDLE
))
1932 Reply
->Status
= Status
;
1937 /* Discard all entries in the input event queue */
1938 while (!IsListEmpty(&Console
->InputEvents
))
1940 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
1941 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1942 /* Destroy the event */
1943 RtlFreeHeap( CsrssApiHeap
, 0, Input
);
1945 Console
->WaitingChars
=0;
1948 return (Reply
->Status
= STATUS_SUCCESS
);
1951 CSR_API(CsrScrollConsoleScreenBuffer
)
1953 SHORT i
, X
, Y
, SizeX
, SizeY
;
1954 PCSRSS_SCREEN_BUFFER Buff
;
1955 SMALL_RECT ScreenBuffer
;
1956 SMALL_RECT SrcRegion
;
1957 SMALL_RECT DstRegion
;
1958 SMALL_RECT FillRegion
;
1959 IO_STATUS_BLOCK Iosb
;
1960 CHAR_INFO
* CharInfo
;
1966 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
1967 ALIAS(ScrollRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
);
1968 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
1969 ALIAS(ClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
);
1970 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
1971 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
1973 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1974 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1976 Status
= CsrGetObject( ProcessData
, ConsoleHandle
, (Object_t
**)&Buff
);
1977 if( !NT_SUCCESS( Status
) || (Status
= Buff
->Header
.Type
== CSRSS_SCREEN_BUFFER_MAGIC
? STATUS_SUCCESS
: STATUS_INVALID_HANDLE
))
1979 Reply
->Status
= Status
;
1984 /* Make sure source rectangle is inside the screen buffer */
1985 CsrpInitRect(ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1986 if (!CsrpGetIntersection(&SrcRegion
, ScreenBuffer
, ScrollRectangle
))
1989 return (Reply
->Status
= STATUS_INVALID_PARAMETER
);
1992 if (UseClipRectangle
)
1994 if (!CsrpGetIntersection(&SrcRegion
, SrcRegion
, ClipRectangle
))
1997 return (Reply
->Status
= STATUS_SUCCESS
);
2004 DestinationOrigin
.Y
,
2005 DestinationOrigin
.X
,
2006 DestinationOrigin
.Y
+ CsrpRectHeight(ScrollRectangle
) - 1,
2007 DestinationOrigin
.X
+ CsrpRectWidth(ScrollRectangle
) - 1)
2009 /* Make sure destination rectangle is inside the screen buffer */
2010 if (!CsrpGetIntersection(&DstRegion
, DstRegion
, ScreenBuffer
))
2013 return (Reply
->Status
= STATUS_INVALID_PARAMETER
);
2016 CsrpCopyRegion(Buff
, SrcRegion
, DstRegion
);
2019 /* Get the region that should be filled with the specified character and attributes */
2023 CsrpGetUnion(&FillRegion
, SrcRegion
, DstRegion
);
2025 if (CsrpSubtractRect(&FillRegion
, FillRegion
, DstRegion
))
2027 /* FIXME: The subtracted rectangle is off by one line */
2028 FillRegion
.Top
+= 1;
2030 CsrpFillRegion(Buff
, FillRegion
, Fill
);
2034 if (Buff
== ActiveConsole
->ActiveBuffer
)
2036 /* Draw destination region */
2037 CsrpDrawRegion(ActiveConsole
->ActiveBuffer
, DstRegion
);
2041 /* Draw filled region */
2042 CsrpDrawRegion(ActiveConsole
->ActiveBuffer
, FillRegion
);
2047 return(Reply
->Status
= STATUS_SUCCESS
);
2051 CSR_API(CsrReadConsoleOutputChar
)
2054 PCSRSS_SCREEN_BUFFER ScreenBuffer
;
2059 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2060 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- sizeof(LPC_MESSAGE
);
2061 ReadBuffer
= Reply
->Data
.ReadConsoleOutputCharReply
.String
;
2065 Status
= CsrGetObject(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, (Object_t
**)&ScreenBuffer
);
2066 if (!NT_SUCCESS(Status
))
2068 Reply
->Status
= Status
;
2070 return(Reply
->Status
);
2073 if (ScreenBuffer
->Header
.Type
!= CSRSS_SCREEN_BUFFER_MAGIC
)
2075 Reply
->Status
= STATUS_INVALID_HANDLE
;
2077 return(Reply
->Status
);
2080 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ ScreenBuffer
->ShowX
;
2081 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
2083 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2085 *ReadBuffer
= ScreenBuffer
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * ScreenBuffer
->MaxX
)];
2090 if (Xpos
== ScreenBuffer
->MaxX
)
2095 if (Ypos
== ScreenBuffer
->MaxY
)
2102 Reply
->Status
= STATUS_SUCCESS
;
2103 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.X
= Xpos
- ScreenBuffer
->ShowX
;
2104 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.Y
= (Ypos
- ScreenBuffer
->ShowY
+ ScreenBuffer
->MaxY
) % ScreenBuffer
->MaxY
;
2105 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2106 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2110 return(Reply
->Status
);
2114 CSR_API(CsrReadConsoleOutputAttrib
)
2117 PCSRSS_SCREEN_BUFFER ScreenBuffer
;
2122 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2123 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- sizeof(LPC_MESSAGE
);
2124 ReadBuffer
= Reply
->Data
.ReadConsoleOutputAttribReply
.String
;
2128 Status
= CsrGetObject(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, (Object_t
**)&ScreenBuffer
);
2129 if (!NT_SUCCESS(Status
))
2131 Reply
->Status
= Status
;
2133 return(Reply
->Status
);
2136 if (ScreenBuffer
->Header
.Type
!= CSRSS_SCREEN_BUFFER_MAGIC
)
2138 Reply
->Status
= STATUS_INVALID_HANDLE
;
2140 return(Reply
->Status
);
2143 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ ScreenBuffer
->ShowX
;
2144 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
2146 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2148 *ReadBuffer
= ScreenBuffer
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * ScreenBuffer
->MaxX
) + 1];
2153 if (Xpos
== ScreenBuffer
->MaxX
)
2158 if (Ypos
== ScreenBuffer
->MaxY
)
2165 Reply
->Status
= STATUS_SUCCESS
;
2166 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.X
= Xpos
- ScreenBuffer
->ShowX
;
2167 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.Y
= (Ypos
- ScreenBuffer
->ShowY
+ ScreenBuffer
->MaxY
) % ScreenBuffer
->MaxY
;
2168 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2169 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2173 return(Reply
->Status
);
2177 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2180 PCSRSS_CONSOLE Console
;
2181 PLIST_ENTRY CurrentItem
;
2184 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2185 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- sizeof(LPC_MESSAGE
);
2189 Status
= CsrGetObject(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, (Object_t
**)&Console
);
2190 if (!NT_SUCCESS(Status
))
2192 Reply
->Status
= Status
;
2194 return(Reply
->Status
);
2197 if (Console
->Header
.Type
!= CSRSS_CONSOLE_MAGIC
)
2199 Reply
->Status
= STATUS_INVALID_HANDLE
;
2201 return(Reply
->Status
);
2204 CurrentItem
= &Console
->InputEvents
;
2207 // If there are any events ...
2208 if(CurrentItem
->Flink
!= CurrentItem
)
2212 CurrentItem
= CurrentItem
->Flink
;
2214 }while(CurrentItem
!= &Console
->InputEvents
);
2219 Reply
->Status
= STATUS_SUCCESS
;
2220 Reply
->Data
.GetNumInputEventsReply
.NumInputEvents
= NumEvents
;
2222 return Reply
->Status
;
2226 CSR_API(CsrPeekConsoleInput
)
2229 PCSRSS_CONSOLE Console
;
2232 PLIST_ENTRY CurrentItem
;
2233 PLIST_ENTRY NextItem
;
2234 PINPUT_RECORD InputRecord
;
2238 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2239 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2243 Status
= CsrGetObject(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, (Object_t
**)&Console
);
2244 if(!NT_SUCCESS(Status
))
2246 Reply
->Status
= Status
;
2248 return Reply
->Status
;
2251 if(Console
->Header
.Type
!= CSRSS_CONSOLE_MAGIC
)
2253 Reply
->Status
= STATUS_INVALID_HANDLE
;
2255 return Reply
->Status
;
2258 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2259 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2260 Size
= Length
* sizeof(INPUT_RECORD
);
2262 if(((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2263 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2266 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2267 return Reply
->Status
;
2272 if(!IsListEmpty(&Console
->InputEvents
))
2274 CurrentItem
= &Console
->InputEvents
;
2276 while(NumItems
< Length
)
2279 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2280 *InputRecord
++ = Item
->InputEvent
;
2282 if(CurrentItem
->Flink
== &Console
->InputEvents
)
2285 CurrentItem
= CurrentItem
->Flink
;
2291 Reply
->Status
= STATUS_SUCCESS
;
2292 Reply
->Data
.PeekConsoleInputReply
.Length
= NumItems
;
2293 return Reply
->Status
;
2297 CSR_API(CsrReadConsoleOutput
)
2299 PCHAR_INFO CharInfo
;
2300 PCHAR_INFO CurCharInfo
;
2301 PCSRSS_SCREEN_BUFFER ScreenBuffer
;
2308 SMALL_RECT ReadRegion
;
2309 SMALL_RECT ScreenRect
;
2310 DWORD i
, Y
, X
, Offset
;
2312 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2313 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2317 Status
= CsrGetObject(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, (Object_t
**)&ScreenBuffer
);
2318 if(!NT_SUCCESS(Status
))
2320 Reply
->Status
= Status
;
2322 return Reply
->Status
;
2325 if(ScreenBuffer
->Header
.Type
!= CSRSS_SCREEN_BUFFER_MAGIC
)
2327 Reply
->Status
= STATUS_INVALID_HANDLE
;
2329 return Reply
->Status
;
2332 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2333 ReadRegion
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
;
2334 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2335 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2336 Length
= BufferSize
.X
* BufferSize
.Y
;
2337 Size
= Length
* sizeof(INPUT_RECORD
);
2339 if(((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2340 || (((PVOID
)CharInfo
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2343 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2344 return Reply
->Status
;
2347 SizeY
= RtlMin(BufferSize
.Y
- BufferCoord
.Y
, CsrpRectHeight(ReadRegion
));
2348 SizeX
= RtlMin(BufferSize
.X
- BufferCoord
.X
, CsrpRectWidth(ReadRegion
));
2349 ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
;
2350 ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
;
2352 CsrpInitRect(ScreenRect
, 0, 0, ScreenBuffer
->MaxY
- 1, ScreenBuffer
->MaxX
- 1);
2353 if (!CsrpGetIntersection(&ReadRegion
, ScreenRect
, ReadRegion
))
2356 Reply
->Status
= STATUS_SUCCESS
;
2357 return Reply
->Status
;
2360 for(i
= 0, Y
= ReadRegion
.Top
; Y
< ReadRegion
.Bottom
; ++i
, ++Y
)
2362 CurCharInfo
= CharInfo
+ (i
* BufferSize
.Y
);
2364 Offset
= (((Y
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
) * ScreenBuffer
->MaxX
+ ReadRegion
.Left
) * 2;
2365 for(X
= ReadRegion
.Left
; X
< ReadRegion
.Right
; ++X
)
2367 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(ScreenBuffer
, Offset
);
2368 CurCharInfo
->Attributes
= GET_CELL_BUFFER(ScreenBuffer
, Offset
);
2375 Reply
->Status
= STATUS_SUCCESS
;
2376 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
- 1;
2377 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
- 1;
2378 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Left
= ReadRegion
.Left
;
2379 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Top
= ReadRegion
.Top
;
2381 return Reply
->Status
;
2385 CSR_API(CsrWriteConsoleInput
)
2387 PINPUT_RECORD InputRecord
;
2388 PCSRSS_CONSOLE Console
;
2393 PLIST_ENTRY NextItem
;
2394 ConsoleInput
* Record
;
2396 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2397 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2401 Status
= CsrGetObject(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, (Object_t
**)&Console
);
2402 if(!NT_SUCCESS(Status
))
2404 Reply
->Status
= Status
;
2406 return Reply
->Status
;
2409 if(Console
->Header
.Type
!= CSRSS_CONSOLE_MAGIC
)
2411 Reply
->Status
= STATUS_INVALID_HANDLE
;
2413 return Reply
->Status
;
2416 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2417 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2418 Size
= Length
* sizeof(INPUT_RECORD
);
2420 if(((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2421 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2424 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2425 return Reply
->Status
;
2428 for(i
= 0; i
< Length
; ++i
)
2430 Record
= RtlAllocateHeap(CsrssApiHeap
, 0, sizeof(ConsoleInput
));
2434 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2435 return Reply
->Status
;
2438 Record
->InputEvent
= *InputRecord
++;
2439 InsertTailList(&Console
->InputEvents
, &Record
->ListEntry
);
2444 Reply
->Status
= STATUS_SUCCESS
;
2445 Reply
->Data
.WriteConsoleInputReply
.Length
= i
;
2446 return Reply
->Status
;
2449 /**********************************************************************
2450 * HardwareStateProperty
2453 * Set/Get the value of the HardwareState and switch
2454 * between direct video buffer ouput and GDI windowed
2457 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2458 * object. We use the same object to reply.
2460 * ConsoleHwState has the correct size to be compatible
2461 * with NT's, but values are not.
2463 static NTSTATUS FASTCALL
SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2465 if ( (CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2466 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2468 if (Console
->HardwareState
!= ConsoleHwState
)
2470 /* TODO: implement switching from full screen to windowed mode */
2471 /* TODO: or back; now simply store the hardware state */
2472 Console
->HardwareState
= ConsoleHwState
;
2474 return STATUS_SUCCESS
;
2476 return STATUS_INVALID_PARAMETER_3
; // Client: (handle, set_get, [mode])
2479 CSR_API(CsrHardwareStateProperty
)
2481 PCSRSS_CONSOLE Console
;
2484 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2485 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2489 Status
= CsrGetObject (
2491 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2492 (Object_t
**) & Console
2494 if (!NT_SUCCESS(Status
))
2496 Reply
->Status
= Status
;
2500 if(Console
->Header
.Type
!= CSRSS_CONSOLE_MAGIC
)
2502 Reply
->Status
= STATUS_INVALID_HANDLE
;
2506 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2508 case CONSOLE_HARDWARE_STATE_GET
:
2509 Reply
->Data
.ConsoleHardwareStateReply
.State
= Console
->HardwareState
;
2512 case CONSOLE_HARDWARE_STATE_SET
:
2513 Reply
->Status
= SetConsoleHardwareState (Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2517 Reply
->Status
= STATUS_INVALID_PARAMETER_2
; // Client: (handle, [set_get], mode)
2525 return Reply
->Status
;
2528 CSR_API(CsrGetConsoleWindow
)
2530 PCSRSS_CONSOLE Console
;
2533 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2534 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2538 Status
= CsrGetObject (
2540 Request
->Data
.ConsoleWindowRequest
.ConsoleHandle
,
2541 (Object_t
**) & Console
2543 if (!NT_SUCCESS(Status
))
2545 Reply
->Status
= Status
;
2549 if(Console
->Header
.Type
!= CSRSS_CONSOLE_MAGIC
)
2551 Reply
->Status
= STATUS_INVALID_HANDLE
;
2555 // Is this GDI handle valid in the client's context?
2556 Reply
->Data
.ConsoleWindowReply
.WindowHandle
= Console
->hWindow
;
2562 return Reply
->Status
;