ReactOS  0.4.14-dev-52-g6116262
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  */
10 
11 /* INCLUDES *******************************************************************/
12 
13 #include <consrv.h>
14 
15 #include <coninput.h>
16 
17 #define NDEBUG
18 #include <debug.h>
19 
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 already have a pause event, just exit... */
83  if (Console->UnpauseEvent) return;
84 
85  /* ... otherwise create it */
86  NtCreateEvent(&Console->UnpauseEvent, EVENT_ALL_ACCESS,
88 }
89 
90 VOID NTAPI
92 {
93  /* In case we already freed the event, just exit... */
94  if (!Console->UnpauseEvent) return;
95 
96  /* ... otherwise set and free it */
97  NtSetEvent(Console->UnpauseEvent, NULL);
98  NtClose(Console->UnpauseEvent);
99  Console->UnpauseEvent = NULL;
100 }
101 
102 
103 /*
104  * Console accessibility check helpers
105  */
106 
109  IN CONSOLE_STATE ExpectedState)
110 {
111  // if (!Console) return FALSE;
112 
113  /* The console must be locked */
114  // ASSERT(Console_locked);
115 
116  return (Console->State == ExpectedState);
117 }
118 
121  IN CONSOLE_STATE ExpectedState,
122  IN BOOLEAN LockConsole)
123 {
124  if (!Console) return FALSE;
125 
126  /*
127  * Lock the console to forbid possible console's state changes
128  * (which must be done when the console is already locked).
129  * If we don't want to lock it, it's because the lock is already
130  * held. So there must be no problems.
131  */
132  if (LockConsole) EnterCriticalSection(&Console->Lock);
133 
134  // ASSERT(Console_locked);
135 
136  /* Check whether the console's state is what we expect */
137  if (!ConDrvValidateConsoleState(Console, ExpectedState))
138  {
139  if (LockConsole) LeaveCriticalSection(&Console->Lock);
140  return FALSE;
141  }
142 
143  return TRUE;
144 }
145 
146 
147 /* CONSOLE INITIALIZATION FUNCTIONS *******************************************/
148 
149 VOID NTAPI
151 {
152  DPRINT("CONSRV: ConDrvInitConsoleSupport()\n");
153 
154  /* Initialize the console list and its lock */
157 }
158 
159 /* For resetting the terminal - defined in dummyterm.c */
161 
165 {
167  // CONSOLE_INFO CapturedConsoleInfo;
170  PCONSOLE_SCREEN_BUFFER NewBuffer;
171 
172  if (NewConsole == NULL || ConsoleInfo == NULL)
174 
175  *NewConsole = NULL;
176 
177  /*
178  * Allocate a new console
179  */
181  if (NULL == Console)
182  {
183  DPRINT1("Not enough memory for console creation.\n");
184  return STATUS_NO_MEMORY;
185  }
186 
187  /*
188  * Fix the screen buffer size if needed. The rule is:
189  * ScreenBufferSize >= ConsoleSize
190  */
191  if (ConsoleInfo->ScreenBufferSize.X < ConsoleInfo->ConsoleSize.X)
192  ConsoleInfo->ScreenBufferSize.X = ConsoleInfo->ConsoleSize.X;
193  if (ConsoleInfo->ScreenBufferSize.Y < ConsoleInfo->ConsoleSize.Y)
194  ConsoleInfo->ScreenBufferSize.Y = ConsoleInfo->ConsoleSize.Y;
195 
196  /*
197  * Initialize the console
198  */
199  Console->State = CONSOLE_INITIALIZING;
200  Console->ReferenceCount = 0;
202 
203  /* Initialize the terminal interface */
205 
206  Console->ConsoleSize = ConsoleInfo->ConsoleSize;
207  Console->FixedSize = FALSE; // Value by default; is reseted by the terminals if needed.
208 
209  /* Initialize the input buffer */
210  Status = ConDrvInitInputBuffer(Console, 0 /* ConsoleInfo->InputBufferSize */);
211  if (!NT_SUCCESS(Status))
212  {
213  DPRINT1("ConDrvInitInputBuffer: failed, Status = 0x%08lx\n", Status);
216  return Status;
217  }
218 
219  /* Set-up the code page */
220  if (IsValidCodePage(ConsoleInfo->CodePage))
221  Console->InputCodePage = Console->OutputCodePage = ConsoleInfo->CodePage;
222 
223  /* Initialize a new text-mode screen buffer with default settings */
224  ScreenBufferInfo.ScreenBufferSize = ConsoleInfo->ScreenBufferSize;
225  ScreenBufferInfo.ScreenAttrib = ConsoleInfo->ScreenAttrib;
226  ScreenBufferInfo.PopupAttrib = ConsoleInfo->PopupAttrib;
227  ScreenBufferInfo.IsCursorVisible = TRUE;
228  ScreenBufferInfo.CursorSize = ConsoleInfo->CursorSize;
229 
230  InitializeListHead(&Console->BufferList);
231  Status = ConDrvCreateScreenBuffer(&NewBuffer,
232  Console,
233  NULL,
236  if (!NT_SUCCESS(Status))
237  {
238  DPRINT1("ConDrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
242  return Status;
243  }
244  /* Make the new screen buffer active */
245  Console->ActiveBuffer = NewBuffer;
246  Console->UnpauseEvent = NULL;
247 
248  DPRINT("Console initialized\n");
249 
250  /* All went right, so add the console to the list */
252  if (!NT_SUCCESS(Status))
253  {
254  /* Fail */
256  return Status;
257  }
258 
259  /* The initialization is finished */
260  DPRINT("Change state\n");
261  Console->State = CONSOLE_RUNNING;
262 
263  /* Return the newly created console to the caller and a success code too */
264  *NewConsole = Console;
265  return STATUS_SUCCESS;
266 }
267 
270  IN PTERMINAL Terminal)
271 {
273 
274  if (Console == NULL || Terminal == NULL)
276 
277  /* FIXME: Lock the console before ?? */
278 
279  /*
280  * Attach the terminal to the console. Use now the TermIFace of the console,
281  * and not the user-defined temporary Terminal pointer.
282  */
283  Console->TermIFace = *Terminal;
284  Console->TermIFace.Console = Console;
285 
286  /* Initialize the terminal AFTER having attached it to the console */
287  DPRINT("Finish initialization of terminal\n");
288  Status = Console->TermIFace.Vtbl->InitTerminal(&Console->TermIFace, Console);
289  if (!NT_SUCCESS(Status))
290  {
291  DPRINT1("Terminal initialization failed, Status = 0x%08lx\n", Status);
292 
293  /* We failed, detach the terminal from the console */
294  Terminal->Console = NULL; // For the caller
296  return Status;
297  }
298 
299  /* Copy buffer contents to screen */
300  // Terminal.Draw();
301 
302  DPRINT("Terminal initialization done\n");
303  return STATUS_SUCCESS;
304 }
305 
308 {
309  if (Console == NULL) return STATUS_INVALID_PARAMETER;
310 
311  /* FIXME: Lock the console before ?? */
312 
313  /* Deinitialize the terminal BEFORE detaching it from the console */
314  Console->TermIFace.Vtbl->DeinitTerminal(&Console->TermIFace/*, Console*/);
315 
316  /*
317  * Detach the terminal from the console:
318  * reinitialize the terminal interface.
319  */
321 
322  DPRINT("Terminal unregistered\n");
323  return STATUS_SUCCESS;
324 }
325 
326 VOID NTAPI
328 {
329  DPRINT("ConDrvDeleteConsole(0x%p)\n", Console);
330 
331  /*
332  * Forbid validation of any console by other threads
333  * during the deletion of this console.
334  */
336 
337  /*
338  * If the console is already being destroyed, i.e. not running
339  * or finishing to be initialized, just return.
340  */
343  {
344  /* Unlock the console list and return */
346  return;
347  }
348 
349  /*
350  * We are about to be destroyed. Signal it to other people
351  * so that they can terminate what they are doing, and that
352  * they cannot longer validate the console.
353  */
354  Console->State = CONSOLE_TERMINATING;
355 
356  /*
357  * Allow other threads to finish their job: basically, unlock
358  * all other calls to EnterCriticalSection(&Console->Lock); by
359  * ConDrvValidateConsoleUnsafe functions so that they just see
360  * that we are not in CONSOLE_RUNNING state anymore, or unlock
361  * other concurrent calls to ConDrvDeleteConsole so that they
362  * can see that we are in fact already deleting the console.
363  */
366 
367  /* Deregister the terminal */
368  DPRINT("Deregister terminal\n");
370  DPRINT("Terminal deregistered\n");
371 
372  /***
373  * Check that the console is in terminating state before continuing
374  * (the cleanup code must not change the state of the console...
375  * ...unless to cancel console deletion ?).
376  ***/
377 
379 
381  {
383  return;
384  }
385 
386  /* We are now in destruction */
388 
389  /* We really delete the console. Reset the count to be sure. */
390  Console->ReferenceCount = 0;
391 
392  /* Remove the console from the list */
394 
395  /* Delete the last screen buffer */
396  ConDrvDeleteScreenBuffer(Console->ActiveBuffer);
397  Console->ActiveBuffer = NULL;
398  if (!IsListEmpty(&Console->BufferList))
399  {
400  /***ConDrvUnlockConsoleList();***/
401  ASSERTMSG("BUGBUGBUG!! screen buffer list not empty\n", FALSE);
402  }
403 
404  /* Deinitialize the input buffer */
406 
407  if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
408 
409  DPRINT("ConDrvDeleteConsole - Unlocking\n");
411  DPRINT("ConDrvDeleteConsole - Destroying lock\n");
413  DPRINT("ConDrvDeleteConsole - Lock destroyed ; freeing console\n");
414 
416  DPRINT("ConDrvDeleteConsole - Console destroyed\n");
417 
418  /* Unlock the console list and return */
420 }
421 
422 
423 /* PUBLIC DRIVER APIS *********************************************************/
424 
428  OUT PULONG ConsoleMode)
429 {
431 
432  if (Console == NULL || Object == NULL || ConsoleMode == NULL)
434 
435  /* Validity check */
436  ASSERT(Console == Object->Console);
437 
438  /*** FIXME: */ *ConsoleMode = 0; /***/
439 
440  if (INPUT_BUFFER == Object->Type)
441  {
443  *ConsoleMode = InputBuffer->Mode;
444  }
445  else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
446  {
448  *ConsoleMode = Buffer->Mode;
449  }
450  else
451  {
453  }
454 
455  return Status;
456 }
457 
461  IN ULONG ConsoleMode)
462 {
463 #define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \
464  ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \
465  ENABLE_MOUSE_INPUT )
466 #define CONSOLE_VALID_OUTPUT_MODES ( ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT )
467 
469 
470  if (Console == NULL || Object == NULL)
472 
473  /* Validity check */
474  ASSERT(Console == Object->Console);
475 
476  if (INPUT_BUFFER == Object->Type)
477  {
479 
480  /* Only the presence of valid mode flags is allowed */
481  if (ConsoleMode & ~CONSOLE_VALID_INPUT_MODES)
482  {
484  }
485  else
486  {
487  InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
488  }
489  }
490  else if (TEXTMODE_BUFFER == Object->Type || GRAPHICS_BUFFER == Object->Type)
491  {
493 
494  /* Only the presence of valid mode flags is allowed */
495  if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
496  {
498  }
499  else
500  {
501  Buffer->Mode = (ConsoleMode & CONSOLE_VALID_OUTPUT_MODES);
502  }
503  }
504  else
505  {
507  }
508 
509  return Status;
510 }
511 
514  OUT PUINT CodePage,
515  IN BOOLEAN OutputCP)
516 {
517  if (Console == NULL || CodePage == NULL)
519 
520  *CodePage = (OutputCP ? Console->OutputCodePage : Console->InputCodePage);
521 
522  return STATUS_SUCCESS;
523 }
524 
527  IN UINT CodePage,
528  IN BOOLEAN OutputCP)
529 {
530  if (Console == NULL || !IsValidCodePage(CodePage))
532 
533  if (OutputCP)
534  Console->OutputCodePage = CodePage;
535  else
536  Console->InputCodePage = CodePage;
537 
538  return STATUS_SUCCESS;
539 }
540 
541 /* EOF */
#define ConDrvUnlockConsoleList()
Definition: console.c:35
BOOLEAN NTAPI ConDrvValidateConsoleState(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState)
Definition: console.c:108
#define IN
Definition: typedefs.h:38
static RTL_RESOURCE ListLock
Definition: console.c:27
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#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:307
CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo
Definition: notevil.c:38
VOID NTAPI ConDrvInitConsoleSupport(VOID)
Definition: console.c:150
#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
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:100
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:426
_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:91
NTSTATUS NTAPI ConDrvSetConsoleMode(IN PCONSOLE Console, IN PCONSOLE_IO_OBJECT Object, IN ULONG ConsoleMode)
Definition: console.c:459
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
VOID NTAPI ConDrvDeleteConsole(IN PCONSOLE Console)
Definition: console.c:327
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 EVENT_ALL_ACCESS
Definition: isotest.c:82
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
VOID NTAPI ConDrvDeinitInputBuffer(IN PCONSOLE Console)
Definition: coninput.c:217
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)
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:458
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
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
NTSTATUS NTAPI ConDrvAttachTerminal(IN PCONSOLE Console, IN PTERMINAL Terminal)
Definition: console.c:269
VOID ResetTerminal(IN PCONSOLE Console)
Definition: dummyterm.c:156
Definition: typedefs.h:117
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:526
BOOL WINAPI IsValidCodePage(UINT CodePage)
Definition: nls.c:1468
NTSTATUS NTAPI ConDrvInitInputBuffer(IN PCONSOLE Console, IN ULONG InputBufferSize)
Definition: coninput.c:189
#define CONSOLE_TEXTMODE_BUFFER
Definition: wincon.h:59
BOOLEAN NTAPI ConDrvValidateConsoleUnsafe(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState, IN BOOLEAN LockConsole)
Definition: console.c:120
#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:513
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:163
#define OUT
Definition: typedefs.h:39
#define CONSOLE_VALID_OUTPUT_MODES
unsigned int ULONG
Definition: retypes.h:1
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
return STATUS_SUCCESS
Definition: btrfs.c:2966
signed int * PLONG
Definition: retypes.h:5
unsigned int * PUINT
Definition: ndis.h:50