ReactOS  0.4.14-dev-1331-g167fa2c
console.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Console Driver DLL
4  * FILE: win32ss/user/winsrv/consrv/condrv/console.c
5  * PURPOSE: Console Management Functions
6  * PROGRAMMERS: Gé van Geldorp
7  * Jeffrey Morlan
8  * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9  * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
10  */
11 
12 /* INCLUDES *******************************************************************/
13 
14 #include <consrv.h>
15 #include <coninput.h>
16 #include "../../concfg/font.h"
17 
18 #define NDEBUG
19 #include <debug.h>
20 
21 /* GLOBALS ********************************************************************/
22 
24 
25 /* Linked list of consoles */
28 
29 #define ConDrvLockConsoleListExclusive() \
30  RtlAcquireResourceExclusive(&ListLock, TRUE)
31 
32 #define ConDrvLockConsoleListShared() \
33  RtlAcquireResourceShared(&ListLock, TRUE)
34 
35 #define ConDrvUnlockConsoleList() \
36  RtlReleaseResource(&ListLock)
37 
38 
39 static NTSTATUS
41 {
42  ASSERT(Console);
43 
44  /* All went right, so add the console to the list */
46 
47  DPRINT("Insert in the list\n");
49 
50  // FIXME: Move this code to the caller function!!
51  /* Get a new console ID */
54 
55  /* Unlock the console list and return success */
57  return STATUS_SUCCESS;
58 }
59 
60 static NTSTATUS
62 {
63  // ASSERT(Console);
64  if (!Console) return STATUS_INVALID_PARAMETER;
65 
66  /* Remove the console from the list */
68 
69  RemoveEntryList(&Console->ListEntry);
70 
71  /* Unlock the console list and return success */
73  return STATUS_SUCCESS;
74 }
75 
76 
77 /* PRIVATE FUNCTIONS **********************************************************/
78 
79 VOID NTAPI
81 {
82  /* In case we are already paused, just exit... */
83  if (Console->ConsolePaused) return;
84 
85  /* ... otherwise set the flag */
86  Console->ConsolePaused = TRUE;
87 }
88 
89 VOID NTAPI
91 {
92  /* In case we are already unpaused, just exit... */
93  if (!Console->ConsolePaused) return;
94 
95  /* ... otherwise reset the flag */
96  Console->ConsolePaused = FALSE;
97 }
98 
99 
100 /*
101  * Console accessibility check helpers
102  */
103 
106  IN CONSOLE_STATE ExpectedState)
107 {
108  // if (!Console) return FALSE;
109 
110  /* The console must be locked */
111  // ASSERT(Console_locked);
112 
113  return (Console->State == ExpectedState);
114 }
115 
118  IN CONSOLE_STATE ExpectedState,
119  IN BOOLEAN LockConsole)
120 {
121  if (!Console) return FALSE;
122 
123  /*
124  * Lock the console to forbid possible console's state changes
125  * (which must be done when the console is already locked).
126  * If we don't want to lock it, it's because the lock is already
127  * held. So there must be no problems.
128  */
129  if (LockConsole) EnterCriticalSection(&Console->Lock);
130 
131  // ASSERT(Console_locked);
132 
133  /* Check whether the console's state is what we expect */
134  if (!ConDrvValidateConsoleState(Console, ExpectedState))
135  {
136  if (LockConsole) LeaveCriticalSection(&Console->Lock);
137  return FALSE;
138  }
139 
140  return TRUE;
141 }
142 
143 
144 /* CONSOLE INITIALIZATION FUNCTIONS *******************************************/
145 
146 VOID NTAPI
148 {
149  DPRINT("CONSRV: ConDrvInitConsoleSupport()\n");
150 
151  /* Initialize the console list and its lock */
154 }
155 
156 /* For resetting the terminal - defined in dummyterm.c */
158 
162 {
164  // CONSOLE_INFO CapturedConsoleInfo;
167  PCONSOLE_SCREEN_BUFFER NewBuffer;
168 
169  if (NewConsole == NULL || ConsoleInfo == NULL)
171 
172  *NewConsole = NULL;
173 
174  /*
175  * Allocate a new console
176  */
178  if (NULL == Console)
179  {
180  DPRINT1("Not enough memory for console creation.\n");
181  return STATUS_NO_MEMORY;
182  }
183 
184  /*
185  * Set and fix the screen buffer size if needed.
186  * The rule is: ScreenBufferSize >= ConsoleSize
187  */
188  if (ConsoleInfo->ScreenBufferSize.X == 0) ConsoleInfo->ScreenBufferSize.X = 1;
189  if (ConsoleInfo->ScreenBufferSize.Y == 0) ConsoleInfo->ScreenBufferSize.Y = 1;
190  if (ConsoleInfo->ScreenBufferSize.X < ConsoleInfo->ConsoleSize.X)
191  ConsoleInfo->ScreenBufferSize.X = ConsoleInfo->ConsoleSize.X;
192  if (ConsoleInfo->ScreenBufferSize.Y < ConsoleInfo->ConsoleSize.Y)
193  ConsoleInfo->ScreenBufferSize.Y = ConsoleInfo->ConsoleSize.Y;
194 
195  /*
196  * Initialize the console
197  */
198  Console->State = CONSOLE_INITIALIZING;
199  Console->ReferenceCount = 0;
201 
202  /* Initialize the terminal interface */
204 
205  Console->ConsoleSize = ConsoleInfo->ConsoleSize;
206  Console->FixedSize = FALSE; // Value by default; is reseted by the terminals if needed.
207 
208  /* Initialize the input buffer */
209  Status = ConDrvInitInputBuffer(Console, 0 /* ConsoleInfo->InputBufferSize */);
210  if (!NT_SUCCESS(Status))
211  {
212  DPRINT1("ConDrvInitInputBuffer: failed, Status = 0x%08lx\n", Status);
215  return Status;
216  }
217 
218  /* Set-up the code page */
219  if (IsValidCodePage(ConsoleInfo->CodePage))
220  Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
221 
222  Console->IsCJK = IsCJKCodePage(Console->OutputCodePage);
223 
224  /* Initialize a new text-mode screen buffer with default settings */
225  ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
226  ScreenBufferInfo.ViewSize = ConsoleInfo->ConsoleSize;
227  ScreenBufferInfo.ScreenAttrib = ConsoleInfo->ScreenAttrib;
228  ScreenBufferInfo.PopupAttrib = ConsoleInfo->PopupAttrib;
229  ScreenBufferInfo.CursorSize = ConsoleInfo->CursorSize;
230  ScreenBufferInfo.IsCursorVisible = TRUE;
231 
232  InitializeListHead(&Console->BufferList);
233  Status = ConDrvCreateScreenBuffer(&NewBuffer,
234  Console,
235  NULL,
238  if (!NT_SUCCESS(Status))
239  {
240  DPRINT1("ConDrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
244  return Status;
245  }
246  /* Make the new screen buffer active */
247  Console->ActiveBuffer = NewBuffer;
248  Console->ConsolePaused = FALSE;
249 
250  DPRINT("Console initialized\n");
251 
252  /* All went right, so add the console to the list */
254  if (!NT_SUCCESS(Status))
255  {
256  /* Fail */
258  return Status;
259  }
260 
261  /* The initialization is finished */
262  DPRINT("Change state\n");
263  Console->State = CONSOLE_RUNNING;
264 
265  /* Return the newly created console to the caller and a success code too */
266  *NewConsole = Console;
267  return STATUS_SUCCESS;
268 }
269 
272  IN PTERMINAL Terminal)
273 {
275 
276  if (Console == NULL || Terminal == NULL)
278 
279  /* FIXME: Lock the console before ?? */
280 
281  /*
282  * Attach the terminal to the console. Use now the TermIFace of the console,
283  * and not the user-defined temporary Terminal pointer.
284  */
285  Console->TermIFace = *Terminal;
286  Console->TermIFace.Console = Console;
287 
288  /* Initialize the terminal AFTER having attached it to the console */
289  DPRINT("Finish initialization of terminal\n");
290  Status = Console->TermIFace.Vtbl->InitTerminal(&Console->TermIFace, Console);
291  if (!NT_SUCCESS(Status))
292  {
293  DPRINT1("Terminal initialization failed, Status = 0x%08lx\n", Status);
294 
295  /* We failed, detach the terminal from the console */
296  Terminal->Console = NULL; // For the caller
298  return Status;
299  }
300 
301  /* Copy buffer contents to screen */
302  // Terminal.Draw();
303 
304  DPRINT("Terminal initialization done\n");
305  return STATUS_SUCCESS;
306 }
307 
310 {
311  if (Console == NULL) return STATUS_INVALID_PARAMETER;
312 
313  /* FIXME: Lock the console before ?? */
314 
315  /* Deinitialize the terminal BEFORE detaching it from the console */
316  Console->TermIFace.Vtbl->DeinitTerminal(&Console->TermIFace/*, Console*/);
317 
318  /*
319  * Detach the terminal from the console:
320  * reinitialize the terminal interface.
321  */
323 
324  DPRINT("Terminal unregistered\n");
325  return STATUS_SUCCESS;
326 }
327 
328 VOID NTAPI
330 {
331  DPRINT("ConDrvDeleteConsole(0x%p)\n", Console);
332 
333  /*
334  * Forbid validation of any console by other threads
335  * during the deletion of this console.
336  */
338 
339  /*
340  * If the console is already being destroyed, i.e. not running
341  * or finishing to be initialized, just return.
342  */
345  {
346  /* Unlock the console list and return */
348  return;
349  }
350 
351  /*
352  * We are about to be destroyed. Signal it to other people
353  * so that they can terminate what they are doing, and that
354  * they cannot longer validate the console.
355  */
356  Console->State = CONSOLE_TERMINATING;
357 
358  /*
359  * Allow other threads to finish their job: basically, unlock
360  * all other calls to EnterCriticalSection(&Console->Lock); by
361  * ConDrvValidateConsoleUnsafe functions so that they just see
362  * that we are not in CONSOLE_RUNNING state anymore, or unlock
363  * other concurrent calls to ConDrvDeleteConsole so that they
364  * can see that we are in fact already deleting the console.
365  */
368 
369  /* Deregister the terminal */
370  DPRINT("Deregister terminal\n");
372  DPRINT("Terminal deregistered\n");
373 
374  /***
375  * Check that the console is in terminating state before continuing
376  * (the cleanup code must not change the state of the console...
377  * ...unless to cancel console deletion ?).
378  ***/
379 
381 
383  {
385  return;
386  }
387 
388  /* We are now in destruction */
390 
391  /* We really delete the console. Reset the count to be sure. */
392  Console->ReferenceCount = 0;
393 
394  /* Remove the console from the list */
396 
397  /* Delete the last screen buffer */
398  ConDrvDeleteScreenBuffer(Console->ActiveBuffer);
399  Console->ActiveBuffer = NULL;
400  if (!IsListEmpty(&Console->BufferList))
401  {
402  /***ConDrvUnlockConsoleList();***/
403  ASSERTMSG("BUGBUGBUG!! screen buffer list not empty\n", FALSE);
404  }
405 
406  /* Deinitialize the input buffer */
408 
409  Console->ConsolePaused = FALSE;
410 
411  DPRINT("ConDrvDeleteConsole - Unlocking\n");
413  DPRINT("ConDrvDeleteConsole - Destroying lock\n");
415  DPRINT("ConDrvDeleteConsole - Lock destroyed ; freeing console\n");
416 
418  DPRINT("ConDrvDeleteConsole - Console destroyed\n");
419 
420  /* Unlock the console list and return */
422 }
423 
424 
425 /* PUBLIC DRIVER APIS *********************************************************/
426 
430  OUT PULONG ConsoleMode)
431 {
433 
434  if (Console == NULL || Object == NULL || ConsoleMode == NULL)
436 
437  /* Validity check */
438  ASSERT(Console == Object->Console);
439 
440  /*** FIXME: */ *ConsoleMode = 0; /***/
441 
442  if (INPUT_BUFFER == Object->Type)
443  {
445  *ConsoleMode = InputBuffer->Mode;
446  }
447  else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
448  {
450  *ConsoleMode = Buffer->Mode;
451  }
452  else
453  {
455  }
456 
457  return Status;
458 }
459 
463  IN ULONG ConsoleMode)
464 {
465 #define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \
466  ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \
467  ENABLE_MOUSE_INPUT )
468 #define CONSOLE_VALID_OUTPUT_MODES ( ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT )
469 
471 
472  if (Console == NULL || Object == NULL)
474 
475  /* Validity check */
476  ASSERT(Console == Object->Console);
477 
478  if (INPUT_BUFFER == Object->Type)
479  {
481 
482  /* Only the presence of valid mode flags is allowed */
483  if (ConsoleMode & ~CONSOLE_VALID_INPUT_MODES)
484  {
486  }
487  else
488  {
489  InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
490  }
491  }
492  else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
493  {
495 
496  /* Only the presence of valid mode flags is allowed */
497  if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
498  {
500  }
501  else
502  {
503  Buffer->Mode = (ConsoleMode & CONSOLE_VALID_OUTPUT_MODES);
504  }
505  }
506  else
507  {
509  }
510 
511  return Status;
512 }
513 
516  OUT PUINT CodePage,
517  IN BOOLEAN OutputCP)
518 {
519  if (Console == NULL || CodePage == NULL)
521 
522  *CodePage = (OutputCP ? Console->OutputCodePage : Console->InputCodePage);
523 
524  return STATUS_SUCCESS;
525 }
526 
529  IN UINT CodePage,
530  IN BOOLEAN OutputCP)
531 {
532  if (Console == NULL || !IsValidCodePage(CodePage))
534 
535  if (OutputCP)
536  {
537  Console->OutputCodePage = CodePage;
538  Console->IsCJK = IsCJKCodePage(CodePage);
539  }
540  else
541  {
542  Console->InputCodePage = CodePage;
543  }
544 
545  return STATUS_SUCCESS;
546 }
547 
548 /* EOF */
#define ConDrvUnlockConsoleList()
Definition: console.c:35
BOOLEAN NTAPI ConDrvValidateConsoleState(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState)
Definition: console.c:105
#define IN
Definition: typedefs.h:39
static RTL_RESOURCE ListLock
Definition: console.c:27
#define TRUE
Definition: types.h:120
#define ConDrvLockConsoleListExclusive()
Definition: console.c:29
VOID NTAPI ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
Definition: conoutput.c:123
NTSTATUS NTAPI ConDrvDetachTerminal(IN PCONSOLE Console)
Definition: console.c:309
CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo
Definition: notevil.c:38
VOID NTAPI ConDrvInitConsoleSupport(VOID)
Definition: console.c:147
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
long __cdecl _InterlockedExchange(_Interlocked_operand_ long volatile *_Target, long _Value)
LONG NTSTATUS
Definition: precomp.h:26
#define ConsoleAllocHeap(Flags, Size)
Definition: heap.h:14
VOID NTAPI ConDrvPause(PCONSOLE Console)
Definition: console.c:80
NTSTATUS ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER *Buffer, IN PCONSOLE Console, IN HANDLE ProcessHandle OPTIONAL, IN ULONG BufferType, IN PVOID ScreenBufferInfo)
Definition: conoutput.c:79
#define TEXTMODE_BUFFER
Definition: pccons.c:21
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define InsertTailList(ListHead, Entry)
NTSTATUS NTAPI ConDrvGetConsoleMode(IN PCONSOLE Console, IN PCONSOLE_IO_OBJECT Object, OUT PULONG ConsoleMode)
Definition: console.c:428
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
CHAR InputBuffer[80]
Definition: conmgr.c:33
VOID NTAPI ConDrvUnpause(PCONSOLE Console)
Definition: console.c:90
NTSTATUS NTAPI ConDrvSetConsoleMode(IN PCONSOLE Console, IN PCONSOLE_IO_OBJECT Object, IN ULONG ConsoleMode)
Definition: console.c:461
#define IsCJKCodePage(CodePage)
Definition: font.h:23
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
VOID NTAPI ConDrvDeleteConsole(IN PCONSOLE Console)
Definition: console.c:329
struct _CONSOLE_INPUT_BUFFER * PCONSOLE_INPUT_BUFFER
long __cdecl _InterlockedIncrement(_Interlocked_operand_ long volatile *_Addend)
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
VOID NTAPI ConDrvDeinitInputBuffer(IN PCONSOLE Console)
Definition: coninput.c:221
struct _CONSOLE_SCREEN_BUFFER * PCONSOLE_SCREEN_BUFFER
Definition: conio.h:70
unsigned char BOOLEAN
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
#define CONSOLE_VALID_INPUT_MODES
static NTSTATUS ConDrvInsertConsole(IN PCONSOLE Console)
Definition: console.c:40
NTSYSAPI VOID NTAPI RtlInitializeResource(_In_ PRTL_RESOURCE Resource)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static LIST_ENTRY ConDrvConsoleList
Definition: console.c:26
static IUnknown Object
Definition: main.c:512
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
NTSTATUS NTAPI ConDrvAttachTerminal(IN PCONSOLE Console, IN PTERMINAL Terminal)
Definition: console.c:271
VOID ResetTerminal(IN PCONSOLE Console)
Definition: dummyterm.c:156
Definition: typedefs.h:118
Status
Definition: gdiplustypes.h:24
static ULONG CurrentConsoleID
Definition: console.c:23
NTSTATUS NTAPI ConDrvSetConsoleCP(IN PCONSOLE Console, IN UINT CodePage, IN BOOLEAN OutputCP)
Definition: console.c:528
BOOL WINAPI IsValidCodePage(UINT CodePage)
Definition: nls.c:1479
NTSTATUS NTAPI ConDrvInitInputBuffer(IN PCONSOLE Console, IN ULONG InputBufferSize)
Definition: coninput.c:192
#define CONSOLE_TEXTMODE_BUFFER
Definition: wincon.h:62
BOOLEAN NTAPI ConDrvValidateConsoleUnsafe(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState, IN BOOLEAN LockConsole)
Definition: console.c:117
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
Definition: video.c:47
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI ConDrvGetConsoleCP(IN PCONSOLE Console, OUT PUINT CodePage, IN BOOLEAN OutputCP)
Definition: console.c:515
unsigned int UINT
Definition: ndis.h:50
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
CConsole Console
#define DPRINT1
Definition: precomp.h:8
#define ConsoleFreeHeap(HeapBase)
Definition: heap.h:15
static NTSTATUS RemoveConsole(IN PCONSOLE Console)
Definition: console.c:61
NTSTATUS NTAPI ConDrvInitConsole(OUT PCONSOLE *NewConsole, IN PCONSOLE_INFO ConsoleInfo)
Definition: console.c:160
#define OUT
Definition: typedefs.h:40
#define CONSOLE_VALID_OUTPUT_MODES
unsigned int ULONG
Definition: retypes.h:1
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
return STATUS_SUCCESS
Definition: btrfs.c:2938
signed int * PLONG
Definition: retypes.h:5
unsigned int * PUINT
Definition: ndis.h:50