ReactOS  0.4.15-dev-4869-g35a816a
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  {
121  Console->InputCodePage = ConsoleInfo->CodePage;
122  }
123 
124  /* Initialize a new text-mode screen buffer with default settings */
125  ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
126  ScreenBufferInfo.ViewSize = ConsoleInfo->ConsoleSize;
127  ScreenBufferInfo.ScreenAttrib = ConsoleInfo->ScreenAttrib;
128  ScreenBufferInfo.PopupAttrib = ConsoleInfo->PopupAttrib;
129  ScreenBufferInfo.CursorSize = ConsoleInfo->CursorSize;
130  ScreenBufferInfo.IsCursorVisible = TRUE;
131 
132  InitializeListHead(&Console->BufferList);
133  Status = ConDrvCreateScreenBuffer(&NewBuffer,
134  Console,
135  NULL,
138  if (!NT_SUCCESS(Status))
139  {
140  DPRINT1("ConDrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
143  return Status;
144  }
145  /* Make the new screen buffer active */
146  Console->ActiveBuffer = NewBuffer;
147  Console->ConsolePaused = FALSE;
148 
149  DPRINT("Console initialized\n");
150 
151  /* The initialization is finished */
152  DPRINT("Change state\n");
153  Console->State = CONSOLE_RUNNING;
154 
155  /* The caller now has a newly initialized console */
156  return STATUS_SUCCESS;
157 }
158 
161  IN PTERMINAL Terminal)
162 {
164 
165  if (Console == NULL || Terminal == NULL)
167 
168  /* FIXME: Lock the console before ?? */
169 
170  /*
171  * Attach the terminal to the console. Use now the TermIFace of the console,
172  * and not the user-defined temporary Terminal pointer.
173  */
174  Console->TermIFace = *Terminal;
175  Console->TermIFace.Console = Console;
176 
177  /* Initialize the terminal AFTER having attached it to the console */
178  DPRINT("Finish initialization of terminal\n");
179  Status = Console->TermIFace.Vtbl->InitTerminal(&Console->TermIFace, Console);
180  if (!NT_SUCCESS(Status))
181  {
182  DPRINT1("Terminal initialization failed, Status = 0x%08lx\n", Status);
183 
184  /* We failed, detach the terminal from the console */
185  Terminal->Console = NULL; // For the caller
187  return Status;
188  }
189 
190  /* Copy buffer contents to screen */
191  // Terminal.Draw();
192 
193  DPRINT("Terminal initialization done\n");
194  return STATUS_SUCCESS;
195 }
196 
199 {
200  if (Console == NULL) return STATUS_INVALID_PARAMETER;
201 
202  /* FIXME: Lock the console before ?? */
203 
204  /* Deinitialize the terminal BEFORE detaching it from the console */
205  Console->TermIFace.Vtbl->DeinitTerminal(&Console->TermIFace/*, Console*/);
206 
207  /*
208  * Detach the terminal from the console:
209  * reinitialize the terminal interface.
210  */
212 
213  DPRINT("Terminal unregistered\n");
214  return STATUS_SUCCESS;
215 }
216 
217 VOID NTAPI
219 {
220  DPRINT("ConDrvDeleteConsole(0x%p)\n", Console);
221 
222  /*
223  * Forbid validation of any console by other threads
224  * during the deletion of this console.
225  */
226  // ConDrvLockConsoleListExclusive();
227 
228  /*
229  * If the console is already being destroyed, i.e. not running
230  * or finishing to be initialized, just return.
231  */
234  {
235  return;
236  }
237 
238  /*
239  * We are about to be destroyed. Signal it to other people
240  * so that they can terminate what they are doing, and that
241  * they cannot longer validate the console.
242  */
243  Console->State = CONSOLE_TERMINATING;
244 
245  /*
246  * Allow other threads to finish their job: basically, unlock
247  * all other calls to EnterCriticalSection(&Console->Lock); by
248  * ConDrvValidateConsoleUnsafe() functions so that they just see
249  * that we are not in CONSOLE_RUNNING state anymore, or unlock
250  * other concurrent calls to ConDrvDeleteConsole() so that they
251  * can see that we are in fact already deleting the console.
252  */
254 
255  /* Deregister the terminal */
256  DPRINT("Deregister terminal\n");
258  DPRINT("Terminal deregistered\n");
259 
260  /***
261  * Check that the console is in terminating state before continuing
262  * (the cleanup code must not change the state of the console...
263  * ...unless to cancel console deletion ?).
264  ***/
265 
267  {
268  return;
269  }
270 
271  /* We are now in destruction */
273 
274  /* We really delete the console. Reset the count to be sure. */
275  Console->ReferenceCount = 0;
276 
277  /* Delete the last screen buffer */
278  ConDrvDeleteScreenBuffer(Console->ActiveBuffer);
279  Console->ActiveBuffer = NULL;
280  if (!IsListEmpty(&Console->BufferList))
281  {
282  /***ConDrvUnlockConsoleList();***/
283  ASSERTMSG("BUGBUGBUG!! screen buffer list not empty\n", FALSE);
284  }
285 
286  /* Deinitialize the input buffer */
288 
289  Console->ConsolePaused = FALSE;
290 
291  DPRINT("ConDrvDeleteConsole - Unlocking\n");
293  DPRINT("ConDrvDeleteConsole - Destroying lock\n");
295  DPRINT("ConDrvDeleteConsole - Lock destroyed\n");
296 
297  DPRINT("ConDrvDeleteConsole - Console destroyed\n");
298 }
299 
300 
301 /* PUBLIC DRIVER APIS *********************************************************/
302 
303 VOID NTAPI
305 {
306  /* In case we are already paused, just exit... */
307  if (Console->ConsolePaused) return;
308 
309  /* ... otherwise set the flag */
310  Console->ConsolePaused = TRUE;
311 }
312 
313 VOID NTAPI
315 {
316  /* In case we are already unpaused, just exit... */
317  if (!Console->ConsolePaused) return;
318 
319  /* ... otherwise reset the flag */
320  Console->ConsolePaused = FALSE;
321 }
322 
326  OUT PULONG ConsoleMode)
327 {
329 
330  if (Console == NULL || Object == NULL || ConsoleMode == NULL)
332 
333  /* Validity check */
334  ASSERT(Console == Object->Console);
335 
336  /*** FIXME: */ *ConsoleMode = 0; /***/
337 
338  if (INPUT_BUFFER == Object->Type)
339  {
341  *ConsoleMode = InputBuffer->Mode;
342  }
343  else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
344  {
346  *ConsoleMode = Buffer->Mode;
347  }
348  else
349  {
351  }
352 
353  return Status;
354 }
355 
359  IN ULONG ConsoleMode)
360 {
361 #define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \
362  ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \
363  ENABLE_MOUSE_INPUT )
364 #define CONSOLE_VALID_OUTPUT_MODES ( ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT )
365 
367 
368  if (Console == NULL || Object == NULL)
370 
371  /* Validity check */
372  ASSERT(Console == Object->Console);
373 
374  if (INPUT_BUFFER == Object->Type)
375  {
377 
378  /* Only the presence of valid mode flags is allowed */
379  if (ConsoleMode & ~CONSOLE_VALID_INPUT_MODES)
380  {
382  }
383  else
384  {
385  InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
386  }
387  }
388  else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
389  {
391 
392  /* Only the presence of valid mode flags is allowed */
393  if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
394  {
396  }
397  else
398  {
399  Buffer->Mode = (ConsoleMode & CONSOLE_VALID_OUTPUT_MODES);
400  }
401  }
402  else
403  {
405  }
406 
407  return Status;
408 }
409 
412  OUT PUINT CodePage,
413  IN BOOLEAN OutputCP)
414 {
415  if (Console == NULL || CodePage == NULL)
417 
418  *CodePage = (OutputCP ? Console->OutputCodePage : Console->InputCodePage);
419 
420  return STATUS_SUCCESS;
421 }
422 
425  IN UINT CodePage,
426  IN BOOLEAN OutputCP)
427 {
428  if (Console == NULL || !IsValidCodePage(CodePage))
430 
431  if (OutputCP)
432  {
433  /* Request the terminal to change its code page support */
434  if (!TermSetCodePage(Console, CodePage))
435  return STATUS_UNSUCCESSFUL;
436 
437  /* All is fine, actually set the output code page */
438  CON_SET_OUTPUT_CP(Console, CodePage);
439  return STATUS_SUCCESS;
440  }
441  else
442  {
443  Console->InputCodePage = CodePage;
444  return STATUS_SUCCESS;
445  }
446 }
447 
448 /* EOF */
BOOLEAN NTAPI ConDrvValidateConsoleState(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState)
Definition: console.c:24
#define IN
Definition: typedefs.h:39
VOID NTAPI ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
Definition: conoutput.c:130
NTSTATUS NTAPI ConDrvDetachTerminal(IN PCONSOLE Console)
Definition: console.c:198
CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo
Definition: notevil.c:38
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI ConDrvPause(PCONSOLE Console)
Definition: console.c:304
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:324
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define CON_SET_OUTPUT_CP(Console, CodePage)
Definition: conio.h:323
VOID NTAPI ConDrvUnpause(PCONSOLE Console)
Definition: console.c:314
NTSTATUS NTAPI ConDrvSetConsoleMode(IN PCONSOLE Console, IN PCONSOLE_IO_OBJECT Object, IN ULONG ConsoleMode)
Definition: console.c:357
VOID NTAPI ConDrvDeleteConsole(IN PCONSOLE Console)
Definition: console.c:218
struct _CONSOLE_INPUT_BUFFER * PCONSOLE_INPUT_BUFFER
#define TermSetCodePage(Console, CodePage)
Definition: term.h:38
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h: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
Definition: bufpool.h:45
#define CONSOLE_VALID_INPUT_MODES
Status
Definition: gdiplustypes.h:24
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:949
#define ASSERT(a)
Definition: mode.c:44
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
NTSTATUS NTAPI ConDrvAttachTerminal(IN PCONSOLE Console, IN PTERMINAL Terminal)
Definition: console.c:160
VOID ResetTerminal(IN PCONSOLE Console)
Definition: dummyterm.c:164
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
NTSTATUS NTAPI ConDrvSetConsoleCP(IN PCONSOLE Console, IN UINT CodePage, IN BOOLEAN OutputCP)
Definition: console.c:424
BOOL WINAPI IsValidCodePage(UINT CodePage)
Definition: nls.c:1515
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:411
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
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:262
#define STATUS_SUCCESS
Definition: shellext.h:65
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define DPRINT
Definition: sndvol32.h:71
unsigned int * PUINT
Definition: ndis.h:50
NTSTATUS NTAPI ConDrvInitConsole(IN OUT PCONSOLE Console, IN PCONSOLE_INFO ConsoleInfo)
Definition: console.c:69