2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
16 /* FIXME: Is there a way to create real aliasses with gcc? [CSH] */
17 #define ALIAS(Name, Target) typeof(Target) Name = Target
19 /* GLOBALS *******************************************************************/
21 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
22 ((Rect)->top) = Top; \
23 ((Rect)->left) = Left; \
24 ((Rect)->bottom) = Bottom; \
25 ((Rect)->right) = Right
27 #define ConioIsRectEmpty(Rect) \
28 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
30 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
31 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
33 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
34 MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
37 /* FUNCTIONS *****************************************************************/
39 static NTSTATUS FASTCALL
40 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
42 if (NULL
== ProcessData
->Console
)
45 return STATUS_SUCCESS
;
48 EnterCriticalSection(&(ProcessData
->Console
->Header
.Lock
));
49 *Console
= ProcessData
->Console
;
51 return STATUS_SUCCESS
;
55 ConioConsoleCtrlEventTimeout(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
, DWORD Timeout
)
59 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
61 if (ProcessData
->CtrlDispatcher
)
64 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
65 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
66 (PVOID
) Event
, 0, NULL
);
69 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
72 WaitForSingleObject(Thread
, Timeout
);
78 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
80 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, INFINITE
);
83 #define GET_CELL_BUFFER(b,o)\
86 #define SET_CELL_BUFFER(b,o,c,a)\
87 (b)->Buffer[(o)++]=(c),\
88 (b)->Buffer[(o)++]=(a)
91 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
93 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
96 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
98 /* Fill the cell: Offset is incremented by the macro */
99 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
103 static NTSTATUS FASTCALL
104 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
105 PCSRSS_SCREEN_BUFFER Buffer
)
107 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
109 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
110 Buffer
->Header
.ReferenceCount
= 0;
113 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* sizeof(WCHAR
));
114 if (NULL
== Buffer
->Buffer
)
116 return STATUS_INSUFFICIENT_RESOURCES
;
118 InitializeCriticalSection(&Buffer
->Header
.Lock
);
119 ConioInitScreenBuffer(Console
, Buffer
);
120 /* initialize buffer to be empty with default attributes */
121 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
123 ClearLineBuffer(Buffer
);
125 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
126 Buffer
->CurrentX
= 0;
127 Buffer
->CurrentY
= 0;
129 return STATUS_SUCCESS
;
132 static NTSTATUS STDCALL
133 CsrInitConsole(PCSRSS_CONSOLE Console
)
136 SECURITY_ATTRIBUTES SecurityAttributes
;
137 PCSRSS_SCREEN_BUFFER NewBuffer
;
140 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
141 Console
->Title
.Buffer
= NULL
;
144 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
146 Console
->Header
.ReferenceCount
= 0;
147 Console
->WaitingChars
= 0;
148 Console
->WaitingLines
= 0;
149 Console
->EchoCount
= 0;
150 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
151 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
152 Console
->EarlyReturn
= FALSE
;
153 Console
->ActiveBuffer
= NULL
;
154 InitializeListHead(&Console
->InputEvents
);
155 Console
->CodePage
= GetOEMCP();
156 Console
->OutputCodePage
= GetOEMCP();
158 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
159 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
160 SecurityAttributes
.bInheritHandle
= TRUE
;
162 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
163 if (NULL
== Console
->ActiveEvent
)
165 RtlFreeUnicodeString(&Console
->Title
);
166 return STATUS_UNSUCCESSFUL
;
168 Console
->PrivateData
= NULL
;
169 InitializeCriticalSection(&Console
->Header
.Lock
);
171 GuiMode
= DtbgIsDesktopVisible();
173 /* allocate console screen buffer */
174 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
175 /* init screen buffer with defaults */
176 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
177 NewBuffer
->CursorInfo
.dwSize
= 5;
178 /* make console active, and insert into console list */
179 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
180 /* add a reference count because the buffer is tied to the console */
181 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
182 if (NULL
== NewBuffer
)
184 RtlFreeUnicodeString(&Console
->Title
);
185 DeleteCriticalSection(&Console
->Header
.Lock
);
186 CloseHandle(Console
->ActiveEvent
);
187 return STATUS_INSUFFICIENT_RESOURCES
;
192 Status
= TuiInitConsole(Console
);
193 if (! NT_SUCCESS(Status
))
195 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
201 Status
= GuiInitConsole(Console
);
202 if (! NT_SUCCESS(Status
))
204 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
205 RtlFreeUnicodeString(&Console
->Title
);
206 DeleteCriticalSection(&Console
->Header
.Lock
);
207 CloseHandle(Console
->ActiveEvent
);
208 DPRINT1("GuiInitConsole: failed\n");
213 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
214 if (! NT_SUCCESS(Status
))
216 ConioCleanupConsole(Console
);
217 RtlFreeUnicodeString(&Console
->Title
);
218 DeleteCriticalSection(&Console
->Header
.Lock
);
219 CloseHandle(Console
->ActiveEvent
);
220 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
221 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
226 /* copy buffer contents to screen */
227 ConioDrawConsole(Console
);
229 return STATUS_SUCCESS
;
233 CSR_API(CsrAllocConsole
)
235 PCSRSS_CONSOLE Console
;
236 NTSTATUS Status
= STATUS_SUCCESS
;
237 BOOLEAN NewConsole
= FALSE
;
239 DPRINT("CsrAllocConsole\n");
241 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
242 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
244 if (ProcessData
== NULL
)
246 DPRINT1("No process data\n");
247 return Request
->Status
= STATUS_INVALID_PARAMETER
;
250 if (ProcessData
->Console
)
252 DPRINT1("Process already has a console\n");
253 Request
->Status
= STATUS_INVALID_PARAMETER
;
254 return STATUS_INVALID_PARAMETER
;
258 Request
->Status
= STATUS_SUCCESS
;
260 /* If we don't need a console, then get out of here */
261 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
263 DPRINT("No console needed\n");
264 return STATUS_SUCCESS
;
267 /* If we already have one, then don't create a new one... */
268 if (!Request
->Data
.AllocConsoleRequest
.Console
||
269 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
271 /* Allocate a console structure */
273 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
276 DPRINT1("Not enough memory for console\n");
277 Request
->Status
= STATUS_NO_MEMORY
;
278 return STATUS_NO_MEMORY
;
280 /* initialize list head */
281 InitializeListHead(&Console
->ProcessList
);
282 /* insert process data required for GUI initialization */
283 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
284 /* Initialize the Console */
285 Request
->Status
= CsrInitConsole(Console
);
286 if (!NT_SUCCESS(Request
->Status
))
288 DPRINT1("Console init failed\n");
289 HeapFree(Win32CsrApiHeap
, 0, Console
);
290 return Request
->Status
;
295 /* Reuse our current console */
296 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
299 /* Set the Process Console */
300 ProcessData
->Console
= Console
;
302 /* Return it to the caller */
303 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
305 /* Add a reference count because the process is tied to the console */
306 Console
->Header
.ReferenceCount
++;
308 if (NewConsole
|| !ProcessData
->bInheritHandles
)
310 /* Insert the Objects */
311 Status
= Win32CsrInsertObject(ProcessData
,
312 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
314 if (! NT_SUCCESS(Status
))
316 DPRINT1("Failed to insert object\n");
317 ConioDeleteConsole((Object_t
*) Console
);
318 ProcessData
->Console
= 0;
319 return Request
->Status
= Status
;
322 Status
= Win32CsrInsertObject(ProcessData
,
323 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
324 &Console
->ActiveBuffer
->Header
);
325 if (!NT_SUCCESS(Status
))
327 DPRINT1("Failed to insert object\n");
328 ConioDeleteConsole((Object_t
*) Console
);
329 Win32CsrReleaseObject(ProcessData
,
330 Request
->Data
.AllocConsoleRequest
.InputHandle
);
331 ProcessData
->Console
= 0;
332 return Request
->Status
= Status
;
336 /* Duplicate the Event */
337 if (!DuplicateHandle(GetCurrentProcess(),
338 ProcessData
->Console
->ActiveEvent
,
339 ProcessData
->Process
,
340 &ProcessData
->ConsoleEvent
,
345 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
346 ConioDeleteConsole((Object_t
*) Console
);
347 if (NewConsole
|| !ProcessData
->bInheritHandles
)
349 Win32CsrReleaseObject(ProcessData
,
350 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
351 Win32CsrReleaseObject(ProcessData
,
352 Request
->Data
.AllocConsoleRequest
.InputHandle
);
354 ProcessData
->Console
= 0;
355 return Request
->Status
= Status
;
358 /* Set the Ctrl Dispatcher */
359 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
360 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
364 /* Insert into the list if it has not been added */
365 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
368 return STATUS_SUCCESS
;
371 CSR_API(CsrFreeConsole
)
373 PCSRSS_CONSOLE Console
;
376 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
377 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
379 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
381 return Request
->Status
= STATUS_INVALID_PARAMETER
;
384 Console
= ProcessData
->Console
;
385 ProcessData
->Console
= NULL
;
386 if (0 == InterlockedDecrement(&Console
->Header
.ReferenceCount
))
388 ConioDeleteConsole((Object_t
*) Console
);
390 return STATUS_SUCCESS
;
394 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
396 /* slide the viewable screen */
397 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == (ULONG
)Buff
->MaxY
- 1)
399 if (++Buff
->ShowY
== Buff
->MaxY
)
405 if (++Buff
->CurrentY
== Buff
->MaxY
)
409 ClearLineBuffer(Buff
);
410 UpdateRect
->left
= 0;
411 UpdateRect
->right
= Buff
->MaxX
- 1;
412 if (UpdateRect
->top
== (LONG
)Buff
->CurrentY
)
414 if (++UpdateRect
->top
== Buff
->MaxY
)
419 UpdateRect
->bottom
= Buff
->CurrentY
;
422 static NTSTATUS FASTCALL
423 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
424 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
429 LONG CursorStartX
, CursorStartY
;
432 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
433 UpdateRect
.left
= Buff
->MaxX
;
434 UpdateRect
.top
= Buff
->CurrentY
;
435 UpdateRect
.right
= -1;
436 UpdateRect
.bottom
= Buff
->CurrentY
;
439 for (i
= 0; i
< Length
; i
++)
441 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
444 if (Buffer
[i
] == '\n')
447 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
451 else if (Buffer
[i
] == '\b')
453 /* Only handle BS if we're not on the first pos of the first line */
454 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
456 if (0 == Buff
->CurrentX
)
458 /* slide virtual position up */
459 Buff
->CurrentX
= Buff
->MaxX
- 1;
460 if (0 == Buff
->CurrentY
)
462 Buff
->CurrentY
= Buff
->MaxY
;
468 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< (LONG
)Buff
->CurrentY
)
469 || (0 != UpdateRect
.top
&& (LONG
)Buff
->CurrentY
< UpdateRect
.top
))
471 UpdateRect
.top
= Buff
->CurrentY
;
478 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
479 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
480 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
481 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
486 else if (Buffer
[i
] == '\r')
489 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
490 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
494 else if (Buffer
[i
] == '\t')
498 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
499 EndX
= (Buff
->CurrentX
+ 8) & ~7;
500 if (EndX
> Buff
->MaxX
)
504 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
505 while (Buff
->CurrentX
< EndX
)
507 Buff
->Buffer
[Offset
] = ' ';
511 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
512 if (Buff
->CurrentX
== Buff
->MaxX
)
514 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
517 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
527 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
528 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
529 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
530 Buff
->Buffer
[Offset
++] = Buffer
[i
];
533 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
536 if (Buff
->CurrentX
== Buff
->MaxX
)
538 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
541 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
545 Buff
->CurrentX
= CursorStartX
;
550 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
552 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
553 &(UpdateRect
.bottom
));
554 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
556 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
560 return STATUS_SUCCESS
;
563 CSR_API(CsrReadConsole
)
565 PLIST_ENTRY CurrentEntry
;
568 PWCHAR UnicodeBuffer
;
570 ULONG nNumberOfCharsToRead
, CharSize
;
571 PCSRSS_CONSOLE Console
;
574 DPRINT("CsrReadConsole\n");
576 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
578 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
579 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
580 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
581 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
583 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
584 UnicodeBuffer
= (PWCHAR
)Buffer
;
585 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
587 if (! NT_SUCCESS(Status
))
589 return Request
->Status
= Status
;
591 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
592 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
594 /* remove input event from queue */
595 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
596 if (IsListEmpty(&Console
->InputEvents
))
599 ResetEvent(Console
->ActiveEvent
);
601 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
603 /* only pay attention to valid ascii chars, on key down */
604 if (KEY_EVENT
== Input
->InputEvent
.EventType
605 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
606 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
609 * backspace handling - if we are in charge of echoing it then we handle it here
610 * otherwise we treat it like a normal char.
612 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
613 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
615 /* echo if it has not already been done, and either we or the client has chars to be deleted */
617 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
619 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
620 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
624 i
-= 2; /* if we already have something to return, just back it up by 2 */
627 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
628 Console
->WaitingChars
--;
629 ConioUnlockConsole(Console
);
630 HeapFree(Win32CsrApiHeap
, 0, Input
);
631 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
632 Request
->Status
= STATUS_NOTIFY_CLEANUP
;
633 return STATUS_NOTIFY_CLEANUP
;
636 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
637 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
639 /* do not copy backspace to buffer */
642 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
643 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
645 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
647 /* echo to screen if enabled and we did not already echo the char */
648 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
650 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
652 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
653 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
660 Console
->WaitingChars
--;
661 HeapFree(Win32CsrApiHeap
, 0, Input
);
663 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
666 Request
->Status
= STATUS_PENDING
; /* we didn't read anything */
668 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
670 if (0 == Console
->WaitingLines
||
671 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
673 Request
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
677 Console
->WaitingLines
--;
678 Request
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
683 Request
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
686 if (Request
->Status
== STATUS_PENDING
)
688 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
692 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
695 ConioUnlockConsole(Console
);
697 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
699 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
700 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
703 return Request
->Status
;
707 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
713 *LogicalX
= PhysicalX
;
714 if (PhysicalY
< Buff
->ShowY
)
716 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
720 *LogicalY
= PhysicalY
- Buff
->ShowY
;
724 inline BOOLEAN
ConioIsEqualRect(
728 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
729 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
732 inline BOOLEAN
ConioGetIntersection(
737 if (ConioIsRectEmpty(Rect1
) ||
738 (ConioIsRectEmpty(Rect2
)) ||
739 (Rect1
->top
> Rect2
->bottom
) ||
740 (Rect1
->left
> Rect2
->right
) ||
741 (Rect1
->bottom
< Rect2
->top
) ||
742 (Rect1
->right
< Rect2
->left
))
744 /* The rectangles do not intersect */
745 ConioInitRect(Intersection
, 0, -1, 0, -1);
749 ConioInitRect(Intersection
,
750 max(Rect1
->top
, Rect2
->top
),
751 max(Rect1
->left
, Rect2
->left
),
752 min(Rect1
->bottom
, Rect2
->bottom
),
753 min(Rect1
->right
, Rect2
->right
));
758 inline BOOLEAN
ConioGetUnion(
763 if (ConioIsRectEmpty(Rect1
))
765 if (ConioIsRectEmpty(Rect2
))
767 ConioInitRect(Union
, 0, -1, 0, -1);
775 else if (ConioIsRectEmpty(Rect2
))
782 min(Rect1
->top
, Rect2
->top
),
783 min(Rect1
->left
, Rect2
->left
),
784 max(Rect1
->bottom
, Rect2
->bottom
),
785 max(Rect1
->right
, Rect2
->right
));
791 inline BOOLEAN
ConioSubtractRect(
798 if (ConioIsRectEmpty(Rect1
))
800 ConioInitRect(Subtraction
, 0, -1, 0, -1);
803 *Subtraction
= *Rect1
;
804 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
806 if (ConioIsEqualRect(&tmp
, Subtraction
))
808 ConioInitRect(Subtraction
, 0, -1, 0, -1);
811 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
813 if (tmp
.left
== Subtraction
->left
)
815 Subtraction
->left
= tmp
.right
;
817 else if (tmp
.right
== Subtraction
->right
)
819 Subtraction
->right
= tmp
.left
;
822 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
824 if (tmp
.top
== Subtraction
->top
)
826 Subtraction
->top
= tmp
.bottom
;
828 else if (tmp
.bottom
== Subtraction
->bottom
)
830 Subtraction
->bottom
= tmp
.top
;
839 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
849 DstY
= DstRegion
->top
;
850 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
852 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
853 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
854 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
855 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
857 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
860 &ScreenBuffer
->Buffer
[DstOffset
],
861 &ScreenBuffer
->Buffer
[SrcOffset
],
864 if (++DstY
== ScreenBuffer
->MaxY
)
867 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
871 DstOffset
+= ScreenBuffer
->MaxX
* 2;
874 if (++SrcY
== ScreenBuffer
->MaxY
)
877 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
881 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
887 ConioFillRegion(PCSRSS_CONSOLE Console
,
888 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
900 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
902 Char
= CharInfo
->Char
.AsciiChar
;
904 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
905 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
906 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
908 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
910 for (X
= Region
->left
; X
<= Region
->right
; X
++)
912 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
914 if (++Y
== ScreenBuffer
->MaxY
)
917 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
927 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
929 if (InputEvent
->EventType
== KEY_EVENT
)
931 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
932 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
933 ConsoleUnicodeCharToAnsiChar(Console
,
934 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
939 CSR_API(CsrWriteConsole
)
943 PCSRSS_SCREEN_BUFFER Buff
;
944 PCSRSS_CONSOLE Console
;
947 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
949 DPRINT("CsrWriteConsole\n");
951 if (Request
->Header
.u1
.s1
.TotalLength
952 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
953 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
955 DPRINT1("Invalid request size\n");
956 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
957 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
958 return Request
->Status
= STATUS_INVALID_PARAMETER
;
960 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
962 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
963 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
965 if (! NT_SUCCESS(Status
))
967 return Request
->Status
= Status
;
970 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
972 Length
= WideCharToMultiByte(Console
->CodePage
, 0,
973 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
974 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
975 NULL
, 0, NULL
, NULL
);
976 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
979 WideCharToMultiByte(Console
->CodePage
, 0,
980 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
981 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
982 Buffer
, Length
, NULL
, NULL
);
986 Status
= STATUS_NO_MEMORY
;
991 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
996 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
997 if (NT_SUCCESS(Status
))
999 Request
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
1000 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
1001 if (NT_SUCCESS(Status
))
1003 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
1005 ConioUnlockScreenBuffer(Buff
);
1007 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1009 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
1012 if (NULL
!= Console
)
1014 ConioUnlockConsole(Console
);
1017 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
1019 return Request
->Status
= Status
;
1023 ConioDeleteScreenBuffer(Object_t
*Object
)
1025 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
1026 DeleteCriticalSection(&Buffer
->Header
.Lock
);
1027 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
1028 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
1032 ConioDrawConsole(PCSRSS_CONSOLE Console
)
1036 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
1038 ConioDrawRegion(Console
, &Region
);
1043 ConioDeleteConsole(Object_t
*Object
)
1045 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
1046 ConsoleInput
*Event
;
1048 DPRINT("ConioDeleteConsole\n");
1050 /* Drain input event queue */
1051 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
1053 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
1054 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
1055 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
1056 HeapFree(Win32CsrApiHeap
, 0, Event
);
1059 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
1061 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
1064 Console
->ActiveBuffer
= NULL
;
1065 ConioCleanupConsole(Console
);
1067 CloseHandle(Console
->ActiveEvent
);
1068 DeleteCriticalSection(&Console
->Header
.Lock
);
1069 RtlFreeUnicodeString(&Console
->Title
);
1070 HeapFree(Win32CsrApiHeap
, 0, Console
);
1074 CsrInitConsoleSupport(VOID
)
1076 DPRINT("CSR: CsrInitConsoleSupport()\n");
1078 /* Should call LoadKeyboardLayout */
1081 static VOID FASTCALL
1082 ConioProcessChar(PCSRSS_CONSOLE Console
,
1083 ConsoleInput
*KeyEventRecord
)
1086 BOOL bClientWake
= FALSE
;
1087 ConsoleInput
*TempInput
;
1089 /* process Ctrl-C and Ctrl-Break */
1090 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1091 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1092 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1093 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1094 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1096 PCSRSS_PROCESS_DATA current
;
1097 PLIST_ENTRY current_entry
;
1098 DPRINT1("Console_Api Ctrl-C\n");
1099 current_entry
= Console
->ProcessList
.Flink
;
1100 while (current_entry
!= &Console
->ProcessList
)
1102 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1103 current_entry
= current_entry
->Flink
;
1104 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1106 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1110 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1111 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1112 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1113 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1115 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1117 /* scroll up or down */
1118 if (NULL
== Console
)
1120 DPRINT1("No Active Console!\n");
1121 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1124 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1126 /* only scroll up if there is room to scroll up into */
1127 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1128 Console
->ActiveBuffer
->MaxY
))
1130 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1131 Console
->ActiveBuffer
->MaxY
- 1) %
1132 Console
->ActiveBuffer
->MaxY
;
1135 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1136 /* only scroll down if there is room to scroll down into */
1138 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1139 Console
->ActiveBuffer
->CurrentY
)
1141 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1142 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1143 Console
->ActiveBuffer
->MaxY
)
1145 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1146 Console
->ActiveBuffer
->MaxY
;
1150 ConioDrawConsole(Console
);
1152 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1155 if (NULL
== Console
)
1157 DPRINT1("No Active Console!\n");
1158 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1162 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1164 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1167 /* first add the \r */
1168 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1169 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1170 KeyEventRecord
->Echoed
= FALSE
;
1171 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1172 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1173 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1174 Console
->WaitingChars
++;
1175 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1176 if (NULL
== KeyEventRecord
)
1178 DPRINT1("Failed to allocate KeyEventRecord\n");
1181 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1182 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1183 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1184 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1185 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1186 KeyEventRecord
->Fake
= TRUE
;
1190 /* add event to the queue */
1191 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1192 Console
->WaitingChars
++;
1193 /* if line input mode is enabled, only wake the client on enter key down */
1194 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1195 || Console
->EarlyReturn
1196 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1197 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1199 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1201 Console
->WaitingLines
++;
1204 SetEvent(Console
->ActiveEvent
);
1206 KeyEventRecord
->Echoed
= FALSE
;
1207 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1208 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1209 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1211 /* walk the input queue looking for a char to backspace */
1212 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1213 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1214 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1215 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1216 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1217 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1221 /* if we found one, delete it, otherwise, wake the client */
1222 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1224 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1225 RemoveEntryList(&TempInput
->ListEntry
);
1226 if (TempInput
->Echoed
)
1228 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1229 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1232 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1233 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1234 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1235 Console
->WaitingChars
-= 2;
1239 SetEvent(Console
->ActiveEvent
);
1244 /* echo chars if we are supposed to and client is waiting for some */
1245 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1246 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1247 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1248 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1250 /* mark the char as already echoed */
1251 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1252 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1254 Console
->EchoCount
--;
1255 KeyEventRecord
->Echoed
= TRUE
;
1259 /* Console->WaitingChars++; */
1260 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1262 SetEvent(Console
->ActiveEvent
);
1266 static DWORD FASTCALL
1267 ConioGetShiftState(PBYTE KeyState
)
1271 if (KeyState
[VK_CAPITAL
] & 1)
1272 ssOut
|= CAPSLOCK_ON
;
1274 if (KeyState
[VK_NUMLOCK
] & 1)
1275 ssOut
|= NUMLOCK_ON
;
1277 if (KeyState
[VK_SCROLL
] & 1)
1278 ssOut
|= SCROLLLOCK_ON
;
1280 if (KeyState
[VK_SHIFT
] & 0x80)
1281 ssOut
|= SHIFT_PRESSED
;
1283 if (KeyState
[VK_LCONTROL
] & 0x80)
1284 ssOut
|= LEFT_CTRL_PRESSED
;
1285 if (KeyState
[VK_RCONTROL
] & 0x80)
1286 ssOut
|= RIGHT_CTRL_PRESSED
;
1288 if (KeyState
[VK_LMENU
] & 0x80)
1289 ssOut
|= LEFT_ALT_PRESSED
;
1290 if (KeyState
[VK_RMENU
] & 0x80)
1291 ssOut
|= RIGHT_ALT_PRESSED
;
1297 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1299 static BYTE KeyState
[256] = { 0 };
1300 /* MSDN mentions that you should use the last virtual key code received
1301 * when putting a virtual key identity to a WM_CHAR message since multiple
1302 * or translated keys may be involved. */
1303 static UINT LastVirtualKey
= 0;
1305 ConsoleInput
*ConInRec
;
1309 UINT VirtualKeyCode
;
1310 UINT VirtualScanCode
;
1313 ULONG ResultSize
= 0;
1316 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1317 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1318 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1320 GetKeyboardState(KeyState
);
1321 ShiftState
= ConioGetShiftState(KeyState
);
1323 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1325 VirtualKeyCode
= LastVirtualKey
;
1326 UnicodeChar
= msg
->wParam
;
1333 VirtualKeyCode
= msg
->wParam
;
1334 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1341 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1344 if (0 == ResultSize
)
1349 er
.EventType
= KEY_EVENT
;
1350 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1351 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1352 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1353 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1354 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1355 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1359 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1360 && VK_TAB
== VirtualKeyCode
)
1364 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1369 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1371 if (TuiSwapConsole(0))
1378 if (NULL
== Console
)
1383 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1385 if (NULL
== ConInRec
)
1390 ConInRec
->InputEvent
= er
;
1391 ConInRec
->Fake
= UnicodeChar
&&
1392 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1393 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1394 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1395 ConInRec
->Echoed
= FALSE
;
1396 if (ConInRec
->NotChar
)
1397 LastVirtualKey
= msg
->wParam
;
1399 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1400 Down
? "down" : "up ",
1401 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1403 ConInRec
->Fake
? "fake" : "real",
1404 ConInRec
->NotChar
? "notc" : "char",
1407 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1410 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1412 /* FIXME - convert to ascii */
1413 ConioProcessChar(Console
, ConInRec
);
1417 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1421 CSR_API(CsrGetScreenBufferInfo
)
1424 PCSRSS_SCREEN_BUFFER Buff
;
1425 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1427 DPRINT("CsrGetScreenBufferInfo\n");
1429 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1430 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1432 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1433 if (! NT_SUCCESS(Status
))
1435 return Request
->Status
= Status
;
1437 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1438 pInfo
->dwSize
.X
= Buff
->MaxX
;
1439 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1440 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1441 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1442 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1443 pInfo
->srWindow
.Left
= 0;
1444 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1445 pInfo
->srWindow
.Top
= 0;
1446 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1447 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1448 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1449 ConioUnlockScreenBuffer(Buff
);
1451 Request
->Status
= STATUS_SUCCESS
;
1453 return Request
->Status
;
1456 CSR_API(CsrSetCursor
)
1459 PCSRSS_CONSOLE Console
;
1460 PCSRSS_SCREEN_BUFFER Buff
;
1461 LONG OldCursorX
, OldCursorY
;
1462 LONG NewCursorX
, NewCursorY
;
1464 DPRINT("CsrSetCursor\n");
1466 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1467 if (! NT_SUCCESS(Status
))
1469 return Request
->Status
= Status
;
1472 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1473 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1475 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1476 if (! NT_SUCCESS(Status
))
1478 if (NULL
!= Console
)
1480 ConioUnlockConsole(Console
);
1482 return Request
->Status
= Status
;
1485 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1486 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1487 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1488 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1490 ConioUnlockScreenBuffer(Buff
);
1491 if (NULL
!= Console
)
1493 ConioUnlockConsole(Console
);
1495 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1497 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1498 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1499 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1500 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1502 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1504 ConioUnlockScreenBuffer(Buff
);
1505 if (NULL
!= Console
)
1507 ConioUnlockConsole(Console
);
1509 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1513 ConioUnlockScreenBuffer(Buff
);
1514 if (NULL
!= Console
)
1516 ConioUnlockConsole(Console
);
1519 return Request
->Status
= STATUS_SUCCESS
;
1522 static FASTCALL VOID
1523 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1525 if (Buff
->MaxX
<= Start
->X
+ Length
)
1527 UpdateRect
->left
= 0;
1531 UpdateRect
->left
= Start
->X
;
1533 if (Buff
->MaxX
<= Start
->X
+ Length
)
1535 UpdateRect
->right
= Buff
->MaxX
- 1;
1539 UpdateRect
->right
= Start
->X
+ Length
- 1;
1541 UpdateRect
->top
= Start
->Y
;
1542 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1543 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1545 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1549 CSR_API(CsrWriteConsoleOutputChar
)
1552 PCHAR String
, tmpString
= NULL
;
1554 PCSRSS_CONSOLE Console
;
1555 PCSRSS_SCREEN_BUFFER Buff
;
1556 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1559 DPRINT("CsrWriteConsoleOutputChar\n");
1561 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1563 if (Request
->Header
.u1
.s1
.TotalLength
1564 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1565 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1567 DPRINT1("Invalid request size\n");
1568 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1569 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1570 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1573 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1574 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1575 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1576 if (NT_SUCCESS(Status
))
1578 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1580 Length
= WideCharToMultiByte(Console
->CodePage
, 0,
1581 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1582 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1583 NULL
, 0, NULL
, NULL
);
1584 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1587 WideCharToMultiByte(Console
->CodePage
, 0,
1588 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1589 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1590 String
, Length
, NULL
, NULL
);
1594 Status
= STATUS_NO_MEMORY
;
1599 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1604 Status
= ConioLockScreenBuffer(ProcessData
,
1605 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1607 if (NT_SUCCESS(Status
))
1609 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1610 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1611 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1612 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1615 *Buffer
= *String
++;
1618 if (++X
== Buff
->MaxX
)
1620 if (++Y
== Buff
->MaxY
)
1623 Buffer
= Buff
->Buffer
;
1628 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1630 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1631 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1632 ConioDrawRegion(Console
, &UpdateRect
);
1635 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
- Buff
->ShowX
;
1636 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1638 ConioUnlockScreenBuffer(Buff
);
1640 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1642 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1645 if (NULL
!= Console
)
1647 ConioUnlockConsole(Console
);
1650 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1651 return Request
->Status
= Status
;
1654 CSR_API(CsrFillOutputChar
)
1657 PCSRSS_CONSOLE Console
;
1658 PCSRSS_SCREEN_BUFFER Buff
;
1659 DWORD X
, Y
, Length
, Written
= 0;
1664 DPRINT("CsrFillOutputChar\n");
1666 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1667 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1669 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1670 if (! NT_SUCCESS(Status
))
1672 return Request
->Status
= Status
;
1675 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1676 if (! NT_SUCCESS(Status
))
1678 if (NULL
!= Console
)
1680 ConioUnlockConsole(Console
);
1682 return Request
->Status
= Status
;
1685 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1686 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1687 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1688 if(Request
->Data
.FillOutputRequest
.Unicode
)
1689 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1691 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1692 Length
= Request
->Data
.FillOutputRequest
.Length
;
1698 if (++X
== Buff
->MaxX
)
1700 if (++Y
== Buff
->MaxY
)
1703 Buffer
= Buff
->Buffer
;
1709 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1711 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1712 Request
->Data
.FillOutputRequest
.Length
);
1713 ConioDrawRegion(Console
, &UpdateRect
);
1716 ConioUnlockScreenBuffer(Buff
);
1717 if (NULL
!= Console
)
1719 ConioUnlockConsole(Console
);
1721 Length
= Request
->Data
.FillOutputRequest
.Length
;
1722 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1723 return Request
->Status
;
1726 CSR_API(CsrReadInputEvent
)
1728 PLIST_ENTRY CurrentEntry
;
1729 PCSRSS_CONSOLE Console
;
1731 BOOLEAN Done
= FALSE
;
1732 ConsoleInput
*Input
;
1734 DPRINT("CsrReadInputEvent\n");
1736 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1737 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1738 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1740 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1741 if (! NT_SUCCESS(Status
))
1743 return Request
->Status
= Status
;
1746 /* only get input if there is any */
1747 CurrentEntry
= Console
->InputEvents
.Flink
;
1748 while (CurrentEntry
!= &Console
->InputEvents
)
1750 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1751 CurrentEntry
= CurrentEntry
->Flink
;
1753 if (Done
&& !Input
->Fake
)
1755 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1759 RemoveEntryList(&Input
->ListEntry
);
1761 if (!Done
&& !Input
->Fake
)
1763 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1764 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1766 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1771 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1773 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1774 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1775 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1777 Console
->WaitingLines
--;
1779 Console
->WaitingChars
--;
1781 HeapFree(Win32CsrApiHeap
, 0, Input
);
1786 Status
= STATUS_SUCCESS
;
1787 Console
->EarlyReturn
= FALSE
;
1791 Status
= STATUS_PENDING
;
1792 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1795 if (IsListEmpty(&Console
->InputEvents
))
1797 ResetEvent(Console
->ActiveEvent
);
1800 ConioUnlockConsole(Console
);
1802 return Request
->Status
= Status
;
1805 CSR_API(CsrWriteConsoleOutputAttrib
)
1807 PCSRSS_CONSOLE Console
;
1808 PCSRSS_SCREEN_BUFFER Buff
;
1815 DPRINT("CsrWriteConsoleOutputAttrib\n");
1817 if (Request
->Header
.u1
.s1
.TotalLength
1818 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1819 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1821 DPRINT1("Invalid request size\n");
1822 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1823 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1824 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1827 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1828 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1829 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1830 if (! NT_SUCCESS(Status
))
1832 return Request
->Status
= Status
;
1835 Status
= ConioLockScreenBuffer(ProcessData
,
1836 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1838 if (! NT_SUCCESS(Status
))
1840 if (NULL
!= Console
)
1842 ConioUnlockConsole(Console
);
1844 return Request
->Status
= Status
;
1847 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1848 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1849 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1850 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1851 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1854 *Buffer
= (UCHAR
)(*Attribute
++);
1856 if (++X
== Buff
->MaxX
)
1858 if (++Y
== Buff
->MaxY
)
1861 Buffer
= Buff
->Buffer
+ 1;
1867 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1869 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1870 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1871 ConioDrawRegion(Console
, &UpdateRect
);
1874 if (NULL
!= Console
)
1876 ConioUnlockConsole(Console
);
1879 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1880 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1882 ConioUnlockScreenBuffer(Buff
);
1884 return Request
->Status
= STATUS_SUCCESS
;
1887 CSR_API(CsrFillOutputAttrib
)
1889 PCSRSS_SCREEN_BUFFER Buff
;
1895 PCSRSS_CONSOLE Console
;
1897 DPRINT("CsrFillOutputAttrib\n");
1899 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1900 if (! NT_SUCCESS(Status
))
1902 return Request
->Status
= Status
;
1905 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1906 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1907 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1908 if (! NT_SUCCESS(Status
))
1910 if (NULL
!= Console
)
1912 ConioUnlockConsole(Console
);
1914 return Request
->Status
= Status
;
1917 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1918 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1919 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1920 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1921 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1926 if (++X
== Buff
->MaxX
)
1928 if (++Y
== Buff
->MaxY
)
1931 Buffer
= Buff
->Buffer
+ 1;
1937 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1939 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1940 Request
->Data
.FillOutputAttribRequest
.Length
);
1941 ConioDrawRegion(Console
, &UpdateRect
);
1944 ConioUnlockScreenBuffer(Buff
);
1945 if (NULL
!= Console
)
1947 ConioUnlockConsole(Console
);
1950 return Request
->Status
= STATUS_SUCCESS
;
1954 CSR_API(CsrGetCursorInfo
)
1956 PCSRSS_SCREEN_BUFFER Buff
;
1959 DPRINT("CsrGetCursorInfo\n");
1961 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1962 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1964 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1965 if (! NT_SUCCESS(Status
))
1967 return Request
->Status
= Status
;
1969 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1970 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1971 ConioUnlockScreenBuffer(Buff
);
1973 return Request
->Status
= STATUS_SUCCESS
;
1976 CSR_API(CsrSetCursorInfo
)
1978 PCSRSS_CONSOLE Console
;
1979 PCSRSS_SCREEN_BUFFER Buff
;
1984 DPRINT("CsrSetCursorInfo\n");
1986 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1987 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1989 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1990 if (! NT_SUCCESS(Status
))
1992 return Request
->Status
= Status
;
1995 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1996 if (! NT_SUCCESS(Status
))
1998 if (NULL
!= Console
)
2000 ConioUnlockConsole(Console
);
2002 return Request
->Status
= Status
;
2005 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
2006 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
2016 if (Size
!= Buff
->CursorInfo
.dwSize
2017 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
2019 Buff
->CursorInfo
.dwSize
= Size
;
2020 Buff
->CursorInfo
.bVisible
= Visible
;
2022 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
2024 ConioUnlockScreenBuffer(Buff
);
2025 ConioUnlockConsole(Console
);
2026 return Request
->Status
= STATUS_UNSUCCESSFUL
;
2030 ConioUnlockScreenBuffer(Buff
);
2031 if (NULL
!= Console
)
2033 ConioUnlockConsole(Console
);
2036 return Request
->Status
= STATUS_SUCCESS
;
2039 CSR_API(CsrSetTextAttrib
)
2042 PCSRSS_CONSOLE Console
;
2043 PCSRSS_SCREEN_BUFFER Buff
;
2044 LONG OldCursorX
, OldCursorY
;
2046 DPRINT("CsrSetTextAttrib\n");
2048 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2049 if (! NT_SUCCESS(Status
))
2051 return Request
->Status
= Status
;
2054 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
2055 if (! NT_SUCCESS(Status
))
2057 if (NULL
!= Console
)
2059 ConioUnlockConsole(Console
);
2061 return Request
->Status
= Status
;
2064 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
2066 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
2067 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2069 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
2071 ConioUnlockScreenBuffer(Buff
);
2072 ConioUnlockConsole(Console
);
2073 return Request
->Status
= STATUS_UNSUCCESSFUL
;
2077 ConioUnlockScreenBuffer(Buff
);
2078 if (NULL
!= Console
)
2080 ConioUnlockConsole(Console
);
2083 return Request
->Status
= STATUS_SUCCESS
;
2086 CSR_API(CsrSetConsoleMode
)
2089 PCSRSS_CONSOLE Console
;
2090 PCSRSS_SCREEN_BUFFER Buff
;
2092 DPRINT("CsrSetConsoleMode\n");
2094 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2095 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2096 Status
= Win32CsrGetObject(ProcessData
,
2097 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2098 (Object_t
**) &Console
);
2099 if (! NT_SUCCESS(Status
))
2101 return Request
->Status
= Status
;
2104 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2105 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2107 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2109 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2111 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2115 return Request
->Status
= STATUS_INVALID_HANDLE
;
2118 Request
->Status
= STATUS_SUCCESS
;
2120 return Request
->Status
;
2123 CSR_API(CsrGetConsoleMode
)
2126 PCSRSS_CONSOLE Console
;
2127 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2129 DPRINT("CsrGetConsoleMode\n");
2131 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2132 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2133 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2134 (Object_t
**) &Console
);
2135 if (! NT_SUCCESS(Status
))
2137 return Request
->Status
= Status
;
2139 Request
->Status
= STATUS_SUCCESS
;
2140 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2141 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2143 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
2145 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2147 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
2151 Request
->Status
= STATUS_INVALID_HANDLE
;
2154 return Request
->Status
;
2157 CSR_API(CsrCreateScreenBuffer
)
2159 PCSRSS_CONSOLE Console
;
2160 PCSRSS_SCREEN_BUFFER Buff
;
2163 DPRINT("CsrCreateScreenBuffer\n");
2165 if (ProcessData
== NULL
)
2167 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2170 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2171 if (! NT_SUCCESS(Status
))
2173 return Request
->Status
= Status
;
2175 if (NULL
== Console
)
2177 return Request
->Status
= STATUS_INVALID_HANDLE
;
2180 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2181 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2183 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
2187 if (Console
->ActiveBuffer
)
2189 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
2190 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
2191 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
2192 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
2196 Buff
->CursorInfo
.bVisible
= TRUE
;
2197 Buff
->CursorInfo
.dwSize
= 5;
2200 if (Buff
->MaxX
== 0)
2205 if (Buff
->MaxY
== 0)
2210 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2211 if(! NT_SUCCESS(Status
))
2213 Request
->Status
= Status
;
2217 Request
->Status
= Win32CsrInsertObject(ProcessData
, &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
, &Buff
->Header
);
2222 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2225 ConioUnlockConsole(Console
);
2226 return Request
->Status
;
2229 CSR_API(CsrSetScreenBuffer
)
2232 PCSRSS_CONSOLE Console
;
2233 PCSRSS_SCREEN_BUFFER Buff
;
2235 DPRINT("CsrSetScreenBuffer\n");
2237 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2238 if (! NT_SUCCESS(Status
))
2240 return Request
->Status
= Status
;
2242 if (NULL
== Console
)
2244 DPRINT1("Trying to set screen buffer for app without console\n");
2245 return Request
->Status
= STATUS_INVALID_HANDLE
;
2248 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2249 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2251 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2252 if (! NT_SUCCESS(Status
))
2254 ConioUnlockConsole(Console
);
2255 return Request
->Status
;
2258 if (Buff
== Console
->ActiveBuffer
)
2260 ConioUnlockScreenBuffer(Buff
);
2261 ConioUnlockConsole(Console
);
2262 return STATUS_SUCCESS
;
2265 /* drop reference to old buffer, maybe delete */
2266 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2268 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2270 /* tie console to new buffer */
2271 Console
->ActiveBuffer
= Buff
;
2272 /* inc ref count on new buffer */
2273 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2274 /* Redraw the console */
2275 ConioDrawConsole(Console
);
2277 ConioUnlockScreenBuffer(Buff
);
2278 ConioUnlockConsole(Console
);
2280 return Request
->Status
= STATUS_SUCCESS
;
2283 CSR_API(CsrSetTitle
)
2286 PCSRSS_CONSOLE Console
;
2289 DPRINT("CsrSetTitle\n");
2291 if (Request
->Header
.u1
.s1
.TotalLength
2292 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2293 + Request
->Data
.SetTitleRequest
.Length
)
2295 DPRINT1("Invalid request size\n");
2296 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2297 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2298 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2301 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2302 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2303 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2304 if(! NT_SUCCESS(Status
))
2306 Request
->Status
= Status
;
2310 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2313 /* copy title to console */
2314 RtlFreeUnicodeString(&Console
->Title
);
2315 Console
->Title
.Buffer
= Buffer
;
2316 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2317 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2318 if (! ConioChangeTitle(Console
))
2320 Request
->Status
= STATUS_UNSUCCESSFUL
;
2324 Request
->Status
= STATUS_SUCCESS
;
2329 Request
->Status
= STATUS_NO_MEMORY
;
2332 ConioUnlockConsole(Console
);
2334 return Request
->Status
;
2337 CSR_API(CsrGetTitle
)
2340 PCSRSS_CONSOLE Console
;
2343 DPRINT("CsrGetTitle\n");
2345 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2346 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2347 Status
= ConioLockConsole(ProcessData
,
2348 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2350 if (! NT_SUCCESS(Status
))
2352 DPRINT1("Can't get console\n");
2353 return Request
->Status
= Status
;
2356 /* Copy title of the console to the user title buffer */
2357 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2358 Request
->Data
.GetTitleRequest
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2359 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2360 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2361 Console
->Title
.Length
);
2362 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2364 ConioUnlockConsole(Console
);
2366 if (Length
> sizeof(CSR_API_MESSAGE
))
2368 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2369 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2371 Request
->Status
= STATUS_SUCCESS
;
2373 return Request
->Status
;
2376 CSR_API(CsrWriteConsoleOutput
)
2378 SHORT i
, X
, Y
, SizeX
, SizeY
;
2379 PCSRSS_CONSOLE Console
;
2380 PCSRSS_SCREEN_BUFFER Buff
;
2382 CHAR_INFO
* CurCharInfo
;
2384 CHAR_INFO
* CharInfo
;
2391 DPRINT("CsrWriteConsoleOutput\n");
2393 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2394 if (! NT_SUCCESS(Status
))
2396 return Request
->Status
= Status
;
2399 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2400 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2401 Status
= ConioLockScreenBuffer(ProcessData
,
2402 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2404 if (! NT_SUCCESS(Status
))
2406 if (NULL
!= Console
)
2408 ConioUnlockConsole(Console
);
2410 return Request
->Status
= Status
;
2413 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2414 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2415 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2416 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2417 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2418 (((ULONG_PTR
)CharInfo
+ PSize
) >
2419 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2421 ConioUnlockScreenBuffer(Buff
);
2422 ConioUnlockConsole(Console
);
2423 return Request
->Status
= STATUS_ACCESS_VIOLATION
;
2425 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2426 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2427 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2428 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2430 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2431 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2432 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2433 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2435 /* Make sure WriteRegion is inside the screen buffer */
2436 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2437 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2439 ConioUnlockScreenBuffer(Buff
);
2440 ConioUnlockConsole(Console
);
2442 /* It is okay to have a WriteRegion completely outside the screen buffer.
2443 No data is written then. */
2444 return Request
->Status
= STATUS_SUCCESS
;
2447 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2449 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2450 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2451 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2453 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2456 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2457 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2461 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2467 if (NULL
!= Console
)
2469 ConioDrawRegion(Console
, &WriteRegion
);
2472 ConioUnlockScreenBuffer(Buff
);
2473 ConioUnlockConsole(Console
);
2475 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2476 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2477 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2478 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2480 return Request
->Status
= STATUS_SUCCESS
;
2483 CSR_API(CsrFlushInputBuffer
)
2485 PLIST_ENTRY CurrentEntry
;
2486 PCSRSS_CONSOLE Console
;
2487 ConsoleInput
* Input
;
2490 DPRINT("CsrFlushInputBuffer\n");
2492 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2493 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2494 Status
= ConioLockConsole(ProcessData
,
2495 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2497 if(! NT_SUCCESS(Status
))
2499 return Request
->Status
= Status
;
2502 /* Discard all entries in the input event queue */
2503 while (!IsListEmpty(&Console
->InputEvents
))
2505 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2506 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2507 /* Destroy the event */
2508 HeapFree(Win32CsrApiHeap
, 0, Input
);
2510 ResetEvent(Console
->ActiveEvent
);
2511 Console
->WaitingChars
=0;
2513 ConioUnlockConsole(Console
);
2515 return Request
->Status
= STATUS_SUCCESS
;
2518 CSR_API(CsrScrollConsoleScreenBuffer
)
2520 PCSRSS_CONSOLE Console
;
2521 PCSRSS_SCREEN_BUFFER Buff
;
2526 RECT ScrollRectangle
;
2531 DPRINT("CsrScrollConsoleScreenBuffer\n");
2533 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2534 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2535 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2536 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2538 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2539 if (! NT_SUCCESS(Status
))
2541 return Request
->Status
= Status
;
2544 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2545 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2546 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2547 if (! NT_SUCCESS(Status
))
2549 if (NULL
!= Console
)
2551 ConioUnlockConsole(Console
);
2553 return Request
->Status
= Status
;
2556 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2557 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2558 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2559 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2560 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2561 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2562 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2563 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2565 /* Make sure source rectangle is inside the screen buffer */
2566 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2567 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2569 ConioUnlockScreenBuffer(Buff
);
2570 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2573 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2575 ConioUnlockScreenBuffer(Buff
);
2576 return Request
->Status
= STATUS_SUCCESS
;
2580 ConioInitRect(&DstRegion
,
2581 DestinationOrigin
.Y
,
2582 DestinationOrigin
.X
,
2583 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2584 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2586 /* Make sure destination rectangle is inside the screen buffer */
2587 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2589 ConioUnlockScreenBuffer(Buff
);
2590 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2593 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2595 /* Get the region that should be filled with the specified character and attributes */
2599 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2601 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2603 /* FIXME: The subtracted rectangle is off by one line */
2604 FillRegion
.top
+= 1;
2606 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2610 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2612 /* Draw destination region */
2613 ConioDrawRegion(Console
, &DstRegion
);
2617 /* Draw filled region */
2618 ConioDrawRegion(Console
, &FillRegion
);
2622 ConioUnlockScreenBuffer(Buff
);
2623 if (NULL
!= Console
)
2625 ConioUnlockConsole(Console
);
2628 return Request
->Status
= STATUS_SUCCESS
;
2631 CSR_API(CsrReadConsoleOutputChar
)
2634 PCSRSS_CONSOLE Console
;
2635 PCSRSS_SCREEN_BUFFER Buff
;
2642 DPRINT("CsrReadConsoleOutputChar\n");
2644 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2645 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2646 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2648 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2650 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2651 if (! NT_SUCCESS(Status
))
2653 return Request
->Status
= Status
;
2656 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2657 if (! NT_SUCCESS(Status
))
2659 return Request
->Status
= Status
;
2662 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2663 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2665 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2667 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2669 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2671 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2672 ReadBuffer
+= sizeof(WCHAR
);
2675 *(ReadBuffer
++) = Char
;
2679 if (Xpos
== Buff
->MaxX
)
2684 if (Ypos
== Buff
->MaxY
)
2692 Request
->Status
= STATUS_SUCCESS
;
2693 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2694 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2696 ConioUnlockScreenBuffer(Buff
);
2697 if (NULL
!= Console
)
2699 ConioUnlockConsole(Console
);
2702 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2703 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2705 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2706 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2709 return Request
->Status
;
2713 CSR_API(CsrReadConsoleOutputAttrib
)
2716 PCSRSS_SCREEN_BUFFER Buff
;
2720 DWORD CurrentLength
;
2722 DPRINT("CsrReadConsoleOutputAttrib\n");
2724 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2725 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2726 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2728 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2729 if (! NT_SUCCESS(Status
))
2731 return Request
->Status
= Status
;
2734 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2735 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2737 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2739 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2744 if (Xpos
== Buff
->MaxX
)
2749 if (Ypos
== Buff
->MaxY
)
2758 Request
->Status
= STATUS_SUCCESS
;
2759 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2760 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2762 ConioUnlockScreenBuffer(Buff
);
2764 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2765 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2766 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2768 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2769 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2772 return Request
->Status
;
2776 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2779 PCSRSS_CONSOLE Console
;
2780 PLIST_ENTRY CurrentItem
;
2782 ConsoleInput
*Input
;
2784 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2786 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2787 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2789 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2790 if (! NT_SUCCESS(Status
))
2792 return Request
->Status
= Status
;
2795 CurrentItem
= Console
->InputEvents
.Flink
;
2798 /* If there are any events ... */
2799 while (CurrentItem
!= &Console
->InputEvents
)
2801 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2802 CurrentItem
= CurrentItem
->Flink
;
2809 ConioUnlockConsole(Console
);
2811 Request
->Status
= STATUS_SUCCESS
;
2812 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2814 return Request
->Status
;
2818 CSR_API(CsrPeekConsoleInput
)
2821 PCSRSS_CONSOLE Console
;
2824 PLIST_ENTRY CurrentItem
;
2825 PINPUT_RECORD InputRecord
;
2829 DPRINT("CsrPeekConsoleInput\n");
2831 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2832 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2834 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2835 if(! NT_SUCCESS(Status
))
2837 return Request
->Status
= Status
;
2840 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2841 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2842 Size
= Length
* sizeof(INPUT_RECORD
);
2844 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2845 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2847 ConioUnlockConsole(Console
);
2848 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2849 return Request
->Status
;
2854 if (! IsListEmpty(&Console
->InputEvents
))
2856 CurrentItem
= Console
->InputEvents
.Flink
;
2858 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2860 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2864 CurrentItem
= CurrentItem
->Flink
;
2869 *InputRecord
= Item
->InputEvent
;
2871 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2873 ConioInputEventToAnsi(Console
, InputRecord
);
2877 CurrentItem
= CurrentItem
->Flink
;
2881 ConioUnlockConsole(Console
);
2883 Request
->Status
= STATUS_SUCCESS
;
2884 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2886 return Request
->Status
;
2890 CSR_API(CsrReadConsoleOutput
)
2892 PCHAR_INFO CharInfo
;
2893 PCHAR_INFO CurCharInfo
;
2894 PCSRSS_SCREEN_BUFFER Buff
;
2907 DPRINT("CsrReadConsoleOutput\n");
2909 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2910 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2912 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2913 if (! NT_SUCCESS(Status
))
2915 return Request
->Status
= Status
;
2918 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2919 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2920 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2921 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2922 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2923 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2924 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2925 Length
= BufferSize
.X
* BufferSize
.Y
;
2926 Size
= Length
* sizeof(CHAR_INFO
);
2928 /* FIXME: Is this correct? */
2929 CodePage
= ProcessData
->Console
->OutputCodePage
;
2931 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2932 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2934 ConioUnlockScreenBuffer(Buff
);
2935 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2936 return Request
->Status
;
2939 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2940 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2941 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2942 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2944 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2945 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2947 ConioUnlockScreenBuffer(Buff
);
2948 Request
->Status
= STATUS_SUCCESS
;
2949 return Request
->Status
;
2952 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2954 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2956 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2957 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2959 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2961 MultiByteToWideChar(CodePage
, 0,
2962 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2963 &CurCharInfo
->Char
.UnicodeChar
, 1);
2967 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2969 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2974 ConioUnlockScreenBuffer(Buff
);
2976 Request
->Status
= STATUS_SUCCESS
;
2977 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2978 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2979 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2980 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2982 return Request
->Status
;
2986 CSR_API(CsrWriteConsoleInput
)
2988 PINPUT_RECORD InputRecord
;
2989 PCSRSS_CONSOLE Console
;
2994 ConsoleInput
* Record
;
2996 DPRINT("CsrWriteConsoleInput\n");
2998 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2999 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3001 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
3002 if (! NT_SUCCESS(Status
))
3004 return Request
->Status
= Status
;
3007 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
3008 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
3009 Size
= Length
* sizeof(INPUT_RECORD
);
3011 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
3012 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
3014 ConioUnlockConsole(Console
);
3015 Request
->Status
= STATUS_ACCESS_VIOLATION
;
3016 return Request
->Status
;
3019 for (i
= 0; i
< Length
; i
++)
3021 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
3024 ConioUnlockConsole(Console
);
3025 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
3026 return Request
->Status
;
3029 Record
->Echoed
= FALSE
;
3030 Record
->Fake
= FALSE
;
3031 //Record->InputEvent = *InputRecord++;
3032 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
3033 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
3035 /* FIXME - convert from unicode to ascii!! */
3036 ConioProcessChar(Console
, Record
);
3040 ConioUnlockConsole(Console
);
3042 Request
->Status
= STATUS_SUCCESS
;
3043 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
3045 return Request
->Status
;
3048 /**********************************************************************
3049 * HardwareStateProperty
3052 * Set/Get the value of the HardwareState and switch
3053 * between direct video buffer ouput and GDI windowed
3056 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
3057 * object. We use the same object to Request.
3059 * ConsoleHwState has the correct size to be compatible
3060 * with NT's, but values are not.
3062 static NTSTATUS FASTCALL
3063 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
3065 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
3067 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
3068 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
3070 if (Console
->HardwareState
!= ConsoleHwState
)
3072 /* TODO: implement switching from full screen to windowed mode */
3073 /* TODO: or back; now simply store the hardware state */
3074 Console
->HardwareState
= ConsoleHwState
;
3077 return STATUS_SUCCESS
;
3080 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
3083 CSR_API(CsrHardwareStateProperty
)
3085 PCSRSS_CONSOLE Console
;
3088 DPRINT("CsrHardwareStateProperty\n");
3090 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3091 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3093 Status
= ConioLockConsole(ProcessData
,
3094 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
3096 if (! NT_SUCCESS(Status
))
3098 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
3099 return Request
->Status
= Status
;
3102 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
3104 case CONSOLE_HARDWARE_STATE_GET
:
3105 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
3108 case CONSOLE_HARDWARE_STATE_SET
:
3109 DPRINT("Setting console hardware state.\n");
3110 Request
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
3114 Request
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
3118 ConioUnlockConsole(Console
);
3120 return Request
->Status
;
3123 CSR_API(CsrGetConsoleWindow
)
3125 PCSRSS_CONSOLE Console
;
3128 DPRINT("CsrGetConsoleWindow\n");
3130 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3131 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3133 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3134 if (! NT_SUCCESS(Status
))
3136 return Request
->Status
= Status
;
3139 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
3140 ConioUnlockConsole(Console
);
3142 return Request
->Status
= STATUS_SUCCESS
;
3145 CSR_API(CsrSetConsoleIcon
)
3147 PCSRSS_CONSOLE Console
;
3150 DPRINT("CsrSetConsoleIcon\n");
3152 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3153 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3155 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3156 if (! NT_SUCCESS(Status
))
3158 return Request
->Status
= Status
;
3161 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3162 Request
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3163 ConioUnlockConsole(Console
);
3165 return Request
->Status
;
3168 CSR_API(CsrGetConsoleCodePage
)
3170 PCSRSS_CONSOLE Console
;
3173 DPRINT("CsrGetConsoleCodePage\n");
3175 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3176 if (! NT_SUCCESS(Status
))
3178 return Request
->Status
= Status
;
3181 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3182 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3183 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3184 ConioUnlockConsole(Console
);
3185 return Request
->Status
= STATUS_SUCCESS
;
3188 CSR_API(CsrSetConsoleCodePage
)
3190 PCSRSS_CONSOLE Console
;
3193 DPRINT("CsrSetConsoleCodePage\n");
3195 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3196 if (! NT_SUCCESS(Status
))
3198 return Request
->Status
= Status
;
3201 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3202 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3203 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3205 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3206 ConioUnlockConsole(Console
);
3207 return Request
->Status
= STATUS_SUCCESS
;
3209 ConioUnlockConsole(Console
);
3210 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3213 CSR_API(CsrGetConsoleOutputCodePage
)
3215 PCSRSS_CONSOLE Console
;
3218 DPRINT("CsrGetConsoleOutputCodePage\n");
3220 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3221 if (! NT_SUCCESS(Status
))
3223 return Request
->Status
= Status
;
3226 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3227 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3228 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3229 ConioUnlockConsole(Console
);
3230 return Request
->Status
= STATUS_SUCCESS
;
3233 CSR_API(CsrSetConsoleOutputCodePage
)
3235 PCSRSS_CONSOLE Console
;
3238 DPRINT("CsrSetConsoleOutputCodePage\n");
3240 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3241 if (! NT_SUCCESS(Status
))
3243 return Request
->Status
= Status
;
3246 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3247 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3248 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3250 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3251 ConioUnlockConsole(Console
);
3252 return Request
->Status
= STATUS_SUCCESS
;
3254 ConioUnlockConsole(Console
);
3255 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3258 CSR_API(CsrGetProcessList
)
3261 PCSRSS_CONSOLE Console
;
3262 PCSRSS_PROCESS_DATA current
;
3263 PLIST_ENTRY current_entry
;
3264 ULONG nItems
, nCopied
, Length
;
3267 DPRINT("CsrGetProcessList\n");
3269 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3270 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3271 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3273 nItems
= nCopied
= 0;
3274 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3275 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3277 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3278 if (! NT_SUCCESS(Status
))
3280 return Request
->Status
= Status
;
3283 DPRINT1("Console_Api Ctrl-C\n");
3285 for(current_entry
= Console
->ProcessList
.Flink
;
3286 current_entry
!= &Console
->ProcessList
;
3287 current_entry
= current_entry
->Flink
)
3289 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3290 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3292 *(Buffer
++) = current
->ProcessId
;
3297 ConioUnlockConsole(Console
);
3299 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3300 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3302 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3303 if (Length
> sizeof(CSR_API_MESSAGE
))
3305 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3306 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3308 return Request
->Status
= STATUS_SUCCESS
;