Fixed compiler warning
[reactos.git] / reactos / subsys / csrss / api / conio.c
1 /* $Id: conio.c,v 1.12 2000/10/09 00:12:01 ekohl Exp $
2 *
3 * reactos/subsys/csrss/api/conio.c
4 *
5 * Console I/O functions
6 *
7 * ReactOS Operating System
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ddk/ntddk.h>
13
14 #include <csrss/csrss.h>
15 #include "api.h"
16 #include <ntdll/rtl.h>
17 #include <ddk/ntddblue.h>
18 #include <debug.h>
19
20 /* GLOBALS *******************************************************************/
21
22 static HANDLE ConsoleDeviceHandle;
23 static HANDLE KeyboardDeviceHandle;
24 static PCSRSS_CONSOLE ActiveConsole;
25 CRITICAL_SECTION ActiveConsoleLock;
26 static COORD PhysicalConsoleSize;
27
28 /* FUNCTIONS *****************************************************************/
29
30 NTSTATUS CsrAllocConsole(PCSRSS_PROCESS_DATA ProcessData,
31 PCSRSS_API_REQUEST LpcMessage,
32 PCSRSS_API_REPLY LpcReply)
33 {
34 PCSRSS_CONSOLE Console;
35 HANDLE Process;
36 NTSTATUS Status;
37 CLIENT_ID ClientId;
38
39 LpcReply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
40 LpcReply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
41 sizeof(LPC_MESSAGE_HEADER);
42 if( ProcessData->Console )
43 {
44 LpcReply->Status = STATUS_INVALID_PARAMETER;
45 return STATUS_INVALID_PARAMETER;
46 }
47 LpcReply->Status = STATUS_SUCCESS;
48 Console = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( CSRSS_CONSOLE ) );
49 if( Console == 0 )
50 {
51 LpcReply->Status = STATUS_INSUFFICIENT_RESOURCES;
52 return STATUS_INSUFFICIENT_RESOURCES;
53 }
54 LpcReply->Status = CsrInitConsole( ProcessData, Console );
55 if( !NT_SUCCESS( LpcReply->Status ) )
56 {
57 RtlFreeHeap( CsrssApiHeap, 0, Console );
58 return LpcReply->Status;
59 }
60 ProcessData->Console = Console;
61 Console->ReferenceCount++;
62 CsrInsertObject( ProcessData, &LpcReply->Data.AllocConsoleReply.ConsoleHandle, (Object_t *)Console );
63 ClientId.UniqueProcess = (HANDLE)ProcessData->ProcessId;
64 Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId );
65 if( !NT_SUCCESS( Status ) )
66 {
67 DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" );
68 Console->ReferenceCount--;
69 ProcessData->Console = 0;
70 CsrReleaseObject( ProcessData, LpcReply->Data.AllocConsoleReply.ConsoleHandle );
71 LpcReply->Status = Status;
72 return Status;
73 }
74 Status = NtDuplicateObject( NtCurrentProcess(), &ProcessData->Console->ActiveEvent, Process, &ProcessData->ConsoleEvent, SYNCHRONIZE, FALSE, 0 );
75 if( !NT_SUCCESS( Status ) )
76 {
77 DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status );
78 NtClose( Process );
79 Console->ReferenceCount--;
80 CsrReleaseObject( ProcessData, LpcReply->Data.AllocConsoleReply.ConsoleHandle );
81 ProcessData->Console = 0;
82 LpcReply->Status = Status;
83 return Status;
84 }
85 NtClose( Process );
86 return STATUS_SUCCESS;
87 }
88
89 NTSTATUS CsrFreeConsole(PCSRSS_PROCESS_DATA ProcessData,
90 PCSRSS_API_REQUEST LpcMessage,
91 PCSRSS_API_REPLY LpcReply)
92 {
93 LpcReply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
94 LpcReply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
95 sizeof(LPC_MESSAGE_HEADER);
96
97 LpcReply->Status = STATUS_NOT_IMPLEMENTED;
98
99 return(STATUS_NOT_IMPLEMENTED);
100 }
101
102 NTSTATUS CsrReadConsole(PCSRSS_PROCESS_DATA ProcessData,
103 PCSRSS_API_REQUEST LpcMessage,
104 PCSRSS_API_REPLY LpcReply)
105 {
106 ConsoleInput *Input;
107 PCHAR Buffer;
108 int i = 0;
109 ULONG nNumberOfCharsToRead;
110 PCSRSS_CONSOLE Console;
111 NTSTATUS Status;
112
113 nNumberOfCharsToRead = LpcMessage->Data.ReadConsoleRequest.NrCharactersToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : LpcMessage->Data.ReadConsoleRequest.NrCharactersToRead;
114
115 // DbgPrint("CSR: NrCharactersToRead %d\n", nNumberOfCharsToRead);
116
117 LpcReply->Header.MessageSize = sizeof(CSRSS_API_REPLY) +
118 nNumberOfCharsToRead;
119 LpcReply->Header.DataSize = LpcReply->Header.MessageSize -
120 sizeof(LPC_MESSAGE_HEADER);
121 Buffer = LpcReply->Data.ReadConsoleReply.Buffer;
122 LpcReply->Data.ReadConsoleReply.EventHandle = ProcessData->ConsoleEvent;
123
124 Status = CsrGetObject( ProcessData, LpcMessage->Data.ReadConsoleRequest.ConsoleHandle, (Object_t **)&Console );
125 if( !NT_SUCCESS( Status ) )
126 {
127 LpcReply->Status = Status;
128 return Status;
129 }
130 RtlEnterCriticalSection( &ActiveConsoleLock );
131 if( !(Console->ConsoleMode & ENABLE_LINE_INPUT) || Console->WaitingLines )
132 for (; i<nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++ )
133 {
134 // remove input event from queue
135 Input = (ConsoleInput *)Console->InputEvents.Flink;
136 Input->ListEntry.Blink->Flink = Input->ListEntry.Flink;
137 Input->ListEntry.Flink->Blink = Input->ListEntry.Blink;
138 // only pay attention to valid ascii chars, on key down
139 if( Input->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
140 Input->InputEvent.Event.KeyEvent.uChar.AsciiChar )
141 {
142 Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
143 // process newline on line buffered mode
144 if( Console->ConsoleMode & ENABLE_LINE_INPUT &&
145 Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
146 {
147 Console->WaitingChars--;
148 Console->WaitingLines--;
149 RtlFreeHeap( CsrssApiHeap, 0, Input );
150 i++;
151 break;
152 }
153 }
154 else i--;
155 Console->WaitingChars--;
156 RtlFreeHeap( CsrssApiHeap, 0, Input );
157 }
158 Buffer[i] = 0;
159 RtlLeaveCriticalSection( &ActiveConsoleLock );
160 LpcReply->Data.ReadConsoleReply.NrCharactersRead = i;
161 LpcReply->Status = i ? STATUS_SUCCESS : STATUS_PENDING;
162 return(Status);
163 }
164
165
166
167 NTSTATUS CsrpWriteConsole( PCSRSS_CONSOLE Console, CHAR *Buffer, DWORD Length, BOOL Attrib )
168 {
169 IO_STATUS_BLOCK Iosb;
170 NTSTATUS Status;
171 int i;
172
173 for( i = 0; i < Length; i++ )
174 {
175 switch( Buffer[ i ] )
176 {
177 case '\n': {
178 int c;
179 Console->CurrentX = 0;
180 /* slide the viewable screen */
181 if( ((PhysicalConsoleSize.Y + Console->ShowY) % Console->MaxY) == (Console->CurrentY + 1) % Console->MaxY)
182 if( ++Console->ShowY == (Console->MaxY - 1) )
183 Console->ShowY = 0;
184 if( ++Console->CurrentY == Console->MaxY )
185 {
186 Console->CurrentY = 0;
187 for( c = 0; c < Console->MaxX; c++ )
188 {
189 /* clear new line */
190 Console->Buffer[ c * 2 ] = ' ';
191 Console->Buffer[ (c * 2) + 1 ] = Console->DefaultAttrib;
192 }
193 }
194 else for( c = 0; c < Console->MaxX; c++ )
195 {
196 /* clear new line */
197 Console->Buffer[ 2 * ((Console->CurrentY * Console->MaxX) + c) ] = ' ';
198 Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + c)) + 1 ] = Console->DefaultAttrib;
199 }
200 break;
201 }
202 case '\b': {
203 if( Console->CurrentX == 0 )
204 {
205 /* slide viewable screen up */
206 if( Console->ShowY == Console->CurrentY )
207 {
208 if( Console->ShowY == 0 )
209 Console->ShowY = Console->MaxY;
210 else
211 Console->ShowY--;
212 }
213 /* slide virtual position up */
214 Console->CurrentX = Console->MaxX;
215 if( Console->CurrentY == 0 )
216 Console->CurrentY = Console->MaxY;
217 else
218 Console->CurrentY--;
219 }
220 else
221 Console->CurrentX--;
222 Console->Buffer[ 2 * ((Console->CurrentY * Console->MaxX) + Console->CurrentX) ] = ' ';
223 Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + Console->CurrentX)) + 1 ] = Console->DefaultAttrib;
224 break;
225 }
226 default: {
227 int c;
228 Console->Buffer[ 2 * (((Console->CurrentY * Console->MaxX)) + Console->CurrentX) ] = Buffer[ i ];
229 if( Attrib )
230 Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + Console->CurrentX)) + 1 ] = Console->DefaultAttrib;
231 Console->CurrentX++;
232 if( Console->CurrentX == Console->MaxX )
233 {
234 /* if end of line, go to next */
235 Console->CurrentX = 0;
236 if( ++Console->CurrentY == Console->MaxY )
237 {
238 /* if end of buffer, wrap back to beginning */
239 Console->CurrentY = 0;
240 /* clear new line */
241 for( c = 0; c < Console->MaxX; c++ )
242 {
243 Console->Buffer[ 2 * ((Console->CurrentY * Console->MaxX) + c) ] = ' ';
244 Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + c)) + 1 ] = Console->DefaultAttrib;
245 }
246 }
247 else {
248 /* clear new line */
249 for( c = 0; c < Console->MaxX; c += 2 )
250 {
251 Console->Buffer[ 2 * ((Console->CurrentY * Console->MaxX) + c) ] = ' ';
252 Console->Buffer[ (2 * ((Console->CurrentY * Console->MaxX) + c)) + 1 ] = Console->DefaultAttrib;
253 }
254 }
255 /* slide the viewable screen */
256 if( (Console->CurrentY - Console->ShowY) == PhysicalConsoleSize.Y )
257 if( ++Console->ShowY == Console->MaxY )
258 Console->ShowY = 0;
259 }
260 }
261 }
262 }
263 if( Console == ActiveConsole )
264 { /* only write to screen if Console is Active, and not scrolled up */
265 if( Attrib )
266 {
267 Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, Buffer, Length, NULL, 0);
268 if (!NT_SUCCESS(Status))
269 DbgPrint("CSR: Write failed\n");
270 }
271 else CsrDrawConsole( Console );
272 }
273 return(STATUS_SUCCESS);
274 }
275
276 NTSTATUS CsrWriteConsole(PCSRSS_PROCESS_DATA ProcessData,
277 PCSRSS_API_REQUEST LpcMessage,
278 PCSRSS_API_REPLY Reply)
279 {
280 BYTE *Buffer = LpcMessage->Data.WriteConsoleRequest.Buffer;
281 PCSRSS_CONSOLE Console;
282
283 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
284 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
285 sizeof(LPC_MESSAGE_HEADER);
286
287 if( !NT_SUCCESS( CsrGetObject( ProcessData, LpcMessage->Data.WriteConsoleRequest.ConsoleHandle, (Object_t **)&Console ) ) )
288 return Reply->Status = STATUS_INVALID_HANDLE;
289 RtlEnterCriticalSection( &ActiveConsoleLock );
290 CsrpWriteConsole( Console, Buffer, LpcMessage->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE );
291 RtlLeaveCriticalSection( &ActiveConsoleLock );
292 return Reply->Status = STATUS_SUCCESS;
293 }
294
295
296 NTSTATUS CsrInitConsole(PCSRSS_PROCESS_DATA ProcessData,
297 PCSRSS_CONSOLE Console)
298 {
299 NTSTATUS Status;
300
301 Console->MaxX = PhysicalConsoleSize.X;
302 Console->MaxY = PhysicalConsoleSize.Y * 2;
303 Console->ShowX = 0;
304 Console->ShowY = 0;
305 Console->CurrentX = 0;
306 Console->CurrentY = 0;
307 Console->ReferenceCount = 0;
308 Console->WaitingChars = 0;
309 Console->WaitingLines = 0;
310 Console->Type = CSRSS_CONSOLE_MAGIC;
311 Console->ConsoleMode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
312 Console->Buffer = RtlAllocateHeap( CsrssApiHeap, 0, Console->MaxX * Console->MaxY * 2 );
313 if( Console->Buffer == 0 )
314 return STATUS_INSUFFICIENT_RESOURCES;
315 Console->InputEvents.Flink = Console->InputEvents.Blink = &Console->InputEvents;
316 Status = NtCreateEvent( &Console->ActiveEvent, STANDARD_RIGHTS_ALL, 0, FALSE, FALSE );
317 if( !NT_SUCCESS( Status ) )
318 {
319 RtlFreeHeap( CsrssApiHeap, 0, Console->Buffer );
320 return Status;
321 }
322 Console->DefaultAttrib = 0x17;
323 /* initialize buffer to be empty with default attributes */
324 for( ; Console->CurrentY < Console->MaxY; Console->CurrentY++ )
325 {
326 for( ; Console->CurrentX < Console->MaxX; Console->CurrentX++ )
327 {
328 Console->Buffer[ (Console->CurrentX * 2) + (Console->CurrentY * Console->MaxX * 2) ] = ' ';
329 Console->Buffer[ (Console->CurrentX * 2) + (Console->CurrentY * Console->MaxX * 2)+ 1 ] = Console->DefaultAttrib;
330 }
331 Console->CurrentX = 0;
332 }
333 Console->CursorInfo.bVisible = TRUE;
334 Console->CursorInfo.dwSize = 5;
335 /* make console active, and insert into console list */
336 RtlEnterCriticalSection( &ActiveConsoleLock );
337 if( ActiveConsole )
338 {
339 Console->Prev = ActiveConsole;
340 Console->Next = ActiveConsole->Next;
341 ActiveConsole->Next->Prev = Console;
342 ActiveConsole->Next = Console;
343 }
344 else {
345 Console->Prev = Console;
346 Console->Next = Console;
347 }
348 Console->CurrentX = 0;
349 Console->CurrentY = 0;
350 ActiveConsole = Console;
351 /* copy buffer contents to screen */
352 CsrDrawConsole( Console );
353 RtlLeaveCriticalSection( &ActiveConsoleLock );
354 return STATUS_SUCCESS;
355 }
356
357 /***************************************************************
358 * CsrDrawConsole blasts the console buffer onto the screen *
359 * must be called while holding the active console lock *
360 **************************************************************/
361 VOID CsrDrawConsole( PCSRSS_CONSOLE Console )
362 {
363 IO_STATUS_BLOCK Iosb;
364 NTSTATUS Status;
365 CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
366 CONSOLE_MODE Mode;
367 int i, y;
368
369 /* first set position to 0,0 */
370 ScrInfo.dwCursorPosition.X = 0;
371 ScrInfo.dwCursorPosition.Y = 0;
372 ScrInfo.wAttributes = Console->DefaultAttrib;
373 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
374 if( !NT_SUCCESS( Status ) )
375 {
376 DbgPrint( "CSR: Failed to set console info\n" );
377 return;
378 }
379 Mode.dwMode = 0; /* clear ENABLE_PROCESSED_OUTPUT mode */
380 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
381 if( !NT_SUCCESS( Status ) )
382 {
383 DbgPrint( "CSR: Failed to set console mode\n" );
384 return;
385 }
386 /* blast out buffer */
387 for( i = 0, y = Console->ShowY; i < PhysicalConsoleSize.Y; i++ )
388 {
389 Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, &Console->Buffer[ (Console->ShowX * 2) + (y * Console->MaxX * 2) ], PhysicalConsoleSize.X * 2, 0, 0 );
390 if( !NT_SUCCESS( Status ) )
391 {
392 DbgPrint( "CSR: Write to console failed\n" );
393 return;
394 }
395 /* wrap back around the end of the buffer */
396 if( ++y == Console->MaxY )
397 y = 0;
398 }
399 Mode.dwMode = ENABLE_PROCESSED_OUTPUT;
400 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 );
401 if( !NT_SUCCESS( Status ) )
402 {
403 DbgPrint( "CSR: Failed to set console mode\n" );
404 return;
405 }
406 ScrInfo.dwCursorPosition.X = Console->CurrentX - Console->ShowX;
407 ScrInfo.dwCursorPosition.Y = ((Console->CurrentY + Console->MaxY) - Console->ShowY) % Console->MaxY;
408 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
409 if( !NT_SUCCESS( Status ) )
410 {
411 DbgPrint( "CSR: Failed to set console info\n" );
412 return;
413 }
414 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_CURSOR_INFO, &Console->CursorInfo, sizeof( Console->CursorInfo ), 0, 0 );
415 if( !NT_SUCCESS( Status ) )
416 {
417 DbgPrint( "CSR: Failed to set cursor info\n" );
418 return;
419 }
420 }
421
422
423 VOID CsrDeleteConsole( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE Console )
424 {
425 ConsoleInput *Event;
426 RtlEnterCriticalSection( &ActiveConsoleLock );
427 RtlFreeHeap( CsrssApiHeap, 0, Console->Buffer );
428 while( Console->InputEvents.Flink != &Console->InputEvents )
429 {
430 Event = (ConsoleInput *)Console->InputEvents.Flink;
431 Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
432 Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents;
433 RtlFreeHeap( CsrssApiHeap, 0, Event );
434 }
435 if( ActiveConsole == Console )
436 {
437 if( Console->Next != Console )
438 {
439 ActiveConsole = Console->Next;
440 Console->Prev->Next = Console->Next;
441 Console->Next->Prev = Console->Prev;
442 }
443 else ActiveConsole = 0;
444 }
445 if( ActiveConsole )
446 CsrDrawConsole( ActiveConsole );
447 RtlLeaveCriticalSection( &ActiveConsoleLock );
448 NtClose( Console->ActiveEvent );
449 }
450
451 VOID CsrInitConsoleSupport(VOID)
452 {
453 OBJECT_ATTRIBUTES ObjectAttributes;
454 UNICODE_STRING DeviceName;
455 NTSTATUS Status;
456 IO_STATUS_BLOCK Iosb;
457 CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
458
459 DbgPrint("CSR: CsrInitConsoleSupport()\n");
460
461 RtlInitUnicodeString(&DeviceName, L"\\??\\BlueScreen");
462 InitializeObjectAttributes(&ObjectAttributes,
463 &DeviceName,
464 0,
465 NULL,
466 NULL);
467 Status = NtOpenFile(&ConsoleDeviceHandle,
468 FILE_ALL_ACCESS,
469 &ObjectAttributes,
470 &Iosb,
471 0,
472 FILE_SYNCHRONOUS_IO_ALERT);
473 if (!NT_SUCCESS(Status))
474 {
475 DbgPrint("CSR: Failed to open console. Expect problems.\n");
476 }
477 // DbgPrint("CSR: ConsoleDeviceHandle %x\n", ConsoleDeviceHandle);
478
479 RtlInitUnicodeString(&DeviceName, L"\\??\\Keyboard");
480 InitializeObjectAttributes(&ObjectAttributes,
481 &DeviceName,
482 0,
483 NULL,
484 NULL);
485 Status = NtOpenFile(&KeyboardDeviceHandle,
486 FILE_ALL_ACCESS,
487 &ObjectAttributes,
488 &Iosb,
489 0,
490 0);
491 if (!NT_SUCCESS(Status))
492 {
493 DbgPrint("CSR: Failed to open keyboard. Expect problems.\n");
494 }
495
496 ActiveConsole = 0;
497 RtlInitializeCriticalSection( &ActiveConsoleLock );
498 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, &ScrInfo, sizeof( ScrInfo ) );
499 if( !NT_SUCCESS( Status ) )
500 {
501 DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
502 return;
503 }
504 PhysicalConsoleSize = ScrInfo.dwSize;
505 }
506
507 VOID Console_Api( DWORD RefreshEvent )
508 {
509 /* keep reading events from the keyboard and stuffing them into the current
510 console's input queue */
511 ConsoleInput *KeyEventRecord;
512 IO_STATUS_BLOCK Iosb;
513 NTSTATUS Status;
514 HANDLE Events[2]; // 0 = keyboard, 1 = refresh
515 int c;
516
517 Events[0] = 0;
518 Status = NtCreateEvent( &Events[0], STANDARD_RIGHTS_ALL, NULL, FALSE, FALSE );
519 if( !NT_SUCCESS( Status ) )
520 {
521 DbgPrint( "CSR: NtCreateEvent failed: %x\n", Status );
522 return;
523 }
524 Events[1] = (HANDLE)RefreshEvent;
525 while( 1 )
526 {
527 KeyEventRecord = RtlAllocateHeap(CsrssApiHeap,
528 0,
529 sizeof(ConsoleInput));
530 if ( KeyEventRecord == 0 )
531 {
532 DbgPrint( "CSR: Memory allocation failure!" );
533 continue;
534 }
535 KeyEventRecord->InputEvent.EventType = KEY_EVENT;
536 Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb, &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 );
537 if( !NT_SUCCESS( Status ) )
538 {
539 DbgPrint( "CSR: ReadFile on keyboard device failed\n" );
540 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
541 continue;
542 }
543 if( Status == STATUS_PENDING )
544 {
545 while( 1 )
546 {
547 Status = NtWaitForMultipleObjects( 2, Events, WaitAny, FALSE, NULL );
548 if( Status == STATUS_WAIT_0 + 1 )
549 {
550 RtlEnterCriticalSection( &ActiveConsoleLock );
551 CsrDrawConsole( ActiveConsole );
552 RtlLeaveCriticalSection( &ActiveConsoleLock );
553 continue;
554 }
555 else if( Status != STATUS_WAIT_0 )
556 {
557 DbgPrint( "CSR: NtWaitForMultipleObjects failed: %x, exiting\n", Status );
558 return;
559 }
560 else break;
561 }
562 }
563 // DbgPrint( "Char: %c\n", KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar );
564 if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&& KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == 'q' )
565 if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
566 {
567 /* alt-tab, swap consoles */
568 RtlEnterCriticalSection( &ActiveConsoleLock );
569 if( ActiveConsole->Next != ActiveConsole )
570 ActiveConsole = ActiveConsole->Next;
571 CsrDrawConsole( ActiveConsole );
572 RtlLeaveCriticalSection( &ActiveConsoleLock );
573 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
574 continue;
575 }
576 else {
577 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
578 continue;
579 }
580 else if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) && (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP || KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) )
581 {
582 if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
583 {
584 /* scroll up or down */
585 RtlEnterCriticalSection( &ActiveConsoleLock );
586 if( ActiveConsole == 0 )
587 {
588 DbgPrint( "CSR: No Active Console!\n" );
589 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
590 continue;
591 }
592 if( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP )
593 {
594 /* only scroll up if there is room to scroll up into */
595 if( ActiveConsole->ShowY != ((ActiveConsole->CurrentY + 1) % ActiveConsole->MaxY) )
596 ActiveConsole->ShowY = (ActiveConsole->ShowY + ActiveConsole->MaxY - 1) % ActiveConsole->MaxY;
597 }
598 else if( ActiveConsole->ShowY != ActiveConsole->CurrentY )
599 /* only scroll down if there is room to scroll down into */
600 if( ActiveConsole->ShowY % ActiveConsole->MaxY != ActiveConsole->CurrentY )
601 if( ((ActiveConsole->CurrentY + 1) % ActiveConsole->MaxY) != (ActiveConsole->ShowY + PhysicalConsoleSize.Y) % ActiveConsole->MaxY )
602 ActiveConsole->ShowY = (ActiveConsole->ShowY + 1) % ActiveConsole->MaxY;
603 CsrDrawConsole( ActiveConsole );
604 RtlLeaveCriticalSection( &ActiveConsoleLock );
605 }
606 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
607 continue;
608 }
609 RtlEnterCriticalSection( &ActiveConsoleLock );
610 if( ActiveConsole == 0 )
611 {
612 DbgPrint( "CSR: No Active Console!\n" );
613 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
614 continue;
615 }
616 // echo to screen if enabled, but do not echo '\b' if there are no keys in buffer to delete
617 if( ActiveConsole->ConsoleMode & ENABLE_ECHO_INPUT &&
618 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE &&
619 KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar &&
620 ( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\b' ||
621 ActiveConsole->InputEvents.Flink != &ActiveConsole->InputEvents ) )
622 {
623 CsrpWriteConsole( ActiveConsole, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE );
624 }
625 // process special keys if enabled
626 if( ActiveConsole->ConsoleMode & ENABLE_PROCESSED_INPUT )
627 switch( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar )
628 {
629 case '\b':
630 if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE )
631 for( c = 0; c < 2; c++ )
632 {
633 ConsoleInput *Input = ActiveConsole->InputEvents.Blink;
634
635 CHECKPOINT1;
636 ActiveConsole->InputEvents.Blink->Blink->Flink = &ActiveConsole->InputEvents;
637 ActiveConsole->InputEvents.Blink = ActiveConsole->InputEvents.Blink->Blink;
638 RtlFreeHeap( CsrssApiHeap, 0, Input );
639 }
640 RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord );
641 RtlLeaveCriticalSection( &ActiveConsoleLock );
642 continue;
643 }
644 // add event to the queue
645 KeyEventRecord->ListEntry.Flink = &ActiveConsole->InputEvents;
646 KeyEventRecord->ListEntry.Blink = ActiveConsole->InputEvents.Blink;
647 ActiveConsole->InputEvents.Blink->Flink = &KeyEventRecord->ListEntry;
648 ActiveConsole->InputEvents.Blink = &KeyEventRecord->ListEntry;
649 // if line input mode is enabled, only wake the client on enter key up
650 if( !(ActiveConsole->ConsoleMode & ENABLE_LINE_INPUT ) ||
651 ( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' &&
652 KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == FALSE ) )
653 {
654 NtSetEvent( ActiveConsole->ActiveEvent, 0 );
655 ActiveConsole->WaitingLines++;
656 }
657 ActiveConsole->WaitingChars++;
658 RtlLeaveCriticalSection( &ActiveConsoleLock );
659 }
660 }
661
662 NTSTATUS CsrGetScreenBufferInfo( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
663 {
664 NTSTATUS Status;
665 PCSRSS_CONSOLE Console;
666 PCONSOLE_SCREEN_BUFFER_INFO pInfo;
667 IO_STATUS_BLOCK Iosb;
668
669 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
670 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
671 sizeof(LPC_MESSAGE_HEADER);
672
673 if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, (Object_t **)&Console ) ) )
674 return Reply->Status = STATUS_INVALID_HANDLE;
675 pInfo = &Reply->Data.ScreenBufferInfoReply.Info;
676 RtlEnterCriticalSection( &ActiveConsoleLock );
677 if( Console == ActiveConsole )
678 {
679 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, pInfo, sizeof( *pInfo ) );
680 if( !NT_SUCCESS( Status ) )
681 DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
682 Reply->Status = STATUS_SUCCESS;
683 }
684 else {
685 pInfo->dwSize.X = PhysicalConsoleSize.X;
686 pInfo->dwSize.Y = PhysicalConsoleSize.Y;
687 pInfo->dwCursorPosition.X = Console->CurrentX - Console->ShowX;
688 pInfo->dwCursorPosition.Y = (Console->CurrentY + Console->MaxY - Console->ShowY) % Console->MaxY;
689 pInfo->wAttributes = Console->DefaultAttrib;
690 pInfo->srWindow.Left = 0;
691 pInfo->srWindow.Right = PhysicalConsoleSize.X - 1;
692 pInfo->srWindow.Top = 0;
693 pInfo->srWindow.Bottom = PhysicalConsoleSize.Y - 1;
694 Reply->Status = STATUS_SUCCESS;
695 }
696 RtlLeaveCriticalSection( &ActiveConsoleLock );
697 return Reply->Status;
698 }
699
700 NTSTATUS CsrSetCursor( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
701 {
702 NTSTATUS Status;
703 PCSRSS_CONSOLE Console;
704 CONSOLE_SCREEN_BUFFER_INFO Info;
705 IO_STATUS_BLOCK Iosb;
706
707 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
708 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
709 sizeof(LPC_MESSAGE_HEADER);
710
711 if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, (Object_t **)&Console ) ) )
712 return Reply->Status = STATUS_INVALID_HANDLE;
713 RtlEnterCriticalSection( &ActiveConsoleLock );
714 Info.dwCursorPosition = Request->Data.SetCursorRequest.Position;
715 Info.wAttributes = Console->DefaultAttrib;
716 if( Console == ActiveConsole )
717 {
718 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &Info, sizeof( Info ), 0, 0 );
719 if( !NT_SUCCESS( Status ) )
720 DbgPrint( "CSR: Failed to set console info, expect trouble\n" );
721 }
722 Console->CurrentX = Info.dwCursorPosition.X + Console->ShowX;
723 Console->CurrentY = (Info.dwCursorPosition.Y + Console->ShowY) % Console->MaxY;
724 RtlLeaveCriticalSection( &ActiveConsoleLock );
725 return Reply->Status = Status;
726 }
727
728 NTSTATUS CsrWriteConsoleOutputChar( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
729 {
730 BYTE *Buffer = Request->Data.WriteConsoleOutputCharRequest.String;
731 PCSRSS_CONSOLE Console;
732 DWORD X, Y;
733
734 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
735 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
736 sizeof(LPC_MESSAGE_HEADER);
737
738 if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle, (Object_t **)&Console ) ) )
739 return Reply->Status = STATUS_INVALID_HANDLE;
740 RtlEnterCriticalSection( &ActiveConsoleLock );
741 X = Console->CurrentX;
742 Y = Console->CurrentY;
743 CsrpWriteConsole( Console, Buffer, Request->Data.WriteConsoleOutputCharRequest.Length, TRUE );
744 Reply->Data.WriteConsoleOutputCharReply.EndCoord.X = Console->CurrentX - Console->ShowX;
745 Reply->Data.WriteConsoleOutputCharReply.EndCoord.Y = (Console->CurrentY + Console->MaxY - Console->ShowY) % Console->MaxY;
746 Console->CurrentY = Y;
747 Console->CurrentX = X;
748 RtlLeaveCriticalSection( &ActiveConsoleLock );
749 return Reply->Status = STATUS_SUCCESS;
750 }
751
752 NTSTATUS CsrFillOutputChar( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
753 {
754 PCSRSS_CONSOLE Console;
755 DWORD X, Y, i;
756
757 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
758 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
759 sizeof(LPC_MESSAGE_HEADER);
760
761 if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, (Object_t **)&Console ) ) )
762 return Reply->Status = STATUS_INVALID_HANDLE;
763 RtlEnterCriticalSection( &ActiveConsoleLock );
764 X = Request->Data.FillOutputRequest.Position.X + Console->ShowX;
765 Y = Request->Data.FillOutputRequest.Position.Y + Console->ShowY;
766 for( i = 0; i < 20000; i++ );
767 for( i = 0; i < Request->Data.FillOutputRequest.Length; i++ )
768 {
769 Console->Buffer[ (Y * 2 * Console->MaxX) + (X * 2) ] = Request->Data.FillOutputRequest.Char;
770 if( ++X == Console->MaxX )
771 {
772 if( ++Y == Console->MaxY )
773 Y = 0;
774 X = 0;
775 }
776 }
777 if( Console == ActiveConsole )
778 CsrDrawConsole( Console );
779 RtlLeaveCriticalSection( &ActiveConsoleLock );
780 return Reply->Status;
781 }
782
783 NTSTATUS CsrReadInputEvent( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
784 {
785 PCSRSS_CONSOLE Console;
786 NTSTATUS Status;
787 ConsoleInput *Input;
788
789 // DbgPrint("CSR: NrCharactersToRead %d\n", nNumberOfCharsToRead);
790
791 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
792 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
793 sizeof(LPC_MESSAGE_HEADER);
794 Reply->Data.ReadInputReply.Event = ProcessData->ConsoleEvent;
795
796 Status = CsrGetObject( ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, (Object_t **)&Console );
797 if( !NT_SUCCESS( Status ) )
798 {
799 Reply->Status = Status;
800 return Status;
801 }
802 RtlEnterCriticalSection( &ActiveConsoleLock );
803 // only get input if there is input, and we are not in line input mode, or if we are, if we have a whole line
804 if( Console->InputEvents.Flink != &Console->InputEvents &&
805 ( !Console->ConsoleMode & ENABLE_LINE_INPUT || Console->WaitingLines ) )
806 {
807 Input = (ConsoleInput *)Console->InputEvents.Flink;
808 Input->ListEntry.Blink->Flink = Input->ListEntry.Flink;
809 Input->ListEntry.Flink->Blink = Input->ListEntry.Blink;
810 Reply->Data.ReadInputReply.Input = Input->InputEvent;
811 if( Console->ConsoleMode & ENABLE_LINE_INPUT &&
812 Input->InputEvent.Event.KeyEvent.bKeyDown == FALSE &&
813 Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' )
814 Console->WaitingLines--;
815 Console->WaitingChars--;
816 RtlFreeHeap( CsrssApiHeap, 0, Input );
817 Reply->Data.ReadInputReply.MoreEvents = (Console->InputEvents.Flink != &Console->InputEvents) ? TRUE : FALSE;
818 Status = STATUS_SUCCESS;
819 }
820 else Status = STATUS_PENDING;
821 RtlLeaveCriticalSection( &ActiveConsoleLock );
822 return Reply->Status = Status;
823 }
824
825 NTSTATUS CsrWriteConsoleOutputAttrib( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
826 {
827 int c;
828 PCSRSS_CONSOLE Console;
829 NTSTATUS Status;
830 int X, Y;
831
832 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
833 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
834 sizeof(LPC_MESSAGE_HEADER);
835 Status = CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle, (Object_t **)&Console );
836 if( !NT_SUCCESS( Status ) )
837 {
838 Reply->Status = Status;
839 return Status;
840 }
841 RtlEnterCriticalSection( &ActiveConsoleLock );
842 X = Console->CurrentX;
843 Y = Console->CurrentY;
844 Console->CurrentX = Request->Data.WriteConsoleOutputAttribRequest.Coord.X + Console->ShowX;
845 Console->CurrentY = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Console->ShowY) % Console->MaxY;
846 for( c = 0; c < Request->Data.WriteConsoleOutputAttribRequest.Length; c++ )
847 {
848 Console->Buffer[(Console->CurrentY * Console->MaxX * 2) + (Console->CurrentX * 2) + 1] = Request->Data.WriteConsoleOutputAttribRequest.String[c];
849 if( ++Console->CurrentX == Console->MaxX )
850 {
851 Console->CurrentX = 0;
852 if( ++Console->CurrentY == Console->MaxY )
853 Console->CurrentY = 0;
854 }
855 }
856 if( Console == ActiveConsole )
857 CsrDrawConsole( Console );
858 Reply->Data.WriteConsoleOutputAttribReply.EndCoord.X = Console->CurrentX - Console->ShowX;
859 Reply->Data.WriteConsoleOutputAttribReply.EndCoord.Y = ( Console->CurrentY + Console->MaxY - Console->ShowY ) % Console->MaxY;
860 Console->CurrentX = X;
861 Console->CurrentY = Y;
862 RtlLeaveCriticalSection( &ActiveConsoleLock );
863 return Reply->Status = STATUS_SUCCESS;
864 }
865
866 NTSTATUS CsrFillOutputAttrib( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
867 {
868 int c;
869 PCSRSS_CONSOLE Console;
870 NTSTATUS Status;
871 int X, Y;
872
873 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
874 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
875 sizeof(LPC_MESSAGE_HEADER);
876 Status = CsrGetObject( ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, (Object_t **)&Console );
877 if( !NT_SUCCESS( Status ) )
878 {
879 Reply->Status = Status;
880 return Status;
881 }
882 RtlEnterCriticalSection( &ActiveConsoleLock );
883 X = Console->CurrentX;
884 Y = Console->CurrentY;
885 Console->CurrentX = Request->Data.FillOutputAttribRequest.Coord.X + Console->ShowX;
886 Console->CurrentY = Request->Data.FillOutputAttribRequest.Coord.Y + Console->ShowY;
887 for( c = 0; c < Request->Data.FillOutputAttribRequest.Length; c++ )
888 {
889 Console->Buffer[(Console->CurrentY * Console->MaxX * 2) + (Console->CurrentX * 2) + 1] = Request->Data.FillOutputAttribRequest.Attribute;
890 if( ++Console->CurrentX == Console->MaxX )
891 {
892 Console->CurrentX = 0;
893 if( ++Console->CurrentY == Console->MaxY )
894 Console->CurrentY = 0;
895 }
896 }
897 if( Console == ActiveConsole )
898 CsrDrawConsole( Console );
899 Console->CurrentX = X;
900 Console->CurrentY = Y;
901 RtlLeaveCriticalSection( &ActiveConsoleLock );
902 return Reply->Status = STATUS_SUCCESS;
903 }
904
905
906 NTSTATUS CsrGetCursorInfo( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
907 {
908 PCSRSS_CONSOLE Console;
909 NTSTATUS Status;
910
911 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
912 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
913 sizeof(LPC_MESSAGE_HEADER);
914 Status = CsrGetObject( ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, (Object_t **)&Console );
915 if( !NT_SUCCESS( Status ) )
916 {
917 Reply->Status = Status;
918 return Status;
919 }
920 RtlEnterCriticalSection( &ActiveConsoleLock );
921 Reply->Data.GetCursorInfoReply.Info = Console->CursorInfo;
922 RtlLeaveCriticalSection( &ActiveConsoleLock );
923 return Reply->Status = STATUS_SUCCESS;
924 }
925
926 NTSTATUS CsrSetCursorInfo( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
927 {
928 PCSRSS_CONSOLE Console;
929 NTSTATUS Status;
930 IO_STATUS_BLOCK Iosb;
931
932 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
933 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
934 sizeof(LPC_MESSAGE_HEADER);
935 Status = CsrGetObject( ProcessData, Request->Data.SetCursorInfoRequest.ConsoleHandle, (Object_t **)&Console );
936 if( !NT_SUCCESS( Status ) )
937 {
938 Reply->Status = Status;
939 return Status;
940 }
941 RtlEnterCriticalSection( &ActiveConsoleLock );
942 Console->CursorInfo = Request->Data.SetCursorInfoRequest.Info;
943 if( Console == ActiveConsole )
944 {
945 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_CURSOR_INFO, &Console->CursorInfo, sizeof( Console->CursorInfo ), 0, 0 );
946 if( !NT_SUCCESS( Status ) )
947 {
948 DbgPrint( "CSR: Failed to set cursor info\n" );
949 return Reply->Status = Status;
950 }
951 }
952 RtlLeaveCriticalSection( &ActiveConsoleLock );
953 return Reply->Status = STATUS_SUCCESS;
954 }
955
956 NTSTATUS CsrSetTextAttrib( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
957 {
958 NTSTATUS Status;
959 CONSOLE_SCREEN_BUFFER_INFO ScrInfo;
960 IO_STATUS_BLOCK Iosb;
961 PCSRSS_CONSOLE Console;
962
963 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
964 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) -
965 sizeof(LPC_MESSAGE_HEADER);
966 Status = CsrGetObject( ProcessData, Request->Data.SetAttribRequest.ConsoleHandle, (Object_t **)&Console );
967 if( !NT_SUCCESS( Status ) )
968 {
969 Reply->Status = Status;
970 return Status;
971 }
972 RtlEnterCriticalSection( &ActiveConsoleLock );
973 Console->DefaultAttrib = Request->Data.SetAttribRequest.Attrib;
974 if( Console == ActiveConsole )
975 {
976 ScrInfo.wAttributes = Console->DefaultAttrib;
977 ScrInfo.dwCursorPosition.X = Console->CurrentX - Console->ShowX;
978 ScrInfo.dwCursorPosition.Y = ((Console->CurrentY + Console->MaxY) - Console->ShowY) % Console->MaxY;
979 Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 );
980 if( !NT_SUCCESS( Status ) )
981 {
982 DbgPrint( "CSR: Failed to set console info\n" );
983 return Reply->Status = Status;
984 }
985 }
986 return Reply->Status = STATUS_SUCCESS;
987 }
988
989 NTSTATUS CsrSetConsoleMode( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
990 {
991 NTSTATUS Status;
992 PCSRSS_CONSOLE Console;
993
994 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
995 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER);
996 if( Request->Data.SetConsoleModeRequest.Mode & (~CONSOLE_MODE_VALID) ||
997 ( Request->Data.SetConsoleModeRequest.Mode & (ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT) &&
998 !( Request->Data.SetConsoleModeRequest.Mode & ENABLE_LINE_INPUT ) ) )
999 {
1000 Reply->Status = STATUS_INVALID_PARAMETER;
1001 return Reply->Status;
1002 }
1003 Status = CsrGetObject( ProcessData, Request->Data.SetConsoleModeRequest.ConsoleHandle, (Object_t **)&Console );
1004 if( !NT_SUCCESS( Status ) )
1005 {
1006 Reply->Status = Status;
1007 return Status;
1008 }
1009 RtlEnterCriticalSection( &ActiveConsoleLock );
1010 Console->ConsoleMode = Request->Data.SetConsoleModeRequest.Mode;
1011 RtlLeaveCriticalSection( &ActiveConsoleLock );
1012 Reply->Status = STATUS_SUCCESS;
1013 return Reply->Status;
1014 }
1015
1016 NTSTATUS CsrGetConsoleMode( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply )
1017 {
1018 NTSTATUS Status;
1019 PCSRSS_CONSOLE Console;
1020
1021 Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY);
1022 Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER);
1023 Status = CsrGetObject( ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle, (Object_t **)&Console );
1024 if( !NT_SUCCESS( Status ) )
1025 {
1026 Reply->Status = Status;
1027 return Status;
1028 }
1029 RtlEnterCriticalSection( &ActiveConsoleLock );
1030 Reply->Data.GetConsoleModeReply.ConsoleMode = Console->ConsoleMode;
1031 RtlLeaveCriticalSection( &ActiveConsoleLock );
1032 Reply->Status = STATUS_SUCCESS;
1033 return Reply->Status;
1034 }
1035
1036
1037
1038
1039
1040
1041