Kill large parts of rosrtl. devmode conversion implented in gdi32 because it's actual...
[reactos.git] / reactos / subsys / csrss / win32csr / conio.c
1 /*
2 * reactos/subsys/csrss/win32csr/conio.c
3 *
4 * Console I/O functions
5 *
6 * ReactOS Operating System
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <windows.h>
12 #define NTOS_MODE_USER
13 #include <ndk/ntndk.h>
14 #include <ddk/ntddblue.h>
15 #include <rosrtl/string.h>
16
17 #include <string.h>
18
19 #include "api.h"
20 #include "conio.h"
21 #include "desktopbg.h"
22 #include "guiconsole.h"
23 #include "tuiconsole.h"
24 #include "win32csr.h"
25
26 #define NDEBUG
27 #include <debug.h>
28
29 /* FIXME: Is there a way to create real aliasses with gcc? [CSH] */
30 #define ALIAS(Name, Target) typeof(Target) Name = Target
31
32 /* Private user32 routines for CSRSS, not defined in any header file */
33 extern VOID STDCALL PrivateCsrssRegisterPrimitive(VOID);
34 extern VOID STDCALL PrivateCsrssAcquireOrReleaseInputOwnership(BOOL Release);
35
36 /* GLOBALS *******************************************************************/
37
38 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
39 ((Rect)->top) = Top; \
40 ((Rect)->left) = Left; \
41 ((Rect)->bottom) = Bottom; \
42 ((Rect)->right) = Right
43
44 #define ConioIsRectEmpty(Rect) \
45 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
46
47 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
48 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
49
50 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
51 MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
52
53 #define ConsoleUnicodeToAnsiN(Console, dChar, sWChar, nChars) \
54 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), (nChars), (dChar), (nChars) * sizeof(WCHAR), NULL, NULL)
55
56 /* FUNCTIONS *****************************************************************/
57
58 STATIC NTSTATUS FASTCALL
59 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console)
60 {
61 if (NULL == ProcessData->Console)
62 {
63 *Console = NULL;
64 return STATUS_SUCCESS;
65 }
66
67 EnterCriticalSection(&(ProcessData->Console->Header.Lock));
68 *Console = ProcessData->Console;
69
70 return STATUS_SUCCESS;
71 }
72
73 VOID FASTCALL
74 ConioConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData)
75 {
76 HANDLE Thread;
77
78 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->ProcessId);
79
80 if (ProcessData->CtrlDispatcher)
81 {
82
83 Thread = CreateRemoteThread(ProcessData->Process, NULL, 0,
84 (LPTHREAD_START_ROUTINE) ProcessData->CtrlDispatcher,
85 (PVOID) Event, 0, NULL);
86 if (NULL == Thread)
87 {
88 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
89 return;
90 }
91 CloseHandle(Thread);
92 }
93 }
94
95 #define GET_CELL_BUFFER(b,o)\
96 (b)->Buffer[(o)++]
97
98 #define SET_CELL_BUFFER(b,o,c,a)\
99 (b)->Buffer[(o)++]=(c),\
100 (b)->Buffer[(o)++]=(a)
101
102 static VOID FASTCALL
103 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff)
104 {
105 DWORD Offset = 2 * (Buff->CurrentY * Buff->MaxX);
106 UINT Pos;
107
108 for (Pos = 0; Pos < Buff->MaxX; Pos++)
109 {
110 /* Fill the cell: Offset is incremented by the macro */
111 SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib);
112 }
113 }
114
115 STATIC NTSTATUS FASTCALL
116 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
117 PCSRSS_SCREEN_BUFFER Buffer)
118 {
119 Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC;
120 Buffer->Header.ReferenceCount = 0;
121 Buffer->MaxX = Console->Size.X;
122 Buffer->MaxY = Console->Size.Y;
123 Buffer->ShowX = 0;
124 Buffer->ShowY = 0;
125 Buffer->Buffer = HeapAlloc(Win32CsrApiHeap, 0, Buffer->MaxX * Buffer->MaxY * 2);
126 if (NULL == Buffer->Buffer)
127 {
128 return STATUS_INSUFFICIENT_RESOURCES;
129 }
130 InitializeCriticalSection(&Buffer->Header.Lock);
131 ConioInitScreenBuffer(Console, Buffer);
132 /* initialize buffer to be empty with default attributes */
133 for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++)
134 {
135 ClearLineBuffer(Buffer);
136 }
137 Buffer->CursorInfo.bVisible = TRUE;
138 Buffer->CursorInfo.dwSize = 5;
139 Buffer->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
140 Buffer->CurrentX = 0;
141 Buffer->CurrentY = 0;
142
143 return STATUS_SUCCESS;
144 }
145
146 STATIC NTSTATUS STDCALL
147 CsrInitConsole(PCSRSS_CONSOLE Console)
148 {
149 NTSTATUS Status;
150 SECURITY_ATTRIBUTES SecurityAttributes;
151 PCSRSS_SCREEN_BUFFER NewBuffer;
152 BOOL GuiMode;
153
154 Console->Title.MaximumLength = Console->Title.Length = 0;
155 Console->Title.Buffer = NULL;
156
157 RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
158
159 Console->Header.ReferenceCount = 0;
160 Console->WaitingChars = 0;
161 Console->WaitingLines = 0;
162 Console->EchoCount = 0;
163 Console->Header.Type = CONIO_CONSOLE_MAGIC;
164 Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
165 Console->EarlyReturn = FALSE;
166 Console->ActiveBuffer = NULL;
167 InitializeListHead(&Console->InputEvents);
168 InitializeListHead(&Console->ProcessList);
169
170 Console->CodePage = GetOEMCP();
171 Console->OutputCodePage = GetOEMCP();
172
173 SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
174 SecurityAttributes.lpSecurityDescriptor = NULL;
175 SecurityAttributes.bInheritHandle = TRUE;
176
177 Console->ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
178 if (NULL == Console->ActiveEvent)
179 {
180 RtlFreeUnicodeString(&Console->Title);
181 return STATUS_UNSUCCESSFUL;
182 }
183 Console->PrivateData = NULL;
184 InitializeCriticalSection(&Console->Header.Lock);
185 GuiMode = DtbgIsDesktopVisible();
186 if (! GuiMode)
187 {
188 Status = TuiInitConsole(Console);
189 if (! NT_SUCCESS(Status))
190 {
191 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
192 GuiMode = TRUE;
193 }
194 }
195 if (GuiMode)
196 {
197 Status = GuiInitConsole(Console);
198 if (! NT_SUCCESS(Status))
199 {
200 RtlFreeUnicodeString(&Console->Title);
201 DeleteCriticalSection(&Console->Header.Lock);
202 CloseHandle(Console->ActiveEvent);
203 return Status;
204 }
205 }
206
207 NewBuffer = HeapAlloc(Win32CsrApiHeap, 0, sizeof(CSRSS_SCREEN_BUFFER));
208 if (NULL == NewBuffer)
209 {
210 ConioCleanupConsole(Console);
211 RtlFreeUnicodeString(&Console->Title);
212 DeleteCriticalSection(&Console->Header.Lock);
213 CloseHandle(Console->ActiveEvent);
214 return STATUS_INSUFFICIENT_RESOURCES;
215 }
216 Status = CsrInitConsoleScreenBuffer(Console, NewBuffer);
217 if (! NT_SUCCESS(Status))
218 {
219 ConioCleanupConsole(Console);
220 RtlFreeUnicodeString(&Console->Title);
221 DeleteCriticalSection(&Console->Header.Lock);
222 CloseHandle(Console->ActiveEvent);
223 HeapFree(Win32CsrApiHeap, 0, NewBuffer);
224 return Status;
225 }
226 Console->ActiveBuffer = NewBuffer;
227 /* add a reference count because the buffer is tied to the console */
228 Console->ActiveBuffer->Header.ReferenceCount++;
229 /* make console active, and insert into console list */
230 /* copy buffer contents to screen */
231 ConioDrawConsole(Console);
232
233 return STATUS_SUCCESS;
234 }
235
236
237 CSR_API(CsrAllocConsole)
238 {
239 PCSRSS_CONSOLE Console;
240 NTSTATUS Status;
241
242 DPRINT("CsrAllocConsole\n");
243
244 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
245 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
246
247 if (ProcessData == NULL)
248 {
249 return Request->Status = STATUS_INVALID_PARAMETER;
250 }
251
252 if (ProcessData->Console)
253 {
254 Request->Status = STATUS_INVALID_PARAMETER;
255 return STATUS_INVALID_PARAMETER;
256 }
257
258 Request->Status = STATUS_SUCCESS;
259 Console = HeapAlloc(Win32CsrApiHeap, 0, sizeof(CSRSS_CONSOLE));
260 if (NULL == Console)
261 {
262 Request->Status = STATUS_NO_MEMORY;
263 return STATUS_NO_MEMORY;
264 }
265 Request->Status = CsrInitConsole(Console);
266 if (! NT_SUCCESS(Request->Status))
267 {
268 HeapFree(Win32CsrApiHeap, 0, Console);
269 return Request->Status;
270 }
271 ProcessData->Console = Console;
272 Request->Data.AllocConsoleRequest.Console = Console;
273
274 /* add a reference count because the process is tied to the console */
275 Console->Header.ReferenceCount++;
276 Status = Win32CsrInsertObject(ProcessData, &Request->Data.AllocConsoleRequest.InputHandle, &Console->Header);
277 if (! NT_SUCCESS(Status))
278 {
279 ConioDeleteConsole((Object_t *) Console);
280 ProcessData->Console = 0;
281 return Request->Status = Status;
282 }
283 Status = Win32CsrInsertObject(ProcessData, &Request->Data.AllocConsoleRequest.OutputHandle, &Console->ActiveBuffer->Header);
284 if (!NT_SUCCESS(Status))
285 {
286 Console->Header.ReferenceCount--;
287 Win32CsrReleaseObject(ProcessData, Request->Data.AllocConsoleRequest.InputHandle);
288 ProcessData->Console = 0;
289 return Request->Status = Status;
290 }
291
292 if (! DuplicateHandle(GetCurrentProcess(), ProcessData->Console->ActiveEvent,
293 ProcessData->Process, &ProcessData->ConsoleEvent, EVENT_ALL_ACCESS, FALSE, 0))
294 {
295 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError);
296 Console->Header.ReferenceCount--;
297 Win32CsrReleaseObject(ProcessData, Request->Data.AllocConsoleRequest.OutputHandle);
298 Win32CsrReleaseObject(ProcessData, Request->Data.AllocConsoleRequest.InputHandle);
299 ProcessData->Console = 0;
300 Request->Status = Status;
301 return Status;
302 }
303 ProcessData->CtrlDispatcher = Request->Data.AllocConsoleRequest.CtrlDispatcher;
304 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
305 InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ProcessEntry);
306
307 return STATUS_SUCCESS;
308 }
309
310 CSR_API(CsrFreeConsole)
311 {
312 PCSRSS_CONSOLE Console;
313
314 DPRINT("CsrFreeConsole\n");
315
316 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
317 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
318
319 if (ProcessData == NULL || ProcessData->Console == NULL)
320 {
321 return Request->Status = STATUS_INVALID_PARAMETER;
322 }
323
324 Console = ProcessData->Console;
325 Console->Header.ReferenceCount--;
326 ProcessData->Console = NULL;
327 if (0 == Console->Header.ReferenceCount)
328 {
329 ConioDeleteConsole((Object_t *) Console);
330 }
331
332 return STATUS_SUCCESS;
333 }
334
335 STATIC VOID FASTCALL
336 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, UINT *ScrolledLines)
337 {
338 /* slide the viewable screen */
339 if (((Buff->CurrentY - Buff->ShowY + Buff->MaxY) % Buff->MaxY) == Buff->MaxY - 1)
340 {
341 if (++Buff->ShowY == Buff->MaxY)
342 {
343 Buff->ShowY = 0;
344 }
345 (*ScrolledLines)++;
346 }
347 if (++Buff->CurrentY == Buff->MaxY)
348 {
349 Buff->CurrentY = 0;
350 }
351 ClearLineBuffer(Buff);
352 UpdateRect->left = 0;
353 UpdateRect->right = Buff->MaxX - 1;
354 if (UpdateRect->top == Buff->CurrentY)
355 {
356 if (++UpdateRect->top == Buff->MaxY)
357 {
358 UpdateRect->top = 0;
359 }
360 }
361 UpdateRect->bottom = Buff->CurrentY;
362 }
363
364 STATIC NTSTATUS FASTCALL
365 ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
366 CHAR *Buffer, DWORD Length, BOOL Attrib)
367 {
368 int i;
369 DWORD Offset;
370 RECT UpdateRect;
371 LONG CursorStartX, CursorStartY;
372 UINT ScrolledLines;
373
374 ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &CursorStartX, &CursorStartY);
375 UpdateRect.left = Buff->MaxX;
376 UpdateRect.top = Buff->CurrentY;
377 UpdateRect.right = -1;
378 UpdateRect.bottom = Buff->CurrentY;
379 ScrolledLines = 0;
380
381 for (i = 0; i < Length; i++)
382 {
383 if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
384 {
385 /* --- LF --- */
386 if (Buffer[i] == '\n')
387 {
388 Buff->CurrentX = 0;
389 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
390 continue;
391 }
392 /* --- BS --- */
393 else if (Buffer[i] == '\b')
394 {
395 /* Only handle BS if we're not on the first pos of the first line */
396 if (0 != Buff->CurrentX || Buff->ShowY != Buff->CurrentY)
397 {
398 if (0 == Buff->CurrentX)
399 {
400 /* slide virtual position up */
401 Buff->CurrentX = Buff->MaxX - 1;
402 if (0 == Buff->CurrentY)
403 {
404 Buff->CurrentY = Buff->MaxY;
405 }
406 else
407 {
408 Buff->CurrentY--;
409 }
410 if ((0 == UpdateRect.top && UpdateRect.bottom < Buff->CurrentY)
411 || (0 != UpdateRect.top && Buff->CurrentY < UpdateRect.top))
412 {
413 UpdateRect.top = Buff->CurrentY;
414 }
415 }
416 else
417 {
418 Buff->CurrentX--;
419 }
420 Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + Buff->CurrentX);
421 SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib);
422 UpdateRect.left = min(UpdateRect.left, Buff->CurrentX);
423 UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
424 }
425 continue;
426 }
427 /* --- CR --- */
428 else if (Buffer[i] == '\r')
429 {
430 Buff->CurrentX = 0;
431 UpdateRect.left = min(UpdateRect.left, Buff->CurrentX);
432 UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
433 continue;
434 }
435 /* --- TAB --- */
436 else if (Buffer[i] == '\t')
437 {
438 UINT EndX;
439
440 UpdateRect.left = min(UpdateRect.left, Buff->CurrentX);
441 EndX = (Buff->CurrentX + 8) & ~7;
442 if (EndX > Buff->MaxX)
443 {
444 EndX = Buff->MaxX;
445 }
446 Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX);
447 while (Buff->CurrentX < EndX)
448 {
449 Buff->Buffer[Offset] = ' ';
450 Offset += 2;
451 Buff->CurrentX++;
452 }
453 UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX - 1);
454 if (Buff->CurrentX == Buff->MaxX)
455 {
456 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
457 {
458 Buff->CurrentX = 0;
459 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
460 }
461 else
462 {
463 Buff->CurrentX--;
464 }
465 }
466 continue;
467 }
468 }
469 UpdateRect.left = min(UpdateRect.left, Buff->CurrentX);
470 UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
471 Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX);
472 Buff->Buffer[Offset++] = Buffer[i];
473 if (Attrib)
474 {
475 Buff->Buffer[Offset] = Buff->DefaultAttrib;
476 }
477 Buff->CurrentX++;
478 if (Buff->CurrentX == Buff->MaxX)
479 {
480 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
481 {
482 Buff->CurrentX = 0;
483 ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
484 }
485 else
486 {
487 Buff->CurrentX = CursorStartX;
488 }
489 }
490 }
491
492 ConioPhysicalToLogical(Buff, UpdateRect.left, UpdateRect.top, &(UpdateRect.left),
493 &(UpdateRect.top));
494 ConioPhysicalToLogical(Buff, UpdateRect.right, UpdateRect.bottom, &(UpdateRect.right),
495 &(UpdateRect.bottom));
496 if (! ConioIsRectEmpty(&UpdateRect) && NULL != Console && Buff == Console->ActiveBuffer)
497 {
498 ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, ScrolledLines,
499 Buffer, Length);
500 }
501
502 return STATUS_SUCCESS;
503 }
504
505 CSR_API(CsrReadConsole)
506 {
507 PLIST_ENTRY CurrentEntry;
508 ConsoleInput *Input;
509 PUCHAR Buffer;
510 PWCHAR UnicodeBuffer;
511 int i;
512 ULONG nNumberOfCharsToRead, CharSize;
513 PCSRSS_CONSOLE Console;
514 NTSTATUS Status;
515
516 DPRINT("CsrReadConsole\n");
517
518 CharSize = (Request->Data.ReadConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
519
520 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
521 nNumberOfCharsToRead = min(Request->Data.ReadConsoleRequest.NrCharactersToRead, CSRSS_MAX_READ_CONSOLE / CharSize);
522 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
523 Request->Header.DataSize = Request->Header.MessageSize - LPC_MESSAGE_BASE_SIZE;
524
525 Buffer = Request->Data.ReadConsoleRequest.Buffer;
526 UnicodeBuffer = (PWCHAR)Buffer;
527 Status = ConioLockConsole(ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle,
528 &Console);
529 if (! NT_SUCCESS(Status))
530 {
531 return Request->Status = Status;
532 }
533 Request->Data.ReadConsoleRequest.EventHandle = ProcessData->ConsoleEvent;
534 for (i = 0; i < nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++)
535 {
536 /* remove input event from queue */
537 CurrentEntry = RemoveHeadList(&Console->InputEvents);
538 if (IsListEmpty(&Console->InputEvents))
539 {
540 CHECKPOINT;
541 ResetEvent(Console->ActiveEvent);
542 }
543 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
544
545 /* only pay attention to valid ascii chars, on key down */
546 if (KEY_EVENT == Input->InputEvent.EventType
547 && Input->InputEvent.Event.KeyEvent.bKeyDown
548 && Input->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\0')
549 {
550 /* backspace handling */
551 if ('\b' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar)
552 {
553 /* echo if it has not already been done, and either we or the client has chars to be deleted */
554 if (! Input->Echoed
555 && (0 != i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted))
556 {
557 ConioWriteConsole(Console, Console->ActiveBuffer,
558 &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
559 }
560 if (0 != i)
561 {
562 i -= 2; /* if we already have something to return, just back it up by 2 */
563 }
564 else
565 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
566 Console->WaitingChars--;
567 ConioUnlockConsole(Console);
568 HeapFree(Win32CsrApiHeap, 0, Input);
569 Request->Data.ReadConsoleRequest.NrCharactersRead = 0;
570 Request->Status = STATUS_NOTIFY_CLEANUP;
571 return STATUS_NOTIFY_CLEANUP;
572 }
573 Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--;
574 Input->Echoed = TRUE; /* mark as echoed so we don't echo it below */
575 }
576 /* do not copy backspace to buffer */
577 else
578 {
579 if(Request->Data.ReadConsoleRequest.Unicode)
580 UnicodeBuffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar; /* FIXME */
581 else
582 Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
583 }
584 /* echo to screen if enabled and we did not already echo the char */
585 if (0 != (Console->Mode & ENABLE_ECHO_INPUT)
586 && ! Input->Echoed
587 && '\r' != Input->InputEvent.Event.KeyEvent.uChar.AsciiChar)
588 {
589 ConioWriteConsole(Console, Console->ActiveBuffer,
590 &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
591 }
592 }
593 else
594 {
595 i--;
596 }
597 Console->WaitingChars--;
598 HeapFree(Win32CsrApiHeap, 0, Input);
599 }
600 Request->Data.ReadConsoleRequest.NrCharactersRead = i;
601 if (0 == i)
602 {
603 Request->Status = STATUS_PENDING; /* we didn't read anything */
604 }
605 else if (0 != (Console->Mode & ENABLE_LINE_INPUT))
606 {
607 if (0 == Console->WaitingLines ||
608 (Request->Data.ReadConsoleRequest.Unicode ? (L'\n' != UnicodeBuffer[i - 1]) : ('\n' != Buffer[i - 1])))
609 {
610 Request->Status = STATUS_PENDING; /* line buffered, didn't get a complete line */
611 }
612 else
613 {
614 Console->WaitingLines--;
615 Request->Status = STATUS_SUCCESS; /* line buffered, did get a complete line */
616 }
617 }
618 else
619 {
620 Request->Status = STATUS_SUCCESS; /* not line buffered, did read something */
621 }
622
623 if (Request->Status == STATUS_PENDING)
624 {
625 Console->EchoCount = nNumberOfCharsToRead - i;
626 }
627 else
628 {
629 Console->EchoCount = 0; /* if the client is no longer waiting on input, do not echo */
630 }
631 Request->Header.MessageSize += i * CharSize;
632
633 ConioUnlockConsole(Console);
634 return Request->Status;
635 }
636
637 VOID FASTCALL
638 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff,
639 ULONG PhysicalX,
640 ULONG PhysicalY,
641 LONG *LogicalX,
642 LONG *LogicalY)
643 {
644 *LogicalX = PhysicalX;
645 if (PhysicalY < Buff->ShowY)
646 {
647 *LogicalY = Buff->MaxY - Buff->ShowY + PhysicalY;
648 }
649 else
650 {
651 *LogicalY = PhysicalY - Buff->ShowY;
652 }
653 }
654
655 inline BOOLEAN ConioIsEqualRect(
656 RECT *Rect1,
657 RECT *Rect2)
658 {
659 return ((Rect1->left == Rect2->left) && (Rect1->right == Rect2->right) &&
660 (Rect1->top == Rect2->top) && (Rect1->bottom == Rect2->bottom));
661 }
662
663 inline BOOLEAN ConioGetIntersection(
664 RECT *Intersection,
665 RECT *Rect1,
666 RECT *Rect2)
667 {
668 if (ConioIsRectEmpty(Rect1) ||
669 (ConioIsRectEmpty(Rect2)) ||
670 (Rect1->top > Rect2->bottom) ||
671 (Rect1->left > Rect2->right) ||
672 (Rect1->bottom < Rect2->top) ||
673 (Rect1->right < Rect2->left))
674 {
675 /* The rectangles do not intersect */
676 ConioInitRect(Intersection, 0, -1, 0, -1);
677 return FALSE;
678 }
679
680 ConioInitRect(Intersection,
681 max(Rect1->top, Rect2->top),
682 max(Rect1->left, Rect2->left),
683 min(Rect1->bottom, Rect2->bottom),
684 min(Rect1->right, Rect2->right));
685
686 return TRUE;
687 }
688
689 inline BOOLEAN ConioGetUnion(
690 RECT *Union,
691 RECT *Rect1,
692 RECT *Rect2)
693 {
694 if (ConioIsRectEmpty(Rect1))
695 {
696 if (ConioIsRectEmpty(Rect2))
697 {
698 ConioInitRect(Union, 0, -1, 0, -1);
699 return FALSE;
700 }
701 else
702 {
703 *Union = *Rect2;
704 }
705 }
706 else if (ConioIsRectEmpty(Rect2))
707 {
708 *Union = *Rect1;
709 }
710 else
711 {
712 ConioInitRect(Union,
713 min(Rect1->top, Rect2->top),
714 min(Rect1->left, Rect2->left),
715 max(Rect1->bottom, Rect2->bottom),
716 max(Rect1->right, Rect2->right));
717 }
718
719 return TRUE;
720 }
721
722 inline BOOLEAN ConioSubtractRect(
723 RECT *Subtraction,
724 RECT *Rect1,
725 RECT *Rect2)
726 {
727 RECT tmp;
728
729 if (ConioIsRectEmpty(Rect1))
730 {
731 ConioInitRect(Subtraction, 0, -1, 0, -1);
732 return FALSE;
733 }
734 *Subtraction = *Rect1;
735 if (ConioGetIntersection(&tmp, Rect1, Rect2))
736 {
737 if (ConioIsEqualRect(&tmp, Subtraction))
738 {
739 ConioInitRect(Subtraction, 0, -1, 0, -1);
740 return FALSE;
741 }
742 if ((tmp.top == Subtraction->top) && (tmp.bottom == Subtraction->bottom))
743 {
744 if (tmp.left == Subtraction->left)
745 {
746 Subtraction->left = tmp.right;
747 }
748 else if (tmp.right == Subtraction->right)
749 {
750 Subtraction->right = tmp.left;
751 }
752 }
753 else if ((tmp.left == Subtraction->left) && (tmp.right == Subtraction->right))
754 {
755 if (tmp.top == Subtraction->top)
756 {
757 Subtraction->top = tmp.bottom;
758 }
759 else if (tmp.bottom == Subtraction->bottom)
760 {
761 Subtraction->bottom = tmp.top;
762 }
763 }
764 }
765
766 return TRUE;
767 }
768
769 STATIC VOID FASTCALL
770 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
771 RECT *SrcRegion,
772 RECT *DstRegion)
773 {
774 SHORT SrcY, DstY;
775 DWORD SrcOffset;
776 DWORD DstOffset;
777 DWORD BytesPerLine;
778 ULONG i;
779
780 DstY = DstRegion->top;
781 BytesPerLine = ConioRectWidth(DstRegion) * 2;
782
783 SrcY = (SrcRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
784 DstY = (DstRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
785 SrcOffset = (SrcY * ScreenBuffer->MaxX + SrcRegion->left + ScreenBuffer->ShowX) * 2;
786 DstOffset = (DstY * ScreenBuffer->MaxX + DstRegion->left + ScreenBuffer->ShowX) * 2;
787
788 for (i = SrcRegion->top; i <= SrcRegion->bottom; i++)
789 {
790 RtlCopyMemory(
791 &ScreenBuffer->Buffer[DstOffset],
792 &ScreenBuffer->Buffer[SrcOffset],
793 BytesPerLine);
794
795 if (++DstY == ScreenBuffer->MaxY)
796 {
797 DstY = 0;
798 DstOffset = (DstRegion->left + ScreenBuffer->ShowX) * 2;
799 }
800 else
801 {
802 DstOffset += ScreenBuffer->MaxX * 2;
803 }
804
805 if (++SrcY == ScreenBuffer->MaxY)
806 {
807 SrcY = 0;
808 SrcOffset = (SrcRegion->left + ScreenBuffer->ShowX) * 2;
809 }
810 else
811 {
812 SrcOffset += ScreenBuffer->MaxX * 2;
813 }
814 }
815 }
816
817 STATIC VOID FASTCALL
818 ConioFillRegion(PCSRSS_CONSOLE Console,
819 PCSRSS_SCREEN_BUFFER ScreenBuffer,
820 RECT *Region,
821 CHAR_INFO *CharInfo,
822 BOOL bUnicode)
823 {
824 SHORT X, Y;
825 DWORD Offset;
826 DWORD Delta;
827 ULONG i;
828 CHAR Char;
829
830 if(bUnicode)
831 ConsoleUnicodeCharToAnsiChar(Console, &Char, &CharInfo->Char.UnicodeChar);
832 else
833 Char = CharInfo->Char.AsciiChar;
834
835 Y = (Region->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
836 Offset = (Y * ScreenBuffer->MaxX + Region->left + ScreenBuffer->ShowX) * 2;
837 Delta = (ScreenBuffer->MaxX - ConioRectWidth(Region)) * 2;
838
839 for (i = Region->top; i <= Region->bottom; i++)
840 {
841 for (X = Region->left; X <= Region->right; X++)
842 {
843 SET_CELL_BUFFER(ScreenBuffer, Offset, Char, CharInfo->Attributes);
844 }
845 if (++Y == ScreenBuffer->MaxY)
846 {
847 Y = 0;
848 Offset = (Region->left + ScreenBuffer->ShowX) * 2;
849 }
850 else
851 {
852 Offset += Delta;
853 }
854 }
855 }
856
857 STATIC VOID FASTCALL
858 ConioInputEventToAnsi(PCSRSS_CONSOLE Console, PINPUT_RECORD InputEvent)
859 {
860 if (InputEvent->EventType == KEY_EVENT)
861 {
862 ConsoleUnicodeCharToAnsiChar(Console,
863 &InputEvent->Event.KeyEvent.uChar.AsciiChar,
864 &InputEvent->Event.KeyEvent.uChar.UnicodeChar);
865 }
866 }
867
868 CSR_API(CsrWriteConsole)
869 {
870 NTSTATUS Status;
871 PCHAR Buffer = (PCHAR)Request->Data.WriteConsoleRequest.Buffer;
872 PCSRSS_SCREEN_BUFFER Buff;
873 PCSRSS_CONSOLE Console;
874 ULONG CharSize = (Request->Data.WriteConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
875
876 DPRINT("CsrWriteConsole\n");
877
878 if (Request->Header.DataSize
879 < sizeof(CSRSS_WRITE_CONSOLE) - 1
880 + (Request->Data.WriteConsoleRequest.NrCharactersToWrite * CharSize))
881 {
882 DPRINT1("Invalid request size\n");
883 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
884 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
885 return Request->Status = STATUS_INVALID_PARAMETER;
886 }
887 Status = ConioConsoleFromProcessData(ProcessData, &Console);
888
889 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
890 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
891
892 if (! NT_SUCCESS(Status))
893 {
894 return Request->Status = Status;
895 }
896
897 if(Request->Data.WriteConsoleRequest.Unicode)
898 {
899 ConsoleUnicodeToAnsiN(Console, Buffer, (PWCHAR)Buffer, Request->Data.WriteConsoleRequest.NrCharactersToWrite);
900 }
901
902 Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff);
903 if (! NT_SUCCESS(Status))
904 {
905 if (NULL != Console)
906 {
907 ConioUnlockConsole(Console);
908 }
909 return Request->Status = Status;
910 }
911
912 Request->Status = ConioWriteConsole(Console, Buff, Buffer,
913 Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE);
914 ConioUnlockScreenBuffer(Buff);
915 if (NULL != Console)
916 {
917 ConioUnlockConsole(Console);
918 }
919
920 if(NT_SUCCESS(Request->Status))
921 {
922 Request->Data.WriteConsoleRequest.NrCharactersWritten = Request->Data.WriteConsoleRequest.NrCharactersToWrite;
923 }
924 else
925 {
926 Request->Data.WriteConsoleRequest.NrCharactersWritten = 0; /* FIXME - return the actual number of characters written! */
927 }
928
929 return Request->Status = STATUS_SUCCESS;
930 }
931
932 VOID STDCALL
933 ConioDeleteScreenBuffer(Object_t *Object)
934 {
935 PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object;
936 DeleteCriticalSection(&Buffer->Header.Lock);
937 HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer);
938 HeapFree(Win32CsrApiHeap, 0, Buffer);
939 }
940
941 VOID FASTCALL
942 ConioDrawConsole(PCSRSS_CONSOLE Console)
943 {
944 RECT Region;
945
946 ConioInitRect(&Region, 0, 0, Console->Size.Y - 1, Console->Size.X - 1);
947
948 ConioDrawRegion(Console, &Region);
949 }
950
951
952 VOID STDCALL
953 ConioDeleteConsole(Object_t *Object)
954 {
955 PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
956 ConsoleInput *Event;
957
958 DPRINT("ConioDeleteConsole\n");
959
960 /* Drain input event queue */
961 while (Console->InputEvents.Flink != &Console->InputEvents)
962 {
963 Event = (ConsoleInput *) Console->InputEvents.Flink;
964 Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
965 Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents;
966 HeapFree(Win32CsrApiHeap, 0, Event);
967 }
968
969 if (0 == --Console->ActiveBuffer->Header.ReferenceCount)
970 {
971 ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
972 }
973
974 Console->ActiveBuffer = NULL;
975 ConioCleanupConsole(Console);
976
977 CloseHandle(Console->ActiveEvent);
978 DeleteCriticalSection(&Console->Header.Lock);
979 RtlFreeUnicodeString(&Console->Title);
980 HeapFree(Win32CsrApiHeap, 0, Console);
981 }
982
983 VOID STDCALL
984 CsrInitConsoleSupport(VOID)
985 {
986 DPRINT("CSR: CsrInitConsoleSupport()\n");
987
988 /* Should call LoadKeyboardLayout */
989 }
990
991 STATIC VOID FASTCALL
992 ConioProcessChar(PCSRSS_CONSOLE Console,
993 ConsoleInput *KeyEventRecord)
994 {
995 BOOL updown;
996 BOOL bClientWake = FALSE;
997 ConsoleInput *TempInput;
998
999 /* process Ctrl-C and Ctrl-Break */
1000 if (Console->Mode & ENABLE_PROCESSED_INPUT &&
1001 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown &&
1002 ((KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
1003 (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
1004 (KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)))
1005 {
1006 PCSRSS_PROCESS_DATA current;
1007 PLIST_ENTRY current_entry;
1008 DPRINT1("Console_Api Ctrl-C\n");
1009 current_entry = Console->ProcessList.Flink;
1010 while (current_entry != &Console->ProcessList)
1011 {
1012 current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
1013 current_entry = current_entry->Flink;
1014 ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
1015 }
1016 HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
1017 return;
1018 }
1019
1020 if (0 != (KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState
1021 & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
1022 && (VK_UP == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode
1023 || VK_DOWN == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode))
1024 {
1025 if (KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)
1026 {
1027 /* scroll up or down */
1028 if (NULL == Console)
1029 {
1030 DPRINT1("No Active Console!\n");
1031 HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
1032 return;
1033 }
1034 if (VK_UP == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode)
1035 {
1036 /* only scroll up if there is room to scroll up into */
1037 if (Console->ActiveBuffer->ShowY != ((Console->ActiveBuffer->CurrentY + 1) %
1038 Console->ActiveBuffer->MaxY))
1039 {
1040 Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY +
1041 Console->ActiveBuffer->MaxY - 1) %
1042 Console->ActiveBuffer->MaxY;
1043 }
1044 }
1045 else if (Console->ActiveBuffer->ShowY != Console->ActiveBuffer->CurrentY)
1046 /* only scroll down if there is room to scroll down into */
1047 {
1048 if (Console->ActiveBuffer->ShowY % Console->ActiveBuffer->MaxY !=
1049 Console->ActiveBuffer->CurrentY)
1050 {
1051 if (((Console->ActiveBuffer->CurrentY + 1) % Console->ActiveBuffer->MaxY) !=
1052 (Console->ActiveBuffer->ShowY + Console->ActiveBuffer->MaxY) %
1053 Console->ActiveBuffer->MaxY)
1054 {
1055 Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY + 1) %
1056 Console->ActiveBuffer->MaxY;
1057 }
1058 }
1059 }
1060 ConioDrawConsole(Console);
1061 }
1062 HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
1063 return;
1064 }
1065 if (NULL == Console)
1066 {
1067 DPRINT1("No Active Console!\n");
1068 HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
1069 return;
1070 }
1071
1072 if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)))
1073 {
1074 switch(KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar)
1075 {
1076 case '\r':
1077 /* first add the \r */
1078 KeyEventRecord->InputEvent.EventType = KEY_EVENT;
1079 updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown;
1080 KeyEventRecord->Echoed = FALSE;
1081 KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
1082 KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\r';
1083 InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry);
1084 Console->WaitingChars++;
1085 KeyEventRecord = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
1086 if (NULL == KeyEventRecord)
1087 {
1088 DPRINT1("Failed to allocate KeyEventRecord\n");
1089 return;
1090 }
1091 KeyEventRecord->InputEvent.EventType = KEY_EVENT;
1092 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown = updown;
1093 KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = 0;
1094 KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualScanCode = 0;
1095 KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\n';
1096 KeyEventRecord->Fake = TRUE;
1097 break;
1098 }
1099 }
1100 /* add event to the queue */
1101 InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry);
1102 Console->WaitingChars++;
1103 /* if line input mode is enabled, only wake the client on enter key down */
1104 if (0 == (Console->Mode & ENABLE_LINE_INPUT)
1105 || Console->EarlyReturn
1106 || ('\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar
1107 && KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown))
1108 {
1109 if ('\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar)
1110 {
1111 Console->WaitingLines++;
1112 }
1113 bClientWake = TRUE;
1114 SetEvent(Console->ActiveEvent);
1115 }
1116 KeyEventRecord->Echoed = FALSE;
1117 if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT))
1118 && '\b' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar
1119 && KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)
1120 {
1121 /* walk the input queue looking for a char to backspace */
1122 for (TempInput = (ConsoleInput *) Console->InputEvents.Blink;
1123 TempInput != (ConsoleInput *) &Console->InputEvents
1124 && (KEY_EVENT == TempInput->InputEvent.EventType
1125 || ! TempInput->InputEvent.Event.KeyEvent.bKeyDown
1126 || '\b' == TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar);
1127 TempInput = (ConsoleInput *) TempInput->ListEntry.Blink)
1128 {
1129 /* NOP */;
1130 }
1131 /* if we found one, delete it, otherwise, wake the client */
1132 if (TempInput != (ConsoleInput *) &Console->InputEvents)
1133 {
1134 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1135 RemoveEntryList(&TempInput->ListEntry);
1136 if (TempInput->Echoed)
1137 {
1138 ConioWriteConsole(Console, Console->ActiveBuffer,
1139 &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar,
1140 1, TRUE);
1141 }
1142 HeapFree(Win32CsrApiHeap, 0, TempInput);
1143 RemoveEntryList(&KeyEventRecord->ListEntry);
1144 HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
1145 Console->WaitingChars -= 2;
1146 }
1147 else
1148 {
1149 SetEvent(Console->ActiveEvent);
1150 }
1151 }
1152 else
1153 {
1154 /* echo chars if we are supposed to and client is waiting for some */
1155 if (0 != (Console->Mode & ENABLE_ECHO_INPUT) && Console->EchoCount
1156 && KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar
1157 && KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown
1158 && '\r' != KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar)
1159 {
1160 /* mark the char as already echoed */
1161 ConioWriteConsole(Console, Console->ActiveBuffer,
1162 &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar,
1163 1, TRUE);
1164 Console->EchoCount--;
1165 KeyEventRecord->Echoed = TRUE;
1166 }
1167 }
1168
1169 /* Console->WaitingChars++; */
1170 if (bClientWake || 0 == (Console->Mode & ENABLE_LINE_INPUT))
1171 {
1172 SetEvent(Console->ActiveEvent);
1173 }
1174 }
1175
1176 STATIC DWORD FASTCALL
1177 ConioGetShiftState(PBYTE KeyState)
1178 {
1179 DWORD ssOut = 0;
1180
1181 if (KeyState[VK_CAPITAL] & 1)
1182 ssOut |= CAPSLOCK_ON;
1183
1184 if (KeyState[VK_NUMLOCK] & 1)
1185 ssOut |= NUMLOCK_ON;
1186
1187 if (KeyState[VK_SCROLL] & 1)
1188 ssOut |= SCROLLLOCK_ON;
1189
1190 if (KeyState[VK_SHIFT] & 0x80)
1191 ssOut |= SHIFT_PRESSED;
1192
1193 if (KeyState[VK_LCONTROL] & 0x80)
1194 ssOut |= LEFT_CTRL_PRESSED;
1195 if (KeyState[VK_RCONTROL] & 0x80)
1196 ssOut |= RIGHT_CTRL_PRESSED;
1197
1198 if (KeyState[VK_LMENU] & 0x80)
1199 ssOut |= LEFT_ALT_PRESSED;
1200 if (KeyState[VK_RMENU] & 0x80)
1201 ssOut |= RIGHT_ALT_PRESSED;
1202
1203 return ssOut;
1204 }
1205
1206 VOID STDCALL
1207 ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
1208 {
1209 static BYTE KeyState[256] = { 0 };
1210 /* MSDN mentions that you should use the last virtual key code received
1211 * when putting a virtual key identity to a WM_CHAR message since multiple
1212 * or translated keys may be involved. */
1213 static UINT LastVirtualKey = 0;
1214 DWORD ShiftState;
1215 ConsoleInput *ConInRec;
1216 UINT RepeatCount;
1217 CHAR AsciiChar;
1218 WCHAR UnicodeChar;
1219 UINT VirtualKeyCode;
1220 UINT VirtualScanCode;
1221 BOOL Down = FALSE;
1222 INPUT_RECORD er;
1223 ULONG ResultSize = 0;
1224
1225 RepeatCount = 1;
1226 VirtualScanCode = (msg->lParam >> 16) & 0xff;
1227 Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
1228 msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
1229
1230 GetKeyboardState(KeyState);
1231 ShiftState = ConioGetShiftState(KeyState);
1232
1233 if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
1234 {
1235 VirtualKeyCode = LastVirtualKey;
1236 UnicodeChar = msg->wParam;
1237 }
1238 else
1239 {
1240 WCHAR Chars[2];
1241 INT RetChars = 0;
1242
1243 VirtualKeyCode = msg->wParam;
1244 RetChars = ToUnicodeEx(VirtualKeyCode,
1245 VirtualScanCode,
1246 KeyState,
1247 Chars,
1248 2,
1249 0,
1250 0);
1251 UnicodeChar = (1 == RetChars ? Chars[0] : 0);
1252 }
1253
1254 if (0 == ResultSize)
1255 {
1256 AsciiChar = 0;
1257 }
1258
1259 er.EventType = KEY_EVENT;
1260 er.Event.KeyEvent.bKeyDown = Down;
1261 er.Event.KeyEvent.wRepeatCount = RepeatCount;
1262 er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
1263 er.Event.KeyEvent.dwControlKeyState = ShiftState;
1264 er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
1265 er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
1266
1267 if (TextMode)
1268 {
1269 if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
1270 && VK_TAB == VirtualKeyCode)
1271 {
1272 if (Down)
1273 {
1274 TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1);
1275 }
1276
1277 return;
1278 }
1279 else if (VK_MENU == VirtualKeyCode && ! Down)
1280 {
1281 if (TuiSwapConsole(0))
1282 {
1283 return;
1284 }
1285 }
1286 }
1287
1288 if (NULL == Console)
1289 {
1290 return;
1291 }
1292
1293 ConInRec = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
1294
1295 if (NULL == ConInRec)
1296 {
1297 return;
1298 }
1299
1300 ConInRec->InputEvent = er;
1301 ConInRec->Fake = UnicodeChar &&
1302 (msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
1303 msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
1304 ConInRec->NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
1305 ConInRec->Echoed = FALSE;
1306 if (ConInRec->NotChar)
1307 LastVirtualKey = msg->wParam;
1308
1309 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1310 Down ? "down" : "up ",
1311 (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
1312 "char" : "key ",
1313 ConInRec->Fake ? "fake" : "real",
1314 ConInRec->NotChar ? "notc" : "char",
1315 VirtualScanCode,
1316 VirtualKeyCode,
1317 (AsciiChar >= ' ') ? AsciiChar : '.',
1318 ShiftState);
1319
1320 if (! ConInRec->Fake || ! ConInRec->NotChar)
1321 {
1322 /* FIXME - convert to ascii */
1323 ConioProcessChar(Console, ConInRec);
1324 }
1325 else
1326 {
1327 HeapFree(Win32CsrApiHeap, 0, ConInRec);
1328 }
1329 }
1330
1331 DWORD STDCALL
1332 Console_Api (PVOID unused)
1333 {
1334 /* keep reading events from the keyboard and stuffing them into the current
1335 console's input queue */
1336 MSG msg;
1337
1338 /* This call establishes our message queue */
1339 PeekMessageW(&msg, 0, 0, 0, PM_NOREMOVE);
1340 /* This call registers our message queue */
1341 PrivateCsrssRegisterPrimitive();
1342 /* This call turns on the input system in win32k */
1343 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE);
1344
1345 while (TRUE)
1346 {
1347 GetMessageW(&msg, 0, 0, 0);
1348 TranslateMessage(&msg);
1349
1350 if (msg.message == WM_CHAR || msg.message == WM_SYSCHAR ||
1351 msg.message == WM_KEYDOWN || msg.message == WM_KEYUP ||
1352 msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP)
1353 {
1354 ConioProcessKey(&msg, TuiGetFocusConsole(), TRUE);
1355 }
1356 }
1357
1358 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE);
1359 return 0;
1360 }
1361
1362 CSR_API(CsrGetScreenBufferInfo)
1363 {
1364 NTSTATUS Status;
1365 PCSRSS_SCREEN_BUFFER Buff;
1366 PCONSOLE_SCREEN_BUFFER_INFO pInfo;
1367
1368 DPRINT("CsrGetScreenBufferInfo\n");
1369
1370 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1371 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1372
1373 Status = ConioLockScreenBuffer(ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, &Buff);
1374 if (! NT_SUCCESS(Status))
1375 {
1376 return Request->Status = Status;
1377 }
1378 pInfo = &Request->Data.ScreenBufferInfoRequest.Info;
1379 pInfo->dwSize.X = Buff->MaxX;
1380 pInfo->dwSize.Y = Buff->MaxY;
1381 pInfo->dwCursorPosition.X = Buff->CurrentX - Buff->ShowX;
1382 pInfo->dwCursorPosition.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY;
1383 pInfo->wAttributes = Buff->DefaultAttrib;
1384 pInfo->srWindow.Left = 0;
1385 pInfo->srWindow.Right = Buff->MaxX - 1;
1386 pInfo->srWindow.Top = 0;
1387 pInfo->srWindow.Bottom = Buff->MaxY - 1;
1388 pInfo->dwMaximumWindowSize.X = Buff->MaxX;
1389 pInfo->dwMaximumWindowSize.Y = Buff->MaxY;
1390 ConioUnlockScreenBuffer(Buff);
1391
1392 Request->Status = STATUS_SUCCESS;
1393
1394 return Request->Status;
1395 }
1396
1397 CSR_API(CsrSetCursor)
1398 {
1399 NTSTATUS Status;
1400 PCSRSS_CONSOLE Console;
1401 PCSRSS_SCREEN_BUFFER Buff;
1402 LONG OldCursorX, OldCursorY;
1403 LONG NewCursorX, NewCursorY;
1404
1405 DPRINT("CsrSetCursor\n");
1406
1407 Status = ConioConsoleFromProcessData(ProcessData, &Console);
1408 if (! NT_SUCCESS(Status))
1409 {
1410 return Request->Status = Status;
1411 }
1412
1413 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1414 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1415
1416 Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff);
1417 if (! NT_SUCCESS(Status))
1418 {
1419 if (NULL != Console)
1420 {
1421 ConioUnlockConsole(Console);
1422 }
1423 return Request->Status = Status;
1424 }
1425
1426 NewCursorX = Request->Data.SetCursorRequest.Position.X;
1427 NewCursorY = Request->Data.SetCursorRequest.Position.Y;
1428 if (NewCursorX < 0 || NewCursorX >= Buff->MaxX ||
1429 NewCursorY < 0 || NewCursorY >= Buff->MaxY)
1430 {
1431 ConioUnlockScreenBuffer(Buff);
1432 return Request->Status = STATUS_INVALID_PARAMETER;
1433 }
1434 ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &OldCursorX, &OldCursorY);
1435 Buff->CurrentX = NewCursorX + Buff->ShowX;
1436 Buff->CurrentY = (NewCursorY + Buff->ShowY) % Buff->MaxY;
1437 if (NULL != Console && Buff == Console->ActiveBuffer)
1438 {
1439 if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
1440 {
1441 ConioUnlockScreenBuffer(Buff);
1442 return Request->Status = STATUS_UNSUCCESSFUL;
1443 }
1444 }
1445
1446 ConioUnlockScreenBuffer(Buff);
1447 if (NULL != Console)
1448 {
1449 ConioUnlockConsole(Console);
1450 }
1451
1452 return Request->Status = STATUS_SUCCESS;
1453 }
1454
1455 STATIC FASTCALL VOID
1456 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, COORD *Start, UINT Length)
1457 {
1458 if (Buff->MaxX <= Start->X + Length)
1459 {
1460 UpdateRect->left = 0;
1461 }
1462 else
1463 {
1464 UpdateRect->left = Start->X;
1465 }
1466 if (Buff->MaxX <= Start->X + Length)
1467 {
1468 UpdateRect->right = Buff->MaxX - 1;
1469 }
1470 else
1471 {
1472 UpdateRect->right = Start->X + Length - 1;
1473 }
1474 UpdateRect->top = Start->Y;
1475 UpdateRect->bottom = Start->Y+ (Start->X + Length - 1) / Buff->MaxX;
1476 if (Buff->MaxY <= UpdateRect->bottom)
1477 {
1478 UpdateRect->bottom = Buff->MaxY - 1;
1479 }
1480 }
1481
1482 CSR_API(CsrWriteConsoleOutputChar)
1483 {
1484 NTSTATUS Status;
1485 PCHAR String = (PCHAR)Request->Data.WriteConsoleOutputCharRequest.String;
1486 PBYTE Buffer;
1487 PCSRSS_CONSOLE Console;
1488 PCSRSS_SCREEN_BUFFER Buff;
1489 DWORD X, Y, Length, CharSize, Written = 0;
1490 RECT UpdateRect;
1491
1492 DPRINT("CsrWriteConsoleOutputChar\n");
1493
1494 CharSize = (Request->Data.WriteConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
1495
1496 if (Request->Header.DataSize
1497 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR) - 1
1498 + (Request->Data.WriteConsoleOutputCharRequest.Length * CharSize))
1499 {
1500 DPRINT1("Invalid request size\n");
1501 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1502 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1503 return Request->Status = STATUS_INVALID_PARAMETER;
1504 }
1505
1506 Status = ConioConsoleFromProcessData(ProcessData, &Console);
1507 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1508 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1509 if (! NT_SUCCESS(Status))
1510 {
1511 return Request->Status = Status;
1512 }
1513
1514 if(Request->Data.WriteConsoleOutputCharRequest.Unicode)
1515 {
1516 ConsoleUnicodeToAnsiN(Console, String, (PWCHAR)String, Request->Data.WriteConsoleOutputCharRequest.Length);
1517 }
1518
1519 Status = ConioLockScreenBuffer(ProcessData,
1520 Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle,
1521 &Buff);
1522 if (! NT_SUCCESS(Status))
1523 {
1524 if (NULL != Console)
1525 {
1526 ConioUnlockConsole(Console);
1527 }
1528 return Request->Status = Status;
1529 }
1530
1531 X = Request->Data.WriteConsoleOutputCharRequest.Coord.X + Buff->ShowX;
1532 Y = (Request->Data.WriteConsoleOutputCharRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
1533 Length = Request->Data.WriteConsoleOutputCharRequest.Length;
1534 Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
1535 while (Length--)
1536 {
1537 *Buffer = *String++;
1538 Written++;
1539 Buffer += 2;
1540 if (++X == Buff->MaxX)
1541 {
1542 if (++Y == Buff->MaxY)
1543 {
1544 Y = 0;
1545 Buffer = Buff->Buffer;
1546 }
1547 X = 0;
1548 }
1549 }
1550
1551 if (NULL != Console && Buff == Console->ActiveBuffer)
1552 {
1553 ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.WriteConsoleOutputCharRequest.Coord,
1554 Request->Data.WriteConsoleOutputCharRequest.Length);
1555 ConioDrawRegion(Console, &UpdateRect);
1556 }
1557
1558 Request->Data.WriteConsoleOutputCharRequest.EndCoord.X = X - Buff->ShowX;
1559 Request->Data.WriteConsoleOutputCharRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->ShowY) % Buff->MaxY;
1560
1561 ConioUnlockScreenBuffer(Buff);
1562 if (NULL != Console)
1563 {
1564 ConioUnlockConsole(Console);
1565 }
1566
1567 Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten = Written;
1568 return Request->Status = STATUS_SUCCESS;
1569 }
1570
1571 CSR_API(CsrFillOutputChar)
1572 {
1573 NTSTATUS Status;
1574 PCSRSS_CONSOLE Console;
1575 PCSRSS_SCREEN_BUFFER Buff;
1576 DWORD X, Y, Length, Written = 0;
1577 CHAR Char;
1578 PBYTE Buffer;
1579 RECT UpdateRect;
1580
1581 DPRINT("CsrFillOutputChar\n");
1582
1583 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1584 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1585
1586 Status = ConioConsoleFromProcessData(ProcessData, &Console);
1587 if (! NT_SUCCESS(Status))
1588 {
1589 return Request->Status = Status;
1590 }
1591
1592 Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, &Buff);
1593 if (! NT_SUCCESS(Status))
1594 {
1595 if (NULL != Console)
1596 {
1597 ConioUnlockConsole(Console);
1598 }
1599 return Request->Status = Status;
1600 }
1601
1602 X = Request->Data.FillOutputRequest.Position.X + Buff->ShowX;
1603 Y = (Request->Data.FillOutputRequest.Position.Y + Buff->ShowY) % Buff->MaxY;
1604 Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
1605 if(Request->Data.FillOutputRequest.Unicode)
1606 ConsoleUnicodeCharToAnsiChar(Console, &Char, &Request->Data.FillOutputRequest.Char.UnicodeChar);
1607 else
1608 Char = Request->Data.FillOutputRequest.Char.AsciiChar;
1609 Length = Request->Data.FillOutputRequest.Length;
1610 while (Length--)
1611 {
1612 *Buffer = Char;
1613 Buffer += 2;
1614 Written++;
1615 if (++X == Buff->MaxX)
1616 {
1617 if (++Y == Buff->MaxY)
1618 {
1619 Y = 0;
1620 Buffer = Buff->Buffer;
1621 }
1622 X = 0;
1623 }
1624 }
1625
1626 if (NULL != Console && Buff == Console->ActiveBuffer)
1627 {
1628 ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.FillOutputRequest.Position,
1629 Request->Data.FillOutputRequest.Length);
1630 ConioDrawRegion(Console, &UpdateRect);
1631 }
1632
1633 ConioUnlockScreenBuffer(Buff);
1634 if (NULL != Console)
1635 {
1636 ConioUnlockConsole(Console);
1637 }
1638
1639 return Request->Status;
1640 }
1641
1642 CSR_API(CsrReadInputEvent)
1643 {
1644 PLIST_ENTRY CurrentEntry;
1645 PCSRSS_CONSOLE Console;
1646 NTSTATUS Status;
1647 BOOLEAN Done = FALSE;
1648 ConsoleInput *Input;
1649
1650 DPRINT("CsrReadInputEvent\n");
1651
1652 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1653 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1654 Request->Data.ReadInputRequest.Event = ProcessData->ConsoleEvent;
1655
1656 Status = ConioLockConsole(ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, &Console);
1657 if (! NT_SUCCESS(Status))
1658 {
1659 return Request->Status = Status;
1660 }
1661
1662 /* only get input if there is any */
1663 CurrentEntry = Console->InputEvents.Flink;
1664 while (CurrentEntry != &Console->InputEvents)
1665 {
1666 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
1667 CurrentEntry = CurrentEntry->Flink;
1668
1669 if (Done && !Input->Fake)
1670 {
1671 Request->Data.ReadInputRequest.MoreEvents = TRUE;
1672 break;
1673 }
1674
1675 RemoveEntryList(&Input->ListEntry);
1676
1677 if (!Done && !Input->Fake)
1678 {
1679 Request->Data.ReadInputRequest.Input = Input->InputEvent;
1680 if (Request->Data.ReadInputRequest.Unicode == FALSE)
1681 {
1682 ConioInputEventToAnsi(Console, &Request->Data.ReadInputRequest.Input);
1683 }
1684 Done = TRUE;
1685 }
1686
1687 if (Input->InputEvent.EventType == KEY_EVENT)
1688 {
1689 if (0 != (Console->Mode & ENABLE_LINE_INPUT)
1690 && Input->InputEvent.Event.KeyEvent.bKeyDown
1691 && '\r' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar)
1692 {
1693 Console->WaitingLines--;
1694 }
1695 Console->WaitingChars--;
1696 }
1697 HeapFree(Win32CsrApiHeap, 0, Input);
1698 }
1699
1700 if (Done)
1701 {
1702 Status = STATUS_SUCCESS;
1703 Console->EarlyReturn = FALSE;
1704 }
1705 else
1706 {
1707 Status = STATUS_PENDING;
1708 Console->EarlyReturn = TRUE; /* mark for early return */
1709 }
1710
1711 if (IsListEmpty(&Console->InputEvents))
1712 {
1713 ResetEvent(Console->ActiveEvent);
1714 }
1715
1716 ConioUnlockConsole(Console);
1717
1718 return Request->Status = Status;
1719 }
1720
1721 CSR_API(CsrWriteConsoleOutputAttrib)
1722 {
1723 PCSRSS_CONSOLE Console;
1724 PCSRSS_SCREEN_BUFFER Buff;
1725 PUCHAR Buffer, Attribute;
1726 int X, Y, Length;
1727 NTSTATUS Status;
1728 RECT UpdateRect;
1729
1730 DPRINT("CsrWriteConsoleOutputAttrib\n");
1731
1732 if (Request->Header.DataSize
1733 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB) - 1
1734 + Request->Data.WriteConsoleOutputAttribRequest.Length)
1735 {
1736 DPRINT1("Invalid request size\n");
1737 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1738 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1739 return Request->Status = STATUS_INVALID_PARAMETER;
1740 }
1741
1742 Status = ConioConsoleFromProcessData(ProcessData, &Console);
1743 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1744 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1745 if (! NT_SUCCESS(Status))
1746 {
1747 return Request->Status = Status;
1748 }
1749
1750 Status = ConioLockScreenBuffer(ProcessData,
1751 Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle,
1752 &Buff);
1753 if (! NT_SUCCESS(Status))
1754 {
1755 if (NULL != Console)
1756 {
1757 ConioUnlockConsole(Console);
1758 }
1759 return Request->Status = Status;
1760 }
1761
1762 X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X + Buff->ShowX;
1763 Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
1764 Length = Request->Data.WriteConsoleOutputAttribRequest.Length;
1765 Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + 1];
1766 Attribute = (PUCHAR)Request->Data.WriteConsoleOutputAttribRequest.String;
1767 while (Length--)
1768 {
1769 *Buffer = *Attribute++;
1770 Buffer += 2;
1771 if (++X == Buff->MaxX)
1772 {
1773 if (++Y == Buff->MaxY)
1774 {
1775 Y = 0;
1776 Buffer = Buff->Buffer + 1;
1777 }
1778 X = 0;
1779 }
1780 }
1781
1782 if (NULL != Console && Buff == Console->ActiveBuffer)
1783 {
1784 ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.WriteConsoleOutputAttribRequest.Coord,
1785 Request->Data.WriteConsoleOutputAttribRequest.Length);
1786 ConioDrawRegion(Console, &UpdateRect);
1787 }
1788
1789 if (NULL != Console)
1790 {
1791 ConioUnlockConsole(Console);
1792 }
1793
1794 Request->Data.WriteConsoleOutputAttribRequest.EndCoord.X = Buff->CurrentX - Buff->ShowX;
1795 Request->Data.WriteConsoleOutputAttribRequest.EndCoord.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY;
1796
1797 ConioUnlockScreenBuffer(Buff);
1798
1799 return Request->Status = STATUS_SUCCESS;
1800 }
1801
1802 CSR_API(CsrFillOutputAttrib)
1803 {
1804 PCSRSS_SCREEN_BUFFER Buff;
1805 PUCHAR Buffer;
1806 NTSTATUS Status;
1807 int X, Y, Length;
1808 UCHAR Attr;
1809 RECT UpdateRect;
1810 PCSRSS_CONSOLE Console;
1811
1812 DPRINT("CsrFillOutputAttrib\n");
1813
1814 Status = ConioConsoleFromProcessData(ProcessData, &Console);
1815 if (! NT_SUCCESS(Status))
1816 {
1817 return Request->Status = Status;
1818 }
1819
1820 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1821 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1822 Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, &Buff);
1823 if (! NT_SUCCESS(Status))
1824 {
1825 if (NULL != Console)
1826 {
1827 ConioUnlockConsole(Console);
1828 }
1829 return Request->Status = Status;
1830 }
1831
1832 X = Request->Data.FillOutputAttribRequest.Coord.X + Buff->ShowX;
1833 Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
1834 Length = Request->Data.FillOutputAttribRequest.Length;
1835 Attr = Request->Data.FillOutputAttribRequest.Attribute;
1836 Buffer = &Buff->Buffer[(Y * Buff->MaxX * 2) + (X * 2) + 1];
1837 while (Length--)
1838 {
1839 *Buffer = Attr;
1840 Buffer += 2;
1841 if (++X == Buff->MaxX)
1842 {
1843 if (++Y == Buff->MaxY)
1844 {
1845 Y = 0;
1846 Buffer = Buff->Buffer + 1;
1847 }
1848 X = 0;
1849 }
1850 }
1851
1852 if (NULL != Console && Buff == Console->ActiveBuffer)
1853 {
1854 ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.FillOutputAttribRequest.Coord,
1855 Request->Data.FillOutputAttribRequest.Length);
1856 ConioDrawRegion(Console, &UpdateRect);
1857 }
1858
1859 ConioUnlockScreenBuffer(Buff);
1860 if (NULL != Console)
1861 {
1862 ConioUnlockConsole(Console);
1863 }
1864
1865 return Request->Status = STATUS_SUCCESS;
1866 }
1867
1868
1869 CSR_API(CsrGetCursorInfo)
1870 {
1871 PCSRSS_SCREEN_BUFFER Buff;
1872 NTSTATUS Status;
1873
1874 DPRINT("CsrGetCursorInfo\n");
1875
1876 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1877 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1878
1879 Status = ConioLockScreenBuffer(ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, &Buff);
1880 if (! NT_SUCCESS(Status))
1881 {
1882 return Request->Status = Status;
1883 }
1884 Request->Data.GetCursorInfoRequest.Info = Buff->CursorInfo;
1885 ConioUnlockScreenBuffer(Buff);
1886
1887 return Request->Status = STATUS_SUCCESS;
1888 }
1889
1890 CSR_API(CsrSetCursorInfo)
1891 {
1892 PCSRSS_CONSOLE Console;
1893 PCSRSS_SCREEN_BUFFER Buff;
1894 DWORD Size;
1895 BOOL Visible;
1896 NTSTATUS Status;
1897
1898 DPRINT("CsrSetCursorInfo\n");
1899
1900 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
1901 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
1902
1903 Status = ConioConsoleFromProcessData(ProcessData, &Console);
1904 if (! NT_SUCCESS(Status))
1905 {
1906 return Request->Status = Status;
1907 }
1908
1909 Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorInfoRequest.ConsoleHandle, &Buff);
1910 if (! NT_SUCCESS(Status))
1911 {
1912 if (NULL != Console)
1913 {
1914 ConioUnlockConsole(Console);
1915 }
1916 return Request->Status = Status;
1917 }
1918
1919 Size = Request->Data.SetCursorInfoRequest.Info.dwSize;
1920 Visible = Request->Data.SetCursorInfoRequest.Info.bVisible;
1921 if (Size < 1)
1922 {
1923 Size = 1;
1924 }
1925 if (100 < Size)
1926 {
1927 Size = 100;
1928 }
1929
1930 if (Size != Buff->CursorInfo.dwSize
1931 || (Visible && ! Buff->CursorInfo.bVisible) || (! Visible && Buff->CursorInfo.bVisible))
1932 {
1933 Buff->CursorInfo.dwSize = Size;
1934 Buff->CursorInfo.bVisible = Visible;
1935
1936 if (NULL != Console && ! ConioSetCursorInfo(Console, Buff))
1937 {
1938 ConioUnlockScreenBuffer(Buff);
1939 ConioUnlockConsole(Console);
1940 return Request->Status = STATUS_UNSUCCESSFUL;
1941 }
1942 }
1943
1944 ConioUnlockScreenBuffer(Buff);
1945 if (NULL != Console)
1946 {
1947 ConioUnlockConsole(Console);
1948 }
1949
1950 return Request->Status = STATUS_SUCCESS;
1951 }
1952
1953 CSR_API(CsrSetTextAttrib)
1954 {
1955 NTSTATUS Status;
1956 PCSRSS_CONSOLE Console;
1957 PCSRSS_SCREEN_BUFFER Buff;
1958 LONG OldCursorX, OldCursorY;
1959
1960 DPRINT("CsrSetTextAttrib\n");
1961
1962 Status = ConioConsoleFromProcessData(ProcessData, &Console);
1963 if (! NT_SUCCESS(Status))
1964 {
1965 return Request->Status = Status;
1966 }
1967
1968 Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff);
1969 if (! NT_SUCCESS(Status))
1970 {
1971 if (NULL != Console)
1972 {
1973 ConioUnlockConsole(Console);
1974 }
1975 return Request->Status = Status;
1976 }
1977
1978 ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &OldCursorX, &OldCursorY);
1979
1980 Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib;
1981 if (NULL != Console && Buff == Console->ActiveBuffer)
1982 {
1983 if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
1984 {
1985 ConioUnlockScreenBuffer(Buff);
1986 ConioUnlockConsole(Console);
1987 return Request->Status = STATUS_UNSUCCESSFUL;
1988 }
1989 }
1990
1991 ConioUnlockScreenBuffer(Buff);
1992 if (NULL != Console)
1993 {
1994 ConioUnlockConsole(Console);
1995 }
1996
1997 return Request->Status = STATUS_SUCCESS;
1998 }
1999
2000 CSR_API(CsrSetConsoleMode)
2001 {
2002 NTSTATUS Status;
2003 PCSRSS_CONSOLE Console;
2004 PCSRSS_SCREEN_BUFFER Buff;
2005
2006 DPRINT("CsrSetConsoleMode\n");
2007
2008 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2009 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2010 Status = Win32CsrGetObject(ProcessData,
2011 Request->Data.SetConsoleModeRequest.ConsoleHandle,
2012 (Object_t **) &Console);
2013 if (! NT_SUCCESS(Status))
2014 {
2015 return Request->Status = Status;
2016 }
2017
2018 Buff = (PCSRSS_SCREEN_BUFFER)Console;
2019 if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
2020 {
2021 Console->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_INPUT_MODE_VALID;
2022 }
2023 else if (CONIO_SCREEN_BUFFER_MAGIC == Console->Header.Type)
2024 {
2025 Buff->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_OUTPUT_MODE_VALID;
2026 }
2027 else
2028 {
2029 return Request->Status = STATUS_INVALID_HANDLE;
2030 }
2031
2032 Request->Status = STATUS_SUCCESS;
2033
2034 return Request->Status;
2035 }
2036
2037 CSR_API(CsrGetConsoleMode)
2038 {
2039 NTSTATUS Status;
2040 PCSRSS_CONSOLE Console;
2041 PCSRSS_SCREEN_BUFFER Buff; /* gee, I really wish I could use an anonymous union here */
2042
2043 DPRINT("CsrGetConsoleMode\n");
2044
2045 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2046 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2047 Status = Win32CsrGetObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle,
2048 (Object_t **) &Console);
2049 if (! NT_SUCCESS(Status))
2050 {
2051 return Request->Status = Status;
2052 }
2053 Request->Status = STATUS_SUCCESS;
2054 Buff = (PCSRSS_SCREEN_BUFFER) Console;
2055 if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
2056 {
2057 Request->Data.GetConsoleModeRequest.ConsoleMode = Console->Mode;
2058 }
2059 else if (CONIO_SCREEN_BUFFER_MAGIC == Buff->Header.Type)
2060 {
2061 Request->Data.GetConsoleModeRequest.ConsoleMode = Buff->Mode;
2062 }
2063 else
2064 {
2065 Request->Status = STATUS_INVALID_HANDLE;
2066 }
2067
2068 return Request->Status;
2069 }
2070
2071 CSR_API(CsrCreateScreenBuffer)
2072 {
2073 PCSRSS_CONSOLE Console;
2074 PCSRSS_SCREEN_BUFFER Buff;
2075 NTSTATUS Status;
2076
2077 DPRINT("CsrCreateScreenBuffer\n");
2078
2079 if (ProcessData == NULL)
2080 {
2081 return Request->Status = STATUS_INVALID_PARAMETER;
2082 }
2083
2084 Status = ConioConsoleFromProcessData(ProcessData, &Console);
2085 if (! NT_SUCCESS(Status))
2086 {
2087 return Request->Status = Status;
2088 }
2089 if (NULL == Console)
2090 {
2091 return Request->Status = STATUS_INVALID_HANDLE;
2092 }
2093
2094 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2095 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2096
2097 Buff = HeapAlloc(Win32CsrApiHeap, 0, sizeof(CSRSS_SCREEN_BUFFER));
2098 if (NULL == Buff)
2099 {
2100 Request->Status = STATUS_INSUFFICIENT_RESOURCES;
2101 }
2102
2103 Status = CsrInitConsoleScreenBuffer(Console, Buff);
2104 if(! NT_SUCCESS(Status))
2105 {
2106 Request->Status = Status;
2107 }
2108 else
2109 {
2110 Request->Status = Win32CsrInsertObject(ProcessData, &Request->Data.CreateScreenBufferRequest.OutputHandle, &Buff->Header);
2111 }
2112
2113 ConioUnlockConsole(Console);
2114
2115 return Request->Status;
2116 }
2117
2118 CSR_API(CsrSetScreenBuffer)
2119 {
2120 NTSTATUS Status;
2121 PCSRSS_CONSOLE Console;
2122 PCSRSS_SCREEN_BUFFER Buff;
2123
2124 DPRINT("CsrSetScreenBuffer\n");
2125
2126 Status = ConioConsoleFromProcessData(ProcessData, &Console);
2127 if (! NT_SUCCESS(Status))
2128 {
2129 return Request->Status = Status;
2130 }
2131 if (NULL == Console)
2132 {
2133 DPRINT1("Trying to set screen buffer for app without console\n");
2134 return Request->Status = STATUS_INVALID_HANDLE;
2135 }
2136
2137 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2138 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2139
2140 Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferRequest.OutputHandle, &Buff);
2141 if (! NT_SUCCESS(Status))
2142 {
2143 ConioUnlockConsole(Console);
2144 return Request->Status;
2145 }
2146
2147 if (Buff == Console->ActiveBuffer)
2148 {
2149 ConioUnlockScreenBuffer(Buff);
2150 ConioUnlockConsole(Console);
2151 return STATUS_SUCCESS;
2152 }
2153
2154 /* drop reference to old buffer, maybe delete */
2155 if (! InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount))
2156 {
2157 ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
2158 }
2159 /* tie console to new buffer */
2160 Console->ActiveBuffer = Buff;
2161 /* inc ref count on new buffer */
2162 InterlockedIncrement(&Buff->Header.ReferenceCount);
2163 /* Redraw the console */
2164 ConioDrawConsole(Console);
2165
2166 ConioUnlockScreenBuffer(Buff);
2167 ConioUnlockConsole(Console);
2168
2169 return Request->Status = STATUS_SUCCESS;
2170 }
2171
2172 CSR_API(CsrSetTitle)
2173 {
2174 NTSTATUS Status;
2175 PCSRSS_CONSOLE Console;
2176
2177 DPRINT("CsrSetTitle\n");
2178
2179 if (Request->Header.DataSize
2180 < sizeof(CSRSS_SET_TITLE) - 1
2181 + Request->Data.SetTitleRequest.Length)
2182 {
2183 DPRINT1("Invalid request size\n");
2184 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2185 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2186 return Request->Status = STATUS_INVALID_PARAMETER;
2187 }
2188
2189 Status = ConioLockConsole(ProcessData, Request->Data.SetTitleRequest.Console, &Console);
2190 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2191 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2192 if(! NT_SUCCESS(Status))
2193 {
2194 Request->Status = Status;
2195 }
2196 else
2197 {
2198 /* copy title to console */
2199 RtlFreeUnicodeString(&Console->Title);
2200 RtlCreateUnicodeString(&Console->Title, Request->Data.SetTitleRequest.Title);
2201 if (! ConioChangeTitle(Console))
2202 {
2203 Request->Status = STATUS_UNSUCCESSFUL;
2204 }
2205 else
2206 {
2207 Request->Status = STATUS_SUCCESS;
2208 }
2209 }
2210 ConioUnlockConsole(Console);
2211
2212 return Request->Status;
2213 }
2214
2215 CSR_API(CsrGetTitle)
2216 {
2217 NTSTATUS Status;
2218 PCSRSS_CONSOLE Console;
2219
2220 DPRINT("CsrGetTitle\n");
2221
2222 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2223 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2224 Status = ConioLockConsole(ProcessData,
2225 Request->Data.GetTitleRequest.ConsoleHandle,
2226 &Console);
2227 if (! NT_SUCCESS(Status))
2228 {
2229 DPRINT1("Can't get console\n");
2230 return Request->Status = Status;
2231 }
2232
2233 /* Copy title of the console to the user title buffer */
2234 RtlZeroMemory(&Request->Data.GetTitleRequest, sizeof(CSRSS_GET_TITLE));
2235 Request->Data.GetTitleRequest.ConsoleHandle = Request->Data.GetTitleRequest.ConsoleHandle;
2236 Request->Data.GetTitleRequest.Length = Console->Title.Length;
2237 wcscpy (Request->Data.GetTitleRequest.Title, Console->Title.Buffer);
2238 Request->Header.MessageSize += Console->Title.Length;
2239 Request->Header.DataSize += Console->Title.Length;
2240 Request->Status = STATUS_SUCCESS;
2241
2242 ConioUnlockConsole(Console);
2243
2244 return Request->Status;
2245 }
2246
2247 CSR_API(CsrWriteConsoleOutput)
2248 {
2249 SHORT i, X, Y, SizeX, SizeY;
2250 PCSRSS_CONSOLE Console;
2251 PCSRSS_SCREEN_BUFFER Buff;
2252 RECT ScreenBuffer;
2253 CHAR_INFO* CurCharInfo;
2254 RECT WriteRegion;
2255 CHAR_INFO* CharInfo;
2256 COORD BufferCoord;
2257 COORD BufferSize;
2258 NTSTATUS Status;
2259 DWORD Offset;
2260 DWORD PSize;
2261
2262 DPRINT("CsrWriteConsoleOutput\n");
2263
2264 Status = ConioConsoleFromProcessData(ProcessData, &Console);
2265 if (! NT_SUCCESS(Status))
2266 {
2267 return Request->Status = Status;
2268 }
2269
2270 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2271 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2272 Status = ConioLockScreenBuffer(ProcessData,
2273 Request->Data.WriteConsoleOutputRequest.ConsoleHandle,
2274 &Buff);
2275 if (! NT_SUCCESS(Status))
2276 {
2277 if (NULL != Console)
2278 {
2279 ConioUnlockConsole(Console);
2280 }
2281 return Request->Status = Status;
2282 }
2283
2284 BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize;
2285 PSize = BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO);
2286 BufferCoord = Request->Data.WriteConsoleOutputRequest.BufferCoord;
2287 CharInfo = Request->Data.WriteConsoleOutputRequest.CharInfo;
2288 if (((PVOID)CharInfo < ProcessData->CsrSectionViewBase) ||
2289 (((PVOID)CharInfo + PSize) >
2290 (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
2291 {
2292 ConioUnlockScreenBuffer(Buff);
2293 ConioUnlockConsole(Console);
2294 return Request->Status = STATUS_ACCESS_VIOLATION;
2295 }
2296 WriteRegion.left = Request->Data.WriteConsoleOutputRequest.WriteRegion.Left;
2297 WriteRegion.top = Request->Data.WriteConsoleOutputRequest.WriteRegion.Top;
2298 WriteRegion.right = Request->Data.WriteConsoleOutputRequest.WriteRegion.Right;
2299 WriteRegion.bottom = Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom;
2300
2301 SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&WriteRegion));
2302 SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&WriteRegion));
2303 WriteRegion.bottom = WriteRegion.top + SizeY - 1;
2304 WriteRegion.right = WriteRegion.left + SizeX - 1;
2305
2306 /* Make sure WriteRegion is inside the screen buffer */
2307 ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
2308 if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
2309 {
2310 ConioUnlockScreenBuffer(Buff);
2311 ConioUnlockConsole(Console);
2312
2313 /* It is okay to have a WriteRegion completely outside the screen buffer.
2314 No data is written then. */
2315 return Request->Status = STATUS_SUCCESS;
2316 }
2317
2318 for (i = 0, Y = WriteRegion.top; Y <= WriteRegion.bottom; i++, Y++)
2319 {
2320 CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
2321 Offset = (((Y + Buff->ShowY) % Buff->MaxY) * Buff->MaxX + WriteRegion.left) * 2;
2322 for (X = WriteRegion.left; X <= WriteRegion.right; X++)
2323 {
2324 if (Request->Data.WriteConsoleOutputRequest.Unicode)
2325 {
2326 CHAR AsciiChar;
2327 ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar);
2328 SET_CELL_BUFFER(Buff, Offset, AsciiChar, CurCharInfo->Attributes);
2329 }
2330 else
2331 {
2332 SET_CELL_BUFFER(Buff, Offset, CurCharInfo->Char.AsciiChar, CurCharInfo->Attributes);
2333 }
2334 CurCharInfo++;
2335 }
2336 }
2337
2338 if (NULL != Console)
2339 {
2340 ConioDrawRegion(Console, &WriteRegion);
2341 }
2342
2343 ConioUnlockScreenBuffer(Buff);
2344 ConioUnlockConsole(Console);
2345
2346 Request->Data.WriteConsoleOutputRequest.WriteRegion.Right = WriteRegion.left + SizeX - 1;
2347 Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom = WriteRegion.top + SizeY - 1;
2348 Request->Data.WriteConsoleOutputRequest.WriteRegion.Left = WriteRegion.left;
2349 Request->Data.WriteConsoleOutputRequest.WriteRegion.Top = WriteRegion.top;
2350
2351 return Request->Status = STATUS_SUCCESS;
2352 }
2353
2354 CSR_API(CsrFlushInputBuffer)
2355 {
2356 PLIST_ENTRY CurrentEntry;
2357 PCSRSS_CONSOLE Console;
2358 ConsoleInput* Input;
2359 NTSTATUS Status;
2360
2361 DPRINT("CsrFlushInputBuffer\n");
2362
2363 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2364 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2365 Status = ConioLockConsole(ProcessData,
2366 Request->Data.FlushInputBufferRequest.ConsoleInput,
2367 &Console);
2368 if(! NT_SUCCESS(Status))
2369 {
2370 return Request->Status = Status;
2371 }
2372
2373 /* Discard all entries in the input event queue */
2374 while (!IsListEmpty(&Console->InputEvents))
2375 {
2376 CurrentEntry = RemoveHeadList(&Console->InputEvents);
2377 Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
2378 /* Destroy the event */
2379 HeapFree(Win32CsrApiHeap, 0, Input);
2380 }
2381 ResetEvent(Console->ActiveEvent);
2382 Console->WaitingChars=0;
2383
2384 ConioUnlockConsole(Console);
2385
2386 return Request->Status = STATUS_SUCCESS;
2387 }
2388
2389 CSR_API(CsrScrollConsoleScreenBuffer)
2390 {
2391 PCSRSS_CONSOLE Console;
2392 PCSRSS_SCREEN_BUFFER Buff;
2393 RECT ScreenBuffer;
2394 RECT SrcRegion;
2395 RECT DstRegion;
2396 RECT FillRegion;
2397 RECT ScrollRectangle;
2398 RECT ClipRectangle;
2399 NTSTATUS Status;
2400 BOOLEAN DoFill;
2401
2402 DPRINT("CsrScrollConsoleScreenBuffer\n");
2403
2404 ALIAS(ConsoleHandle,Request->Data.ScrollConsoleScreenBufferRequest.ConsoleHandle);
2405 ALIAS(UseClipRectangle,Request->Data.ScrollConsoleScreenBufferRequest.UseClipRectangle);
2406 ALIAS(DestinationOrigin,Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin);
2407 ALIAS(Fill,Request->Data.ScrollConsoleScreenBufferRequest.Fill);
2408
2409 Status = ConioConsoleFromProcessData(ProcessData, &Console);
2410 if (! NT_SUCCESS(Status))
2411 {
2412 return Request->Status = Status;
2413 }
2414
2415 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2416 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2417 Status = ConioLockScreenBuffer(ProcessData, ConsoleHandle, &Buff);
2418 if (! NT_SUCCESS(Status))
2419 {
2420 if (NULL != Console)
2421 {
2422 ConioUnlockConsole(Console);
2423 }
2424 return Request->Status = Status;
2425 }
2426
2427 ScrollRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Left;
2428 ScrollRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Top;
2429 ScrollRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Right;
2430 ScrollRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Bottom;
2431 ClipRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Left;
2432 ClipRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Top;
2433 ClipRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Right;
2434 ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom;
2435
2436 /* Make sure source rectangle is inside the screen buffer */
2437 ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
2438 if (! ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle))
2439 {
2440 ConioUnlockScreenBuffer(Buff);
2441 return Request->Status = STATUS_INVALID_PARAMETER;
2442 }
2443
2444 if (UseClipRectangle && ! ConioGetIntersection(&SrcRegion, &SrcRegion, &ClipRectangle))
2445 {
2446 ConioUnlockScreenBuffer(Buff);
2447 return Request->Status = STATUS_SUCCESS;
2448 }
2449
2450
2451 ConioInitRect(&DstRegion,
2452 DestinationOrigin.Y,
2453 DestinationOrigin.X,
2454 DestinationOrigin.Y + ConioRectHeight(&ScrollRectangle) - 1,
2455 DestinationOrigin.X + ConioRectWidth(&ScrollRectangle) - 1);
2456
2457 /* Make sure destination rectangle is inside the screen buffer */
2458 if (! ConioGetIntersection(&DstRegion, &DstRegion, &ScreenBuffer))
2459 {
2460 ConioUnlockScreenBuffer(Buff);
2461 return Request->Status = STATUS_INVALID_PARAMETER;
2462 }
2463
2464 ConioCopyRegion(Buff, &SrcRegion, &DstRegion);
2465
2466 /* Get the region that should be filled with the specified character and attributes */
2467
2468 DoFill = FALSE;
2469
2470 ConioGetUnion(&FillRegion, &SrcRegion, &DstRegion);
2471
2472 if (ConioSubtractRect(&FillRegion, &FillRegion, &DstRegion))
2473 {
2474 /* FIXME: The subtracted rectangle is off by one line */
2475 FillRegion.top += 1;
2476
2477 ConioFillRegion(Console, Buff, &FillRegion, &Fill, Request->Data.ScrollConsoleScreenBufferRequest.Unicode);
2478 DoFill = TRUE;
2479 }
2480
2481 if (NULL != Console && Buff == Console->ActiveBuffer)
2482 {
2483 /* Draw destination region */
2484 ConioDrawRegion(Console, &DstRegion);
2485
2486 if (DoFill)
2487 {
2488 /* Draw filled region */
2489 ConioDrawRegion(Console, &FillRegion);
2490 }
2491 }
2492
2493 ConioUnlockScreenBuffer(Buff);
2494 if (NULL != Console)
2495 {
2496 ConioUnlockConsole(Console);
2497 }
2498
2499 return Request->Status = STATUS_SUCCESS;
2500 }
2501
2502 CSR_API(CsrReadConsoleOutputChar)
2503 {
2504 NTSTATUS Status;
2505 PCSRSS_CONSOLE Console;
2506 PCSRSS_SCREEN_BUFFER Buff;
2507 DWORD Xpos, Ypos;
2508 PCHAR ReadBuffer;
2509 DWORD i;
2510 ULONG CharSize;
2511 CHAR Char;
2512
2513 DPRINT("CsrReadConsoleOutputChar\n");
2514
2515 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2516 Request->Header.DataSize = Request->Header.MessageSize - LPC_MESSAGE_BASE_SIZE;
2517 ReadBuffer = Request->Data.ReadConsoleOutputCharRequest.String;
2518
2519 CharSize = (Request->Data.ReadConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
2520
2521 Status = ConioConsoleFromProcessData(ProcessData, &Console);
2522 if (! NT_SUCCESS(Status))
2523 {
2524 return Request->Status = Status;
2525 }
2526
2527 Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, &Buff);
2528 if (! NT_SUCCESS(Status))
2529 {
2530 return Request->Status = Status;
2531 }
2532
2533 Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X + Buff->ShowX;
2534 Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + Buff->ShowY) % Buff->MaxY;
2535
2536 for (i = 0; i < Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; ++i)
2537 {
2538 Char = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)];
2539
2540 if(Request->Data.ReadConsoleOutputCharRequest.Unicode)
2541 {
2542 ConsoleAnsiCharToUnicodeChar(Console, (WCHAR*)ReadBuffer, &Char);
2543 ReadBuffer += sizeof(WCHAR);
2544 }
2545 else
2546 *(ReadBuffer++) = Char;
2547
2548 Xpos++;
2549
2550 if (Xpos == Buff->MaxX)
2551 {
2552 Xpos = 0;
2553 Ypos++;
2554
2555 if (Ypos == Buff->MaxY)
2556 {
2557 Ypos = 0;
2558 }
2559 }
2560 }
2561
2562 *ReadBuffer = 0;
2563 Request->Status = STATUS_SUCCESS;
2564 Request->Data.ReadConsoleOutputCharRequest.EndCoord.X = Xpos - Buff->ShowX;
2565 Request->Data.ReadConsoleOutputCharRequest.EndCoord.Y = (Ypos - Buff->ShowY + Buff->MaxY) % Buff->MaxY;
2566 Request->Header.MessageSize += Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead;
2567 Request->Header.DataSize += Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead;
2568
2569 ConioUnlockScreenBuffer(Buff);
2570 if (NULL != Console)
2571 {
2572 ConioUnlockConsole(Console);
2573 }
2574
2575 Request->Data.ReadConsoleOutputCharRequest.CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)Request->Data.ReadConsoleOutputCharRequest.String) / CharSize;
2576
2577 return Request->Status;
2578 }
2579
2580
2581 CSR_API(CsrReadConsoleOutputAttrib)
2582 {
2583 NTSTATUS Status;
2584 PCSRSS_SCREEN_BUFFER Buff;
2585 DWORD Xpos, Ypos;
2586 CHAR* ReadBuffer;
2587 DWORD i;
2588
2589 DPRINT("CsrReadConsoleOutputAttrib\n");
2590
2591 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2592 Request->Header.DataSize = Request->Header.MessageSize - LPC_MESSAGE_BASE_SIZE;
2593 ReadBuffer = Request->Data.ReadConsoleOutputAttribRequest.String;
2594
2595 Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle, &Buff);
2596 if (! NT_SUCCESS(Status))
2597 {
2598 return Request->Status = Status;
2599 }
2600
2601 Xpos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.X + Buff->ShowX;
2602 Ypos = (Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.Y + Buff->ShowY) % Buff->MaxY;
2603
2604 for (i = 0; i < Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; ++i)
2605 {
2606 *ReadBuffer = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX) + 1];
2607
2608 ReadBuffer++;
2609 Xpos++;
2610
2611 if (Xpos == Buff->MaxX)
2612 {
2613 Xpos = 0;
2614 Ypos++;
2615
2616 if (Ypos == Buff->MaxY)
2617 {
2618 Ypos = 0;
2619 }
2620 }
2621 }
2622
2623 *ReadBuffer = 0;
2624
2625 Request->Status = STATUS_SUCCESS;
2626 Request->Data.ReadConsoleOutputAttribRequest.EndCoord.X = Xpos - Buff->ShowX;
2627 Request->Data.ReadConsoleOutputAttribRequest.EndCoord.Y = (Ypos - Buff->ShowY + Buff->MaxY) % Buff->MaxY;
2628 Request->Header.MessageSize += Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead;
2629 Request->Header.DataSize += Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead;
2630
2631 ConioUnlockScreenBuffer(Buff);
2632
2633 return Request->Status;
2634 }
2635
2636
2637 CSR_API(CsrGetNumberOfConsoleInputEvents)
2638 {
2639 NTSTATUS Status;
2640 PCSRSS_CONSOLE Console;
2641 PLIST_ENTRY CurrentItem;
2642 DWORD NumEvents;
2643 ConsoleInput *Input;
2644
2645 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2646
2647 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2648 Request->Header.DataSize = Request->Header.MessageSize - LPC_MESSAGE_BASE_SIZE;
2649
2650 Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console);
2651 if (! NT_SUCCESS(Status))
2652 {
2653 return Request->Status = Status;
2654 }
2655
2656 CurrentItem = Console->InputEvents.Flink;
2657 NumEvents = 0;
2658
2659 /* If there are any events ... */
2660 while (CurrentItem != &Console->InputEvents)
2661 {
2662 Input = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
2663 CurrentItem = CurrentItem->Flink;
2664 if (!Input->Fake)
2665 {
2666 NumEvents++;
2667 }
2668 }
2669
2670 ConioUnlockConsole(Console);
2671
2672 Request->Status = STATUS_SUCCESS;
2673 Request->Data.GetNumInputEventsRequest.NumInputEvents = NumEvents;
2674
2675 return Request->Status;
2676 }
2677
2678
2679 CSR_API(CsrPeekConsoleInput)
2680 {
2681 NTSTATUS Status;
2682 PCSRSS_CONSOLE Console;
2683 DWORD Size;
2684 DWORD Length;
2685 PLIST_ENTRY CurrentItem;
2686 PINPUT_RECORD InputRecord;
2687 ConsoleInput* Item;
2688 UINT NumItems;
2689
2690 DPRINT("CsrPeekConsoleInput\n");
2691
2692 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2693 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2694
2695 Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console);
2696 if(! NT_SUCCESS(Status))
2697 {
2698 return Request->Status = Status;
2699 }
2700
2701 InputRecord = Request->Data.PeekConsoleInputRequest.InputRecord;
2702 Length = Request->Data.PeekConsoleInputRequest.Length;
2703 Size = Length * sizeof(INPUT_RECORD);
2704
2705 if (((PVOID)InputRecord < ProcessData->CsrSectionViewBase)
2706 || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
2707 {
2708 ConioUnlockConsole(Console);
2709 Request->Status = STATUS_ACCESS_VIOLATION;
2710 return Request->Status ;
2711 }
2712
2713 NumItems = 0;
2714
2715 if (! IsListEmpty(&Console->InputEvents))
2716 {
2717 CurrentItem = Console->InputEvents.Flink;
2718
2719 while (CurrentItem != &Console->InputEvents && NumItems < Length)
2720 {
2721 Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
2722
2723 if (Item->Fake)
2724 {
2725 CurrentItem = CurrentItem->Flink;
2726 continue;
2727 }
2728
2729 ++NumItems;
2730 *InputRecord = Item->InputEvent;
2731
2732 if (Request->Data.ReadInputRequest.Unicode == FALSE)
2733 {
2734 ConioInputEventToAnsi(Console, InputRecord);
2735 }
2736
2737 InputRecord++;
2738 CurrentItem = CurrentItem->Flink;
2739 }
2740 }
2741
2742 ConioUnlockConsole(Console);
2743
2744 Request->Status = STATUS_SUCCESS;
2745 Request->Data.PeekConsoleInputRequest.Length = NumItems;
2746
2747 return Request->Status;
2748 }
2749
2750
2751 CSR_API(CsrReadConsoleOutput)
2752 {
2753 PCHAR_INFO CharInfo;
2754 PCHAR_INFO CurCharInfo;
2755 PCSRSS_SCREEN_BUFFER Buff;
2756 DWORD Size;
2757 DWORD Length;
2758 DWORD SizeX, SizeY;
2759 NTSTATUS Status;
2760 COORD BufferSize;
2761 COORD BufferCoord;
2762 RECT ReadRegion;
2763 RECT ScreenRect;
2764 DWORD i, Y, X, Offset;
2765 UINT CodePage;
2766
2767 DPRINT("CsrReadConsoleOutput\n");
2768
2769 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2770 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2771
2772 Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputRequest.ConsoleHandle, &Buff);
2773 if (! NT_SUCCESS(Status))
2774 {
2775 return Request->Status = Status;
2776 }
2777
2778 CharInfo = Request->Data.ReadConsoleOutputRequest.CharInfo;
2779 ReadRegion.left = Request->Data.ReadConsoleOutputRequest.ReadRegion.Left;
2780 ReadRegion.top = Request->Data.ReadConsoleOutputRequest.ReadRegion.Top;
2781 ReadRegion.right = Request->Data.ReadConsoleOutputRequest.ReadRegion.Right;
2782 ReadRegion.bottom = Request->Data.ReadConsoleOutputRequest.ReadRegion.Bottom;
2783 BufferSize = Request->Data.ReadConsoleOutputRequest.BufferSize;
2784 BufferCoord = Request->Data.ReadConsoleOutputRequest.BufferCoord;
2785 Length = BufferSize.X * BufferSize.Y;
2786 Size = Length * sizeof(CHAR_INFO);
2787
2788 /* FIXME: Is this correct? */
2789 CodePage = ProcessData->Console->OutputCodePage;
2790
2791 if (((PVOID)CharInfo < ProcessData->CsrSectionViewBase)
2792 || (((PVOID)CharInfo + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
2793 {
2794 ConioUnlockScreenBuffer(Buff);
2795 Request->Status = STATUS_ACCESS_VIOLATION;
2796 return Request->Status ;
2797 }
2798
2799 SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion));
2800 SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion));
2801 ReadRegion.bottom = ReadRegion.top + SizeY;
2802 ReadRegion.right = ReadRegion.left + SizeX;
2803
2804 ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX);
2805 if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
2806 {
2807 ConioUnlockScreenBuffer(Buff);
2808 Request->Status = STATUS_SUCCESS;
2809 return Request->Status;
2810 }
2811
2812 for (i = 0, Y = ReadRegion.top; Y < ReadRegion.bottom; ++i, ++Y)
2813 {
2814 CurCharInfo = CharInfo + (i * BufferSize.X);
2815
2816 Offset = (((Y + Buff->ShowY) % Buff->MaxY) * Buff->MaxX + ReadRegion.left) * 2;
2817 for (X = ReadRegion.left; X < ReadRegion.right; ++X)
2818 {
2819 if (Request->Data.ReadConsoleOutputRequest.Unicode)
2820 {
2821 MultiByteToWideChar(CodePage, 0,
2822 (PCHAR)&GET_CELL_BUFFER(Buff, Offset), 1,
2823 &CurCharInfo->Char.UnicodeChar, 1);
2824 }
2825 else
2826 {
2827 CurCharInfo->Char.AsciiChar = GET_CELL_BUFFER(Buff, Offset);
2828 }
2829 CurCharInfo->Attributes = GET_CELL_BUFFER(Buff, Offset);
2830 ++CurCharInfo;
2831 }
2832 }
2833
2834 ConioUnlockScreenBuffer(Buff);
2835
2836 Request->Status = STATUS_SUCCESS;
2837 Request->Data.ReadConsoleOutputRequest.ReadRegion.Right = ReadRegion.left + SizeX - 1;
2838 Request->Data.ReadConsoleOutputRequest.ReadRegion.Bottom = ReadRegion.top + SizeY - 1;
2839 Request->Data.ReadConsoleOutputRequest.ReadRegion.Left = ReadRegion.left;
2840 Request->Data.ReadConsoleOutputRequest.ReadRegion.Top = ReadRegion.top;
2841
2842 return Request->Status;
2843 }
2844
2845
2846 CSR_API(CsrWriteConsoleInput)
2847 {
2848 PINPUT_RECORD InputRecord;
2849 PCSRSS_CONSOLE Console;
2850 NTSTATUS Status;
2851 DWORD Length;
2852 DWORD Size;
2853 DWORD i;
2854 ConsoleInput* Record;
2855
2856 DPRINT("CsrWriteConsoleInput\n");
2857
2858 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2859 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2860
2861 Status = ConioLockConsole(ProcessData, Request->Data.WriteConsoleInputRequest.ConsoleHandle, &Console);
2862 if (! NT_SUCCESS(Status))
2863 {
2864 return Request->Status = Status;
2865 }
2866
2867 InputRecord = Request->Data.WriteConsoleInputRequest.InputRecord;
2868 Length = Request->Data.WriteConsoleInputRequest.Length;
2869 Size = Length * sizeof(INPUT_RECORD);
2870
2871 if (((PVOID)InputRecord < ProcessData->CsrSectionViewBase)
2872 || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
2873 {
2874 ConioUnlockConsole(Console);
2875 Request->Status = STATUS_ACCESS_VIOLATION;
2876 return Request->Status ;
2877 }
2878
2879 for (i = 0; i < Length; i++)
2880 {
2881 Record = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
2882 if (NULL == Record)
2883 {
2884 ConioUnlockConsole(Console);
2885 Request->Status = STATUS_INSUFFICIENT_RESOURCES;
2886 return Request->Status;
2887 }
2888
2889 Record->Echoed = FALSE;
2890 Record->Fake = FALSE;
2891 Record->InputEvent = *InputRecord++;
2892 if (KEY_EVENT == Record->InputEvent.EventType)
2893 {
2894 /* FIXME - convert from unicode to ascii!! */
2895 ConioProcessChar(Console, Record);
2896 }
2897 }
2898
2899 ConioUnlockConsole(Console);
2900
2901 Request->Status = STATUS_SUCCESS;
2902 Request->Data.WriteConsoleInputRequest.Length = i;
2903
2904 return Request->Status;
2905 }
2906
2907 /**********************************************************************
2908 * HardwareStateProperty
2909 *
2910 * DESCRIPTION
2911 * Set/Get the value of the HardwareState and switch
2912 * between direct video buffer ouput and GDI windowed
2913 * output.
2914 * ARGUMENTS
2915 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2916 * object. We use the same object to Request.
2917 * NOTE
2918 * ConsoleHwState has the correct size to be compatible
2919 * with NT's, but values are not.
2920 */
2921 STATIC NTSTATUS FASTCALL
2922 SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
2923 {
2924 DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
2925
2926 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
2927 ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
2928 {
2929 if (Console->HardwareState != ConsoleHwState)
2930 {
2931 /* TODO: implement switching from full screen to windowed mode */
2932 /* TODO: or back; now simply store the hardware state */
2933 Console->HardwareState = ConsoleHwState;
2934 }
2935
2936 return STATUS_SUCCESS;
2937 }
2938
2939 return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
2940 }
2941
2942 CSR_API(CsrHardwareStateProperty)
2943 {
2944 PCSRSS_CONSOLE Console;
2945 NTSTATUS Status;
2946
2947 DPRINT("CsrHardwareStateProperty\n");
2948
2949 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2950 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2951
2952 Status = ConioLockConsole(ProcessData,
2953 Request->Data.ConsoleHardwareStateRequest.ConsoleHandle,
2954 &Console);
2955 if (! NT_SUCCESS(Status))
2956 {
2957 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2958 return Request->Status = Status;
2959 }
2960
2961 switch (Request->Data.ConsoleHardwareStateRequest.SetGet)
2962 {
2963 case CONSOLE_HARDWARE_STATE_GET:
2964 Request->Data.ConsoleHardwareStateRequest.State = Console->HardwareState;
2965 break;
2966
2967 case CONSOLE_HARDWARE_STATE_SET:
2968 DPRINT("Setting console hardware state.\n");
2969 Request->Status = SetConsoleHardwareState(Console, Request->Data.ConsoleHardwareStateRequest.State);
2970 break;
2971
2972 default:
2973 Request->Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
2974 break;
2975 }
2976
2977 ConioUnlockConsole(Console);
2978
2979 return Request->Status;
2980 }
2981
2982 CSR_API(CsrGetConsoleWindow)
2983 {
2984 PCSRSS_CONSOLE Console;
2985 NTSTATUS Status;
2986
2987 DPRINT("CsrGetConsoleWindow\n");
2988
2989 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
2990 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
2991
2992 Status = ConioConsoleFromProcessData(ProcessData, &Console);
2993 if (! NT_SUCCESS(Status))
2994 {
2995 return Request->Status = Status;
2996 }
2997
2998 Request->Data.GetConsoleWindowRequest.WindowHandle = Console->hWindow;
2999 ConioUnlockConsole(Console);
3000
3001 return Request->Status = STATUS_SUCCESS;
3002 }
3003
3004 CSR_API(CsrSetConsoleIcon)
3005 {
3006 PCSRSS_CONSOLE Console;
3007 NTSTATUS Status;
3008
3009 DPRINT("CsrSetConsoleIcon\n");
3010
3011 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
3012 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
3013
3014 Status = ConioConsoleFromProcessData(ProcessData, &Console);
3015 if (! NT_SUCCESS(Status))
3016 {
3017 return Request->Status = Status;
3018 }
3019
3020 Console->hWindowIcon = Request->Data.SetConsoleIconRequest.WindowIcon;
3021 Request->Status = (ConioChangeIcon(Console) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
3022 ConioUnlockConsole(Console);
3023
3024 return Request->Status;
3025 }
3026
3027 CSR_API(CsrGetConsoleCodePage)
3028 {
3029 PCSRSS_CONSOLE Console;
3030 NTSTATUS Status;
3031
3032 DPRINT("CsrGetConsoleCodePage\n");
3033
3034 Status = ConioConsoleFromProcessData(ProcessData, &Console);
3035 if (! NT_SUCCESS(Status))
3036 {
3037 return Request->Status = Status;
3038 }
3039
3040 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
3041 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
3042 Request->Data.GetConsoleCodePage.CodePage = Console->CodePage;
3043 ConioUnlockConsole(Console);
3044 return Request->Status = STATUS_SUCCESS;
3045 }
3046
3047 CSR_API(CsrSetConsoleCodePage)
3048 {
3049 PCSRSS_CONSOLE Console;
3050 NTSTATUS Status;
3051
3052 DPRINT("CsrSetConsoleCodePage\n");
3053
3054 Status = ConioConsoleFromProcessData(ProcessData, &Console);
3055 if (! NT_SUCCESS(Status))
3056 {
3057 return Request->Status = Status;
3058 }
3059
3060 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
3061 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
3062 if (IsValidCodePage(Request->Data.SetConsoleCodePage.CodePage))
3063 {
3064 Console->CodePage = Request->Data.SetConsoleCodePage.CodePage;
3065 ConioUnlockConsole(Console);
3066 return Request->Status = STATUS_SUCCESS;
3067 }
3068 ConioUnlockConsole(Console);
3069 return Request->Status = STATUS_UNSUCCESSFUL;
3070 }
3071
3072 CSR_API(CsrGetConsoleOutputCodePage)
3073 {
3074 PCSRSS_CONSOLE Console;
3075 NTSTATUS Status;
3076
3077 DPRINT("CsrGetConsoleOutputCodePage\n");
3078
3079 Status = ConioConsoleFromProcessData(ProcessData, &Console);
3080 if (! NT_SUCCESS(Status))
3081 {
3082 return Request->Status = Status;
3083 }
3084
3085 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
3086 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
3087 Request->Data.GetConsoleOutputCodePage.CodePage = Console->OutputCodePage;
3088 ConioUnlockConsole(Console);
3089 return Request->Status = STATUS_SUCCESS;
3090 }
3091
3092 CSR_API(CsrSetConsoleOutputCodePage)
3093 {
3094 PCSRSS_CONSOLE Console;
3095 NTSTATUS Status;
3096
3097 DPRINT("CsrSetConsoleOutputCodePage\n");
3098
3099 Status = ConioConsoleFromProcessData(ProcessData, &Console);
3100 if (! NT_SUCCESS(Status))
3101 {
3102 return Request->Status = Status;
3103 }
3104
3105 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
3106 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
3107 if (IsValidCodePage(Request->Data.SetConsoleOutputCodePage.CodePage))
3108 {
3109 Console->OutputCodePage = Request->Data.SetConsoleOutputCodePage.CodePage;
3110 ConioUnlockConsole(Console);
3111 return Request->Status = STATUS_SUCCESS;
3112 }
3113 ConioUnlockConsole(Console);
3114 return Request->Status = STATUS_UNSUCCESSFUL;
3115 }
3116
3117 CSR_API(CsrGetProcessList)
3118 {
3119 PHANDLE Buffer;
3120 PCSRSS_CONSOLE Console;
3121 PCSRSS_PROCESS_DATA current;
3122 PLIST_ENTRY current_entry;
3123 ULONG nItems, nCopied;
3124 NTSTATUS Status;
3125
3126 DPRINT("CsrGetProcessList\n");
3127
3128 Buffer = Request->Data.GetProcessListRequest.ProcessId;
3129 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
3130 Request->Header.DataSize = Request->Header.MessageSize - LPC_MESSAGE_BASE_SIZE;
3131
3132 nItems = nCopied = 0;
3133 Request->Data.GetProcessListRequest.nProcessIdsCopied = 0;
3134 Request->Data.GetProcessListRequest.nProcessIdsTotal = 0;
3135
3136 Status = ConioConsoleFromProcessData(ProcessData, &Console);
3137 if (! NT_SUCCESS(Status))
3138 {
3139 return Request->Status = Status;
3140 }
3141
3142 DPRINT1("Console_Api Ctrl-C\n");
3143
3144 for(current_entry = Console->ProcessList.Flink;
3145 current_entry != &Console->ProcessList;
3146 current_entry = current_entry->Flink)
3147 {
3148 current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
3149 if(nItems++ < Request->Data.GetProcessListRequest.nMaxIds)
3150 {
3151 *(Buffer++) = current->ProcessId;
3152 nCopied++;
3153 }
3154 }
3155
3156 ConioUnlockConsole(Console);
3157
3158 Request->Data.GetProcessListRequest.nProcessIdsCopied = nCopied;
3159 Request->Data.GetProcessListRequest.nProcessIdsTotal = nItems;
3160
3161 return Request->Status = STATUS_SUCCESS;
3162 }
3163
3164 /* EOF */