2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
18 ((Rect)->top) = Top; \
19 ((Rect)->left) = Left; \
20 ((Rect)->bottom) = Bottom; \
21 ((Rect)->right) = Right
23 #define ConioIsRectEmpty(Rect) \
24 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
26 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
27 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
29 #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
30 MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
32 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
33 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
35 #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
36 MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
39 /* FUNCTIONS *****************************************************************/
42 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
44 PCSRSS_CONSOLE ProcessConsole
;
46 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
47 ProcessConsole
= ProcessData
->Console
;
52 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
53 return STATUS_INVALID_HANDLE
;
56 InterlockedIncrement(&ProcessConsole
->Header
.ReferenceCount
);
57 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
58 EnterCriticalSection(&(ProcessConsole
->Header
.Lock
));
59 *Console
= ProcessConsole
;
61 return STATUS_SUCCESS
;
65 ConioConsoleCtrlEventTimeout(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
, DWORD Timeout
)
69 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
71 if (ProcessData
->CtrlDispatcher
)
74 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
75 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
76 UlongToPtr(Event
), 0, NULL
);
79 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
82 WaitForSingleObject(Thread
, Timeout
);
88 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
90 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, 0);
94 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
96 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
100 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
102 PBYTE Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CurrentY
);
105 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
109 *Ptr
++ = Buff
->DefaultAttrib
;
113 static NTSTATUS FASTCALL
114 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
115 PCSRSS_SCREEN_BUFFER Buffer
)
117 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
119 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
120 Buffer
->Header
.ReferenceCount
= 0;
123 Buffer
->VirtualY
= 0;
124 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
125 if (NULL
== Buffer
->Buffer
)
127 return STATUS_INSUFFICIENT_RESOURCES
;
129 InitializeCriticalSection(&Buffer
->Header
.Lock
);
130 ConioInitScreenBuffer(Console
, Buffer
);
131 /* initialize buffer to be empty with default attributes */
132 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
134 ClearLineBuffer(Buffer
);
136 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
137 Buffer
->CurrentX
= 0;
138 Buffer
->CurrentY
= 0;
140 return STATUS_SUCCESS
;
143 static NTSTATUS WINAPI
144 CsrInitConsole(PCSRSS_CONSOLE Console
)
147 SECURITY_ATTRIBUTES SecurityAttributes
;
148 PCSRSS_SCREEN_BUFFER NewBuffer
;
151 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
152 Console
->Title
.Buffer
= NULL
;
155 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
157 Console
->Header
.ReferenceCount
= 0;
158 Console
->WaitingChars
= 0;
159 Console
->WaitingLines
= 0;
160 Console
->EchoCount
= 0;
161 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
162 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
163 Console
->EarlyReturn
= FALSE
;
164 Console
->ActiveBuffer
= NULL
;
165 InitializeListHead(&Console
->InputEvents
);
166 Console
->CodePage
= GetOEMCP();
167 Console
->OutputCodePage
= GetOEMCP();
169 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
170 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
171 SecurityAttributes
.bInheritHandle
= TRUE
;
173 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
174 if (NULL
== Console
->ActiveEvent
)
176 RtlFreeUnicodeString(&Console
->Title
);
177 return STATUS_UNSUCCESSFUL
;
179 Console
->PrivateData
= NULL
;
180 InitializeCriticalSection(&Console
->Header
.Lock
);
182 GuiMode
= DtbgIsDesktopVisible();
184 /* allocate console screen buffer */
185 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
186 if (NULL
== NewBuffer
)
188 RtlFreeUnicodeString(&Console
->Title
);
189 DeleteCriticalSection(&Console
->Header
.Lock
);
190 CloseHandle(Console
->ActiveEvent
);
191 return STATUS_INSUFFICIENT_RESOURCES
;
193 /* init screen buffer with defaults */
194 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
195 NewBuffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
196 /* make console active, and insert into console list */
197 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
201 Status
= TuiInitConsole(Console
);
202 if (! NT_SUCCESS(Status
))
204 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
210 Status
= GuiInitConsole(Console
);
211 if (! NT_SUCCESS(Status
))
213 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
214 RtlFreeUnicodeString(&Console
->Title
);
215 DeleteCriticalSection(&Console
->Header
.Lock
);
216 CloseHandle(Console
->ActiveEvent
);
217 DPRINT1("GuiInitConsole: failed\n");
222 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
223 if (! NT_SUCCESS(Status
))
225 ConioCleanupConsole(Console
);
226 RtlFreeUnicodeString(&Console
->Title
);
227 DeleteCriticalSection(&Console
->Header
.Lock
);
228 CloseHandle(Console
->ActiveEvent
);
229 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
230 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
234 /* add a reference count because the buffer is tied to the console */
235 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
237 /* copy buffer contents to screen */
238 ConioDrawConsole(Console
);
240 return STATUS_SUCCESS
;
244 CSR_API(CsrAllocConsole
)
246 PCSRSS_CONSOLE Console
;
247 NTSTATUS Status
= STATUS_SUCCESS
;
248 BOOLEAN NewConsole
= FALSE
;
250 DPRINT("CsrAllocConsole\n");
252 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
253 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
255 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
256 if (ProcessData
->Console
)
258 DPRINT1("Process already has a console\n");
259 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
260 return STATUS_INVALID_PARAMETER
;
263 /* If we don't need a console, then get out of here */
264 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
266 DPRINT("No console needed\n");
267 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
268 return STATUS_SUCCESS
;
271 /* If we already have one, then don't create a new one... */
272 if (!Request
->Data
.AllocConsoleRequest
.Console
||
273 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
275 /* Allocate a console structure */
277 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
280 DPRINT1("Not enough memory for console\n");
281 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
282 return STATUS_NO_MEMORY
;
284 /* initialize list head */
285 InitializeListHead(&Console
->ProcessList
);
286 /* insert process data required for GUI initialization */
287 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
288 /* Initialize the Console */
289 Status
= CsrInitConsole(Console
);
290 if (!NT_SUCCESS(Status
))
292 DPRINT1("Console init failed\n");
293 HeapFree(Win32CsrApiHeap
, 0, Console
);
294 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
300 /* Reuse our current console */
301 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
304 /* Set the Process Console */
305 ProcessData
->Console
= Console
;
307 /* Return it to the caller */
308 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
310 /* Add a reference count because the process is tied to the console */
311 Console
->Header
.ReferenceCount
++;
313 if (NewConsole
|| !ProcessData
->bInheritHandles
)
315 /* Insert the Objects */
316 Status
= Win32CsrInsertObject(ProcessData
,
317 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
319 GENERIC_READ
| GENERIC_WRITE
,
321 if (! NT_SUCCESS(Status
))
323 DPRINT1("Failed to insert object\n");
324 ConioDeleteConsole((Object_t
*) Console
);
325 ProcessData
->Console
= 0;
326 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
330 Status
= Win32CsrInsertObject(ProcessData
,
331 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
332 &Console
->ActiveBuffer
->Header
,
333 GENERIC_READ
| GENERIC_WRITE
,
335 if (!NT_SUCCESS(Status
))
337 DPRINT1("Failed to insert object\n");
338 ConioDeleteConsole((Object_t
*) Console
);
339 Win32CsrReleaseObject(ProcessData
,
340 Request
->Data
.AllocConsoleRequest
.InputHandle
);
341 ProcessData
->Console
= 0;
342 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
347 /* Duplicate the Event */
348 if (!DuplicateHandle(GetCurrentProcess(),
349 ProcessData
->Console
->ActiveEvent
,
350 ProcessData
->Process
,
351 &ProcessData
->ConsoleEvent
,
356 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
357 ConioDeleteConsole((Object_t
*) Console
);
358 if (NewConsole
|| !ProcessData
->bInheritHandles
)
360 Win32CsrReleaseObject(ProcessData
,
361 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
362 Win32CsrReleaseObject(ProcessData
,
363 Request
->Data
.AllocConsoleRequest
.InputHandle
);
365 ProcessData
->Console
= 0;
366 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
370 /* Set the Ctrl Dispatcher */
371 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
372 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
376 /* Insert into the list if it has not been added */
377 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
380 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
381 return STATUS_SUCCESS
;
384 CSR_API(CsrFreeConsole
)
386 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
387 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
389 return Win32CsrReleaseConsole(ProcessData
);
393 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
395 /* If we hit bottom, slide the viewable screen */
396 if (++Buff
->CurrentY
== Buff
->MaxY
)
399 if (++Buff
->VirtualY
== Buff
->MaxY
)
404 ClearLineBuffer(Buff
);
405 if (UpdateRect
->top
!= 0)
410 UpdateRect
->left
= 0;
411 UpdateRect
->right
= Buff
->MaxX
- 1;
412 UpdateRect
->bottom
= Buff
->CurrentY
;
415 static NTSTATUS FASTCALL
416 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
417 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
422 LONG CursorStartX
, CursorStartY
;
425 CursorStartX
= Buff
->CurrentX
;
426 CursorStartY
= Buff
->CurrentY
;
427 UpdateRect
.left
= Buff
->MaxX
;
428 UpdateRect
.top
= Buff
->CurrentY
;
429 UpdateRect
.right
= -1;
430 UpdateRect
.bottom
= Buff
->CurrentY
;
433 for (i
= 0; i
< Length
; i
++)
435 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
438 if (Buffer
[i
] == '\n')
441 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
445 else if (Buffer
[i
] == '\b')
447 /* Only handle BS if we're not on the first pos of the first line */
448 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
450 if (0 == Buff
->CurrentX
)
452 /* slide virtual position up */
453 Buff
->CurrentX
= Buff
->MaxX
- 1;
455 UpdateRect
.top
= min(UpdateRect
.top
, (LONG
)Buff
->CurrentY
);
461 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
463 Ptr
[1] = Buff
->DefaultAttrib
;
464 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
465 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
470 else if (Buffer
[i
] == '\r')
473 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
474 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
478 else if (Buffer
[i
] == '\t')
482 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
483 EndX
= (Buff
->CurrentX
+ 8) & ~7;
484 if (EndX
> Buff
->MaxX
)
488 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
489 while (Buff
->CurrentX
< EndX
)
492 *Ptr
++ = Buff
->DefaultAttrib
;
495 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
496 if (Buff
->CurrentX
== Buff
->MaxX
)
498 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
501 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
511 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
512 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
513 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
517 Ptr
[1] = Buff
->DefaultAttrib
;
520 if (Buff
->CurrentX
== Buff
->MaxX
)
522 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
525 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
529 Buff
->CurrentX
= CursorStartX
;
534 if (! ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
536 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
540 return STATUS_SUCCESS
;
543 CSR_API(CsrReadConsole
)
545 PLIST_ENTRY CurrentEntry
;
548 PWCHAR UnicodeBuffer
;
550 ULONG nNumberOfCharsToRead
, CharSize
;
551 PCSRSS_CONSOLE Console
;
554 DPRINT("CsrReadConsole\n");
556 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
558 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
559 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
560 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
561 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
563 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
564 UnicodeBuffer
= (PWCHAR
)Buffer
;
565 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
566 &Console
, GENERIC_READ
);
567 if (! NT_SUCCESS(Status
))
571 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
572 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
574 /* remove input event from queue */
575 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
576 if (IsListEmpty(&Console
->InputEvents
))
578 ResetEvent(Console
->ActiveEvent
);
580 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
582 /* only pay attention to valid ascii chars, on key down */
583 if (KEY_EVENT
== Input
->InputEvent
.EventType
584 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
585 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
588 * backspace handling - if we are in charge of echoing it then we handle it here
589 * otherwise we treat it like a normal char.
591 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
592 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
594 /* echo if it has not already been done, and either we or the client has chars to be deleted */
596 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
598 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
599 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
603 i
-= 2; /* if we already have something to return, just back it up by 2 */
606 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
607 Console
->WaitingChars
--;
608 ConioUnlockConsole(Console
);
609 HeapFree(Win32CsrApiHeap
, 0, Input
);
610 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
611 return STATUS_NOTIFY_CLEANUP
;
614 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
615 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
617 /* do not copy backspace to buffer */
620 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
621 ConsoleInputAnsiCharToUnicodeChar(Console
, &UnicodeBuffer
[i
], &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
623 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
625 /* echo to screen if enabled and we did not already echo the char */
626 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
628 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
630 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
631 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
638 Console
->WaitingChars
--;
639 HeapFree(Win32CsrApiHeap
, 0, Input
);
641 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
644 Status
= STATUS_PENDING
; /* we didn't read anything */
646 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
648 if (0 == Console
->WaitingLines
||
649 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
651 Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
655 Console
->WaitingLines
--;
656 Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
661 Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
664 if (Status
== STATUS_PENDING
)
666 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
670 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
673 ConioUnlockConsole(Console
);
675 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
677 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
678 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
684 __inline BOOLEAN
ConioGetIntersection(
689 if (ConioIsRectEmpty(Rect1
) ||
690 (ConioIsRectEmpty(Rect2
)) ||
691 (Rect1
->top
> Rect2
->bottom
) ||
692 (Rect1
->left
> Rect2
->right
) ||
693 (Rect1
->bottom
< Rect2
->top
) ||
694 (Rect1
->right
< Rect2
->left
))
696 /* The rectangles do not intersect */
697 ConioInitRect(Intersection
, 0, -1, 0, -1);
701 ConioInitRect(Intersection
,
702 max(Rect1
->top
, Rect2
->top
),
703 max(Rect1
->left
, Rect2
->left
),
704 min(Rect1
->bottom
, Rect2
->bottom
),
705 min(Rect1
->right
, Rect2
->right
));
710 __inline BOOLEAN
ConioGetUnion(
715 if (ConioIsRectEmpty(Rect1
))
717 if (ConioIsRectEmpty(Rect2
))
719 ConioInitRect(Union
, 0, -1, 0, -1);
727 else if (ConioIsRectEmpty(Rect2
))
734 min(Rect1
->top
, Rect2
->top
),
735 min(Rect1
->left
, Rect2
->left
),
736 max(Rect1
->bottom
, Rect2
->bottom
),
737 max(Rect1
->right
, Rect2
->right
));
743 /* Move from one rectangle to another. We must be careful about the order that
744 * this is done, to avoid overwriting parts of the source before they are moved. */
746 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
752 int Width
= ConioRectWidth(SrcRegion
);
753 int Height
= ConioRectHeight(SrcRegion
);
764 /* Moving down: work from bottom up */
765 SY
= SrcRegion
->bottom
;
766 DY
= DstRegion
->bottom
;
769 for (i
= 0; i
< Height
; i
++)
771 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
772 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
774 SX
= SrcRegion
->left
;
775 DX
= DstRegion
->left
;
779 /* Moving right: work from right to left */
780 SX
= SrcRegion
->right
;
781 DX
= DstRegion
->right
;
784 for (j
= 0; j
< Width
; j
++)
786 WORD Cell
= SRow
[SX
];
787 if (SX
>= ClipRegion
->left
&& SX
<= ClipRegion
->right
788 && SY
>= ClipRegion
->top
&& SY
<= ClipRegion
->bottom
)
792 if (DX
>= ClipRegion
->left
&& DX
<= ClipRegion
->right
793 && DY
>= ClipRegion
->top
&& DY
<= ClipRegion
->bottom
)
806 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
808 if (InputEvent
->EventType
== KEY_EVENT
)
810 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
811 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
812 ConsoleInputUnicodeCharToAnsiChar(Console
,
813 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
818 CSR_API(CsrWriteConsole
)
822 PCSRSS_SCREEN_BUFFER Buff
;
823 PCSRSS_CONSOLE Console
;
826 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
828 DPRINT("CsrWriteConsole\n");
830 if (Request
->Header
.u1
.s1
.TotalLength
831 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
832 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
834 DPRINT1("Invalid request size\n");
835 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
836 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
837 return STATUS_INVALID_PARAMETER
;
839 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
841 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
842 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
844 if (! NT_SUCCESS(Status
))
849 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
851 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
852 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
853 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
854 NULL
, 0, NULL
, NULL
);
855 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
858 WideCharToMultiByte(Console
->OutputCodePage
, 0,
859 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
860 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
861 Buffer
, Length
, NULL
, NULL
);
865 Status
= STATUS_NO_MEMORY
;
870 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
875 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
876 if (NT_SUCCESS(Status
))
878 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
879 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
880 if (NT_SUCCESS(Status
))
882 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
884 ConioUnlockScreenBuffer(Buff
);
886 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
888 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
891 ConioUnlockConsole(Console
);
893 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
899 ConioDeleteScreenBuffer(Object_t
*Object
)
901 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
902 DeleteCriticalSection(&Buffer
->Header
.Lock
);
903 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
904 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
908 ConioDrawConsole(PCSRSS_CONSOLE Console
)
912 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
914 ConioDrawRegion(Console
, &Region
);
919 ConioDeleteConsole(Object_t
*Object
)
921 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
924 DPRINT("ConioDeleteConsole\n");
926 /* Drain input event queue */
927 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
929 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
930 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
931 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
932 HeapFree(Win32CsrApiHeap
, 0, Event
);
935 ConioCleanupConsole(Console
);
936 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
938 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
941 Console
->ActiveBuffer
= NULL
;
943 CloseHandle(Console
->ActiveEvent
);
944 DeleteCriticalSection(&Console
->Header
.Lock
);
945 RtlFreeUnicodeString(&Console
->Title
);
946 IntDeleteAllAliases(Console
->Aliases
);
947 HeapFree(Win32CsrApiHeap
, 0, Console
);
951 CsrInitConsoleSupport(VOID
)
953 DPRINT("CSR: CsrInitConsoleSupport()\n");
955 /* Should call LoadKeyboardLayout */
959 ConioProcessChar(PCSRSS_CONSOLE Console
,
960 ConsoleInput
*KeyEventRecord
)
963 ConsoleInput
*TempInput
;
965 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
967 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
970 /* first add the \r */
971 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
972 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
973 KeyEventRecord
->Echoed
= FALSE
;
974 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
975 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
976 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
977 Console
->WaitingChars
++;
978 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
979 if (NULL
== KeyEventRecord
)
981 DPRINT1("Failed to allocate KeyEventRecord\n");
984 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
985 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
986 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
987 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
988 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
989 KeyEventRecord
->Fake
= TRUE
;
993 /* add event to the queue */
994 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
995 Console
->WaitingChars
++;
996 /* if line input mode is enabled, only wake the client on enter key down */
997 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
998 || Console
->EarlyReturn
999 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1000 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1002 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1004 Console
->WaitingLines
++;
1007 KeyEventRecord
->Echoed
= FALSE
;
1008 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1009 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1010 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1012 /* walk the input queue looking for a char to backspace */
1013 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1014 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1015 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1016 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1017 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1018 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1022 /* if we found one, delete it, otherwise, wake the client */
1023 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1025 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1026 RemoveEntryList(&TempInput
->ListEntry
);
1027 if (TempInput
->Echoed
)
1029 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1030 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1033 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1034 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1035 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1036 Console
->WaitingChars
-= 2;
1042 /* echo chars if we are supposed to and client is waiting for some */
1043 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1044 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1045 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1046 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1048 /* mark the char as already echoed */
1049 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1050 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1052 Console
->EchoCount
--;
1053 KeyEventRecord
->Echoed
= TRUE
;
1057 /* Console->WaitingChars++; */
1058 SetEvent(Console
->ActiveEvent
);
1061 static DWORD FASTCALL
1062 ConioGetShiftState(PBYTE KeyState
)
1066 if (KeyState
[VK_CAPITAL
] & 1)
1067 ssOut
|= CAPSLOCK_ON
;
1069 if (KeyState
[VK_NUMLOCK
] & 1)
1070 ssOut
|= NUMLOCK_ON
;
1072 if (KeyState
[VK_SCROLL
] & 1)
1073 ssOut
|= SCROLLLOCK_ON
;
1075 if (KeyState
[VK_SHIFT
] & 0x80)
1076 ssOut
|= SHIFT_PRESSED
;
1078 if (KeyState
[VK_LCONTROL
] & 0x80)
1079 ssOut
|= LEFT_CTRL_PRESSED
;
1080 if (KeyState
[VK_RCONTROL
] & 0x80)
1081 ssOut
|= RIGHT_CTRL_PRESSED
;
1083 if (KeyState
[VK_LMENU
] & 0x80)
1084 ssOut
|= LEFT_ALT_PRESSED
;
1085 if (KeyState
[VK_RMENU
] & 0x80)
1086 ssOut
|= RIGHT_ALT_PRESSED
;
1092 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1094 static BYTE KeyState
[256] = { 0 };
1095 /* MSDN mentions that you should use the last virtual key code received
1096 * when putting a virtual key identity to a WM_CHAR message since multiple
1097 * or translated keys may be involved. */
1098 static UINT LastVirtualKey
= 0;
1100 ConsoleInput
*ConInRec
;
1104 UINT VirtualKeyCode
;
1105 UINT VirtualScanCode
;
1108 ULONG ResultSize
= 0;
1111 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1112 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1113 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1115 GetKeyboardState(KeyState
);
1116 ShiftState
= ConioGetShiftState(KeyState
);
1118 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1120 VirtualKeyCode
= LastVirtualKey
;
1121 UnicodeChar
= msg
->wParam
;
1128 VirtualKeyCode
= msg
->wParam
;
1129 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1136 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1139 if (0 == ResultSize
)
1144 er
.EventType
= KEY_EVENT
;
1145 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1146 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1147 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1148 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1149 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1150 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1154 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1155 && VK_TAB
== VirtualKeyCode
)
1159 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1164 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1166 if (TuiSwapConsole(0))
1173 if (NULL
== Console
)
1175 DPRINT1("No Active Console!\n");
1179 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1181 if (NULL
== ConInRec
)
1186 ConInRec
->InputEvent
= er
;
1187 ConInRec
->Fake
= UnicodeChar
&&
1188 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1189 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1190 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1191 ConInRec
->Echoed
= FALSE
;
1192 if (ConInRec
->NotChar
)
1193 LastVirtualKey
= msg
->wParam
;
1195 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1196 Down
? "down" : "up ",
1197 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1199 ConInRec
->Fake
? "fake" : "real",
1200 ConInRec
->NotChar
? "notc" : "char",
1203 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1206 if (ConInRec
->Fake
&& ConInRec
->NotChar
)
1208 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1212 /* process Ctrl-C and Ctrl-Break */
1213 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1214 er
.Event
.KeyEvent
.bKeyDown
&&
1215 ((er
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1216 (er
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1217 (er
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1219 PCSRSS_PROCESS_DATA current
;
1220 PLIST_ENTRY current_entry
;
1221 DPRINT1("Console_Api Ctrl-C\n");
1222 current_entry
= Console
->ProcessList
.Flink
;
1223 while (current_entry
!= &Console
->ProcessList
)
1225 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1226 current_entry
= current_entry
->Flink
;
1227 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1229 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1233 if (0 != (er
.Event
.KeyEvent
.dwControlKeyState
1234 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1235 && (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
1236 || VK_DOWN
== er
.Event
.KeyEvent
.wVirtualKeyCode
))
1238 if (er
.Event
.KeyEvent
.bKeyDown
)
1240 /* scroll up or down */
1241 if (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
)
1243 /* only scroll up if there is room to scroll up into */
1244 if (Console
->ActiveBuffer
->CurrentY
!= Console
->ActiveBuffer
->MaxY
- 1)
1246 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+
1247 Console
->ActiveBuffer
->MaxY
- 1) %
1248 Console
->ActiveBuffer
->MaxY
;
1249 Console
->ActiveBuffer
->CurrentY
++;
1254 /* only scroll down if there is room to scroll down into */
1255 if (Console
->ActiveBuffer
->CurrentY
!= 0)
1257 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+ 1) %
1258 Console
->ActiveBuffer
->MaxY
;
1259 Console
->ActiveBuffer
->CurrentY
--;
1262 ConioDrawConsole(Console
);
1264 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1267 /* FIXME - convert to ascii */
1268 ConioProcessChar(Console
, ConInRec
);
1271 CSR_API(CsrGetScreenBufferInfo
)
1274 PCSRSS_CONSOLE Console
;
1275 PCSRSS_SCREEN_BUFFER Buff
;
1276 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1278 DPRINT("CsrGetScreenBufferInfo\n");
1280 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1281 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1283 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1284 if (! NT_SUCCESS(Status
))
1288 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1289 if (! NT_SUCCESS(Status
))
1291 ConioUnlockConsole(Console
);
1294 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1295 pInfo
->dwSize
.X
= Buff
->MaxX
;
1296 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1297 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1298 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1299 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1300 pInfo
->srWindow
.Left
= Buff
->ShowX
;
1301 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
1302 pInfo
->srWindow
.Top
= Buff
->ShowY
;
1303 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
1304 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1305 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1306 ConioUnlockScreenBuffer(Buff
);
1307 ConioUnlockConsole(Console
);
1309 return STATUS_SUCCESS
;
1312 CSR_API(CsrSetCursor
)
1315 PCSRSS_CONSOLE Console
;
1316 PCSRSS_SCREEN_BUFFER Buff
;
1317 LONG OldCursorX
, OldCursorY
;
1318 LONG NewCursorX
, NewCursorY
;
1320 DPRINT("CsrSetCursor\n");
1322 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1323 if (! NT_SUCCESS(Status
))
1328 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1329 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1331 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1332 if (! NT_SUCCESS(Status
))
1334 ConioUnlockConsole(Console
);
1338 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1339 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1340 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1341 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1343 ConioUnlockScreenBuffer(Buff
);
1344 ConioUnlockConsole(Console
);
1345 return STATUS_INVALID_PARAMETER
;
1347 OldCursorX
= Buff
->CurrentX
;
1348 OldCursorY
= Buff
->CurrentY
;
1349 Buff
->CurrentX
= NewCursorX
;
1350 Buff
->CurrentY
= NewCursorY
;
1351 if (Buff
== Console
->ActiveBuffer
)
1353 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1355 ConioUnlockScreenBuffer(Buff
);
1356 ConioUnlockConsole(Console
);
1357 return STATUS_UNSUCCESSFUL
;
1361 ConioUnlockScreenBuffer(Buff
);
1362 ConioUnlockConsole(Console
);
1364 return STATUS_SUCCESS
;
1367 static VOID FASTCALL
1368 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1370 if (Buff
->MaxX
<= Start
->X
+ Length
)
1372 UpdateRect
->left
= 0;
1376 UpdateRect
->left
= Start
->X
;
1378 if (Buff
->MaxX
<= Start
->X
+ Length
)
1380 UpdateRect
->right
= Buff
->MaxX
- 1;
1384 UpdateRect
->right
= Start
->X
+ Length
- 1;
1386 UpdateRect
->top
= Start
->Y
;
1387 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1388 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1390 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1394 CSR_API(CsrWriteConsoleOutputChar
)
1397 PCHAR String
, tmpString
= NULL
;
1399 PCSRSS_CONSOLE Console
;
1400 PCSRSS_SCREEN_BUFFER Buff
;
1401 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1404 DPRINT("CsrWriteConsoleOutputChar\n");
1406 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1408 if (Request
->Header
.u1
.s1
.TotalLength
1409 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1410 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1412 DPRINT1("Invalid request size\n");
1413 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1414 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1415 return STATUS_INVALID_PARAMETER
;
1418 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1419 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1420 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1421 if (NT_SUCCESS(Status
))
1423 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1425 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
1426 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1427 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1428 NULL
, 0, NULL
, NULL
);
1429 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1432 WideCharToMultiByte(Console
->OutputCodePage
, 0,
1433 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1434 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1435 String
, Length
, NULL
, NULL
);
1439 Status
= STATUS_NO_MEMORY
;
1444 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1449 Status
= ConioLockScreenBuffer(ProcessData
,
1450 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1453 if (NT_SUCCESS(Status
))
1455 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
;
1456 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1457 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1458 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1461 *Buffer
= *String
++;
1464 if (++X
== Buff
->MaxX
)
1466 if (++Y
== Buff
->MaxY
)
1469 Buffer
= Buff
->Buffer
;
1474 if (Buff
== Console
->ActiveBuffer
)
1476 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1477 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1478 ConioDrawRegion(Console
, &UpdateRect
);
1481 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
;
1482 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1484 ConioUnlockScreenBuffer(Buff
);
1486 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1488 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1491 ConioUnlockConsole(Console
);
1493 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1497 CSR_API(CsrFillOutputChar
)
1500 PCSRSS_CONSOLE Console
;
1501 PCSRSS_SCREEN_BUFFER Buff
;
1502 DWORD X
, Y
, Length
, Written
= 0;
1507 DPRINT("CsrFillOutputChar\n");
1509 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1510 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1512 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1513 if (! NT_SUCCESS(Status
))
1518 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1519 if (! NT_SUCCESS(Status
))
1521 ConioUnlockConsole(Console
);
1525 X
= Request
->Data
.FillOutputRequest
.Position
.X
;
1526 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1527 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1528 if(Request
->Data
.FillOutputRequest
.Unicode
)
1529 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1531 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1532 Length
= Request
->Data
.FillOutputRequest
.Length
;
1538 if (++X
== Buff
->MaxX
)
1540 if (++Y
== Buff
->MaxY
)
1543 Buffer
= Buff
->Buffer
;
1549 if (Buff
== Console
->ActiveBuffer
)
1551 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1552 Request
->Data
.FillOutputRequest
.Length
);
1553 ConioDrawRegion(Console
, &UpdateRect
);
1556 ConioUnlockScreenBuffer(Buff
);
1557 ConioUnlockConsole(Console
);
1558 Length
= Request
->Data
.FillOutputRequest
.Length
;
1559 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1560 return STATUS_SUCCESS
;
1563 CSR_API(CsrReadInputEvent
)
1565 PLIST_ENTRY CurrentEntry
;
1566 PCSRSS_CONSOLE Console
;
1568 BOOLEAN Done
= FALSE
;
1569 ConsoleInput
*Input
;
1571 DPRINT("CsrReadInputEvent\n");
1573 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1574 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1575 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1577 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
1578 if (! NT_SUCCESS(Status
))
1583 /* only get input if there is any */
1584 CurrentEntry
= Console
->InputEvents
.Flink
;
1585 while (CurrentEntry
!= &Console
->InputEvents
)
1587 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1588 CurrentEntry
= CurrentEntry
->Flink
;
1590 if (Done
&& !Input
->Fake
)
1592 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1596 RemoveEntryList(&Input
->ListEntry
);
1598 if (!Done
&& !Input
->Fake
)
1600 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1601 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1603 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1608 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1610 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1611 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1612 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1614 Console
->WaitingLines
--;
1616 Console
->WaitingChars
--;
1618 HeapFree(Win32CsrApiHeap
, 0, Input
);
1623 Status
= STATUS_SUCCESS
;
1624 Console
->EarlyReturn
= FALSE
;
1628 Status
= STATUS_PENDING
;
1629 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1632 if (IsListEmpty(&Console
->InputEvents
))
1634 ResetEvent(Console
->ActiveEvent
);
1637 ConioUnlockConsole(Console
);
1642 CSR_API(CsrWriteConsoleOutputAttrib
)
1644 PCSRSS_CONSOLE Console
;
1645 PCSRSS_SCREEN_BUFFER Buff
;
1652 DPRINT("CsrWriteConsoleOutputAttrib\n");
1654 if (Request
->Header
.u1
.s1
.TotalLength
1655 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1656 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1658 DPRINT1("Invalid request size\n");
1659 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1660 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1661 return STATUS_INVALID_PARAMETER
;
1664 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1665 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1666 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1667 if (! NT_SUCCESS(Status
))
1672 Status
= ConioLockScreenBuffer(ProcessData
,
1673 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1676 if (! NT_SUCCESS(Status
))
1678 ConioUnlockConsole(Console
);
1682 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
;
1683 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1684 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1685 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1686 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1689 *Buffer
= (UCHAR
)(*Attribute
++);
1691 if (++X
== Buff
->MaxX
)
1693 if (++Y
== Buff
->MaxY
)
1696 Buffer
= Buff
->Buffer
+ 1;
1702 if (Buff
== Console
->ActiveBuffer
)
1704 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1705 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1706 ConioDrawRegion(Console
, &UpdateRect
);
1709 ConioUnlockConsole(Console
);
1711 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= X
;
1712 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1714 ConioUnlockScreenBuffer(Buff
);
1716 return STATUS_SUCCESS
;
1719 CSR_API(CsrFillOutputAttrib
)
1721 PCSRSS_SCREEN_BUFFER Buff
;
1727 PCSRSS_CONSOLE Console
;
1729 DPRINT("CsrFillOutputAttrib\n");
1731 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1732 if (! NT_SUCCESS(Status
))
1737 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1738 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1739 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1740 if (! NT_SUCCESS(Status
))
1742 ConioUnlockConsole(Console
);
1746 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
;
1747 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1748 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1749 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1750 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1755 if (++X
== Buff
->MaxX
)
1757 if (++Y
== Buff
->MaxY
)
1760 Buffer
= Buff
->Buffer
+ 1;
1766 if (Buff
== Console
->ActiveBuffer
)
1768 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1769 Request
->Data
.FillOutputAttribRequest
.Length
);
1770 ConioDrawRegion(Console
, &UpdateRect
);
1773 ConioUnlockScreenBuffer(Buff
);
1774 ConioUnlockConsole(Console
);
1776 return STATUS_SUCCESS
;
1780 CSR_API(CsrGetCursorInfo
)
1782 PCSRSS_SCREEN_BUFFER Buff
;
1785 DPRINT("CsrGetCursorInfo\n");
1787 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1788 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1790 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1791 if (! NT_SUCCESS(Status
))
1795 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1796 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1797 ConioUnlockScreenBuffer(Buff
);
1799 return STATUS_SUCCESS
;
1802 CSR_API(CsrSetCursorInfo
)
1804 PCSRSS_CONSOLE Console
;
1805 PCSRSS_SCREEN_BUFFER Buff
;
1810 DPRINT("CsrSetCursorInfo\n");
1812 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1813 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1815 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1816 if (! NT_SUCCESS(Status
))
1821 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1822 if (! NT_SUCCESS(Status
))
1824 ConioUnlockConsole(Console
);
1828 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1829 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1839 if (Size
!= Buff
->CursorInfo
.dwSize
1840 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1842 Buff
->CursorInfo
.dwSize
= Size
;
1843 Buff
->CursorInfo
.bVisible
= Visible
;
1845 if (! ConioSetCursorInfo(Console
, Buff
))
1847 ConioUnlockScreenBuffer(Buff
);
1848 ConioUnlockConsole(Console
);
1849 return STATUS_UNSUCCESSFUL
;
1853 ConioUnlockScreenBuffer(Buff
);
1854 ConioUnlockConsole(Console
);
1856 return STATUS_SUCCESS
;
1859 CSR_API(CsrSetTextAttrib
)
1862 PCSRSS_CONSOLE Console
;
1863 PCSRSS_SCREEN_BUFFER Buff
;
1865 DPRINT("CsrSetTextAttrib\n");
1867 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1868 if (! NT_SUCCESS(Status
))
1873 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1874 if (! NT_SUCCESS(Status
))
1876 ConioUnlockConsole(Console
);
1880 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1881 if (Buff
== Console
->ActiveBuffer
)
1883 if (! ConioUpdateScreenInfo(Console
, Buff
))
1885 ConioUnlockScreenBuffer(Buff
);
1886 ConioUnlockConsole(Console
);
1887 return STATUS_UNSUCCESSFUL
;
1891 ConioUnlockScreenBuffer(Buff
);
1892 ConioUnlockConsole(Console
);
1894 return STATUS_SUCCESS
;
1897 CSR_API(CsrSetConsoleMode
)
1900 PCSRSS_CONSOLE Console
;
1901 PCSRSS_SCREEN_BUFFER Buff
;
1903 DPRINT("CsrSetConsoleMode\n");
1905 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1906 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1907 Status
= Win32CsrGetObject(ProcessData
,
1908 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
1909 (Object_t
**) &Console
, GENERIC_WRITE
);
1910 if (! NT_SUCCESS(Status
))
1915 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1916 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1918 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
1920 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
1922 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
1926 Status
= STATUS_INVALID_HANDLE
;
1929 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1934 CSR_API(CsrGetConsoleMode
)
1937 PCSRSS_CONSOLE Console
;
1938 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
1940 DPRINT("CsrGetConsoleMode\n");
1942 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1943 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1944 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
1945 (Object_t
**) &Console
, GENERIC_READ
);
1946 if (! NT_SUCCESS(Status
))
1950 Status
= STATUS_SUCCESS
;
1951 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
1952 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1954 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
1956 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
1958 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
1962 Status
= STATUS_INVALID_HANDLE
;
1965 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1969 CSR_API(CsrCreateScreenBuffer
)
1971 PCSRSS_CONSOLE Console
;
1972 PCSRSS_SCREEN_BUFFER Buff
;
1975 DPRINT("CsrCreateScreenBuffer\n");
1977 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
1978 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1979 if (! NT_SUCCESS(Status
))
1984 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1985 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1987 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
1991 if (Console
->ActiveBuffer
)
1993 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
1994 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
1995 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
1996 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
2000 Buff
->CursorInfo
.bVisible
= TRUE
;
2001 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
2004 if (Buff
->MaxX
== 0)
2009 if (Buff
->MaxY
== 0)
2014 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2015 if(NT_SUCCESS(Status
))
2017 Status
= Win32CsrInsertObject(ProcessData
,
2018 &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
,
2020 Request
->Data
.CreateScreenBufferRequest
.Access
,
2021 Request
->Data
.CreateScreenBufferRequest
.Inheritable
);
2026 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2029 ConioUnlockConsole(Console
);
2030 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
2034 CSR_API(CsrSetScreenBuffer
)
2037 PCSRSS_CONSOLE Console
;
2038 PCSRSS_SCREEN_BUFFER Buff
;
2040 DPRINT("CsrSetScreenBuffer\n");
2042 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2043 if (! NT_SUCCESS(Status
))
2048 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2049 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2051 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
, GENERIC_WRITE
);
2052 if (! NT_SUCCESS(Status
))
2054 ConioUnlockConsole(Console
);
2058 if (Buff
== Console
->ActiveBuffer
)
2060 ConioUnlockScreenBuffer(Buff
);
2061 ConioUnlockConsole(Console
);
2062 return STATUS_SUCCESS
;
2065 /* drop reference to old buffer, maybe delete */
2066 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2068 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2070 /* tie console to new buffer */
2071 Console
->ActiveBuffer
= Buff
;
2072 /* inc ref count on new buffer */
2073 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2074 /* Redraw the console */
2075 ConioDrawConsole(Console
);
2077 ConioUnlockScreenBuffer(Buff
);
2078 ConioUnlockConsole(Console
);
2080 return STATUS_SUCCESS
;
2083 CSR_API(CsrSetTitle
)
2086 PCSRSS_CONSOLE Console
;
2089 DPRINT("CsrSetTitle\n");
2091 if (Request
->Header
.u1
.s1
.TotalLength
2092 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2093 + Request
->Data
.SetTitleRequest
.Length
)
2095 DPRINT1("Invalid request size\n");
2096 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2097 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2098 return STATUS_INVALID_PARAMETER
;
2101 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2102 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2103 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2104 if(NT_SUCCESS(Status
))
2106 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2109 /* copy title to console */
2110 RtlFreeUnicodeString(&Console
->Title
);
2111 Console
->Title
.Buffer
= Buffer
;
2112 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2113 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2114 if (! ConioChangeTitle(Console
))
2116 Status
= STATUS_UNSUCCESSFUL
;
2120 Status
= STATUS_SUCCESS
;
2125 Status
= STATUS_NO_MEMORY
;
2127 ConioUnlockConsole(Console
);
2133 CSR_API(CsrGetTitle
)
2136 PCSRSS_CONSOLE Console
;
2139 DPRINT("CsrGetTitle\n");
2141 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2142 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2143 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2144 if (! NT_SUCCESS(Status
))
2146 DPRINT1("Can't get console\n");
2150 /* Copy title of the console to the user title buffer */
2151 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2152 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2153 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2154 Console
->Title
.Length
);
2155 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2157 ConioUnlockConsole(Console
);
2159 if (Length
> sizeof(CSR_API_MESSAGE
))
2161 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2162 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2164 return STATUS_SUCCESS
;
2167 CSR_API(CsrWriteConsoleOutput
)
2169 SHORT i
, X
, Y
, SizeX
, SizeY
;
2170 PCSRSS_CONSOLE Console
;
2171 PCSRSS_SCREEN_BUFFER Buff
;
2173 CHAR_INFO
* CurCharInfo
;
2175 CHAR_INFO
* CharInfo
;
2182 DPRINT("CsrWriteConsoleOutput\n");
2184 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2185 if (! NT_SUCCESS(Status
))
2190 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2191 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2192 Status
= ConioLockScreenBuffer(ProcessData
,
2193 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2196 if (! NT_SUCCESS(Status
))
2198 ConioUnlockConsole(Console
);
2202 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2203 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2204 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2205 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2206 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2207 (((ULONG_PTR
)CharInfo
+ PSize
) >
2208 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2210 ConioUnlockScreenBuffer(Buff
);
2211 ConioUnlockConsole(Console
);
2212 return STATUS_ACCESS_VIOLATION
;
2214 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2215 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2216 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2217 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2219 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2220 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2221 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2222 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2224 /* Make sure WriteRegion is inside the screen buffer */
2225 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2226 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2228 ConioUnlockScreenBuffer(Buff
);
2229 ConioUnlockConsole(Console
);
2231 /* It is okay to have a WriteRegion completely outside the screen buffer.
2232 No data is written then. */
2233 return STATUS_SUCCESS
;
2236 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2238 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2239 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.left
, Y
);
2240 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2243 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2245 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2249 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
2252 *Ptr
++ = CurCharInfo
->Attributes
;
2257 ConioDrawRegion(Console
, &WriteRegion
);
2259 ConioUnlockScreenBuffer(Buff
);
2260 ConioUnlockConsole(Console
);
2262 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2263 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2264 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2265 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2267 return STATUS_SUCCESS
;
2270 CSR_API(CsrFlushInputBuffer
)
2272 PLIST_ENTRY CurrentEntry
;
2273 PCSRSS_CONSOLE Console
;
2274 ConsoleInput
* Input
;
2277 DPRINT("CsrFlushInputBuffer\n");
2279 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2280 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2281 Status
= ConioLockConsole(ProcessData
,
2282 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2285 if(! NT_SUCCESS(Status
))
2290 /* Discard all entries in the input event queue */
2291 while (!IsListEmpty(&Console
->InputEvents
))
2293 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2294 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2295 /* Destroy the event */
2296 HeapFree(Win32CsrApiHeap
, 0, Input
);
2298 ResetEvent(Console
->ActiveEvent
);
2299 Console
->WaitingChars
=0;
2301 ConioUnlockConsole(Console
);
2303 return STATUS_SUCCESS
;
2306 CSR_API(CsrScrollConsoleScreenBuffer
)
2308 PCSRSS_CONSOLE Console
;
2309 PCSRSS_SCREEN_BUFFER Buff
;
2314 RECT ScrollRectangle
;
2317 HANDLE ConsoleHandle
;
2318 BOOLEAN UseClipRectangle
;
2319 COORD DestinationOrigin
;
2323 DPRINT("CsrScrollConsoleScreenBuffer\n");
2325 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
2326 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
2327 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
2328 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
2330 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2331 if (! NT_SUCCESS(Status
))
2336 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2337 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2338 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
2339 if (! NT_SUCCESS(Status
))
2341 ConioUnlockConsole(Console
);
2345 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2346 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2347 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2348 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2350 /* Make sure source rectangle is inside the screen buffer */
2351 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2352 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2354 ConioUnlockScreenBuffer(Buff
);
2355 ConioUnlockConsole(Console
);
2356 return STATUS_SUCCESS
;
2359 /* If the source was clipped on the left or top, adjust the destination accordingly */
2360 if (ScrollRectangle
.left
< 0)
2362 DestinationOrigin
.X
-= ScrollRectangle
.left
;
2364 if (ScrollRectangle
.top
< 0)
2366 DestinationOrigin
.Y
-= ScrollRectangle
.top
;
2369 if (UseClipRectangle
)
2371 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2372 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2373 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2374 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2375 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
2377 ConioUnlockConsole(Console
);
2378 ConioUnlockScreenBuffer(Buff
);
2379 return STATUS_SUCCESS
;
2384 ClipRectangle
= ScreenBuffer
;
2387 ConioInitRect(&DstRegion
,
2388 DestinationOrigin
.Y
,
2389 DestinationOrigin
.X
,
2390 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
2391 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
2393 if (Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
)
2394 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
2396 FillChar
= Fill
.Char
.AsciiChar
;
2398 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
2400 if (Buff
== Console
->ActiveBuffer
)
2402 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
2403 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
2405 /* Draw update region */
2406 ConioDrawRegion(Console
, &UpdateRegion
);
2410 ConioUnlockScreenBuffer(Buff
);
2411 ConioUnlockConsole(Console
);
2413 return STATUS_SUCCESS
;
2416 CSR_API(CsrReadConsoleOutputChar
)
2419 PCSRSS_CONSOLE Console
;
2420 PCSRSS_SCREEN_BUFFER Buff
;
2427 DPRINT("CsrReadConsoleOutputChar\n");
2429 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2430 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2431 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2433 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2435 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2436 if (! NT_SUCCESS(Status
))
2441 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2442 if (! NT_SUCCESS(Status
))
2444 ConioUnlockConsole(Console
);
2448 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
;
2449 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2451 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2453 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2455 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2457 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2458 ReadBuffer
+= sizeof(WCHAR
);
2461 *(ReadBuffer
++) = Char
;
2465 if (Xpos
== Buff
->MaxX
)
2470 if (Ypos
== Buff
->MaxY
)
2478 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
;
2479 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2481 ConioUnlockScreenBuffer(Buff
);
2482 ConioUnlockConsole(Console
);
2484 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2485 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2487 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2488 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2491 return STATUS_SUCCESS
;
2495 CSR_API(CsrReadConsoleOutputAttrib
)
2498 PCSRSS_SCREEN_BUFFER Buff
;
2502 DWORD CurrentLength
;
2504 DPRINT("CsrReadConsoleOutputAttrib\n");
2506 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2507 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2508 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2510 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2511 if (! NT_SUCCESS(Status
))
2516 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
;
2517 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2519 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2521 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2526 if (Xpos
== Buff
->MaxX
)
2531 if (Ypos
== Buff
->MaxY
)
2540 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
;
2541 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2543 ConioUnlockScreenBuffer(Buff
);
2545 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2546 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2547 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2549 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2550 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2553 return STATUS_SUCCESS
;
2557 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2560 PCSRSS_CONSOLE Console
;
2561 PLIST_ENTRY CurrentItem
;
2563 ConsoleInput
*Input
;
2565 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2567 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2568 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2570 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2571 if (! NT_SUCCESS(Status
))
2576 CurrentItem
= Console
->InputEvents
.Flink
;
2579 /* If there are any events ... */
2580 while (CurrentItem
!= &Console
->InputEvents
)
2582 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2583 CurrentItem
= CurrentItem
->Flink
;
2590 ConioUnlockConsole(Console
);
2592 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2594 return STATUS_SUCCESS
;
2598 CSR_API(CsrPeekConsoleInput
)
2601 PCSRSS_CONSOLE Console
;
2604 PLIST_ENTRY CurrentItem
;
2605 PINPUT_RECORD InputRecord
;
2609 DPRINT("CsrPeekConsoleInput\n");
2611 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2612 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2614 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2615 if(! NT_SUCCESS(Status
))
2620 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2621 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2622 Size
= Length
* sizeof(INPUT_RECORD
);
2624 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2625 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2627 ConioUnlockConsole(Console
);
2628 return STATUS_ACCESS_VIOLATION
;
2633 if (! IsListEmpty(&Console
->InputEvents
))
2635 CurrentItem
= Console
->InputEvents
.Flink
;
2637 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2639 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2643 CurrentItem
= CurrentItem
->Flink
;
2648 *InputRecord
= Item
->InputEvent
;
2650 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2652 ConioInputEventToAnsi(Console
, InputRecord
);
2656 CurrentItem
= CurrentItem
->Flink
;
2660 ConioUnlockConsole(Console
);
2662 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2664 return STATUS_SUCCESS
;
2668 CSR_API(CsrReadConsoleOutput
)
2670 PCHAR_INFO CharInfo
;
2671 PCHAR_INFO CurCharInfo
;
2672 PCSRSS_SCREEN_BUFFER Buff
;
2686 DPRINT("CsrReadConsoleOutput\n");
2688 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2689 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2691 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2692 if (! NT_SUCCESS(Status
))
2697 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2698 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2699 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2700 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2701 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2702 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2703 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2704 Length
= BufferSize
.X
* BufferSize
.Y
;
2705 Size
= Length
* sizeof(CHAR_INFO
);
2707 /* FIXME: Is this correct? */
2708 CodePage
= ProcessData
->Console
->OutputCodePage
;
2710 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2711 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2713 ConioUnlockScreenBuffer(Buff
);
2714 return STATUS_ACCESS_VIOLATION
;
2717 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2718 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2719 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2720 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2722 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2723 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2725 ConioUnlockScreenBuffer(Buff
);
2726 return STATUS_SUCCESS
;
2729 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2731 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2733 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.left
, Y
);
2734 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2736 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2738 MultiByteToWideChar(CodePage
, 0,
2740 &CurCharInfo
->Char
.UnicodeChar
, 1);
2744 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
2746 CurCharInfo
->Attributes
= *Ptr
++;
2751 ConioUnlockScreenBuffer(Buff
);
2753 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2754 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2755 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2756 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2758 return STATUS_SUCCESS
;
2762 CSR_API(CsrWriteConsoleInput
)
2764 PINPUT_RECORD InputRecord
;
2765 PCSRSS_CONSOLE Console
;
2770 ConsoleInput
* Record
;
2772 DPRINT("CsrWriteConsoleInput\n");
2774 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2775 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2777 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
, GENERIC_WRITE
);
2778 if (! NT_SUCCESS(Status
))
2783 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2784 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2785 Size
= Length
* sizeof(INPUT_RECORD
);
2787 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2788 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2790 ConioUnlockConsole(Console
);
2791 return STATUS_ACCESS_VIOLATION
;
2794 for (i
= 0; i
< Length
; i
++)
2796 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2799 ConioUnlockConsole(Console
);
2800 return STATUS_INSUFFICIENT_RESOURCES
;
2803 Record
->Echoed
= FALSE
;
2804 Record
->Fake
= FALSE
;
2805 //Record->InputEvent = *InputRecord++;
2806 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
2807 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2809 /* FIXME - convert from unicode to ascii!! */
2810 ConioProcessChar(Console
, Record
);
2814 ConioUnlockConsole(Console
);
2816 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2818 return STATUS_SUCCESS
;
2821 /**********************************************************************
2822 * HardwareStateProperty
2825 * Set/Get the value of the HardwareState and switch
2826 * between direct video buffer ouput and GDI windowed
2829 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2830 * object. We use the same object to Request.
2832 * ConsoleHwState has the correct size to be compatible
2833 * with NT's, but values are not.
2835 static NTSTATUS FASTCALL
2836 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2838 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2840 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2841 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2843 if (Console
->HardwareState
!= ConsoleHwState
)
2845 /* TODO: implement switching from full screen to windowed mode */
2846 /* TODO: or back; now simply store the hardware state */
2847 Console
->HardwareState
= ConsoleHwState
;
2850 return STATUS_SUCCESS
;
2853 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2856 CSR_API(CsrHardwareStateProperty
)
2858 PCSRSS_CONSOLE Console
;
2861 DPRINT("CsrHardwareStateProperty\n");
2863 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2864 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2866 Status
= ConioLockConsole(ProcessData
,
2867 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2870 if (! NT_SUCCESS(Status
))
2872 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2876 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2878 case CONSOLE_HARDWARE_STATE_GET
:
2879 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
2882 case CONSOLE_HARDWARE_STATE_SET
:
2883 DPRINT("Setting console hardware state.\n");
2884 Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2888 Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2892 ConioUnlockConsole(Console
);
2897 CSR_API(CsrGetConsoleWindow
)
2899 PCSRSS_CONSOLE Console
;
2902 DPRINT("CsrGetConsoleWindow\n");
2904 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2905 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2907 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2908 if (! NT_SUCCESS(Status
))
2913 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
2914 ConioUnlockConsole(Console
);
2916 return STATUS_SUCCESS
;
2919 CSR_API(CsrSetConsoleIcon
)
2921 PCSRSS_CONSOLE Console
;
2924 DPRINT("CsrSetConsoleIcon\n");
2926 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2927 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2929 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2930 if (! NT_SUCCESS(Status
))
2935 Status
= (ConioChangeIcon(Console
, Request
->Data
.SetConsoleIconRequest
.WindowIcon
)
2936 ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
2937 ConioUnlockConsole(Console
);
2942 CSR_API(CsrGetConsoleCodePage
)
2944 PCSRSS_CONSOLE Console
;
2947 DPRINT("CsrGetConsoleCodePage\n");
2949 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2950 if (! NT_SUCCESS(Status
))
2955 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2956 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2957 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
2958 ConioUnlockConsole(Console
);
2959 return STATUS_SUCCESS
;
2962 CSR_API(CsrSetConsoleCodePage
)
2964 PCSRSS_CONSOLE Console
;
2967 DPRINT("CsrSetConsoleCodePage\n");
2969 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2970 if (! NT_SUCCESS(Status
))
2975 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2976 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2978 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
2980 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
2981 ConioUnlockConsole(Console
);
2982 return STATUS_SUCCESS
;
2985 ConioUnlockConsole(Console
);
2986 return STATUS_INVALID_PARAMETER
;
2989 CSR_API(CsrGetConsoleOutputCodePage
)
2991 PCSRSS_CONSOLE Console
;
2994 DPRINT("CsrGetConsoleOutputCodePage\n");
2996 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2997 if (! NT_SUCCESS(Status
))
3002 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3003 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3004 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3005 ConioUnlockConsole(Console
);
3006 return STATUS_SUCCESS
;
3009 CSR_API(CsrSetConsoleOutputCodePage
)
3011 PCSRSS_CONSOLE Console
;
3014 DPRINT("CsrSetConsoleOutputCodePage\n");
3016 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3017 if (! NT_SUCCESS(Status
))
3022 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3023 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3025 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3027 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3028 ConioUnlockConsole(Console
);
3029 return STATUS_SUCCESS
;
3032 ConioUnlockConsole(Console
);
3033 return STATUS_INVALID_PARAMETER
;
3036 CSR_API(CsrGetProcessList
)
3039 PCSRSS_CONSOLE Console
;
3040 PCSRSS_PROCESS_DATA current
;
3041 PLIST_ENTRY current_entry
;
3042 ULONG nItems
, nCopied
, Length
;
3045 DPRINT("CsrGetProcessList\n");
3047 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3048 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3049 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3051 nItems
= nCopied
= 0;
3052 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3053 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3055 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3056 if (! NT_SUCCESS(Status
))
3061 DPRINT1("Console_Api Ctrl-C\n");
3063 for(current_entry
= Console
->ProcessList
.Flink
;
3064 current_entry
!= &Console
->ProcessList
;
3065 current_entry
= current_entry
->Flink
)
3067 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3068 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3070 *(Buffer
++) = current
->ProcessId
;
3075 ConioUnlockConsole(Console
);
3077 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3078 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3080 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3081 if (Length
> sizeof(CSR_API_MESSAGE
))
3083 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3084 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3086 return STATUS_SUCCESS
;
3089 CSR_API(CsrGenerateCtrlEvent
)
3091 PCSRSS_CONSOLE Console
;
3092 PCSRSS_PROCESS_DATA current
;
3093 PLIST_ENTRY current_entry
;
3097 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3098 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3100 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3101 if (! NT_SUCCESS(Status
))
3106 Group
= Request
->Data
.GenerateCtrlEvent
.ProcessGroup
;
3107 Status
= STATUS_INVALID_PARAMETER
;
3108 for (current_entry
= Console
->ProcessList
.Flink
;
3109 current_entry
!= &Console
->ProcessList
;
3110 current_entry
= current_entry
->Flink
)
3112 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3113 if (Group
== 0 || current
->ProcessGroup
== Group
)
3115 ConioConsoleCtrlEvent(Request
->Data
.GenerateCtrlEvent
.Event
, current
);
3116 Status
= STATUS_SUCCESS
;
3120 ConioUnlockConsole(Console
);
3125 CSR_API(CsrSetScreenBufferSize
)
3128 PCSRSS_CONSOLE Console
;
3129 PCSRSS_SCREEN_BUFFER Buff
;
3131 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3132 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3134 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3135 if (!NT_SUCCESS(Status
))
3140 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferSize
.OutputHandle
, &Buff
, GENERIC_WRITE
);
3141 if (!NT_SUCCESS(Status
))
3143 ConioUnlockConsole(Console
);
3147 Status
= ConioResizeBuffer(Console
, Buff
, Request
->Data
.SetScreenBufferSize
.Size
);
3148 ConioUnlockScreenBuffer(Buff
);
3149 ConioUnlockConsole(Console
);