Code reorganization only.

svn path=/branches/ros-csrss/; revision=58618
This commit is contained in:
Hermès Bélusca-Maïto 2013-03-30 21:25:27 +00:00
parent ac02b55ded
commit 22ecec636a
10 changed files with 329 additions and 296 deletions

View file

@ -0,0 +1,14 @@
/*
* LICENSE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
* FILE: win32ss/user/consrv/alias.h
* PURPOSE: Alias support functions
* PROGRAMMERS: Christoph Wittich
* Johannes Anderwald
*/
#pragma once
VOID IntDeleteAllAliases(struct _ALIAS_HEADER *RootHeader);
/* EOF */

View file

@ -10,6 +10,7 @@
#include "consrv.h"
#include "conio.h"
#include "lineinput.h"
#define NDEBUG
#include <debug.h>

View file

@ -277,12 +277,4 @@ NTSTATUS FASTCALL ConSrvCreateScreenBuffer(IN OUT PCONSOLE Console,
VOID WINAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
DWORD FASTCALL ConioEffectiveCursorSize(PCONSOLE Console, DWORD Scale);
/* alias.c */
VOID IntDeleteAllAliases(struct _ALIAS_HEADER *RootHeader);
/* lineinput.c */
struct _HISTORY_BUFFER;
VOID FASTCALL HistoryDeleteBuffer(struct _HISTORY_BUFFER *Hist);
VOID FASTCALL LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent);
/* EOF */

View file

