ReactOS  0.4.15-dev-494-g1d8c567
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 /* CONSOLE VALIDATION FUNCTIONS ***********************************************/
22 
25  IN CONSOLE_STATE ExpectedState)
26 {
27  // if (!Console) return FALSE;
28 
29  /* The console must be locked */
30  // ASSERT(Console_locked);
31 
32  return (Console->State == ExpectedState);
33 }
34 
37  IN CONSOLE_STATE ExpectedState,
38  IN BOOLEAN LockConsole)
39 {
40  if (!Console) return FALSE;
41 
42  /*
43  * Lock the console to forbid possible console's state changes
44  * (which must be done when the console is already locked).
45  * If we don't want to lock it, it's because the lock is already
46  * held. So there must be no problems.
47  */
48  if (LockConsole) EnterCriticalSection(&Console->Lock);
49 
50  // ASSERT(Console_locked);
51 
52  /* Check whether the console's state is what we expect */
53  if (!ConDrvValidateConsoleState(Console, ExpectedState))
54  {
55  if (LockConsole) LeaveCriticalSection(&Console->Lock);
56  return FALSE;
57  }
58 
59  return TRUE;
60 }
61 
62 
63 /* CONSOLE INITIALIZATION FUNCTIONS *******************************************/
64 
65 /* For resetting the terminal - defined in dummyterm.c */
67 
72 {
74  // CONSOLE_INFO CapturedConsoleInfo;
76  PCONSOLE_SCREEN_BUFFER NewBuffer;
77 
78  if (Console == NULL || ConsoleInfo == NULL)
80 
81  /* Reset the console structure */
82  RtlZeroMemory(Console, sizeof(*Console));
83 
84  /*
85  * Set and fix the screen buffer size if needed.
86  * The rule is: ScreenBufferSize >= ConsoleSize
87  */
88  if (ConsoleInfo->ScreenBufferSize.X == 0) ConsoleInfo->ScreenBufferSize.X = 1;
89  if (ConsoleInfo->ScreenBufferSize.Y == 0) ConsoleInfo->ScreenBufferSize.Y = 1;
90  if (ConsoleInfo->ScreenBufferSize.X < ConsoleInfo->ConsoleSize.X)
91  ConsoleInfo->ScreenBufferSize.X = ConsoleInfo->ConsoleSize.X;
92  if (ConsoleInfo->ScreenBufferSize.Y < ConsoleInfo->ConsoleSize.Y)
93  ConsoleInfo->ScreenBufferSize.Y = ConsoleInfo->ConsoleSize.Y;
94 
95  /*
96  * Initialize the console
97  */
99  Console->ReferenceCount = 0;
101 
102  /* Initialize the terminal interface */
104 
105  Console->ConsoleSize = ConsoleInfo->ConsoleSize;
106  Console->FixedSize = FALSE; // Value by default; is reseted by the terminals if needed.
107 
108  /* Initialize the input buffer */
109  Status = ConDrvInitInputBuffer(Console, 0 /* ConsoleInfo->InputBufferSize */);
110  if (!NT_SUCCESS(Status))
111  {
112  DPRINT1("ConDrvInitInputBuffer: failed, Status = 0x%08lx\n", Status);
114  return Status;
115  }
116 
117  /* Set-up the code page */
118  if (IsValidCodePage(ConsoleInfo->CodePage))
119  Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
120 
121  Console->IsCJK = IsCJKCodePage(Console->OutputCodePage);
122 
123  /* Initialize a new text-mode screen buffer with default settings */
124  ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
125  ScreenBufferInfo.ViewSize = ConsoleInfo->ConsoleSize;
126  ScreenBufferInfo.ScreenAttrib = ConsoleInfo->ScreenAttrib;
127  ScreenBufferInfo.PopupAttrib = ConsoleInfo->PopupAttrib;
128  ScreenBufferInfo.CursorSize = ConsoleInfo->CursorSize;
129  ScreenBufferInfo.IsCursorVisible = TRUE;
130 
131  InitializeListHead(&Console->BufferList);
132  Status = ConDrvCreateScreenBuffer(&NewBuffer,
133  Console,
134  NULL,
137  if (!NT_SUCCESS(Status))
138  {
139  DPRINT1("ConDrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
142  return Status;
143  }
144  /* Make the new screen buffer active */
145  Console->ActiveBuffer = NewBuffer;
146  Console->ConsolePaused = FALSE;
147 
148  DPRINT("Console initialized\n");
149 
150  /* The initialization is finished */
151  DPRINT("Change state\n");
152  Console->State = CONSOLE_RUNNING;
153 
154  /* The caller now has a newly initialized console */
155  return STATUS_SUCCESS;
156 }
157 
160  IN PTERMINAL Terminal)
161 {
163 
164  if (Console == NULL || Terminal == NULL)
166 
167  /* FIXME: Lock the console before ?? */
168 
169  /*
170  * Attach the terminal to the console. Use now the TermIFace of the console,
171  * and not the user-defined temporary Terminal pointer.
172  */
173  Console->TermIFace = *Terminal;
174  Console->TermIFace.Console = Console;
175 
176  /* Initialize the terminal AFTER having attached it to the console */
177  DPRINT("Finish initialization of terminal\n");
178  Status = Console->TermIFace.Vtbl->InitTerminal(&Console->TermIFace, Console);
179  if (!NT_SUCCESS(Status))
180  {
181  DPRINT1("Terminal initialization failed, Status = 0x%08lx\n", Status);
182 
183  /* We failed, detach the terminal from the console */
184  Terminal->Console = NULL; // For the caller
186  return Status;
187  }
188 
189  /* Copy buffer contents to screen */
190  // Terminal.Draw();
191 
192  DPRINT("Terminal initialization done\n");
193  return STATUS_SUCCESS;
194 }
195 
198 {
199  if (Console == NULL) return STATUS_INVALID_PARAMETER;
200 
201  /* FIXME: Lock the console before ?? */
202 
203  /* Deinitialize the terminal BEFORE detaching it from the console */
204  Console->TermIFace.Vtbl->DeinitTerminal(&Console->TermIFace/*, Console*/);
205 
206  /*
207  * Detach the terminal from the console:
208  * reinitialize the terminal interface.
209  */
211 
212  DPRINT("Terminal unregistered\n");
213  return STATUS_SUCCESS;
214 }
215 
216 VOID NTAPI
218 {
219  DPRINT("ConDrvDeleteConsole(0x%p)\n", Console);
220 
221  /*
222  * Forbid validation of any console by other threads
223  * during the deletion of this console.
224  */
225  // ConDrvLockConsoleListExclusive();
226 
227  /*
228  * If the console is already being destroyed, i.e. not running
229  * or finishing to be initialized, just return.
230  */
233  {
234  return;
235  }
236 
237  /*
238  * We are about to be destroyed. Signal it to other people
239  * so that they can terminate what they are doing, and that
240  * they cannot longer validate the console.
241  */
242  Console->State = CONSOLE_TERMINATING;
243 
244  /*
245  * Allow other threads to finish their job: basically, unlock
246  * all other calls to EnterCriticalSection(&Console->Lock); by
247  * ConDrvValidateConsoleUnsafe() functions so that they just see
248  * that we are not in CONSOLE_RUNNING state anymore, or unlock
249  * other concurrent calls to ConDrvDeleteConsole() so that they
250  * can see that we are in fact already deleting the console.
251  */
253 
254  /* Deregister the terminal */
255  DPRINT("Deregister terminal\n");
257  DPRINT("Terminal deregistered\n");
258 
259  /***
260  * Check that the console is in terminating state before continuing
261  * (the cleanup code must not change the state of the console...
262  * ...unless to cancel console deletion ?).
263  ***/
264 
266  {
267  return;
268  }
269 
270  /* We are now in destruction */
272 
273  /* We really delete the console. Reset the count to be sure. */
274  Console->ReferenceCount = 0;
275 
276  /* Delete the last screen buffer */
277  ConDrvDeleteScreenBuffer(Console->ActiveBuffer);
278  Console->ActiveBuffer = NULL;
279  if (!IsListEmpty(&Console->BufferList))
280  {
281  /***ConDrvUnlockConsoleList();***/
282  ASSERTMSG("BUGBUGBUG!! screen buffer list not empty\n", FALSE);
283  }
284 
285  /* Deinitialize the input buffer */
287 
288  Console->ConsolePaused = FALSE;
289 
290  DPRINT("ConDrvDeleteConsole - Unlocking\n");
292  DPRINT("ConDrvDeleteConsole - Destroying lock\n");
294  DPRINT("ConDrvDeleteConsole - Lock destroyed\n");
295 
296  DPRINT("ConDrvDeleteConsole - Console destroyed\n");
297 }
298 
299 
300 /* PUBLIC DRIVER APIS *********************************************************/
301 
302 VOID NTAPI
304 {
305  /* In case we are already paused, just exit... */
306  if (Console->ConsolePaused) return;
307 
308  /* ... otherwise set the flag */
309  Console->ConsolePaused = TRUE;
310 }
311 
312 VOID NTAPI
314 {
315  /* In case we are already unpaused, just exit... */
316  if (!Console->ConsolePaused) return;
317 
318  /* ... otherwise reset the flag */
319  Console->ConsolePaused = FALSE;
320 }
321 
325  OUT PULONG ConsoleMode)
326 {
328 
329  if (Console == NULL || Object == NULL || ConsoleMode == NULL)
331 
332  /* Validity check */
333  ASSERT(Console == Object->Console);
334 
335  /*** FIXME: */ *ConsoleMode = 0; /***/
336 
337  if (INPUT_BUFFER == Object->Type)
338  {
340  *ConsoleMode = InputBuffer->Mode;
341  }
342  else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
343  {
345  *ConsoleMode = Buffer->Mode;
346  }
347  else
348  {
350  }
351 
352  return Status;
353 }
354 
358  IN ULONG ConsoleMode)
359 {
360 #define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \
361  ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \
362  ENABLE_MOUSE_INPUT )
363 #define CONSOLE_VALID_OUTPUT_MODES ( ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT )
364 
366 
367  if (Console == NULL || Object == NULL)
369 
370  /* Validity check */
371  ASSERT(Console == Object->Console);
372 
373  if (INPUT_BUFFER == Object->Type)
374  {
376 
377  /* Only the presence of valid mode flags is allowed */
378  if (ConsoleMode & ~CONSOLE_VALID_INPUT_MODES)
379  {
381  }
382  else
383  {
384  InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
385  }
386  }
387  else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
388  {
390 
391  /* Only the presence of valid mode flags is allowed */
392  if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
393  {
395  }
396  else
397  {
398  Buffer->Mode = (ConsoleMode & CONSOLE_VALID_OUTPUT_MODES);
399  }
400  }
401  else
402  {
404  }
405 
406  return Status;
407 }
408 
411  OUT PUINT CodePage,
412  IN BOOLEAN OutputCP)
413 {
414  if (Console == NULL || CodePage == NULL)
416 
417  *CodePage = (OutputCP ? Console->OutputCodePage : Console->InputCodePage);
418 
419  return STATUS_SUCCESS;
420 }
421 
424  IN UINT CodePage,
425  IN BOOLEAN OutputCP)
426 {
427  if (Console == NULL || !IsValidCodePage(CodePage))
429 
430  if (OutputCP)
431  {
432  Console->OutputCodePage = CodePage;
433  Console->IsCJK = IsCJKCodePage(CodePage);
434  }
435  else
436  {
437  Console->InputCodePage = CodePage;
438  }
439 
440  return STATUS_SUCCESS;
441 }
442 
443 /* EOF */
BOOLEAN NTAPI ConDrvValidateConsoleState(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState)
Definition: console.c:24
#define IN
Definition: typedefs.h:39
#define TRUE
Definition: types.h:120
VOID NTAPI ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
Definition: conoutput.c:130
NTSTATUS NTAPI ConDrvDetachTerminal(IN PCONSOLE Console)
Definition: console.c:197
CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo
Definition: notevil.c:38
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI ConDrvPause(PCONSOLE Console)
Definition: console.c:303
NTSTATUS ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER *Buffer, IN PCONSOLE Console, IN HANDLE ProcessHandle OPTIONAL, IN ULONG BufferType, IN PVOID ScreenBufferInfo)
Definition: conoutput.c:85
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
NTSTATUS NTAPI ConDrvGetConsoleMode(IN PCONSOLE Console, IN PCONSOLE_IO_OBJECT Object, OUT PULONG ConsoleMode)
Definition: console.c:323
_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:313
NTSTATUS NTAPI ConDrvSetConsoleMode(IN PCONSOLE Console, IN PCONSOLE_IO_OBJECT Object, IN ULONG ConsoleMode)
Definition: console.c:356
#define IsCJKCodePage(CodePage)
Definition: font.h:23
VOID NTAPI ConDrvDeleteConsole(IN PCONSOLE Console)
Definition: console.c:217
struct _CONSOLE_INPUT_BUFFER * PCONSOLE_INPUT_BUFFER
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
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
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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:159
VOID ResetTerminal(IN PCONSOLE Console)
Definition: dummyterm.c:156
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI ConDrvSetConsoleCP(IN PCONSOLE Console, IN UINT CodePage, IN BOOLEAN OutputCP)
Definition: console.c:423
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:36
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
Definition: video.c:47
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI ConDrvGetConsoleCP(IN PCONSOLE Console, OUT PUINT CodePage, IN BOOLEAN OutputCP)
Definition: console.c:410
unsigned int UINT
Definition: ndis.h:50
CConsole Console
#define DPRINT1
Definition: precomp.h:8
#define OUT
Definition: typedefs.h:40
#define CONSOLE_VALID_OUTPUT_MODES
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
return STATUS_SUCCESS
Definition: btrfs.c:3014
unsigned int * PUINT
Definition: ndis.h:50
NTSTATUS NTAPI ConDrvInitConsole(IN OUT PCONSOLE Console, IN PCONSOLE_INFO ConsoleInfo)
Definition: console.c:69