2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
19 ((Rect)->top) = Top; \
20 ((Rect)->left) = Left; \
21 ((Rect)->bottom) = Bottom; \
22 ((Rect)->right) = Right
24 #define ConioIsRectEmpty(Rect) \
25 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
27 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
28 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
30 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
31 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
33 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
34 MultiByteToWideChar((Console)->OutputCodePage, 0, (dChar), 1, (sWChar), 1)
37 /* FUNCTIONS *****************************************************************/
40 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
42 PCSRSS_CONSOLE ProcessConsole
= ProcessData
->Console
;
47 return STATUS_INVALID_HANDLE
;
50 InterlockedIncrement(&ProcessConsole
->Header
.ReferenceCount
);
51 EnterCriticalSection(&(ProcessConsole
->Header
.Lock
));
52 *Console
= ProcessConsole
;
54 return STATUS_SUCCESS
;
58 ConioConsoleCtrlEventTimeout(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
, DWORD Timeout
)
62 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
64 if (ProcessData
->CtrlDispatcher
)
67 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
68 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
69 (PVOID
) Event
, 0, NULL
);
72 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
75 WaitForSingleObject(Thread
, Timeout
);
81 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
83 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, 0);
87 ConioGetBufferOffset(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
89 return 2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
);
92 #define GET_CELL_BUFFER(b,o)\
95 #define SET_CELL_BUFFER(b,o,c,a)\
96 (b)->Buffer[(o)++]=(c),\
97 (b)->Buffer[(o)++]=(a)
100 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
102 DWORD Offset
= ConioGetBufferOffset(Buff
, 0, Buff
->CurrentY
);
105 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
107 /* Fill the cell: Offset is incremented by the macro */
108 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
112 static NTSTATUS FASTCALL
113 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
114 PCSRSS_SCREEN_BUFFER Buffer
)
116 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
118 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
119 Buffer
->Header
.ReferenceCount
= 0;
122 Buffer
->VirtualY
= 0;
123 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
124 if (NULL
== Buffer
->Buffer
)
126 return STATUS_INSUFFICIENT_RESOURCES
;
128 InitializeCriticalSection(&Buffer
->Header
.Lock
);
129 ConioInitScreenBuffer(Console
, Buffer
);
130 /* initialize buffer to be empty with default attributes */
131 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
133 ClearLineBuffer(Buffer
);
135 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
136 Buffer
->CurrentX
= 0;
137 Buffer
->CurrentY
= 0;
139 return STATUS_SUCCESS
;
142 static NTSTATUS STDCALL
143 CsrInitConsole(PCSRSS_CONSOLE Console
)
146 SECURITY_ATTRIBUTES SecurityAttributes
;
147 PCSRSS_SCREEN_BUFFER NewBuffer
;
150 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
151 Console
->Title
.Buffer
= NULL
;
154 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
156 Console
->Header
.ReferenceCount
= 0;
157 Console
->WaitingChars
= 0;
158 Console
->WaitingLines
= 0;
159 Console
->EchoCount
= 0;
160 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
161 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
162 Console
->EarlyReturn
= FALSE
;
163 Console
->ActiveBuffer
= NULL
;
164 InitializeListHead(&Console
->InputEvents
);
165 Console
->CodePage
= GetOEMCP();
166 Console
->OutputCodePage
= GetOEMCP();
168 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
169 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
170 SecurityAttributes
.bInheritHandle
= TRUE
;
172 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
173 if (NULL
== Console
->ActiveEvent
)
175 RtlFreeUnicodeString(&Console
->Title
);
176 return STATUS_UNSUCCESSFUL
;
178 Console
->PrivateData
= NULL
;
179 InitializeCriticalSection(&Console
->Header
.Lock
);
181 GuiMode
= DtbgIsDesktopVisible();
183 /* allocate console screen buffer */
184 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
185 if (NULL
== NewBuffer
)
187 RtlFreeUnicodeString(&Console
->Title
);
188 DeleteCriticalSection(&Console
->Header
.Lock
);
189 CloseHandle(Console
->ActiveEvent
);
190 return STATUS_INSUFFICIENT_RESOURCES
;
192 /* init screen buffer with defaults */
193 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
194 NewBuffer
->CursorInfo
.dwSize
= 5;
195 /* make console active, and insert into console list */
196 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
200 Status
= TuiInitConsole(Console
);
201 if (! NT_SUCCESS(Status
))
203 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
209 Status
= GuiInitConsole(Console
);
210 if (! NT_SUCCESS(Status
))
212 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
213 RtlFreeUnicodeString(&Console
->Title
);
214 DeleteCriticalSection(&Console
->Header
.Lock
);
215 CloseHandle(Console
->ActiveEvent
);
216 DPRINT1("GuiInitConsole: failed\n");
221 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
222 if (! NT_SUCCESS(Status
))
224 ConioCleanupConsole(Console
);
225 RtlFreeUnicodeString(&Console
->Title
);
226 DeleteCriticalSection(&Console
->Header
.Lock
);
227 CloseHandle(Console
->ActiveEvent
);
228 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
229 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
233 /* add a reference count because the buffer is tied to the console */
234 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
236 /* copy buffer contents to screen */
237 ConioDrawConsole(Console
);
239 return STATUS_SUCCESS
;
243 CSR_API(CsrAllocConsole
)
245 PCSRSS_CONSOLE Console
;
246 NTSTATUS Status
= STATUS_SUCCESS
;
247 BOOLEAN NewConsole
= FALSE
;
249 DPRINT("CsrAllocConsole\n");
251 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
252 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
254 if (ProcessData
== NULL
)
256 DPRINT1("No process data\n");
257 return Request
->Status
= STATUS_INVALID_PARAMETER
;
260 if (ProcessData
->Console
)
262 DPRINT1("Process already has a console\n");
263 Request
->Status
= STATUS_INVALID_PARAMETER
;
264 return STATUS_INVALID_PARAMETER
;
268 Request
->Status
= STATUS_SUCCESS
;
270 /* If we don't need a console, then get out of here */
271 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
273 DPRINT("No console needed\n");
274 return STATUS_SUCCESS
;
277 /* If we already have one, then don't create a new one... */
278 if (!Request
->Data
.AllocConsoleRequest
.Console
||
279 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
281 /* Allocate a console structure */
283 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
286 DPRINT1("Not enough memory for console\n");
287 Request
->Status
= STATUS_NO_MEMORY
;
288 return STATUS_NO_MEMORY
;
290 /* initialize list head */
291 InitializeListHead(&Console
->ProcessList
);
292 /* insert process data required for GUI initialization */
293 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
294 /* Initialize the Console */
295 Request
->Status
= CsrInitConsole(Console
);
296 if (!NT_SUCCESS(Request
->Status
))
298 DPRINT1("Console init failed\n");
299 HeapFree(Win32CsrApiHeap
, 0, Console
);
300 return Request
->Status
;
305 /* Reuse our current console */
306 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
309 /* Set the Process Console */
310 ProcessData
->Console
= Console
;
312 /* Return it to the caller */
313 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
315 /* Add a reference count because the process is tied to the console */
316 Console
->Header
.ReferenceCount
++;
318 if (NewConsole
|| !ProcessData
->bInheritHandles
)
320 /* Insert the Objects */
321 Status
= Win32CsrInsertObject(ProcessData
,
322 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
324 GENERIC_READ
| GENERIC_WRITE
,
326 if (! NT_SUCCESS(Status
))
328 DPRINT1("Failed to insert object\n");
329 ConioDeleteConsole((Object_t
*) Console
);
330 ProcessData
->Console
= 0;
331 return Request
->Status
= Status
;
334 Status
= Win32CsrInsertObject(ProcessData
,
335 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
336 &Console
->ActiveBuffer
->Header
,
337 GENERIC_READ
| GENERIC_WRITE
,
339 if (!NT_SUCCESS(Status
))
341 DPRINT1("Failed to insert object\n");
342 ConioDeleteConsole((Object_t
*) Console
);
343 Win32CsrReleaseObject(ProcessData
,
344 Request
->Data
.AllocConsoleRequest
.InputHandle
);
345 ProcessData
->Console
= 0;
346 return Request
->Status
= Status
;
350 /* Duplicate the Event */
351 if (!DuplicateHandle(GetCurrentProcess(),
352 ProcessData
->Console
->ActiveEvent
,
353 ProcessData
->Process
,
354 &ProcessData
->ConsoleEvent
,
359 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
360 ConioDeleteConsole((Object_t
*) Console
);
361 if (NewConsole
|| !ProcessData
->bInheritHandles
)
363 Win32CsrReleaseObject(ProcessData
,
364 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
365 Win32CsrReleaseObject(ProcessData
,
366 Request
->Data
.AllocConsoleRequest
.InputHandle
);
368 ProcessData
->Console
= 0;
369 return Request
->Status
= Status
;
372 /* Set the Ctrl Dispatcher */
373 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
374 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
378 /* Insert into the list if it has not been added */
379 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
382 return STATUS_SUCCESS
;
385 CSR_API(CsrFreeConsole
)
387 PCSRSS_CONSOLE Console
;
390 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
391 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
393 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
395 return Request
->Status
= STATUS_INVALID_PARAMETER
;
398 Console
= ProcessData
->Console
;
399 ProcessData
->Console
= NULL
;
400 RemoveEntryList(&ProcessData
->ProcessEntry
);
401 if (0 == InterlockedDecrement(&Console
->Header
.ReferenceCount
))
403 ConioDeleteConsole((Object_t
*) Console
);
405 return STATUS_SUCCESS
;
409 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
411 /* If we hit bottom, slide the viewable screen */
412 if (++Buff
->CurrentY
== Buff
->MaxY
)
415 if (++Buff
->VirtualY
== Buff
->MaxY
)
420 ClearLineBuffer(Buff
);
421 if (UpdateRect
->top
!= 0)
426 UpdateRect
->left
= 0;
427 UpdateRect
->right
= Buff
->MaxX
- 1;
428 UpdateRect
->bottom
= Buff
->CurrentY
;
431 static NTSTATUS FASTCALL
432 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
433 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
438 LONG CursorStartX
, CursorStartY
;
441 CursorStartX
= Buff
->CurrentX
;
442 CursorStartY
= Buff
->CurrentY
;
443 UpdateRect
.left
= Buff
->MaxX
;
444 UpdateRect
.top
= Buff
->CurrentY
;
445 UpdateRect
.right
= -1;
446 UpdateRect
.bottom
= Buff
->CurrentY
;
449 for (i
= 0; i
< Length
; i
++)
451 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
454 if (Buffer
[i
] == '\n')
457 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
461 else if (Buffer
[i
] == '\b')
463 /* Only handle BS if we're not on the first pos of the first line */
464 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
466 if (0 == Buff
->CurrentX
)
468 /* slide virtual position up */
469 Buff
->CurrentX
= Buff
->MaxX
- 1;
471 UpdateRect
.top
= min(UpdateRect
.top
, (LONG
)Buff
->CurrentY
);
477 Offset
= ConioGetBufferOffset(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
478 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
479 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
480 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
485 else if (Buffer
[i
] == '\r')
488 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
489 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
493 else if (Buffer
[i
] == '\t')
497 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
498 EndX
= (Buff
->CurrentX
+ 8) & ~7;
499 if (EndX
> Buff
->MaxX
)
503 Offset
= ConioGetBufferOffset(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
504 while (Buff
->CurrentX
< EndX
)
506 Buff
->Buffer
[Offset
] = ' ';
507 Buff
->Buffer
[Offset
+ 1] = Buff
->DefaultAttrib
;
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
= ConioGetBufferOffset(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
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 if (! ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
552 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
556 return STATUS_SUCCESS
;
559 CSR_API(CsrReadConsole
)
561 PLIST_ENTRY CurrentEntry
;
564 PWCHAR UnicodeBuffer
;
566 ULONG nNumberOfCharsToRead
, CharSize
;
567 PCSRSS_CONSOLE Console
;
570 DPRINT("CsrReadConsole\n");
572 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
574 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
575 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
576 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
577 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
579 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
580 UnicodeBuffer
= (PWCHAR
)Buffer
;
581 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
582 &Console
, GENERIC_READ
);
583 if (! NT_SUCCESS(Status
))
585 return Request
->Status
= Status
;
587 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
588 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
590 /* remove input event from queue */
591 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
592 if (IsListEmpty(&Console
->InputEvents
))
595 ResetEvent(Console
->ActiveEvent
);
597 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
599 /* only pay attention to valid ascii chars, on key down */
600 if (KEY_EVENT
== Input
->InputEvent
.EventType
601 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
602 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
605 * backspace handling - if we are in charge of echoing it then we handle it here
606 * otherwise we treat it like a normal char.
608 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
609 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
611 /* echo if it has not already been done, and either we or the client has chars to be deleted */
613 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
615 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
616 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
620 i
-= 2; /* if we already have something to return, just back it up by 2 */
623 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
624 Console
->WaitingChars
--;
625 ConioUnlockConsole(Console
);
626 HeapFree(Win32CsrApiHeap
, 0, Input
);
627 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
628 Request
->Status
= STATUS_NOTIFY_CLEANUP
;
629 return STATUS_NOTIFY_CLEANUP
;
632 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
633 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
635 /* do not copy backspace to buffer */
638 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
639 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
641 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
643 /* echo to screen if enabled and we did not already echo the char */
644 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
646 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
648 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
649 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
656 Console
->WaitingChars
--;
657 HeapFree(Win32CsrApiHeap
, 0, Input
);
659 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
662 Request
->Status
= STATUS_PENDING
; /* we didn't read anything */
664 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
666 if (0 == Console
->WaitingLines
||
667 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
669 Request
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
673 Console
->WaitingLines
--;
674 Request
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
679 Request
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
682 if (Request
->Status
== STATUS_PENDING
)
684 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
688 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
691 ConioUnlockConsole(Console
);
693 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
695 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
696 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
699 return Request
->Status
;
702 BOOLEAN __inline
ConioGetIntersection(
707 if (ConioIsRectEmpty(Rect1
) ||
708 (ConioIsRectEmpty(Rect2
)) ||
709 (Rect1
->top
> Rect2
->bottom
) ||
710 (Rect1
->left
> Rect2
->right
) ||
711 (Rect1
->bottom
< Rect2
->top
) ||
712 (Rect1
->right
< Rect2
->left
))
714 /* The rectangles do not intersect */
715 ConioInitRect(Intersection
, 0, -1, 0, -1);
719 ConioInitRect(Intersection
,
720 max(Rect1
->top
, Rect2
->top
),
721 max(Rect1
->left
, Rect2
->left
),
722 min(Rect1
->bottom
, Rect2
->bottom
),
723 min(Rect1
->right
, Rect2
->right
));
728 BOOLEAN __inline
ConioGetUnion(
733 if (ConioIsRectEmpty(Rect1
))
735 if (ConioIsRectEmpty(Rect2
))
737 ConioInitRect(Union
, 0, -1, 0, -1);
745 else if (ConioIsRectEmpty(Rect2
))
752 min(Rect1
->top
, Rect2
->top
),
753 min(Rect1
->left
, Rect2
->left
),
754 max(Rect1
->bottom
, Rect2
->bottom
),
755 max(Rect1
->right
, Rect2
->right
));
761 /* Move from one rectangle to another. We must be careful about the order that
762 * this is done, to avoid overwriting parts of the source before they are moved. */
764 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
770 int Width
= ConioRectWidth(SrcRegion
);
771 int Height
= ConioRectHeight(SrcRegion
);
782 /* Moving down: work from bottom up */
783 SY
= SrcRegion
->bottom
;
784 DY
= DstRegion
->bottom
;
787 for (i
= 0; i
< Height
; i
++)
789 PWORD SRow
= (PWORD
)&ScreenBuffer
->Buffer
[ConioGetBufferOffset(ScreenBuffer
, 0, SY
)];
790 PWORD DRow
= (PWORD
)&ScreenBuffer
->Buffer
[ConioGetBufferOffset(ScreenBuffer
, 0, DY
)];
792 SX
= SrcRegion
->left
;
793 DX
= DstRegion
->left
;
797 /* Moving right: work from right to left */
798 SX
= SrcRegion
->right
;
799 DX
= DstRegion
->right
;
802 for (j
= 0; j
< Width
; j
++)
804 WORD Cell
= SRow
[SX
];
805 if (SX
>= ClipRegion
->left
&& SX
<= ClipRegion
->right
806 && SY
>= ClipRegion
->top
&& SY
<= ClipRegion
->bottom
)
810 if (DX
>= ClipRegion
->left
&& DX
<= ClipRegion
->right
811 && DY
>= ClipRegion
->top
&& DY
<= ClipRegion
->bottom
)
824 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
826 if (InputEvent
->EventType
== KEY_EVENT
)
828 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
829 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
830 ConsoleInputUnicodeCharToAnsiChar(Console
,
831 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
836 CSR_API(CsrWriteConsole
)
840 PCSRSS_SCREEN_BUFFER Buff
;
841 PCSRSS_CONSOLE Console
;
844 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
846 DPRINT("CsrWriteConsole\n");
848 if (Request
->Header
.u1
.s1
.TotalLength
849 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
850 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
852 DPRINT1("Invalid request size\n");
853 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
854 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
855 return Request
->Status
= STATUS_INVALID_PARAMETER
;
857 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
859 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
860 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
862 if (! NT_SUCCESS(Status
))
864 return Request
->Status
= Status
;
867 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
869 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
870 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
871 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
872 NULL
, 0, NULL
, NULL
);
873 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
876 WideCharToMultiByte(Console
->OutputCodePage
, 0,
877 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
878 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
879 Buffer
, Length
, NULL
, NULL
);
883 Status
= STATUS_NO_MEMORY
;
888 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
893 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
894 if (NT_SUCCESS(Status
))
896 Request
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
897 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
898 if (NT_SUCCESS(Status
))
900 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
902 ConioUnlockScreenBuffer(Buff
);
904 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
906 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
909 ConioUnlockConsole(Console
);
911 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
913 return Request
->Status
= Status
;
917 ConioDeleteScreenBuffer(Object_t
*Object
)
919 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
920 DeleteCriticalSection(&Buffer
->Header
.Lock
);
921 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
922 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
926 ConioDrawConsole(PCSRSS_CONSOLE Console
)
930 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
932 ConioDrawRegion(Console
, &Region
);
937 ConioDeleteConsole(Object_t
*Object
)
939 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
942 DPRINT("ConioDeleteConsole\n");
944 /* Drain input event queue */
945 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
947 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
948 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
949 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
950 HeapFree(Win32CsrApiHeap
, 0, Event
);
953 ConioCleanupConsole(Console
);
954 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
956 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
959 Console
->ActiveBuffer
= NULL
;
961 CloseHandle(Console
->ActiveEvent
);
962 DeleteCriticalSection(&Console
->Header
.Lock
);
963 RtlFreeUnicodeString(&Console
->Title
);
964 IntDeleteAllAliases(Console
->Aliases
);
965 HeapFree(Win32CsrApiHeap
, 0, Console
);
969 CsrInitConsoleSupport(VOID
)
971 DPRINT("CSR: CsrInitConsoleSupport()\n");
973 /* Should call LoadKeyboardLayout */
977 ConioProcessChar(PCSRSS_CONSOLE Console
,
978 ConsoleInput
*KeyEventRecord
)
981 BOOL bClientWake
= FALSE
;
982 ConsoleInput
*TempInput
;
984 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
986 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
989 /* first add the \r */
990 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
991 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
992 KeyEventRecord
->Echoed
= FALSE
;
993 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
994 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
995 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
996 Console
->WaitingChars
++;
997 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
998 if (NULL
== KeyEventRecord
)
1000 DPRINT1("Failed to allocate KeyEventRecord\n");
1003 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1004 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1005 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1006 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1007 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1008 KeyEventRecord
->Fake
= TRUE
;
1012 /* add event to the queue */
1013 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1014 Console
->WaitingChars
++;
1015 /* if line input mode is enabled, only wake the client on enter key down */
1016 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1017 || Console
->EarlyReturn
1018 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1019 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1021 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1023 Console
->WaitingLines
++;
1026 SetEvent(Console
->ActiveEvent
);
1028 KeyEventRecord
->Echoed
= FALSE
;
1029 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1030 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1031 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1033 /* walk the input queue looking for a char to backspace */
1034 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1035 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1036 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1037 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1038 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1039 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1043 /* if we found one, delete it, otherwise, wake the client */
1044 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1046 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1047 RemoveEntryList(&TempInput
->ListEntry
);
1048 if (TempInput
->Echoed
)
1050 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1051 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1054 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1055 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1056 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1057 Console
->WaitingChars
-= 2;
1061 SetEvent(Console
->ActiveEvent
);
1066 /* echo chars if we are supposed to and client is waiting for some */
1067 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1068 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1069 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1070 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1072 /* mark the char as already echoed */
1073 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1074 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1076 Console
->EchoCount
--;
1077 KeyEventRecord
->Echoed
= TRUE
;
1081 /* Console->WaitingChars++; */
1082 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1084 SetEvent(Console
->ActiveEvent
);
1088 static DWORD FASTCALL
1089 ConioGetShiftState(PBYTE KeyState
)
1093 if (KeyState
[VK_CAPITAL
] & 1)
1094 ssOut
|= CAPSLOCK_ON
;
1096 if (KeyState
[VK_NUMLOCK
] & 1)
1097 ssOut
|= NUMLOCK_ON
;
1099 if (KeyState
[VK_SCROLL
] & 1)
1100 ssOut
|= SCROLLLOCK_ON
;
1102 if (KeyState
[VK_SHIFT
] & 0x80)
1103 ssOut
|= SHIFT_PRESSED
;
1105 if (KeyState
[VK_LCONTROL
] & 0x80)
1106 ssOut
|= LEFT_CTRL_PRESSED
;
1107 if (KeyState
[VK_RCONTROL
] & 0x80)
1108 ssOut
|= RIGHT_CTRL_PRESSED
;
1110 if (KeyState
[VK_LMENU
] & 0x80)
1111 ssOut
|= LEFT_ALT_PRESSED
;
1112 if (KeyState
[VK_RMENU
] & 0x80)
1113 ssOut
|= RIGHT_ALT_PRESSED
;
1119 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1121 static BYTE KeyState
[256] = { 0 };
1122 /* MSDN mentions that you should use the last virtual key code received
1123 * when putting a virtual key identity to a WM_CHAR message since multiple
1124 * or translated keys may be involved. */
1125 static UINT LastVirtualKey
= 0;
1127 ConsoleInput
*ConInRec
;
1131 UINT VirtualKeyCode
;
1132 UINT VirtualScanCode
;
1135 ULONG ResultSize
= 0;
1138 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1139 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1140 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1142 GetKeyboardState(KeyState
);
1143 ShiftState
= ConioGetShiftState(KeyState
);
1145 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1147 VirtualKeyCode
= LastVirtualKey
;
1148 UnicodeChar
= msg
->wParam
;
1155 VirtualKeyCode
= msg
->wParam
;
1156 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1163 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1166 if (0 == ResultSize
)
1171 er
.EventType
= KEY_EVENT
;
1172 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1173 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1174 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1175 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1176 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1177 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1181 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1182 && VK_TAB
== VirtualKeyCode
)
1186 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1191 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1193 if (TuiSwapConsole(0))
1200 if (NULL
== Console
)
1202 DPRINT1("No Active Console!\n");
1206 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1208 if (NULL
== ConInRec
)
1213 ConInRec
->InputEvent
= er
;
1214 ConInRec
->Fake
= UnicodeChar
&&
1215 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1216 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1217 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1218 ConInRec
->Echoed
= FALSE
;
1219 if (ConInRec
->NotChar
)
1220 LastVirtualKey
= msg
->wParam
;
1222 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1223 Down
? "down" : "up ",
1224 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1226 ConInRec
->Fake
? "fake" : "real",
1227 ConInRec
->NotChar
? "notc" : "char",
1230 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1233 if (ConInRec
->Fake
&& ConInRec
->NotChar
)
1235 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1239 /* process Ctrl-C and Ctrl-Break */
1240 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1241 er
.Event
.KeyEvent
.bKeyDown
&&
1242 ((er
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1243 (er
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1244 (er
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1246 PCSRSS_PROCESS_DATA current
;
1247 PLIST_ENTRY current_entry
;
1248 DPRINT1("Console_Api Ctrl-C\n");
1249 current_entry
= Console
->ProcessList
.Flink
;
1250 while (current_entry
!= &Console
->ProcessList
)
1252 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1253 current_entry
= current_entry
->Flink
;
1254 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1256 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1260 if (0 != (er
.Event
.KeyEvent
.dwControlKeyState
1261 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1262 && (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
1263 || VK_DOWN
== er
.Event
.KeyEvent
.wVirtualKeyCode
))
1265 if (er
.Event
.KeyEvent
.bKeyDown
)
1267 /* scroll up or down */
1268 if (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
)
1270 /* only scroll up if there is room to scroll up into */
1271 if (Console
->ActiveBuffer
->CurrentY
!= Console
->ActiveBuffer
->MaxY
- 1)
1273 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+
1274 Console
->ActiveBuffer
->MaxY
- 1) %
1275 Console
->ActiveBuffer
->MaxY
;
1276 Console
->ActiveBuffer
->CurrentY
++;
1281 /* only scroll down if there is room to scroll down into */
1282 if (Console
->ActiveBuffer
->CurrentY
!= 0)
1284 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+ 1) %
1285 Console
->ActiveBuffer
->MaxY
;
1286 Console
->ActiveBuffer
->CurrentY
--;
1289 ConioDrawConsole(Console
);
1291 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1294 /* FIXME - convert to ascii */
1295 ConioProcessChar(Console
, ConInRec
);
1298 CSR_API(CsrGetScreenBufferInfo
)
1301 PCSRSS_SCREEN_BUFFER Buff
;
1302 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1304 DPRINT("CsrGetScreenBufferInfo\n");
1306 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1307 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1309 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1310 if (! NT_SUCCESS(Status
))
1312 return Request
->Status
= Status
;
1314 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1315 pInfo
->dwSize
.X
= Buff
->MaxX
;
1316 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1317 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1318 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1319 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1320 pInfo
->srWindow
.Left
= 0;
1321 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1322 pInfo
->srWindow
.Top
= 0;
1323 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1324 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1325 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1326 ConioUnlockScreenBuffer(Buff
);
1328 Request
->Status
= STATUS_SUCCESS
;
1330 return Request
->Status
;
1333 CSR_API(CsrSetCursor
)
1336 PCSRSS_CONSOLE Console
;
1337 PCSRSS_SCREEN_BUFFER Buff
;
1338 LONG OldCursorX
, OldCursorY
;
1339 LONG NewCursorX
, NewCursorY
;
1341 DPRINT("CsrSetCursor\n");
1343 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1344 if (! NT_SUCCESS(Status
))
1346 return Request
->Status
= Status
;
1349 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1350 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1352 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1353 if (! NT_SUCCESS(Status
))
1355 ConioUnlockConsole(Console
);
1356 return Request
->Status
= Status
;
1359 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1360 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1361 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1362 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1364 ConioUnlockScreenBuffer(Buff
);
1365 ConioUnlockConsole(Console
);
1366 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1368 OldCursorX
= Buff
->CurrentX
;
1369 OldCursorY
= Buff
->CurrentY
;
1370 Buff
->CurrentX
= NewCursorX
;
1371 Buff
->CurrentY
= NewCursorY
;
1372 if (Buff
== Console
->ActiveBuffer
)
1374 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1376 ConioUnlockScreenBuffer(Buff
);
1377 ConioUnlockConsole(Console
);
1378 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1382 ConioUnlockScreenBuffer(Buff
);
1383 ConioUnlockConsole(Console
);
1385 return Request
->Status
= STATUS_SUCCESS
;
1388 static VOID FASTCALL
1389 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1391 if (Buff
->MaxX
<= Start
->X
+ Length
)
1393 UpdateRect
->left
= 0;
1397 UpdateRect
->left
= Start
->X
;
1399 if (Buff
->MaxX
<= Start
->X
+ Length
)
1401 UpdateRect
->right
= Buff
->MaxX
- 1;
1405 UpdateRect
->right
= Start
->X
+ Length
- 1;
1407 UpdateRect
->top
= Start
->Y
;
1408 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1409 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1411 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1415 CSR_API(CsrWriteConsoleOutputChar
)
1418 PCHAR String
, tmpString
= NULL
;
1420 PCSRSS_CONSOLE Console
;
1421 PCSRSS_SCREEN_BUFFER Buff
;
1422 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1425 DPRINT("CsrWriteConsoleOutputChar\n");
1427 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1429 if (Request
->Header
.u1
.s1
.TotalLength
1430 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1431 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1433 DPRINT1("Invalid request size\n");
1434 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1435 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1436 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1439 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1440 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1441 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1442 if (NT_SUCCESS(Status
))
1444 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1446 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
1447 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1448 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1449 NULL
, 0, NULL
, NULL
);
1450 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1453 WideCharToMultiByte(Console
->OutputCodePage
, 0,
1454 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1455 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1456 String
, Length
, NULL
, NULL
);
1460 Status
= STATUS_NO_MEMORY
;
1465 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1470 Status
= ConioLockScreenBuffer(ProcessData
,
1471 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1474 if (NT_SUCCESS(Status
))
1476 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
;
1477 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1478 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1479 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1482 *Buffer
= *String
++;
1485 if (++X
== Buff
->MaxX
)
1487 if (++Y
== Buff
->MaxY
)
1490 Buffer
= Buff
->Buffer
;
1495 if (Buff
== Console
->ActiveBuffer
)
1497 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1498 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1499 ConioDrawRegion(Console
, &UpdateRect
);
1502 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
;
1503 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1505 ConioUnlockScreenBuffer(Buff
);
1507 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1509 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1512 ConioUnlockConsole(Console
);
1514 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1515 return Request
->Status
= Status
;
1518 CSR_API(CsrFillOutputChar
)
1521 PCSRSS_CONSOLE Console
;
1522 PCSRSS_SCREEN_BUFFER Buff
;
1523 DWORD X
, Y
, Length
, Written
= 0;
1528 DPRINT("CsrFillOutputChar\n");
1530 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1531 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1533 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1534 if (! NT_SUCCESS(Status
))
1536 return Request
->Status
= Status
;
1539 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1540 if (! NT_SUCCESS(Status
))
1542 ConioUnlockConsole(Console
);
1543 return Request
->Status
= Status
;
1546 X
= Request
->Data
.FillOutputRequest
.Position
.X
;
1547 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1548 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1549 if(Request
->Data
.FillOutputRequest
.Unicode
)
1550 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1552 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1553 Length
= Request
->Data
.FillOutputRequest
.Length
;
1559 if (++X
== Buff
->MaxX
)
1561 if (++Y
== Buff
->MaxY
)
1564 Buffer
= Buff
->Buffer
;
1570 if (Buff
== Console
->ActiveBuffer
)
1572 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1573 Request
->Data
.FillOutputRequest
.Length
);
1574 ConioDrawRegion(Console
, &UpdateRect
);
1577 ConioUnlockScreenBuffer(Buff
);
1578 ConioUnlockConsole(Console
);
1579 Length
= Request
->Data
.FillOutputRequest
.Length
;
1580 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1581 return Request
->Status
;
1584 CSR_API(CsrReadInputEvent
)
1586 PLIST_ENTRY CurrentEntry
;
1587 PCSRSS_CONSOLE Console
;
1589 BOOLEAN Done
= FALSE
;
1590 ConsoleInput
*Input
;
1592 DPRINT("CsrReadInputEvent\n");
1594 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1595 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1596 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1598 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
1599 if (! NT_SUCCESS(Status
))
1601 return Request
->Status
= Status
;
1604 /* only get input if there is any */
1605 CurrentEntry
= Console
->InputEvents
.Flink
;
1606 while (CurrentEntry
!= &Console
->InputEvents
)
1608 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1609 CurrentEntry
= CurrentEntry
->Flink
;
1611 if (Done
&& !Input
->Fake
)
1613 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1617 RemoveEntryList(&Input
->ListEntry
);
1619 if (!Done
&& !Input
->Fake
)
1621 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1622 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1624 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1629 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1631 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1632 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1633 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1635 Console
->WaitingLines
--;
1637 Console
->WaitingChars
--;
1639 HeapFree(Win32CsrApiHeap
, 0, Input
);
1644 Status
= STATUS_SUCCESS
;
1645 Console
->EarlyReturn
= FALSE
;
1649 Status
= STATUS_PENDING
;
1650 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1653 if (IsListEmpty(&Console
->InputEvents
))
1655 ResetEvent(Console
->ActiveEvent
);
1658 ConioUnlockConsole(Console
);
1660 return Request
->Status
= Status
;
1663 CSR_API(CsrWriteConsoleOutputAttrib
)
1665 PCSRSS_CONSOLE Console
;
1666 PCSRSS_SCREEN_BUFFER Buff
;
1673 DPRINT("CsrWriteConsoleOutputAttrib\n");
1675 if (Request
->Header
.u1
.s1
.TotalLength
1676 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1677 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1679 DPRINT1("Invalid request size\n");
1680 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1681 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1682 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1685 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1686 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1687 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1688 if (! NT_SUCCESS(Status
))
1690 return Request
->Status
= Status
;
1693 Status
= ConioLockScreenBuffer(ProcessData
,
1694 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1697 if (! NT_SUCCESS(Status
))
1699 ConioUnlockConsole(Console
);
1700 return Request
->Status
= Status
;
1703 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
;
1704 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1705 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1706 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1707 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1710 *Buffer
= (UCHAR
)(*Attribute
++);
1712 if (++X
== Buff
->MaxX
)
1714 if (++Y
== Buff
->MaxY
)
1717 Buffer
= Buff
->Buffer
+ 1;
1723 if (Buff
== Console
->ActiveBuffer
)
1725 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1726 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1727 ConioDrawRegion(Console
, &UpdateRect
);
1730 ConioUnlockConsole(Console
);
1732 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= X
;
1733 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1735 ConioUnlockScreenBuffer(Buff
);
1737 return Request
->Status
= STATUS_SUCCESS
;
1740 CSR_API(CsrFillOutputAttrib
)
1742 PCSRSS_SCREEN_BUFFER Buff
;
1748 PCSRSS_CONSOLE Console
;
1750 DPRINT("CsrFillOutputAttrib\n");
1752 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1753 if (! NT_SUCCESS(Status
))
1755 return Request
->Status
= Status
;
1758 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1759 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1760 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1761 if (! NT_SUCCESS(Status
))
1763 ConioUnlockConsole(Console
);
1764 return Request
->Status
= Status
;
1767 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
;
1768 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1769 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1770 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1771 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1776 if (++X
== Buff
->MaxX
)
1778 if (++Y
== Buff
->MaxY
)
1781 Buffer
= Buff
->Buffer
+ 1;
1787 if (Buff
== Console
->ActiveBuffer
)
1789 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1790 Request
->Data
.FillOutputAttribRequest
.Length
);
1791 ConioDrawRegion(Console
, &UpdateRect
);
1794 ConioUnlockScreenBuffer(Buff
);
1795 ConioUnlockConsole(Console
);
1797 return Request
->Status
= STATUS_SUCCESS
;
1801 CSR_API(CsrGetCursorInfo
)
1803 PCSRSS_SCREEN_BUFFER Buff
;
1806 DPRINT("CsrGetCursorInfo\n");
1808 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1809 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1811 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1812 if (! NT_SUCCESS(Status
))
1814 return Request
->Status
= Status
;
1816 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1817 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1818 ConioUnlockScreenBuffer(Buff
);
1820 return Request
->Status
= STATUS_SUCCESS
;
1823 CSR_API(CsrSetCursorInfo
)
1825 PCSRSS_CONSOLE Console
;
1826 PCSRSS_SCREEN_BUFFER Buff
;
1831 DPRINT("CsrSetCursorInfo\n");
1833 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1834 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1836 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1837 if (! NT_SUCCESS(Status
))
1839 return Request
->Status
= Status
;
1842 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1843 if (! NT_SUCCESS(Status
))
1845 ConioUnlockConsole(Console
);
1846 return Request
->Status
= Status
;
1849 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1850 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1860 if (Size
!= Buff
->CursorInfo
.dwSize
1861 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1863 Buff
->CursorInfo
.dwSize
= Size
;
1864 Buff
->CursorInfo
.bVisible
= Visible
;
1866 if (! ConioSetCursorInfo(Console
, Buff
))
1868 ConioUnlockScreenBuffer(Buff
);
1869 ConioUnlockConsole(Console
);
1870 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1874 ConioUnlockScreenBuffer(Buff
);
1875 ConioUnlockConsole(Console
);
1877 return Request
->Status
= STATUS_SUCCESS
;
1880 CSR_API(CsrSetTextAttrib
)
1883 PCSRSS_CONSOLE Console
;
1884 PCSRSS_SCREEN_BUFFER Buff
;
1886 DPRINT("CsrSetTextAttrib\n");
1888 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1889 if (! NT_SUCCESS(Status
))
1891 return Request
->Status
= Status
;
1894 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1895 if (! NT_SUCCESS(Status
))
1897 ConioUnlockConsole(Console
);
1898 return Request
->Status
= Status
;
1901 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1902 if (Buff
== Console
->ActiveBuffer
)
1904 if (! ConioUpdateScreenInfo(Console
, Buff
))
1906 ConioUnlockScreenBuffer(Buff
);
1907 ConioUnlockConsole(Console
);
1908 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1912 ConioUnlockScreenBuffer(Buff
);
1913 ConioUnlockConsole(Console
);
1915 return Request
->Status
= STATUS_SUCCESS
;
1918 CSR_API(CsrSetConsoleMode
)
1921 PCSRSS_CONSOLE Console
;
1922 PCSRSS_SCREEN_BUFFER Buff
;
1924 DPRINT("CsrSetConsoleMode\n");
1926 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1927 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1928 Status
= Win32CsrGetObject(ProcessData
,
1929 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
1930 (Object_t
**) &Console
, GENERIC_WRITE
);
1931 if (! NT_SUCCESS(Status
))
1933 return Request
->Status
= Status
;
1936 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1937 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1939 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
1941 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
1943 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
1947 Status
= STATUS_INVALID_HANDLE
;
1950 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1952 return Request
->Status
= Status
;
1955 CSR_API(CsrGetConsoleMode
)
1958 PCSRSS_CONSOLE Console
;
1959 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
1961 DPRINT("CsrGetConsoleMode\n");
1963 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1964 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1965 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
1966 (Object_t
**) &Console
, GENERIC_READ
);
1967 if (! NT_SUCCESS(Status
))
1969 return Request
->Status
= Status
;
1971 Request
->Status
= STATUS_SUCCESS
;
1972 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
1973 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1975 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
1977 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
1979 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
1983 Request
->Status
= STATUS_INVALID_HANDLE
;
1986 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1987 return Request
->Status
;
1990 CSR_API(CsrCreateScreenBuffer
)
1992 PCSRSS_CONSOLE Console
;
1993 PCSRSS_SCREEN_BUFFER Buff
;
1996 DPRINT("CsrCreateScreenBuffer\n");
1998 if (ProcessData
== NULL
)
2000 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2003 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2004 if (! NT_SUCCESS(Status
))
2006 return Request
->Status
= Status
;
2009 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2010 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2012 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
2016 if (Console
->ActiveBuffer
)
2018 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
2019 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
2020 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
2021 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
2025 Buff
->CursorInfo
.bVisible
= TRUE
;
2026 Buff
->CursorInfo
.dwSize
= 5;
2029 if (Buff
->MaxX
== 0)
2034 if (Buff
->MaxY
== 0)
2039 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2040 if(! NT_SUCCESS(Status
))
2042 Request
->Status
= Status
;
2046 Request
->Status
= Win32CsrInsertObject(ProcessData
,
2047 &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
,
2049 Request
->Data
.CreateScreenBufferRequest
.Access
,
2050 Request
->Data
.CreateScreenBufferRequest
.Inheritable
);
2055 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2058 ConioUnlockConsole(Console
);
2059 return Request
->Status
;
2062 CSR_API(CsrSetScreenBuffer
)
2065 PCSRSS_CONSOLE Console
;
2066 PCSRSS_SCREEN_BUFFER Buff
;
2068 DPRINT("CsrSetScreenBuffer\n");
2070 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2071 if (! NT_SUCCESS(Status
))
2073 return Request
->Status
= Status
;
2076 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2077 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2079 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
, GENERIC_WRITE
);
2080 if (! NT_SUCCESS(Status
))
2082 ConioUnlockConsole(Console
);
2083 return Request
->Status
= Status
;
2086 if (Buff
== Console
->ActiveBuffer
)
2088 ConioUnlockScreenBuffer(Buff
);
2089 ConioUnlockConsole(Console
);
2090 return Request
->Status
= STATUS_SUCCESS
;
2093 /* drop reference to old buffer, maybe delete */
2094 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2096 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2098 /* tie console to new buffer */
2099 Console
->ActiveBuffer
= Buff
;
2100 /* inc ref count on new buffer */
2101 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2102 /* Redraw the console */
2103 ConioDrawConsole(Console
);
2105 ConioUnlockScreenBuffer(Buff
);
2106 ConioUnlockConsole(Console
);
2108 return Request
->Status
= STATUS_SUCCESS
;
2111 CSR_API(CsrSetTitle
)
2114 PCSRSS_CONSOLE Console
;
2117 DPRINT("CsrSetTitle\n");
2119 if (Request
->Header
.u1
.s1
.TotalLength
2120 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2121 + Request
->Data
.SetTitleRequest
.Length
)
2123 DPRINT1("Invalid request size\n");
2124 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2125 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2126 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2129 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2130 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2131 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2132 if(! NT_SUCCESS(Status
))
2134 Request
->Status
= Status
;
2138 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2141 /* copy title to console */
2142 RtlFreeUnicodeString(&Console
->Title
);
2143 Console
->Title
.Buffer
= Buffer
;
2144 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2145 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2146 if (! ConioChangeTitle(Console
))
2148 Request
->Status
= STATUS_UNSUCCESSFUL
;
2152 Request
->Status
= STATUS_SUCCESS
;
2157 Request
->Status
= STATUS_NO_MEMORY
;
2159 ConioUnlockConsole(Console
);
2162 return Request
->Status
;
2165 CSR_API(CsrGetTitle
)
2168 PCSRSS_CONSOLE Console
;
2171 DPRINT("CsrGetTitle\n");
2173 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2174 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2175 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2176 if (! NT_SUCCESS(Status
))
2178 DPRINT1("Can't get console\n");
2179 return Request
->Status
= Status
;
2182 /* Copy title of the console to the user title buffer */
2183 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2184 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2185 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2186 Console
->Title
.Length
);
2187 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2189 ConioUnlockConsole(Console
);
2191 if (Length
> sizeof(CSR_API_MESSAGE
))
2193 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2194 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2196 Request
->Status
= STATUS_SUCCESS
;
2198 return Request
->Status
;
2201 CSR_API(CsrWriteConsoleOutput
)
2203 SHORT i
, X
, Y
, SizeX
, SizeY
;
2204 PCSRSS_CONSOLE Console
;
2205 PCSRSS_SCREEN_BUFFER Buff
;
2207 CHAR_INFO
* CurCharInfo
;
2209 CHAR_INFO
* CharInfo
;
2216 DPRINT("CsrWriteConsoleOutput\n");
2218 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2219 if (! NT_SUCCESS(Status
))
2221 return Request
->Status
= Status
;
2224 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2225 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2226 Status
= ConioLockScreenBuffer(ProcessData
,
2227 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2230 if (! NT_SUCCESS(Status
))
2232 ConioUnlockConsole(Console
);
2233 return Request
->Status
= Status
;
2236 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2237 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2238 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2239 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2240 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2241 (((ULONG_PTR
)CharInfo
+ PSize
) >
2242 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2244 ConioUnlockScreenBuffer(Buff
);
2245 ConioUnlockConsole(Console
);
2246 return Request
->Status
= STATUS_ACCESS_VIOLATION
;
2248 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2249 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2250 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2251 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2253 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2254 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2255 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2256 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2258 /* Make sure WriteRegion is inside the screen buffer */
2259 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2260 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2262 ConioUnlockScreenBuffer(Buff
);
2263 ConioUnlockConsole(Console
);
2265 /* It is okay to have a WriteRegion completely outside the screen buffer.
2266 No data is written then. */
2267 return Request
->Status
= STATUS_SUCCESS
;
2270 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2272 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2273 Offset
= ConioGetBufferOffset(Buff
, WriteRegion
.left
, Y
);
2274 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2276 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2279 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2280 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2284 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2290 ConioDrawRegion(Console
, &WriteRegion
);
2292 ConioUnlockScreenBuffer(Buff
);
2293 ConioUnlockConsole(Console
);
2295 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2296 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2297 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2298 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2300 return Request
->Status
= STATUS_SUCCESS
;
2303 CSR_API(CsrFlushInputBuffer
)
2305 PLIST_ENTRY CurrentEntry
;
2306 PCSRSS_CONSOLE Console
;
2307 ConsoleInput
* Input
;
2310 DPRINT("CsrFlushInputBuffer\n");
2312 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2313 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2314 Status
= ConioLockConsole(ProcessData
,
2315 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2318 if(! NT_SUCCESS(Status
))
2320 return Request
->Status
= Status
;
2323 /* Discard all entries in the input event queue */
2324 while (!IsListEmpty(&Console
->InputEvents
))
2326 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2327 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2328 /* Destroy the event */
2329 HeapFree(Win32CsrApiHeap
, 0, Input
);
2331 ResetEvent(Console
->ActiveEvent
);
2332 Console
->WaitingChars
=0;
2334 ConioUnlockConsole(Console
);
2336 return Request
->Status
= STATUS_SUCCESS
;
2339 CSR_API(CsrScrollConsoleScreenBuffer
)
2341 PCSRSS_CONSOLE Console
;
2342 PCSRSS_SCREEN_BUFFER Buff
;
2347 RECT ScrollRectangle
;
2350 HANDLE ConsoleHandle
;
2351 BOOLEAN UseClipRectangle
;
2352 COORD DestinationOrigin
;
2356 DPRINT("CsrScrollConsoleScreenBuffer\n");
2358 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
2359 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
2360 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
2361 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
2363 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2364 if (! NT_SUCCESS(Status
))
2366 return Request
->Status
= Status
;
2369 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2370 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2371 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
2372 if (! NT_SUCCESS(Status
))
2374 ConioUnlockConsole(Console
);
2375 return Request
->Status
= Status
;
2378 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2379 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2380 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2381 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2383 /* Make sure source rectangle is inside the screen buffer */
2384 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2385 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2387 ConioUnlockScreenBuffer(Buff
);
2388 ConioUnlockConsole(Console
);
2389 return Request
->Status
= STATUS_SUCCESS
;
2392 /* If the source was clipped on the left or top, adjust the destination accordingly */
2393 if (ScrollRectangle
.left
< 0)
2395 DestinationOrigin
.X
-= ScrollRectangle
.left
;
2397 if (ScrollRectangle
.top
< 0)
2399 DestinationOrigin
.Y
-= ScrollRectangle
.top
;
2402 if (UseClipRectangle
)
2404 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2405 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2406 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2407 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2408 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
2410 ConioUnlockConsole(Console
);
2411 ConioUnlockScreenBuffer(Buff
);
2412 return Request
->Status
= STATUS_SUCCESS
;
2417 ClipRectangle
= ScreenBuffer
;
2420 ConioInitRect(&DstRegion
,
2421 DestinationOrigin
.Y
,
2422 DestinationOrigin
.X
,
2423 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
2424 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
2426 if (Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
)
2427 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
2429 FillChar
= Fill
.Char
.AsciiChar
;
2431 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
2433 if (Buff
== Console
->ActiveBuffer
)
2435 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
2436 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
2438 /* Draw update region */
2439 ConioDrawRegion(Console
, &UpdateRegion
);
2443 ConioUnlockScreenBuffer(Buff
);
2444 ConioUnlockConsole(Console
);
2446 return Request
->Status
= STATUS_SUCCESS
;
2449 CSR_API(CsrReadConsoleOutputChar
)
2452 PCSRSS_CONSOLE Console
;
2453 PCSRSS_SCREEN_BUFFER Buff
;
2460 DPRINT("CsrReadConsoleOutputChar\n");
2462 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2463 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2464 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2466 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2468 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2469 if (! NT_SUCCESS(Status
))
2471 return Request
->Status
= Status
;
2474 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2475 if (! NT_SUCCESS(Status
))
2477 ConioUnlockConsole(Console
);
2478 return Request
->Status
= Status
;
2481 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
;
2482 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2484 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2486 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2488 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2490 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2491 ReadBuffer
+= sizeof(WCHAR
);
2494 *(ReadBuffer
++) = Char
;
2498 if (Xpos
== Buff
->MaxX
)
2503 if (Ypos
== Buff
->MaxY
)
2511 Request
->Status
= STATUS_SUCCESS
;
2512 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
;
2513 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2515 ConioUnlockScreenBuffer(Buff
);
2516 ConioUnlockConsole(Console
);
2518 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2519 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2521 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2522 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2525 return Request
->Status
;
2529 CSR_API(CsrReadConsoleOutputAttrib
)
2532 PCSRSS_SCREEN_BUFFER Buff
;
2536 DWORD CurrentLength
;
2538 DPRINT("CsrReadConsoleOutputAttrib\n");
2540 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2541 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2542 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2544 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2545 if (! NT_SUCCESS(Status
))
2547 return Request
->Status
= Status
;
2550 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
;
2551 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2553 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2555 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2560 if (Xpos
== Buff
->MaxX
)
2565 if (Ypos
== Buff
->MaxY
)
2574 Request
->Status
= STATUS_SUCCESS
;
2575 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
;
2576 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2578 ConioUnlockScreenBuffer(Buff
);
2580 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2581 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2582 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2584 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2585 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2588 return Request
->Status
;
2592 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2595 PCSRSS_CONSOLE Console
;
2596 PLIST_ENTRY CurrentItem
;
2598 ConsoleInput
*Input
;
2600 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2602 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2603 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2605 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2606 if (! NT_SUCCESS(Status
))
2608 return Request
->Status
= Status
;
2611 CurrentItem
= Console
->InputEvents
.Flink
;
2614 /* If there are any events ... */
2615 while (CurrentItem
!= &Console
->InputEvents
)
2617 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2618 CurrentItem
= CurrentItem
->Flink
;
2625 ConioUnlockConsole(Console
);
2627 Request
->Status
= STATUS_SUCCESS
;
2628 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2630 return Request
->Status
;
2634 CSR_API(CsrPeekConsoleInput
)
2637 PCSRSS_CONSOLE Console
;
2640 PLIST_ENTRY CurrentItem
;
2641 PINPUT_RECORD InputRecord
;
2645 DPRINT("CsrPeekConsoleInput\n");
2647 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2648 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2650 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2651 if(! NT_SUCCESS(Status
))
2653 return Request
->Status
= Status
;
2656 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2657 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2658 Size
= Length
* sizeof(INPUT_RECORD
);
2660 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2661 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2663 ConioUnlockConsole(Console
);
2664 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2665 return Request
->Status
;
2670 if (! IsListEmpty(&Console
->InputEvents
))
2672 CurrentItem
= Console
->InputEvents
.Flink
;
2674 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2676 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2680 CurrentItem
= CurrentItem
->Flink
;
2685 *InputRecord
= Item
->InputEvent
;
2687 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2689 ConioInputEventToAnsi(Console
, InputRecord
);
2693 CurrentItem
= CurrentItem
->Flink
;
2697 ConioUnlockConsole(Console
);
2699 Request
->Status
= STATUS_SUCCESS
;
2700 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2702 return Request
->Status
;
2706 CSR_API(CsrReadConsoleOutput
)
2708 PCHAR_INFO CharInfo
;
2709 PCHAR_INFO CurCharInfo
;
2710 PCSRSS_SCREEN_BUFFER Buff
;
2723 DPRINT("CsrReadConsoleOutput\n");
2725 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2726 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2728 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2729 if (! NT_SUCCESS(Status
))
2731 return Request
->Status
= Status
;
2734 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2735 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2736 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2737 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2738 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2739 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2740 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2741 Length
= BufferSize
.X
* BufferSize
.Y
;
2742 Size
= Length
* sizeof(CHAR_INFO
);
2744 /* FIXME: Is this correct? */
2745 CodePage
= ProcessData
->Console
->OutputCodePage
;
2747 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2748 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2750 ConioUnlockScreenBuffer(Buff
);
2751 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2752 return Request
->Status
;
2755 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2756 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2757 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2758 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2760 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2761 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2763 ConioUnlockScreenBuffer(Buff
);
2764 Request
->Status
= STATUS_SUCCESS
;
2765 return Request
->Status
;
2768 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2770 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2772 Offset
= ConioGetBufferOffset(Buff
, ReadRegion
.left
, Y
);
2773 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2775 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2777 MultiByteToWideChar(CodePage
, 0,
2778 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2779 &CurCharInfo
->Char
.UnicodeChar
, 1);
2783 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2785 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2790 ConioUnlockScreenBuffer(Buff
);
2792 Request
->Status
= STATUS_SUCCESS
;
2793 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2794 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2795 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2796 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2798 return Request
->Status
;
2802 CSR_API(CsrWriteConsoleInput
)
2804 PINPUT_RECORD InputRecord
;
2805 PCSRSS_CONSOLE Console
;
2810 ConsoleInput
* Record
;
2812 DPRINT("CsrWriteConsoleInput\n");
2814 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2815 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2817 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
, GENERIC_WRITE
);
2818 if (! NT_SUCCESS(Status
))
2820 return Request
->Status
= Status
;
2823 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2824 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2825 Size
= Length
* sizeof(INPUT_RECORD
);
2827 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2828 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2830 ConioUnlockConsole(Console
);
2831 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2832 return Request
->Status
;
2835 for (i
= 0; i
< Length
; i
++)
2837 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2840 ConioUnlockConsole(Console
);
2841 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2842 return Request
->Status
;
2845 Record
->Echoed
= FALSE
;
2846 Record
->Fake
= FALSE
;
2847 //Record->InputEvent = *InputRecord++;
2848 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
2849 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2851 /* FIXME - convert from unicode to ascii!! */
2852 ConioProcessChar(Console
, Record
);
2856 ConioUnlockConsole(Console
);
2858 Request
->Status
= STATUS_SUCCESS
;
2859 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2861 return Request
->Status
;
2864 /**********************************************************************
2865 * HardwareStateProperty
2868 * Set/Get the value of the HardwareState and switch
2869 * between direct video buffer ouput and GDI windowed
2872 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2873 * object. We use the same object to Request.
2875 * ConsoleHwState has the correct size to be compatible
2876 * with NT's, but values are not.
2878 static NTSTATUS FASTCALL
2879 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2881 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2883 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2884 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2886 if (Console
->HardwareState
!= ConsoleHwState
)
2888 /* TODO: implement switching from full screen to windowed mode */
2889 /* TODO: or back; now simply store the hardware state */
2890 Console
->HardwareState
= ConsoleHwState
;
2893 return STATUS_SUCCESS
;
2896 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2899 CSR_API(CsrHardwareStateProperty
)
2901 PCSRSS_CONSOLE Console
;
2904 DPRINT("CsrHardwareStateProperty\n");
2906 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2907 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2909 Status
= ConioLockConsole(ProcessData
,
2910 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2913 if (! NT_SUCCESS(Status
))
2915 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2916 return Request
->Status
= Status
;
2919 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2921 case CONSOLE_HARDWARE_STATE_GET
:
2922 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
2925 case CONSOLE_HARDWARE_STATE_SET
:
2926 DPRINT("Setting console hardware state.\n");
2927 Request
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2931 Request
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2935 ConioUnlockConsole(Console
);
2937 return Request
->Status
;
2940 CSR_API(CsrGetConsoleWindow
)
2942 PCSRSS_CONSOLE Console
;
2945 DPRINT("CsrGetConsoleWindow\n");
2947 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2948 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2950 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2951 if (! NT_SUCCESS(Status
))
2953 return Request
->Status
= Status
;
2956 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
2957 ConioUnlockConsole(Console
);
2959 return Request
->Status
= STATUS_SUCCESS
;
2962 CSR_API(CsrSetConsoleIcon
)
2964 PCSRSS_CONSOLE Console
;
2967 DPRINT("CsrSetConsoleIcon\n");
2969 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2970 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2972 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2973 if (! NT_SUCCESS(Status
))
2975 return Request
->Status
= Status
;
2978 Request
->Status
= (ConioChangeIcon(Console
, Request
->Data
.SetConsoleIconRequest
.WindowIcon
)
2979 ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
2980 ConioUnlockConsole(Console
);
2982 return Request
->Status
;
2985 CSR_API(CsrGetConsoleCodePage
)
2987 PCSRSS_CONSOLE Console
;
2990 DPRINT("CsrGetConsoleCodePage\n");
2992 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2993 if (! NT_SUCCESS(Status
))
2995 return Request
->Status
= Status
;
2998 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2999 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3000 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3001 ConioUnlockConsole(Console
);
3002 return Request
->Status
= STATUS_SUCCESS
;
3005 CSR_API(CsrSetConsoleCodePage
)
3007 PCSRSS_CONSOLE Console
;
3010 DPRINT("CsrSetConsoleCodePage\n");
3012 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3013 if (! NT_SUCCESS(Status
))
3015 return Request
->Status
= Status
;
3018 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3019 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3020 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3022 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3023 ConioUnlockConsole(Console
);
3024 return Request
->Status
= STATUS_SUCCESS
;
3026 ConioUnlockConsole(Console
);
3027 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3030 CSR_API(CsrGetConsoleOutputCodePage
)
3032 PCSRSS_CONSOLE Console
;
3035 DPRINT("CsrGetConsoleOutputCodePage\n");
3037 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3038 if (! NT_SUCCESS(Status
))
3040 return Request
->Status
= Status
;
3043 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3044 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3045 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3046 ConioUnlockConsole(Console
);
3047 return Request
->Status
= STATUS_SUCCESS
;
3050 CSR_API(CsrSetConsoleOutputCodePage
)
3052 PCSRSS_CONSOLE Console
;
3055 DPRINT("CsrSetConsoleOutputCodePage\n");
3057 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3058 if (! NT_SUCCESS(Status
))
3060 return Request
->Status
= Status
;
3063 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3064 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3065 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3067 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3068 ConioUnlockConsole(Console
);
3069 return Request
->Status
= STATUS_SUCCESS
;
3071 ConioUnlockConsole(Console
);
3072 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3075 CSR_API(CsrGetProcessList
)
3078 PCSRSS_CONSOLE Console
;
3079 PCSRSS_PROCESS_DATA current
;
3080 PLIST_ENTRY current_entry
;
3081 ULONG nItems
, nCopied
, Length
;
3084 DPRINT("CsrGetProcessList\n");
3086 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3087 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3088 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3090 nItems
= nCopied
= 0;
3091 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3092 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3094 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3095 if (! NT_SUCCESS(Status
))
3097 return Request
->Status
= Status
;
3100 DPRINT1("Console_Api Ctrl-C\n");
3102 for(current_entry
= Console
->ProcessList
.Flink
;
3103 current_entry
!= &Console
->ProcessList
;
3104 current_entry
= current_entry
->Flink
)
3106 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3107 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3109 *(Buffer
++) = current
->ProcessId
;
3114 ConioUnlockConsole(Console
);
3116 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3117 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3119 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3120 if (Length
> sizeof(CSR_API_MESSAGE
))
3122 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3123 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3125 return Request
->Status
= STATUS_SUCCESS
;