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 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
89 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
93 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
95 PBYTE Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CurrentY
);
98 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
102 *Ptr
++ = Buff
->DefaultAttrib
;
106 static NTSTATUS FASTCALL
107 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
108 PCSRSS_SCREEN_BUFFER Buffer
)
110 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
112 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
113 Buffer
->Header
.ReferenceCount
= 0;
116 Buffer
->VirtualY
= 0;
117 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
118 if (NULL
== Buffer
->Buffer
)
120 return STATUS_INSUFFICIENT_RESOURCES
;
122 InitializeCriticalSection(&Buffer
->Header
.Lock
);
123 ConioInitScreenBuffer(Console
, Buffer
);
124 /* initialize buffer to be empty with default attributes */
125 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
127 ClearLineBuffer(Buffer
);
129 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
130 Buffer
->CurrentX
= 0;
131 Buffer
->CurrentY
= 0;
133 return STATUS_SUCCESS
;
136 static NTSTATUS STDCALL
137 CsrInitConsole(PCSRSS_CONSOLE Console
)
140 SECURITY_ATTRIBUTES SecurityAttributes
;
141 PCSRSS_SCREEN_BUFFER NewBuffer
;
144 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
145 Console
->Title
.Buffer
= NULL
;
148 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
150 Console
->Header
.ReferenceCount
= 0;
151 Console
->WaitingChars
= 0;
152 Console
->WaitingLines
= 0;
153 Console
->EchoCount
= 0;
154 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
155 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
156 Console
->EarlyReturn
= FALSE
;
157 Console
->ActiveBuffer
= NULL
;
158 InitializeListHead(&Console
->InputEvents
);
159 Console
->CodePage
= GetOEMCP();
160 Console
->OutputCodePage
= GetOEMCP();
162 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
163 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
164 SecurityAttributes
.bInheritHandle
= TRUE
;
166 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
167 if (NULL
== Console
->ActiveEvent
)
169 RtlFreeUnicodeString(&Console
->Title
);
170 return STATUS_UNSUCCESSFUL
;
172 Console
->PrivateData
= NULL
;
173 InitializeCriticalSection(&Console
->Header
.Lock
);
175 GuiMode
= DtbgIsDesktopVisible();
177 /* allocate console screen buffer */
178 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
179 if (NULL
== NewBuffer
)
181 RtlFreeUnicodeString(&Console
->Title
);
182 DeleteCriticalSection(&Console
->Header
.Lock
);
183 CloseHandle(Console
->ActiveEvent
);
184 return STATUS_INSUFFICIENT_RESOURCES
;
186 /* init screen buffer with defaults */
187 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
188 NewBuffer
->CursorInfo
.dwSize
= 5;
189 /* make console active, and insert into console list */
190 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
194 Status
= TuiInitConsole(Console
);
195 if (! NT_SUCCESS(Status
))
197 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
203 Status
= GuiInitConsole(Console
);
204 if (! NT_SUCCESS(Status
))
206 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
207 RtlFreeUnicodeString(&Console
->Title
);
208 DeleteCriticalSection(&Console
->Header
.Lock
);
209 CloseHandle(Console
->ActiveEvent
);
210 DPRINT1("GuiInitConsole: failed\n");
215 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
216 if (! NT_SUCCESS(Status
))
218 ConioCleanupConsole(Console
);
219 RtlFreeUnicodeString(&Console
->Title
);
220 DeleteCriticalSection(&Console
->Header
.Lock
);
221 CloseHandle(Console
->ActiveEvent
);
222 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
223 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
227 /* add a reference count because the buffer is tied to the console */
228 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
230 /* copy buffer contents to screen */
231 ConioDrawConsole(Console
);
233 return STATUS_SUCCESS
;
237 CSR_API(CsrAllocConsole
)
239 PCSRSS_CONSOLE Console
;
240 NTSTATUS Status
= STATUS_SUCCESS
;
241 BOOLEAN NewConsole
= FALSE
;
243 DPRINT("CsrAllocConsole\n");
245 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
246 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
248 if (ProcessData
== NULL
)
250 DPRINT1("No process data\n");
251 return Request
->Status
= STATUS_INVALID_PARAMETER
;
254 if (ProcessData
->Console
)
256 DPRINT1("Process already has a console\n");
257 Request
->Status
= STATUS_INVALID_PARAMETER
;
258 return STATUS_INVALID_PARAMETER
;
262 Request
->Status
= STATUS_SUCCESS
;
264 /* If we don't need a console, then get out of here */
265 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
267 DPRINT("No console needed\n");
268 return STATUS_SUCCESS
;
271 /* If we already have one, then don't create a new one... */
272 if (!Request
->Data
.AllocConsoleRequest
.Console
||
273 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
275 /* Allocate a console structure */
277 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
280 DPRINT1("Not enough memory for console\n");
281 Request
->Status
= STATUS_NO_MEMORY
;
282 return STATUS_NO_MEMORY
;
284 /* initialize list head */
285 InitializeListHead(&Console
->ProcessList
);
286 /* insert process data required for GUI initialization */
287 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
288 /* Initialize the Console */
289 Request
->Status
= CsrInitConsole(Console
);
290 if (!NT_SUCCESS(Request
->Status
))
292 DPRINT1("Console init failed\n");
293 HeapFree(Win32CsrApiHeap
, 0, Console
);
294 return Request
->Status
;
299 /* Reuse our current console */
300 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
303 /* Set the Process Console */
304 ProcessData
->Console
= Console
;
306 /* Return it to the caller */
307 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
309 /* Add a reference count because the process is tied to the console */
310 Console
->Header
.ReferenceCount
++;
312 if (NewConsole
|| !ProcessData
->bInheritHandles
)
314 /* Insert the Objects */
315 Status
= Win32CsrInsertObject(ProcessData
,
316 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
318 GENERIC_READ
| GENERIC_WRITE
,
320 if (! NT_SUCCESS(Status
))
322 DPRINT1("Failed to insert object\n");
323 ConioDeleteConsole((Object_t
*) Console
);
324 ProcessData
->Console
= 0;
325 return Request
->Status
= Status
;
328 Status
= Win32CsrInsertObject(ProcessData
,
329 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
330 &Console
->ActiveBuffer
->Header
,
331 GENERIC_READ
| GENERIC_WRITE
,
333 if (!NT_SUCCESS(Status
))
335 DPRINT1("Failed to insert object\n");
336 ConioDeleteConsole((Object_t
*) Console
);
337 Win32CsrReleaseObject(ProcessData
,
338 Request
->Data
.AllocConsoleRequest
.InputHandle
);
339 ProcessData
->Console
= 0;
340 return Request
->Status
= Status
;
344 /* Duplicate the Event */
345 if (!DuplicateHandle(GetCurrentProcess(),
346 ProcessData
->Console
->ActiveEvent
,
347 ProcessData
->Process
,
348 &ProcessData
->ConsoleEvent
,
353 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
354 ConioDeleteConsole((Object_t
*) Console
);
355 if (NewConsole
|| !ProcessData
->bInheritHandles
)
357 Win32CsrReleaseObject(ProcessData
,
358 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
359 Win32CsrReleaseObject(ProcessData
,
360 Request
->Data
.AllocConsoleRequest
.InputHandle
);
362 ProcessData
->Console
= 0;
363 return Request
->Status
= Status
;
366 /* Set the Ctrl Dispatcher */
367 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
368 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
372 /* Insert into the list if it has not been added */
373 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
376 return STATUS_SUCCESS
;
379 CSR_API(CsrFreeConsole
)
381 PCSRSS_CONSOLE Console
;
384 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
385 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
387 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
389 return Request
->Status
= STATUS_INVALID_PARAMETER
;
392 Console
= ProcessData
->Console
;
393 ProcessData
->Console
= NULL
;
394 RemoveEntryList(&ProcessData
->ProcessEntry
);
395 if (0 == InterlockedDecrement(&Console
->Header
.ReferenceCount
))
397 ConioDeleteConsole((Object_t
*) Console
);
399 return STATUS_SUCCESS
;
403 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
405 /* If we hit bottom, slide the viewable screen */
406 if (++Buff
->CurrentY
== Buff
->MaxY
)
409 if (++Buff
->VirtualY
== Buff
->MaxY
)
414 ClearLineBuffer(Buff
);
415 if (UpdateRect
->top
!= 0)
420 UpdateRect
->left
= 0;
421 UpdateRect
->right
= Buff
->MaxX
- 1;
422 UpdateRect
->bottom
= Buff
->CurrentY
;
425 static NTSTATUS FASTCALL
426 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
427 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
432 LONG CursorStartX
, CursorStartY
;
435 CursorStartX
= Buff
->CurrentX
;
436 CursorStartY
= Buff
->CurrentY
;
437 UpdateRect
.left
= Buff
->MaxX
;
438 UpdateRect
.top
= Buff
->CurrentY
;
439 UpdateRect
.right
= -1;
440 UpdateRect
.bottom
= Buff
->CurrentY
;
443 for (i
= 0; i
< Length
; i
++)
445 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
448 if (Buffer
[i
] == '\n')
451 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
455 else if (Buffer
[i
] == '\b')
457 /* Only handle BS if we're not on the first pos of the first line */
458 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
460 if (0 == Buff
->CurrentX
)
462 /* slide virtual position up */
463 Buff
->CurrentX
= Buff
->MaxX
- 1;
465 UpdateRect
.top
= min(UpdateRect
.top
, (LONG
)Buff
->CurrentY
);
471 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
473 Ptr
[1] = Buff
->DefaultAttrib
;
474 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
475 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
480 else if (Buffer
[i
] == '\r')
483 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
484 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
488 else if (Buffer
[i
] == '\t')
492 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
493 EndX
= (Buff
->CurrentX
+ 8) & ~7;
494 if (EndX
> Buff
->MaxX
)
498 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
499 while (Buff
->CurrentX
< EndX
)
502 *Ptr
++ = Buff
->DefaultAttrib
;
505 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
506 if (Buff
->CurrentX
== Buff
->MaxX
)
508 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
511 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
521 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
522 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
523 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
527 Ptr
[1] = Buff
->DefaultAttrib
;
530 if (Buff
->CurrentX
== Buff
->MaxX
)
532 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
535 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
539 Buff
->CurrentX
= CursorStartX
;
544 if (! ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
546 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
550 return STATUS_SUCCESS
;
553 CSR_API(CsrReadConsole
)
555 PLIST_ENTRY CurrentEntry
;
558 PWCHAR UnicodeBuffer
;
560 ULONG nNumberOfCharsToRead
, CharSize
;
561 PCSRSS_CONSOLE Console
;
564 DPRINT("CsrReadConsole\n");
566 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
568 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
569 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
570 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
571 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
573 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
574 UnicodeBuffer
= (PWCHAR
)Buffer
;
575 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
576 &Console
, GENERIC_READ
);
577 if (! NT_SUCCESS(Status
))
579 return Request
->Status
= Status
;
581 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
582 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
584 /* remove input event from queue */
585 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
586 if (IsListEmpty(&Console
->InputEvents
))
589 ResetEvent(Console
->ActiveEvent
);
591 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
593 /* only pay attention to valid ascii chars, on key down */
594 if (KEY_EVENT
== Input
->InputEvent
.EventType
595 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
596 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
599 * backspace handling - if we are in charge of echoing it then we handle it here
600 * otherwise we treat it like a normal char.
602 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
603 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
605 /* echo if it has not already been done, and either we or the client has chars to be deleted */
607 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
609 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
610 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
614 i
-= 2; /* if we already have something to return, just back it up by 2 */
617 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
618 Console
->WaitingChars
--;
619 ConioUnlockConsole(Console
);
620 HeapFree(Win32CsrApiHeap
, 0, Input
);
621 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
622 Request
->Status
= STATUS_NOTIFY_CLEANUP
;
623 return STATUS_NOTIFY_CLEANUP
;
626 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
627 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
629 /* do not copy backspace to buffer */
632 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
633 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
635 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
637 /* echo to screen if enabled and we did not already echo the char */
638 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
640 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
642 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
643 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
650 Console
->WaitingChars
--;
651 HeapFree(Win32CsrApiHeap
, 0, Input
);
653 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
656 Request
->Status
= STATUS_PENDING
; /* we didn't read anything */
658 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
660 if (0 == Console
->WaitingLines
||
661 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
663 Request
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
667 Console
->WaitingLines
--;
668 Request
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
673 Request
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
676 if (Request
->Status
== STATUS_PENDING
)
678 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
682 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
685 ConioUnlockConsole(Console
);
687 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
689 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
690 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
693 return Request
->Status
;
696 BOOLEAN __inline
ConioGetIntersection(
701 if (ConioIsRectEmpty(Rect1
) ||
702 (ConioIsRectEmpty(Rect2
)) ||
703 (Rect1
->top
> Rect2
->bottom
) ||
704 (Rect1
->left
> Rect2
->right
) ||
705 (Rect1
->bottom
< Rect2
->top
) ||
706 (Rect1
->right
< Rect2
->left
))
708 /* The rectangles do not intersect */
709 ConioInitRect(Intersection
, 0, -1, 0, -1);
713 ConioInitRect(Intersection
,
714 max(Rect1
->top
, Rect2
->top
),
715 max(Rect1
->left
, Rect2
->left
),
716 min(Rect1
->bottom
, Rect2
->bottom
),
717 min(Rect1
->right
, Rect2
->right
));
722 BOOLEAN __inline
ConioGetUnion(
727 if (ConioIsRectEmpty(Rect1
))
729 if (ConioIsRectEmpty(Rect2
))
731 ConioInitRect(Union
, 0, -1, 0, -1);
739 else if (ConioIsRectEmpty(Rect2
))
746 min(Rect1
->top
, Rect2
->top
),
747 min(Rect1
->left
, Rect2
->left
),
748 max(Rect1
->bottom
, Rect2
->bottom
),
749 max(Rect1
->right
, Rect2
->right
));
755 /* Move from one rectangle to another. We must be careful about the order that
756 * this is done, to avoid overwriting parts of the source before they are moved. */
758 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
764 int Width
= ConioRectWidth(SrcRegion
);
765 int Height
= ConioRectHeight(SrcRegion
);
776 /* Moving down: work from bottom up */
777 SY
= SrcRegion
->bottom
;
778 DY
= DstRegion
->bottom
;
781 for (i
= 0; i
< Height
; i
++)
783 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
784 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
786 SX
= SrcRegion
->left
;
787 DX
= DstRegion
->left
;
791 /* Moving right: work from right to left */
792 SX
= SrcRegion
->right
;
793 DX
= DstRegion
->right
;
796 for (j
= 0; j
< Width
; j
++)
798 WORD Cell
= SRow
[SX
];
799 if (SX
>= ClipRegion
->left
&& SX
<= ClipRegion
->right
800 && SY
>= ClipRegion
->top
&& SY
<= ClipRegion
->bottom
)
804 if (DX
>= ClipRegion
->left
&& DX
<= ClipRegion
->right
805 && DY
>= ClipRegion
->top
&& DY
<= ClipRegion
->bottom
)
818 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
820 if (InputEvent
->EventType
== KEY_EVENT
)
822 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
823 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
824 ConsoleInputUnicodeCharToAnsiChar(Console
,
825 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
830 CSR_API(CsrWriteConsole
)
834 PCSRSS_SCREEN_BUFFER Buff
;
835 PCSRSS_CONSOLE Console
;
838 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
840 DPRINT("CsrWriteConsole\n");
842 if (Request
->Header
.u1
.s1
.TotalLength
843 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
844 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
846 DPRINT1("Invalid request size\n");
847 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
848 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
849 return Request
->Status
= STATUS_INVALID_PARAMETER
;
851 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
853 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
854 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
856 if (! NT_SUCCESS(Status
))
858 return Request
->Status
= Status
;
861 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
863 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
864 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
865 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
866 NULL
, 0, NULL
, NULL
);
867 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
870 WideCharToMultiByte(Console
->OutputCodePage
, 0,
871 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
872 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
873 Buffer
, Length
, NULL
, NULL
);
877 Status
= STATUS_NO_MEMORY
;
882 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
887 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
888 if (NT_SUCCESS(Status
))
890 Request
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
891 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
892 if (NT_SUCCESS(Status
))
894 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
896 ConioUnlockScreenBuffer(Buff
);
898 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
900 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
903 ConioUnlockConsole(Console
);
905 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
907 return Request
->Status
= Status
;
911 ConioDeleteScreenBuffer(Object_t
*Object
)
913 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
914 DeleteCriticalSection(&Buffer
->Header
.Lock
);
915 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
916 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
920 ConioDrawConsole(PCSRSS_CONSOLE Console
)
924 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
926 ConioDrawRegion(Console
, &Region
);
931 ConioDeleteConsole(Object_t
*Object
)
933 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
936 DPRINT("ConioDeleteConsole\n");
938 /* Drain input event queue */
939 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
941 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
942 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
943 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
944 HeapFree(Win32CsrApiHeap
, 0, Event
);
947 ConioCleanupConsole(Console
);
948 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
950 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
953 Console
->ActiveBuffer
= NULL
;
955 CloseHandle(Console
->ActiveEvent
);
956 DeleteCriticalSection(&Console
->Header
.Lock
);
957 RtlFreeUnicodeString(&Console
->Title
);
958 IntDeleteAllAliases(Console
->Aliases
);
959 HeapFree(Win32CsrApiHeap
, 0, Console
);
963 CsrInitConsoleSupport(VOID
)
965 DPRINT("CSR: CsrInitConsoleSupport()\n");
967 /* Should call LoadKeyboardLayout */
971 ConioProcessChar(PCSRSS_CONSOLE Console
,
972 ConsoleInput
*KeyEventRecord
)
975 BOOL bClientWake
= FALSE
;
976 ConsoleInput
*TempInput
;
978 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
980 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
983 /* first add the \r */
984 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
985 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
986 KeyEventRecord
->Echoed
= FALSE
;
987 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
988 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
989 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
990 Console
->WaitingChars
++;
991 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
992 if (NULL
== KeyEventRecord
)
994 DPRINT1("Failed to allocate KeyEventRecord\n");
997 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
998 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
999 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1000 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1001 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1002 KeyEventRecord
->Fake
= TRUE
;
1006 /* add event to the queue */
1007 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1008 Console
->WaitingChars
++;
1009 /* if line input mode is enabled, only wake the client on enter key down */
1010 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1011 || Console
->EarlyReturn
1012 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1013 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1015 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1017 Console
->WaitingLines
++;
1020 SetEvent(Console
->ActiveEvent
);
1022 KeyEventRecord
->Echoed
= FALSE
;
1023 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1024 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1025 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1027 /* walk the input queue looking for a char to backspace */
1028 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1029 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1030 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1031 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1032 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1033 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1037 /* if we found one, delete it, otherwise, wake the client */
1038 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1040 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1041 RemoveEntryList(&TempInput
->ListEntry
);
1042 if (TempInput
->Echoed
)
1044 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1045 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1048 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1049 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1050 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1051 Console
->WaitingChars
-= 2;
1055 SetEvent(Console
->ActiveEvent
);
1060 /* echo chars if we are supposed to and client is waiting for some */
1061 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1062 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1063 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1064 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1066 /* mark the char as already echoed */
1067 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1068 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1070 Console
->EchoCount
--;
1071 KeyEventRecord
->Echoed
= TRUE
;
1075 /* Console->WaitingChars++; */
1076 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1078 SetEvent(Console
->ActiveEvent
);
1082 static DWORD FASTCALL
1083 ConioGetShiftState(PBYTE KeyState
)
1087 if (KeyState
[VK_CAPITAL
] & 1)
1088 ssOut
|= CAPSLOCK_ON
;
1090 if (KeyState
[VK_NUMLOCK
] & 1)
1091 ssOut
|= NUMLOCK_ON
;
1093 if (KeyState
[VK_SCROLL
] & 1)
1094 ssOut
|= SCROLLLOCK_ON
;
1096 if (KeyState
[VK_SHIFT
] & 0x80)
1097 ssOut
|= SHIFT_PRESSED
;
1099 if (KeyState
[VK_LCONTROL
] & 0x80)
1100 ssOut
|= LEFT_CTRL_PRESSED
;
1101 if (KeyState
[VK_RCONTROL
] & 0x80)
1102 ssOut
|= RIGHT_CTRL_PRESSED
;
1104 if (KeyState
[VK_LMENU
] & 0x80)
1105 ssOut
|= LEFT_ALT_PRESSED
;
1106 if (KeyState
[VK_RMENU
] & 0x80)
1107 ssOut
|= RIGHT_ALT_PRESSED
;
1113 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1115 static BYTE KeyState
[256] = { 0 };
1116 /* MSDN mentions that you should use the last virtual key code received
1117 * when putting a virtual key identity to a WM_CHAR message since multiple
1118 * or translated keys may be involved. */
1119 static UINT LastVirtualKey
= 0;
1121 ConsoleInput
*ConInRec
;
1125 UINT VirtualKeyCode
;
1126 UINT VirtualScanCode
;
1129 ULONG ResultSize
= 0;
1132 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1133 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1134 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1136 GetKeyboardState(KeyState
);
1137 ShiftState
= ConioGetShiftState(KeyState
);
1139 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1141 VirtualKeyCode
= LastVirtualKey
;
1142 UnicodeChar
= msg
->wParam
;
1149 VirtualKeyCode
= msg
->wParam
;
1150 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1157 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1160 if (0 == ResultSize
)
1165 er
.EventType
= KEY_EVENT
;
1166 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1167 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1168 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1169 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1170 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1171 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1175 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1176 && VK_TAB
== VirtualKeyCode
)
1180 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1185 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1187 if (TuiSwapConsole(0))
1194 if (NULL
== Console
)
1196 DPRINT1("No Active Console!\n");
1200 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1202 if (NULL
== ConInRec
)
1207 ConInRec
->InputEvent
= er
;
1208 ConInRec
->Fake
= UnicodeChar
&&
1209 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1210 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1211 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1212 ConInRec
->Echoed
= FALSE
;
1213 if (ConInRec
->NotChar
)
1214 LastVirtualKey
= msg
->wParam
;
1216 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1217 Down
? "down" : "up ",
1218 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1220 ConInRec
->Fake
? "fake" : "real",
1221 ConInRec
->NotChar
? "notc" : "char",
1224 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1227 if (ConInRec
->Fake
&& ConInRec
->NotChar
)
1229 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1233 /* process Ctrl-C and Ctrl-Break */
1234 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1235 er
.Event
.KeyEvent
.bKeyDown
&&
1236 ((er
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1237 (er
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1238 (er
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1240 PCSRSS_PROCESS_DATA current
;
1241 PLIST_ENTRY current_entry
;
1242 DPRINT1("Console_Api Ctrl-C\n");
1243 current_entry
= Console
->ProcessList
.Flink
;
1244 while (current_entry
!= &Console
->ProcessList
)
1246 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1247 current_entry
= current_entry
->Flink
;
1248 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1250 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1254 if (0 != (er
.Event
.KeyEvent
.dwControlKeyState
1255 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1256 && (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
1257 || VK_DOWN
== er
.Event
.KeyEvent
.wVirtualKeyCode
))
1259 if (er
.Event
.KeyEvent
.bKeyDown
)
1261 /* scroll up or down */
1262 if (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
)
1264 /* only scroll up if there is room to scroll up into */
1265 if (Console
->ActiveBuffer
->CurrentY
!= Console
->ActiveBuffer
->MaxY
- 1)
1267 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+
1268 Console
->ActiveBuffer
->MaxY
- 1) %
1269 Console
->ActiveBuffer
->MaxY
;
1270 Console
->ActiveBuffer
->CurrentY
++;
1275 /* only scroll down if there is room to scroll down into */
1276 if (Console
->ActiveBuffer
->CurrentY
!= 0)
1278 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+ 1) %
1279 Console
->ActiveBuffer
->MaxY
;
1280 Console
->ActiveBuffer
->CurrentY
--;
1283 ConioDrawConsole(Console
);
1285 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1288 /* FIXME - convert to ascii */
1289 ConioProcessChar(Console
, ConInRec
);
1292 CSR_API(CsrGetScreenBufferInfo
)
1295 PCSRSS_CONSOLE Console
;
1296 PCSRSS_SCREEN_BUFFER Buff
;
1297 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1299 DPRINT("CsrGetScreenBufferInfo\n");
1301 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1302 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1304 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1305 if (! NT_SUCCESS(Status
))
1307 return Request
->Status
= Status
;
1309 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1310 if (! NT_SUCCESS(Status
))
1312 ConioUnlockConsole(Console
);
1313 return Request
->Status
= Status
;
1315 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1316 pInfo
->dwSize
.X
= Buff
->MaxX
;
1317 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1318 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1319 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1320 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1321 pInfo
->srWindow
.Left
= Buff
->ShowX
;
1322 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
1323 pInfo
->srWindow
.Top
= Buff
->ShowY
;
1324 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
1325 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1326 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1327 ConioUnlockScreenBuffer(Buff
);
1328 ConioUnlockConsole(Console
);
1330 Request
->Status
= STATUS_SUCCESS
;
1332 return Request
->Status
;
1335 CSR_API(CsrSetCursor
)
1338 PCSRSS_CONSOLE Console
;
1339 PCSRSS_SCREEN_BUFFER Buff
;
1340 LONG OldCursorX
, OldCursorY
;
1341 LONG NewCursorX
, NewCursorY
;
1343 DPRINT("CsrSetCursor\n");
1345 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1346 if (! NT_SUCCESS(Status
))
1348 return Request
->Status
= Status
;
1351 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1352 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1354 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1355 if (! NT_SUCCESS(Status
))
1357 ConioUnlockConsole(Console
);
1358 return Request
->Status
= Status
;
1361 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1362 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1363 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1364 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1366 ConioUnlockScreenBuffer(Buff
);
1367 ConioUnlockConsole(Console
);
1368 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1370 OldCursorX
= Buff
->CurrentX
;
1371 OldCursorY
= Buff
->CurrentY
;
1372 Buff
->CurrentX
= NewCursorX
;
1373 Buff
->CurrentY
= NewCursorY
;
1374 if (Buff
== Console
->ActiveBuffer
)
1376 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1378 ConioUnlockScreenBuffer(Buff
);
1379 ConioUnlockConsole(Console
);
1380 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1384 ConioUnlockScreenBuffer(Buff
);
1385 ConioUnlockConsole(Console
);
1387 return Request
->Status
= STATUS_SUCCESS
;
1390 static VOID FASTCALL
1391 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1393 if (Buff
->MaxX
<= Start
->X
+ Length
)
1395 UpdateRect
->left
= 0;
1399 UpdateRect
->left
= Start
->X
;
1401 if (Buff
->MaxX
<= Start
->X
+ Length
)
1403 UpdateRect
->right
= Buff
->MaxX
- 1;
1407 UpdateRect
->right
= Start
->X
+ Length
- 1;
1409 UpdateRect
->top
= Start
->Y
;
1410 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1411 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1413 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1417 CSR_API(CsrWriteConsoleOutputChar
)
1420 PCHAR String
, tmpString
= NULL
;
1422 PCSRSS_CONSOLE Console
;
1423 PCSRSS_SCREEN_BUFFER Buff
;
1424 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1427 DPRINT("CsrWriteConsoleOutputChar\n");
1429 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1431 if (Request
->Header
.u1
.s1
.TotalLength
1432 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1433 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1435 DPRINT1("Invalid request size\n");
1436 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1437 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1438 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1441 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1442 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1443 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1444 if (NT_SUCCESS(Status
))
1446 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1448 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
1449 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1450 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1451 NULL
, 0, NULL
, NULL
);
1452 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1455 WideCharToMultiByte(Console
->OutputCodePage
, 0,
1456 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1457 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1458 String
, Length
, NULL
, NULL
);
1462 Status
= STATUS_NO_MEMORY
;
1467 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1472 Status
= ConioLockScreenBuffer(ProcessData
,
1473 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1476 if (NT_SUCCESS(Status
))
1478 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
;
1479 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1480 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1481 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1484 *Buffer
= *String
++;
1487 if (++X
== Buff
->MaxX
)
1489 if (++Y
== Buff
->MaxY
)
1492 Buffer
= Buff
->Buffer
;
1497 if (Buff
== Console
->ActiveBuffer
)
1499 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1500 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1501 ConioDrawRegion(Console
, &UpdateRect
);
1504 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
;
1505 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1507 ConioUnlockScreenBuffer(Buff
);
1509 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1511 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1514 ConioUnlockConsole(Console
);
1516 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1517 return Request
->Status
= Status
;
1520 CSR_API(CsrFillOutputChar
)
1523 PCSRSS_CONSOLE Console
;
1524 PCSRSS_SCREEN_BUFFER Buff
;
1525 DWORD X
, Y
, Length
, Written
= 0;
1530 DPRINT("CsrFillOutputChar\n");
1532 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1533 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1535 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1536 if (! NT_SUCCESS(Status
))
1538 return Request
->Status
= Status
;
1541 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1542 if (! NT_SUCCESS(Status
))
1544 ConioUnlockConsole(Console
);
1545 return Request
->Status
= Status
;
1548 X
= Request
->Data
.FillOutputRequest
.Position
.X
;
1549 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1550 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1551 if(Request
->Data
.FillOutputRequest
.Unicode
)
1552 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1554 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1555 Length
= Request
->Data
.FillOutputRequest
.Length
;
1561 if (++X
== Buff
->MaxX
)
1563 if (++Y
== Buff
->MaxY
)
1566 Buffer
= Buff
->Buffer
;
1572 if (Buff
== Console
->ActiveBuffer
)
1574 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1575 Request
->Data
.FillOutputRequest
.Length
);
1576 ConioDrawRegion(Console
, &UpdateRect
);
1579 ConioUnlockScreenBuffer(Buff
);
1580 ConioUnlockConsole(Console
);
1581 Length
= Request
->Data
.FillOutputRequest
.Length
;
1582 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1583 return Request
->Status
;
1586 CSR_API(CsrReadInputEvent
)
1588 PLIST_ENTRY CurrentEntry
;
1589 PCSRSS_CONSOLE Console
;
1591 BOOLEAN Done
= FALSE
;
1592 ConsoleInput
*Input
;
1594 DPRINT("CsrReadInputEvent\n");
1596 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1597 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1598 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1600 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
1601 if (! NT_SUCCESS(Status
))
1603 return Request
->Status
= Status
;
1606 /* only get input if there is any */
1607 CurrentEntry
= Console
->InputEvents
.Flink
;
1608 while (CurrentEntry
!= &Console
->InputEvents
)
1610 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1611 CurrentEntry
= CurrentEntry
->Flink
;
1613 if (Done
&& !Input
->Fake
)
1615 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1619 RemoveEntryList(&Input
->ListEntry
);
1621 if (!Done
&& !Input
->Fake
)
1623 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1624 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1626 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1631 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1633 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1634 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1635 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1637 Console
->WaitingLines
--;
1639 Console
->WaitingChars
--;
1641 HeapFree(Win32CsrApiHeap
, 0, Input
);
1646 Status
= STATUS_SUCCESS
;
1647 Console
->EarlyReturn
= FALSE
;
1651 Status
= STATUS_PENDING
;
1652 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1655 if (IsListEmpty(&Console
->InputEvents
))
1657 ResetEvent(Console
->ActiveEvent
);
1660 ConioUnlockConsole(Console
);
1662 return Request
->Status
= Status
;
1665 CSR_API(CsrWriteConsoleOutputAttrib
)
1667 PCSRSS_CONSOLE Console
;
1668 PCSRSS_SCREEN_BUFFER Buff
;
1675 DPRINT("CsrWriteConsoleOutputAttrib\n");
1677 if (Request
->Header
.u1
.s1
.TotalLength
1678 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1679 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1681 DPRINT1("Invalid request size\n");
1682 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1683 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1684 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1687 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1688 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1689 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1690 if (! NT_SUCCESS(Status
))
1692 return Request
->Status
= Status
;
1695 Status
= ConioLockScreenBuffer(ProcessData
,
1696 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1699 if (! NT_SUCCESS(Status
))
1701 ConioUnlockConsole(Console
);
1702 return Request
->Status
= Status
;
1705 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
;
1706 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1707 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1708 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1709 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1712 *Buffer
= (UCHAR
)(*Attribute
++);
1714 if (++X
== Buff
->MaxX
)
1716 if (++Y
== Buff
->MaxY
)
1719 Buffer
= Buff
->Buffer
+ 1;
1725 if (Buff
== Console
->ActiveBuffer
)
1727 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1728 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1729 ConioDrawRegion(Console
, &UpdateRect
);
1732 ConioUnlockConsole(Console
);
1734 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= X
;
1735 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1737 ConioUnlockScreenBuffer(Buff
);
1739 return Request
->Status
= STATUS_SUCCESS
;
1742 CSR_API(CsrFillOutputAttrib
)
1744 PCSRSS_SCREEN_BUFFER Buff
;
1750 PCSRSS_CONSOLE Console
;
1752 DPRINT("CsrFillOutputAttrib\n");
1754 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1755 if (! NT_SUCCESS(Status
))
1757 return Request
->Status
= Status
;
1760 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1761 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1762 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1763 if (! NT_SUCCESS(Status
))
1765 ConioUnlockConsole(Console
);
1766 return Request
->Status
= Status
;
1769 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
;
1770 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1771 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1772 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1773 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1778 if (++X
== Buff
->MaxX
)
1780 if (++Y
== Buff
->MaxY
)
1783 Buffer
= Buff
->Buffer
+ 1;
1789 if (Buff
== Console
->ActiveBuffer
)
1791 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1792 Request
->Data
.FillOutputAttribRequest
.Length
);
1793 ConioDrawRegion(Console
, &UpdateRect
);
1796 ConioUnlockScreenBuffer(Buff
);
1797 ConioUnlockConsole(Console
);
1799 return Request
->Status
= STATUS_SUCCESS
;
1803 CSR_API(CsrGetCursorInfo
)
1805 PCSRSS_SCREEN_BUFFER Buff
;
1808 DPRINT("CsrGetCursorInfo\n");
1810 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1811 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1813 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1814 if (! NT_SUCCESS(Status
))
1816 return Request
->Status
= Status
;
1818 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1819 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1820 ConioUnlockScreenBuffer(Buff
);
1822 return Request
->Status
= STATUS_SUCCESS
;
1825 CSR_API(CsrSetCursorInfo
)
1827 PCSRSS_CONSOLE Console
;
1828 PCSRSS_SCREEN_BUFFER Buff
;
1833 DPRINT("CsrSetCursorInfo\n");
1835 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1836 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1838 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1839 if (! NT_SUCCESS(Status
))
1841 return Request
->Status
= Status
;
1844 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1845 if (! NT_SUCCESS(Status
))
1847 ConioUnlockConsole(Console
);
1848 return Request
->Status
= Status
;
1851 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1852 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1862 if (Size
!= Buff
->CursorInfo
.dwSize
1863 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1865 Buff
->CursorInfo
.dwSize
= Size
;
1866 Buff
->CursorInfo
.bVisible
= Visible
;
1868 if (! ConioSetCursorInfo(Console
, Buff
))
1870 ConioUnlockScreenBuffer(Buff
);
1871 ConioUnlockConsole(Console
);
1872 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1876 ConioUnlockScreenBuffer(Buff
);
1877 ConioUnlockConsole(Console
);
1879 return Request
->Status
= STATUS_SUCCESS
;
1882 CSR_API(CsrSetTextAttrib
)
1885 PCSRSS_CONSOLE Console
;
1886 PCSRSS_SCREEN_BUFFER Buff
;
1888 DPRINT("CsrSetTextAttrib\n");
1890 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1891 if (! NT_SUCCESS(Status
))
1893 return Request
->Status
= Status
;
1896 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1897 if (! NT_SUCCESS(Status
))
1899 ConioUnlockConsole(Console
);
1900 return Request
->Status
= Status
;
1903 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1904 if (Buff
== Console
->ActiveBuffer
)
1906 if (! ConioUpdateScreenInfo(Console
, Buff
))
1908 ConioUnlockScreenBuffer(Buff
);
1909 ConioUnlockConsole(Console
);
1910 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1914 ConioUnlockScreenBuffer(Buff
);
1915 ConioUnlockConsole(Console
);
1917 return Request
->Status
= STATUS_SUCCESS
;
1920 CSR_API(CsrSetConsoleMode
)
1923 PCSRSS_CONSOLE Console
;
1924 PCSRSS_SCREEN_BUFFER Buff
;
1926 DPRINT("CsrSetConsoleMode\n");
1928 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1929 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1930 Status
= Win32CsrGetObject(ProcessData
,
1931 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
1932 (Object_t
**) &Console
, GENERIC_WRITE
);
1933 if (! NT_SUCCESS(Status
))
1935 return Request
->Status
= Status
;
1938 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1939 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1941 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
1943 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
1945 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
1949 Status
= STATUS_INVALID_HANDLE
;
1952 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1954 return Request
->Status
= Status
;
1957 CSR_API(CsrGetConsoleMode
)
1960 PCSRSS_CONSOLE Console
;
1961 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
1963 DPRINT("CsrGetConsoleMode\n");
1965 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1966 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1967 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
1968 (Object_t
**) &Console
, GENERIC_READ
);
1969 if (! NT_SUCCESS(Status
))
1971 return Request
->Status
= Status
;
1973 Request
->Status
= STATUS_SUCCESS
;
1974 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
1975 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1977 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
1979 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
1981 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
1985 Request
->Status
= STATUS_INVALID_HANDLE
;
1988 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1989 return Request
->Status
;
1992 CSR_API(CsrCreateScreenBuffer
)
1994 PCSRSS_CONSOLE Console
;
1995 PCSRSS_SCREEN_BUFFER Buff
;
1998 DPRINT("CsrCreateScreenBuffer\n");
2000 if (ProcessData
== NULL
)
2002 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2005 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2006 if (! NT_SUCCESS(Status
))
2008 return Request
->Status
= Status
;
2011 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2012 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2014 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
2018 if (Console
->ActiveBuffer
)
2020 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
2021 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
2022 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
2023 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
2027 Buff
->CursorInfo
.bVisible
= TRUE
;
2028 Buff
->CursorInfo
.dwSize
= 5;
2031 if (Buff
->MaxX
== 0)
2036 if (Buff
->MaxY
== 0)
2041 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2042 if(! NT_SUCCESS(Status
))
2044 Request
->Status
= Status
;
2048 Request
->Status
= Win32CsrInsertObject(ProcessData
,
2049 &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
,
2051 Request
->Data
.CreateScreenBufferRequest
.Access
,
2052 Request
->Data
.CreateScreenBufferRequest
.Inheritable
);
2057 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2060 ConioUnlockConsole(Console
);
2061 return Request
->Status
;
2064 CSR_API(CsrSetScreenBuffer
)
2067 PCSRSS_CONSOLE Console
;
2068 PCSRSS_SCREEN_BUFFER Buff
;
2070 DPRINT("CsrSetScreenBuffer\n");
2072 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2073 if (! NT_SUCCESS(Status
))
2075 return Request
->Status
= Status
;
2078 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2079 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2081 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
, GENERIC_WRITE
);
2082 if (! NT_SUCCESS(Status
))
2084 ConioUnlockConsole(Console
);
2085 return Request
->Status
= Status
;
2088 if (Buff
== Console
->ActiveBuffer
)
2090 ConioUnlockScreenBuffer(Buff
);
2091 ConioUnlockConsole(Console
);
2092 return Request
->Status
= STATUS_SUCCESS
;
2095 /* drop reference to old buffer, maybe delete */
2096 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2098 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2100 /* tie console to new buffer */
2101 Console
->ActiveBuffer
= Buff
;
2102 /* inc ref count on new buffer */
2103 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2104 /* Redraw the console */
2105 ConioDrawConsole(Console
);
2107 ConioUnlockScreenBuffer(Buff
);
2108 ConioUnlockConsole(Console
);
2110 return Request
->Status
= STATUS_SUCCESS
;
2113 CSR_API(CsrSetTitle
)
2116 PCSRSS_CONSOLE Console
;
2119 DPRINT("CsrSetTitle\n");
2121 if (Request
->Header
.u1
.s1
.TotalLength
2122 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2123 + Request
->Data
.SetTitleRequest
.Length
)
2125 DPRINT1("Invalid request size\n");
2126 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2127 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2128 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2131 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2132 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2133 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2134 if(! NT_SUCCESS(Status
))
2136 Request
->Status
= Status
;
2140 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2143 /* copy title to console */
2144 RtlFreeUnicodeString(&Console
->Title
);
2145 Console
->Title
.Buffer
= Buffer
;
2146 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2147 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2148 if (! ConioChangeTitle(Console
))
2150 Request
->Status
= STATUS_UNSUCCESSFUL
;
2154 Request
->Status
= STATUS_SUCCESS
;
2159 Request
->Status
= STATUS_NO_MEMORY
;
2161 ConioUnlockConsole(Console
);
2164 return Request
->Status
;
2167 CSR_API(CsrGetTitle
)
2170 PCSRSS_CONSOLE Console
;
2173 DPRINT("CsrGetTitle\n");
2175 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2176 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2177 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2178 if (! NT_SUCCESS(Status
))
2180 DPRINT1("Can't get console\n");
2181 return Request
->Status
= Status
;
2184 /* Copy title of the console to the user title buffer */
2185 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2186 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2187 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2188 Console
->Title
.Length
);
2189 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2191 ConioUnlockConsole(Console
);
2193 if (Length
> sizeof(CSR_API_MESSAGE
))
2195 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2196 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2198 Request
->Status
= STATUS_SUCCESS
;
2200 return Request
->Status
;
2203 CSR_API(CsrWriteConsoleOutput
)
2205 SHORT i
, X
, Y
, SizeX
, SizeY
;
2206 PCSRSS_CONSOLE Console
;
2207 PCSRSS_SCREEN_BUFFER Buff
;
2209 CHAR_INFO
* CurCharInfo
;
2211 CHAR_INFO
* CharInfo
;
2218 DPRINT("CsrWriteConsoleOutput\n");
2220 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2221 if (! NT_SUCCESS(Status
))
2223 return Request
->Status
= Status
;
2226 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2227 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2228 Status
= ConioLockScreenBuffer(ProcessData
,
2229 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2232 if (! NT_SUCCESS(Status
))
2234 ConioUnlockConsole(Console
);
2235 return Request
->Status
= Status
;
2238 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2239 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2240 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2241 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2242 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2243 (((ULONG_PTR
)CharInfo
+ PSize
) >
2244 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2246 ConioUnlockScreenBuffer(Buff
);
2247 ConioUnlockConsole(Console
);
2248 return Request
->Status
= STATUS_ACCESS_VIOLATION
;
2250 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2251 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2252 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2253 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2255 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2256 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2257 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2258 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2260 /* Make sure WriteRegion is inside the screen buffer */
2261 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2262 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2264 ConioUnlockScreenBuffer(Buff
);
2265 ConioUnlockConsole(Console
);
2267 /* It is okay to have a WriteRegion completely outside the screen buffer.
2268 No data is written then. */
2269 return Request
->Status
= STATUS_SUCCESS
;
2272 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2274 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2275 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.left
, Y
);
2276 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2279 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2281 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2285 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
2288 *Ptr
++ = CurCharInfo
->Attributes
;
2293 ConioDrawRegion(Console
, &WriteRegion
);
2295 ConioUnlockScreenBuffer(Buff
);
2296 ConioUnlockConsole(Console
);
2298 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2299 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2300 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2301 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2303 return Request
->Status
= STATUS_SUCCESS
;
2306 CSR_API(CsrFlushInputBuffer
)
2308 PLIST_ENTRY CurrentEntry
;
2309 PCSRSS_CONSOLE Console
;
2310 ConsoleInput
* Input
;
2313 DPRINT("CsrFlushInputBuffer\n");
2315 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2316 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2317 Status
= ConioLockConsole(ProcessData
,
2318 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2321 if(! NT_SUCCESS(Status
))
2323 return Request
->Status
= Status
;
2326 /* Discard all entries in the input event queue */
2327 while (!IsListEmpty(&Console
->InputEvents
))
2329 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2330 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2331 /* Destroy the event */
2332 HeapFree(Win32CsrApiHeap
, 0, Input
);
2334 ResetEvent(Console
->ActiveEvent
);
2335 Console
->WaitingChars
=0;
2337 ConioUnlockConsole(Console
);
2339 return Request
->Status
= STATUS_SUCCESS
;
2342 CSR_API(CsrScrollConsoleScreenBuffer
)
2344 PCSRSS_CONSOLE Console
;
2345 PCSRSS_SCREEN_BUFFER Buff
;
2350 RECT ScrollRectangle
;
2353 HANDLE ConsoleHandle
;
2354 BOOLEAN UseClipRectangle
;
2355 COORD DestinationOrigin
;
2359 DPRINT("CsrScrollConsoleScreenBuffer\n");
2361 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
2362 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
2363 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
2364 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
2366 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2367 if (! NT_SUCCESS(Status
))
2369 return Request
->Status
= Status
;
2372 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2373 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2374 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
2375 if (! NT_SUCCESS(Status
))
2377 ConioUnlockConsole(Console
);
2378 return Request
->Status
= Status
;
2381 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2382 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2383 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2384 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2386 /* Make sure source rectangle is inside the screen buffer */
2387 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2388 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2390 ConioUnlockScreenBuffer(Buff
);
2391 ConioUnlockConsole(Console
);
2392 return Request
->Status
= STATUS_SUCCESS
;
2395 /* If the source was clipped on the left or top, adjust the destination accordingly */
2396 if (ScrollRectangle
.left
< 0)
2398 DestinationOrigin
.X
-= ScrollRectangle
.left
;
2400 if (ScrollRectangle
.top
< 0)
2402 DestinationOrigin
.Y
-= ScrollRectangle
.top
;
2405 if (UseClipRectangle
)
2407 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2408 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2409 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2410 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2411 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
2413 ConioUnlockConsole(Console
);
2414 ConioUnlockScreenBuffer(Buff
);
2415 return Request
->Status
= STATUS_SUCCESS
;
2420 ClipRectangle
= ScreenBuffer
;
2423 ConioInitRect(&DstRegion
,
2424 DestinationOrigin
.Y
,
2425 DestinationOrigin
.X
,
2426 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
2427 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
2429 if (Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
)
2430 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
2432 FillChar
= Fill
.Char
.AsciiChar
;
2434 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
2436 if (Buff
== Console
->ActiveBuffer
)
2438 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
2439 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
2441 /* Draw update region */
2442 ConioDrawRegion(Console
, &UpdateRegion
);
2446 ConioUnlockScreenBuffer(Buff
);
2447 ConioUnlockConsole(Console
);
2449 return Request
->Status
= STATUS_SUCCESS
;
2452 CSR_API(CsrReadConsoleOutputChar
)
2455 PCSRSS_CONSOLE Console
;
2456 PCSRSS_SCREEN_BUFFER Buff
;
2463 DPRINT("CsrReadConsoleOutputChar\n");
2465 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2466 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2467 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2469 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2471 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2472 if (! NT_SUCCESS(Status
))
2474 return Request
->Status
= Status
;
2477 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2478 if (! NT_SUCCESS(Status
))
2480 ConioUnlockConsole(Console
);
2481 return Request
->Status
= Status
;
2484 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
;
2485 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2487 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2489 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2491 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2493 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2494 ReadBuffer
+= sizeof(WCHAR
);
2497 *(ReadBuffer
++) = Char
;
2501 if (Xpos
== Buff
->MaxX
)
2506 if (Ypos
== Buff
->MaxY
)
2514 Request
->Status
= STATUS_SUCCESS
;
2515 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
;
2516 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2518 ConioUnlockScreenBuffer(Buff
);
2519 ConioUnlockConsole(Console
);
2521 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2522 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2524 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2525 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2528 return Request
->Status
;
2532 CSR_API(CsrReadConsoleOutputAttrib
)
2535 PCSRSS_SCREEN_BUFFER Buff
;
2539 DWORD CurrentLength
;
2541 DPRINT("CsrReadConsoleOutputAttrib\n");
2543 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2544 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2545 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2547 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2548 if (! NT_SUCCESS(Status
))
2550 return Request
->Status
= Status
;
2553 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
;
2554 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2556 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2558 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2563 if (Xpos
== Buff
->MaxX
)
2568 if (Ypos
== Buff
->MaxY
)
2577 Request
->Status
= STATUS_SUCCESS
;
2578 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
;
2579 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2581 ConioUnlockScreenBuffer(Buff
);
2583 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2584 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2585 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2587 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2588 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2591 return Request
->Status
;
2595 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2598 PCSRSS_CONSOLE Console
;
2599 PLIST_ENTRY CurrentItem
;
2601 ConsoleInput
*Input
;
2603 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2605 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2606 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2608 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2609 if (! NT_SUCCESS(Status
))
2611 return Request
->Status
= Status
;
2614 CurrentItem
= Console
->InputEvents
.Flink
;
2617 /* If there are any events ... */
2618 while (CurrentItem
!= &Console
->InputEvents
)
2620 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2621 CurrentItem
= CurrentItem
->Flink
;
2628 ConioUnlockConsole(Console
);
2630 Request
->Status
= STATUS_SUCCESS
;
2631 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2633 return Request
->Status
;
2637 CSR_API(CsrPeekConsoleInput
)
2640 PCSRSS_CONSOLE Console
;
2643 PLIST_ENTRY CurrentItem
;
2644 PINPUT_RECORD InputRecord
;
2648 DPRINT("CsrPeekConsoleInput\n");
2650 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2651 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2653 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2654 if(! NT_SUCCESS(Status
))
2656 return Request
->Status
= Status
;
2659 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2660 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2661 Size
= Length
* sizeof(INPUT_RECORD
);
2663 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2664 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2666 ConioUnlockConsole(Console
);
2667 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2668 return Request
->Status
;
2673 if (! IsListEmpty(&Console
->InputEvents
))
2675 CurrentItem
= Console
->InputEvents
.Flink
;
2677 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2679 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2683 CurrentItem
= CurrentItem
->Flink
;
2688 *InputRecord
= Item
->InputEvent
;
2690 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2692 ConioInputEventToAnsi(Console
, InputRecord
);
2696 CurrentItem
= CurrentItem
->Flink
;
2700 ConioUnlockConsole(Console
);
2702 Request
->Status
= STATUS_SUCCESS
;
2703 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2705 return Request
->Status
;
2709 CSR_API(CsrReadConsoleOutput
)
2711 PCHAR_INFO CharInfo
;
2712 PCHAR_INFO CurCharInfo
;
2713 PCSRSS_SCREEN_BUFFER Buff
;
2727 DPRINT("CsrReadConsoleOutput\n");
2729 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2730 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2732 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2733 if (! NT_SUCCESS(Status
))
2735 return Request
->Status
= Status
;
2738 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2739 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2740 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2741 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2742 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2743 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2744 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2745 Length
= BufferSize
.X
* BufferSize
.Y
;
2746 Size
= Length
* sizeof(CHAR_INFO
);
2748 /* FIXME: Is this correct? */
2749 CodePage
= ProcessData
->Console
->OutputCodePage
;
2751 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2752 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2754 ConioUnlockScreenBuffer(Buff
);
2755 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2756 return Request
->Status
;
2759 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2760 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2761 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2762 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2764 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2765 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2767 ConioUnlockScreenBuffer(Buff
);
2768 Request
->Status
= STATUS_SUCCESS
;
2769 return Request
->Status
;
2772 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2774 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2776 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.left
, Y
);
2777 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2779 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2781 MultiByteToWideChar(CodePage
, 0,
2783 &CurCharInfo
->Char
.UnicodeChar
, 1);
2787 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
2789 CurCharInfo
->Attributes
= *Ptr
++;
2794 ConioUnlockScreenBuffer(Buff
);
2796 Request
->Status
= STATUS_SUCCESS
;
2797 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2798 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2799 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2800 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2802 return Request
->Status
;
2806 CSR_API(CsrWriteConsoleInput
)
2808 PINPUT_RECORD InputRecord
;
2809 PCSRSS_CONSOLE Console
;
2814 ConsoleInput
* Record
;
2816 DPRINT("CsrWriteConsoleInput\n");
2818 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2819 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2821 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
, GENERIC_WRITE
);
2822 if (! NT_SUCCESS(Status
))
2824 return Request
->Status
= Status
;
2827 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2828 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2829 Size
= Length
* sizeof(INPUT_RECORD
);
2831 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2832 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2834 ConioUnlockConsole(Console
);
2835 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2836 return Request
->Status
;
2839 for (i
= 0; i
< Length
; i
++)
2841 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2844 ConioUnlockConsole(Console
);
2845 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2846 return Request
->Status
;
2849 Record
->Echoed
= FALSE
;
2850 Record
->Fake
= FALSE
;
2851 //Record->InputEvent = *InputRecord++;
2852 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
2853 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2855 /* FIXME - convert from unicode to ascii!! */
2856 ConioProcessChar(Console
, Record
);
2860 ConioUnlockConsole(Console
);
2862 Request
->Status
= STATUS_SUCCESS
;
2863 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2865 return Request
->Status
;
2868 /**********************************************************************
2869 * HardwareStateProperty
2872 * Set/Get the value of the HardwareState and switch
2873 * between direct video buffer ouput and GDI windowed
2876 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2877 * object. We use the same object to Request.
2879 * ConsoleHwState has the correct size to be compatible
2880 * with NT's, but values are not.
2882 static NTSTATUS FASTCALL
2883 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2885 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2887 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2888 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2890 if (Console
->HardwareState
!= ConsoleHwState
)
2892 /* TODO: implement switching from full screen to windowed mode */
2893 /* TODO: or back; now simply store the hardware state */
2894 Console
->HardwareState
= ConsoleHwState
;
2897 return STATUS_SUCCESS
;
2900 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2903 CSR_API(CsrHardwareStateProperty
)
2905 PCSRSS_CONSOLE Console
;
2908 DPRINT("CsrHardwareStateProperty\n");
2910 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2911 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2913 Status
= ConioLockConsole(ProcessData
,
2914 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2917 if (! NT_SUCCESS(Status
))
2919 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2920 return Request
->Status
= Status
;
2923 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2925 case CONSOLE_HARDWARE_STATE_GET
:
2926 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
2929 case CONSOLE_HARDWARE_STATE_SET
:
2930 DPRINT("Setting console hardware state.\n");
2931 Request
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2935 Request
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2939 ConioUnlockConsole(Console
);
2941 return Request
->Status
;
2944 CSR_API(CsrGetConsoleWindow
)
2946 PCSRSS_CONSOLE Console
;
2949 DPRINT("CsrGetConsoleWindow\n");
2951 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2952 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2954 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2955 if (! NT_SUCCESS(Status
))
2957 return Request
->Status
= Status
;
2960 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
2961 ConioUnlockConsole(Console
);
2963 return Request
->Status
= STATUS_SUCCESS
;
2966 CSR_API(CsrSetConsoleIcon
)
2968 PCSRSS_CONSOLE Console
;
2971 DPRINT("CsrSetConsoleIcon\n");
2973 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2974 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2976 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2977 if (! NT_SUCCESS(Status
))
2979 return Request
->Status
= Status
;
2982 Request
->Status
= (ConioChangeIcon(Console
, Request
->Data
.SetConsoleIconRequest
.WindowIcon
)
2983 ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
2984 ConioUnlockConsole(Console
);
2986 return Request
->Status
;
2989 CSR_API(CsrGetConsoleCodePage
)
2991 PCSRSS_CONSOLE Console
;
2994 DPRINT("CsrGetConsoleCodePage\n");
2996 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2997 if (! NT_SUCCESS(Status
))
2999 return Request
->Status
= Status
;
3002 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3003 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3004 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3005 ConioUnlockConsole(Console
);
3006 return Request
->Status
= STATUS_SUCCESS
;
3009 CSR_API(CsrSetConsoleCodePage
)
3011 PCSRSS_CONSOLE Console
;
3014 DPRINT("CsrSetConsoleCodePage\n");
3016 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3017 if (! NT_SUCCESS(Status
))
3019 return Request
->Status
= Status
;
3022 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3023 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3024 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3026 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3027 ConioUnlockConsole(Console
);
3028 return Request
->Status
= STATUS_SUCCESS
;
3030 ConioUnlockConsole(Console
);
3031 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3034 CSR_API(CsrGetConsoleOutputCodePage
)
3036 PCSRSS_CONSOLE Console
;
3039 DPRINT("CsrGetConsoleOutputCodePage\n");
3041 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3042 if (! NT_SUCCESS(Status
))
3044 return Request
->Status
= Status
;
3047 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3048 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3049 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3050 ConioUnlockConsole(Console
);
3051 return Request
->Status
= STATUS_SUCCESS
;
3054 CSR_API(CsrSetConsoleOutputCodePage
)
3056 PCSRSS_CONSOLE Console
;
3059 DPRINT("CsrSetConsoleOutputCodePage\n");
3061 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3062 if (! NT_SUCCESS(Status
))
3064 return Request
->Status
= Status
;
3067 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3068 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3069 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3071 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3072 ConioUnlockConsole(Console
);
3073 return Request
->Status
= STATUS_SUCCESS
;
3075 ConioUnlockConsole(Console
);
3076 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3079 CSR_API(CsrGetProcessList
)
3082 PCSRSS_CONSOLE Console
;
3083 PCSRSS_PROCESS_DATA current
;
3084 PLIST_ENTRY current_entry
;
3085 ULONG nItems
, nCopied
, Length
;
3088 DPRINT("CsrGetProcessList\n");
3090 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3091 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3092 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3094 nItems
= nCopied
= 0;
3095 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3096 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3098 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3099 if (! NT_SUCCESS(Status
))
3101 return Request
->Status
= Status
;
3104 DPRINT1("Console_Api Ctrl-C\n");
3106 for(current_entry
= Console
->ProcessList
.Flink
;
3107 current_entry
!= &Console
->ProcessList
;
3108 current_entry
= current_entry
->Flink
)
3110 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3111 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3113 *(Buffer
++) = current
->ProcessId
;
3118 ConioUnlockConsole(Console
);
3120 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3121 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3123 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3124 if (Length
> sizeof(CSR_API_MESSAGE
))
3126 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3127 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3129 return Request
->Status
= STATUS_SUCCESS
;