@ -13,6 +13,8 @@
#include "consrv.h"
#include "conio.h"
#include "alias.h"
#include "lineinput.h"
#include "settings.h"
#include "frontends/gui/guiterm.h"
@ -22,6 +24,7 @@
#endif
#include "console.h"
#include "resource.h"
#include <shlwapi.h>
#include <shlobj.h>
@ -31,8 +34,17 @@
/* GLOBALS ********************************************************************/
LIST_ENTRY ConsoleList; /* The list of all the allocated consoles */
/*static*/ RTL_RESOURCE ListLock;
static LIST_ENTRY ConsoleList; /* The list of all the allocated consoles */
static RTL_RESOURCE ListLock;
#define ConSrvLockConsoleListExclusive() \
RtlAcquireResourceExclusive(&ListLock, TRUE)
#define ConSrvLockConsoleListShared() \
RtlAcquireResourceShared(&ListLock, TRUE)
#define ConSrvUnlockConsoleList() \
RtlReleaseResource(&ListLock)
/* PRIVATE FUNCTIONS **********************************************************/
@ -572,7 +584,7 @@ ConSrvDeleteConsole(PCONSOLE Console)
ConSrvLockConsoleListExclusive();
/* Check the existence of the console, and if it's ok, continue */
if (!ConSrvValidatePointer(Console))
if (!ConSrvValidateConsolePointer(Console))
{
/* Unlock the console list and return */
ConSrvUnlockConsoleList();
@ -622,7 +634,7 @@ ConSrvDeleteConsole(PCONSOLE Console)
ConSrvLockConsoleListExclusive();
/* Re-check the existence of the console, and if it's ok, continue */
if (!ConSrvValidatePointer(Console))
if (!ConSrvValidateConsolePointer(Console))
{
/* Unlock the console list and return */
ConSrvUnlockConsoleList();
@ -654,8 +666,8 @@ ConSrvDeleteConsole(PCONSOLE Console)
if (Console->LineBuffer)
RtlFreeHeap(ConSrvHeap, 0, Console->LineBuffer);
while (!IsListEmpty(&Console->HistoryBuffers))
HistoryDeleteBuffer((struct _HISTORY_BUFFER *)Console->HistoryBuffers.Flink);
HistoryDeleteBuffers(Console);
ConioDeleteScreenBuffer(Console->ActiveBuffer);
if (!IsListEmpty(&Console->BufferList))
@ -683,6 +695,94 @@ ConSrvDeleteConsole(PCONSOLE Console)
ConSrvUnlockConsoleList();
}
BOOL FASTCALL
ConSrvValidateConsolePointer(PCONSOLE Console)
{
PLIST_ENTRY ConsoleEntry;
PCONSOLE CurrentConsole = NULL;
if (!Console) return FALSE;
/* The console list must be locked */
// ASSERT(Console_list_locked);
ConsoleEntry = ConsoleList.Flink;
while (ConsoleEntry != &ConsoleList)
{
CurrentConsole = CONTAINING_RECORD(ConsoleEntry, CONSOLE, Entry);
ConsoleEntry = ConsoleEntry->Flink;
if (CurrentConsole == Console) return TRUE;
}
return FALSE;
}
BOOL FASTCALL
ConSrvValidateConsoleState(PCONSOLE Console,
CONSOLE_STATE ExpectedState)
{
// if (!Console) return FALSE;
/* The console must be locked */
// ASSERT(Console_locked);
return (Console->State == ExpectedState);
}
BOOL FASTCALL
ConSrvValidateConsoleUnsafe(PCONSOLE Console,
CONSOLE_STATE ExpectedState,
BOOL LockConsole)
{
if (!Console) return FALSE;
/*
* Lock the console to forbid possible console's state changes
* (which must be done when the console is already locked).
* If we don't want to lock it, it's because the lock is already
* held. So there must be no problems.
*/
if (LockConsole) EnterCriticalSection(&Console->Lock);
// ASSERT(Console_locked);
/* Check whether the console's state is what we expect */
if (!ConSrvValidateConsoleState(Console, ExpectedState))
{
if (LockConsole) LeaveCriticalSection(&Console->Lock);
return FALSE;
}
return TRUE;
}
BOOL FASTCALL
ConSrvValidateConsole(PCONSOLE Console,
CONSOLE_STATE ExpectedState,
BOOL LockConsole)
{
BOOL RetVal = FALSE;
if (!Console) return FALSE;
/*
* Forbid creation or deletion of consoles when
* checking for the existence of a console.
*/
ConSrvLockConsoleListShared();
if (ConSrvValidateConsolePointer(Console))
{
RetVal = ConSrvValidateConsoleUnsafe(Console,
ExpectedState,
LockConsole);
}
/* Unlock the console list and return */
ConSrvUnlockConsoleList();
return RetVal;
}
/* PUBLIC SERVER APIS *********************************************************/

View file

@ -8,18 +8,6 @@
#pragma once
#define ConSrvLockConsoleListExclusive() \
RtlAcquireResourceExclusive(&ListLock, TRUE)
#define ConSrvLockConsoleListShared() \
RtlAcquireResourceShared(&ListLock, TRUE)
#define ConSrvUnlockConsoleList() \
RtlReleaseResource(&ListLock)
extern LIST_ENTRY ConsoleList;
extern RTL_RESOURCE ListLock;
#if 0
/*
* WARNING: Change the state of the console ONLY when the console is locked !
@ -39,7 +27,7 @@ NTSTATUS WINAPI ConSrvInitConsole(OUT PCONSOLE* NewConsole,
IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
IN PCSR_PROCESS ConsoleLeaderProcess);
VOID WINAPI ConSrvDeleteConsole(PCONSOLE Console);
BOOL FASTCALL ConSrvValidatePointer(PCONSOLE Console);
BOOL FASTCALL ConSrvValidateConsolePointer(PCONSOLE Console);
BOOL FASTCALL ConSrvValidateConsoleState(PCONSOLE Console,
CONSOLE_STATE ExpectedState);
BOOL FASTCALL ConSrvValidateConsoleUnsafe(PCONSOLE Console,

View file

@ -44,8 +44,6 @@
#include <win/console.h>
#include <win/conmsg.h>
#include "resource.h"
extern HINSTANCE ConSrvDllInstance;
extern HANDLE ConSrvHeap;

View file

@ -182,7 +182,7 @@ ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData,
return STATUS_SUCCESS;
}
static NTSTATUS
NTSTATUS
ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
IN PCONSOLE_PROCESS_DATA TargetProcessData)
{
@ -564,98 +564,6 @@ ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
}
BOOL
FASTCALL
ConSrvValidatePointer(PCONSOLE Console)
{
PLIST_ENTRY ConsoleEntry;
PCONSOLE CurrentConsole = NULL;
if (!Console) return FALSE;
/* The console list must be locked */
// ASSERT(Console_list_locked);
ConsoleEntry = ConsoleList.Flink;
while (ConsoleEntry != &ConsoleList)
{
CurrentConsole = CONTAINING_RECORD(ConsoleEntry, CONSOLE, Entry);
ConsoleEntry = ConsoleEntry->Flink;
if (CurrentConsole == Console) return TRUE;
}
return FALSE;
}
BOOL
FASTCALL
ConSrvValidateConsoleState(PCONSOLE Console,
CONSOLE_STATE ExpectedState)
{
// if (!Console) return FALSE;
/* The console must be locked */
// ASSERT(Console_locked);
return (Console->State == ExpectedState);
}
BOOL
FASTCALL
ConSrvValidateConsoleUnsafe(PCONSOLE Console,
CONSOLE_STATE ExpectedState,
BOOL LockConsole)
{
if (!Console) return FALSE;
/*
* Lock the console to forbid possible console's state changes
* (which must be done when the console is already locked).
* If we don't want to lock it, it's because the lock is already
* held. So there must be no problems.
*/
if (LockConsole) EnterCriticalSection(&Console->Lock);
// ASSERT(Console_locked);
/* Check whether the console's state is what we expect */
if (!ConSrvValidateConsoleState(Console, ExpectedState))
{
if (LockConsole) LeaveCriticalSection(&Console->Lock);
return FALSE;
}
return TRUE;
}
BOOL
FASTCALL
ConSrvValidateConsole(PCONSOLE Console,
CONSOLE_STATE ExpectedState,
BOOL LockConsole)
{
BOOL RetVal = FALSE;
if (!Console) return FALSE;
/*
* Forbid creation or deletion of consoles when
* checking for the existence of a console.
*/
ConSrvLockConsoleListShared();
if (ConSrvValidatePointer(Console))
{
RetVal = ConSrvValidateConsoleUnsafe(Console,
ExpectedState,
LockConsole);
}
/* Unlock the console list and return */
ConSrvUnlockConsoleList();
return RetVal;
}
NTSTATUS
FASTCALL
ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
@ -711,179 +619,6 @@ ConSrvReleaseConsole(PCONSOLE Console,
if (RefCount <= 0) ConSrvDeleteConsole(Console);
}
NTSTATUS
NTAPI
ConSrvNewProcess(PCSR_PROCESS SourceProcess,
PCSR_PROCESS TargetProcess)
{
/**************************************************************************
* This function is called whenever a new process (GUI or CUI) is created.
*
* Copy the parent's handles table here if both the parent and the child
* processes are CUI. If we must actually create our proper console (and
* thus do not inherit from the console handles of the parent's), then we
* will clean this table in the next ConSrvConnect call. Why we are doing
* this? It's because here, we still don't know whether or not we must create
* a new console instead of inherit it from the parent, and, because in
* ConSrvConnect we don't have any reference to the parent process anymore.
**************************************************************************/
PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
/* An empty target process is invalid */
if (!TargetProcess) return STATUS_INVALID_PARAMETER;
TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
/**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
/* Initialize the new (target) process */
TargetProcessData->Process = TargetProcess;
TargetProcessData->ConsoleEvent = NULL;
TargetProcessData->Console = TargetProcessData->ParentConsole = NULL;
TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
// Testing
TargetProcessData->HandleTableSize = 0;
TargetProcessData->HandleTable = NULL;
RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
/* Do nothing if the source process is NULL */
if (!SourceProcess) return STATUS_SUCCESS;
SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
/*
* If both of the processes (parent and new child) are console applications,
* then try to inherit handles from the parent process.
*/
if ( SourceProcessData->Console != NULL && /* SourceProcessData->ConsoleApp */
TargetProcessData->ConsoleApp )
{
NTSTATUS Status;
Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
if (!NT_SUCCESS(Status)) return Status;
/* Temporary save the parent's console */
TargetProcessData->ParentConsole = SourceProcessData->Console;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ConSrvConnect(IN PCSR_PROCESS CsrProcess,
IN OUT PVOID ConnectionInfo,
IN OUT PULONG ConnectionInfoLength)
{
/**************************************************************************
* This function is called whenever a CUI new process is created.
**************************************************************************/
NTSTATUS Status = STATUS_SUCCESS;
PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
if ( ConnectionInfo == NULL ||
ConnectionInfoLength == NULL ||
*ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
{
DPRINT1("CONSRV: Connection failed\n");
return STATUS_UNSUCCESSFUL;
}
/* If we don't need a console, then get out of here */
if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
{
return STATUS_SUCCESS;
}
/* If we don't have a console, then create a new one... */
if (!ConnectInfo->Console ||
ConnectInfo->Console != ProcessData->ParentConsole)
{
DPRINT1("ConSrvConnect - Allocate a new console\n");
/*
* We are about to create a new console. However when ConSrvNewProcess
* was called, we didn't know that we wanted to create a new console and
* therefore, we by default inherited the handles table from our parent
* process. It's only now that we notice that in fact we do not need
* them, because we've created a new console and thus we must use it.
*
* Therefore, free the console we can have and our handles table,
* and recreate a new one later on.
*/
ConSrvRemoveConsole(ProcessData);
/* Initialize a new Console owned by the Console Leader Process */
Status = ConSrvAllocateConsole(ProcessData,
&ConnectInfo->InputHandle,
&ConnectInfo->OutputHandle,
&ConnectInfo->ErrorHandle,
&ConnectInfo->ConsoleStartInfo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console allocation failed\n");
return Status;
}
}
else /* We inherit it from the parent */
{
DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
/* Reuse our current console */
Status = ConSrvInheritConsole(ProcessData,
ConnectInfo->Console,
FALSE,
NULL, // &ConnectInfo->InputHandle,
NULL, // &ConnectInfo->OutputHandle,
NULL); // &ConnectInfo->ErrorHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console inheritance failed\n");
return Status;
}
}
/* Return it to the caller */
ConnectInfo->Console = ProcessData->Console;
/* Input Wait Handle */
ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent;
/* Set the Property Dialog Handler */
ProcessData->PropDispatcher = ConnectInfo->PropDispatcher;
/* Set the Ctrl Dispatcher */
ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
return STATUS_SUCCESS;
}
VOID
NTAPI
ConSrvDisconnect(PCSR_PROCESS Process)
{
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
/**************************************************************************
* This function is called whenever a new process (GUI or CUI) is destroyed.
**************************************************************************/
if ( ProcessData->Console != NULL ||
ProcessData->HandleTable != NULL )
{
DPRINT1("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
ConSrvRemoveConsole(ProcessData);
}
RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
}
/* PUBLIC SERVER APIS *********************************************************/

View file

@ -300,6 +300,183 @@ PCHAR ConsoleServerApiNameTable[ConsolepMaxApiNumber - CONSRV_FIRST_API_NUMBER]
/* FUNCTIONS ******************************************************************/
NTSTATUS
ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
IN PCONSOLE_PROCESS_DATA TargetProcessData);
NTSTATUS
NTAPI
ConSrvNewProcess(PCSR_PROCESS SourceProcess,
PCSR_PROCESS TargetProcess)
{
/**************************************************************************
* This function is called whenever a new process (GUI or CUI) is created.
*
* Copy the parent's handles table here if both the parent and the child
* processes are CUI. If we must actually create our proper console (and
* thus do not inherit from the console handles of the parent's), then we
* will clean this table in the next ConSrvConnect call. Why we are doing
* this? It's because here, we still don't know whether or not we must create
* a new console instead of inherit it from the parent, and, because in
* ConSrvConnect we don't have any reference to the parent process anymore.
**************************************************************************/
PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
/* An empty target process is invalid */
if (!TargetProcess) return STATUS_INVALID_PARAMETER;
TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
/**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
/* Initialize the new (target) process */
TargetProcessData->Process = TargetProcess;
TargetProcessData->ConsoleEvent = NULL;
TargetProcessData->Console = TargetProcessData->ParentConsole = NULL;
TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
// Testing
TargetProcessData->HandleTableSize = 0;
TargetProcessData->HandleTable = NULL;
RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
/* Do nothing if the source process is NULL */
if (!SourceProcess) return STATUS_SUCCESS;
SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
/*
* If both of the processes (parent and new child) are console applications,
* then try to inherit handles from the parent process.
*/
if ( SourceProcessData->Console != NULL && /* SourceProcessData->ConsoleApp */
TargetProcessData->ConsoleApp )
{
NTSTATUS Status;
Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
if (!NT_SUCCESS(Status)) return Status;
/* Temporary save the parent's console */
TargetProcessData->ParentConsole = SourceProcessData->Console;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ConSrvConnect(IN PCSR_PROCESS CsrProcess,
IN OUT PVOID ConnectionInfo,
IN OUT PULONG ConnectionInfoLength)
{
/**************************************************************************
* This function is called whenever a CUI new process is created.
**************************************************************************/
NTSTATUS Status = STATUS_SUCCESS;
PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
if ( ConnectionInfo == NULL ||
ConnectionInfoLength == NULL ||
*ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
{
DPRINT1("CONSRV: Connection failed\n");
return STATUS_UNSUCCESSFUL;
}
/* If we don't need a console, then get out of here */
if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
{
return STATUS_SUCCESS;
}
/* If we don't have a console, then create a new one... */
if (!ConnectInfo->Console ||
ConnectInfo->Console != ProcessData->ParentConsole)
{
DPRINT1("ConSrvConnect - Allocate a new console\n");
/*
* We are about to create a new console. However when ConSrvNewProcess
* was called, we didn't know that we wanted to create a new console and
* therefore, we by default inherited the handles table from our parent
* process. It's only now that we notice that in fact we do not need
* them, because we've created a new console and thus we must use it.
*
* Therefore, free the console we can have and our handles table,
* and recreate a new one later on.
*/
ConSrvRemoveConsole(ProcessData);
/* Initialize a new Console owned by the Console Leader Process */
Status = ConSrvAllocateConsole(ProcessData,
&ConnectInfo->InputHandle,
&ConnectInfo->OutputHandle,
&ConnectInfo->ErrorHandle,
&ConnectInfo->ConsoleStartInfo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console allocation failed\n");
return Status;
}
}
else /* We inherit it from the parent */
{
DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
/* Reuse our current console */
Status = ConSrvInheritConsole(ProcessData,
ConnectInfo->Console,
FALSE,
NULL, // &ConnectInfo->InputHandle,
NULL, // &ConnectInfo->OutputHandle,
NULL); // &ConnectInfo->ErrorHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console inheritance failed\n");
return Status;
}
}
/* Return it to the caller */
ConnectInfo->Console = ProcessData->Console;
/* Input Wait Handle */
ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent;
/* Set the Property Dialog Handler */
ProcessData->PropDispatcher = ConnectInfo->PropDispatcher;
/* Set the Ctrl Dispatcher */
ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
return STATUS_SUCCESS;
}
VOID
NTAPI
ConSrvDisconnect(PCSR_PROCESS Process)
{
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
/**************************************************************************
* This function is called whenever a new process (GUI or CUI) is destroyed.
**************************************************************************/
if ( ProcessData->Console != NULL ||
ProcessData->HandleTable != NULL )
{
DPRINT1("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
ConSrvRemoveConsole(ProcessData);
}
RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
}
CSR_SERVER_DLL_INIT(ConServerDllInitialization)
{
/* Initialize the memory */

View file

@ -138,7 +138,7 @@ HistoryFindBuffer(PCONSOLE Console, PUNICODE_STRING ExeName)
return NULL;
}
VOID FASTCALL
static VOID
HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
{
if (!Hist) return;
@ -151,6 +151,20 @@ HistoryDeleteBuffer(PHISTORY_BUFFER Hist)
RtlFreeHeap(ConSrvHeap, 0, Hist);
}
VOID FASTCALL
HistoryDeleteBuffers(PCONSOLE Console)
{
PLIST_ENTRY CurrentEntry;
PHISTORY_BUFFER HistoryBuffer;
while (!IsListEmpty(&Console->HistoryBuffers))
{
CurrentEntry = RemoveHeadList(&Console->HistoryBuffers);
HistoryBuffer = CONTAINING_RECORD(CurrentEntry, HISTORY_BUFFER, ListEntry);
HistoryDeleteBuffer(HistoryBuffer);
}
}
static VOID
LineInputSetPos(PCONSOLE Console, UINT Pos)
{

View file

@ -0,0 +1,14 @@
/*
* LICENSE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
* FILE: win32ss/user/consrv/lineinput.c
* PURPOSE: Console line input functions
* PROGRAMMERS: Jeffrey Morlan
*/
#pragma once
VOID FASTCALL HistoryDeleteBuffers(PCONSOLE Console);
VOID FASTCALL LineInputKeyDown(PCONSOLE Console, KEY_EVENT_RECORD *KeyEvent);
/* EOF */