[KERNEL32][CONSRV]

- Remove the USE_CONSOLE_INIT_HANDLES define since now we "support" the console initialization events.
- The events in the CONSOLE_START_INFO structure are console initialization events used for asynchronous console creation, that are set whenever console creation succeeds, or fails.
- Stubplement their usage in CONSRV.

Now we are able to fully use Windows 2k3 kernel32.dll and be able to run console programs with it.

svn path=/trunk/; revision=65449
This commit is contained in:
Hermès Bélusca-Maïto 2014-11-22 22:13:08 +00:00
parent ec34daaa0a
commit b280f71b27
13 changed files with 174 additions and 62 deletions

View file

@ -1166,9 +1166,7 @@ IntAllocConsole(LPWSTR Title,
PCONSOLE_START_INFO ConsoleStartInfo)
{
BOOL Success = TRUE;
#ifdef USE_CONSOLE_INIT_HANDLES
NTSTATUS Status;
#endif
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest;
@ -1229,9 +1227,9 @@ IntAllocConsole(LPWSTR Title,
goto Quit;
}
#ifdef USE_CONSOLE_INIT_HANDLES
// Is AllocConsoleRequest->ConsoleStartInfo->Events aligned on handle boundary ????
Status = NtWaitForMultipleObjects(2, AllocConsoleRequest->ConsoleStartInfo->Events,
// Is AllocConsoleRequest->ConsoleStartInfo->InitEvents aligned on handle boundary ????
Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS,
AllocConsoleRequest->ConsoleStartInfo->InitEvents,
WaitAny, FALSE, NULL);
if (!NT_SUCCESS(Status))
{
@ -1240,15 +1238,14 @@ IntAllocConsole(LPWSTR Title,
goto Quit;
}
NtClose(AllocConsoleRequest->ConsoleStartInfo->Events[0]);
NtClose(AllocConsoleRequest->ConsoleStartInfo->Events[1]);
if (Status != STATUS_SUCCESS)
NtClose(AllocConsoleRequest->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
NtClose(AllocConsoleRequest->ConsoleStartInfo->InitEvents[INIT_FAILURE]);
if (Status != INIT_SUCCESS)
{
NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
Success = FALSE;
}
else
#endif
{
RtlCopyMemory(ConsoleStartInfo,
AllocConsoleRequest->ConsoleStartInfo,
@ -2505,9 +2502,7 @@ IntAttachConsole(DWORD ProcessId,
PCONSOLE_START_INFO ConsoleStartInfo)
{
BOOL Success = TRUE;
#ifdef USE_CONSOLE_INIT_HANDLES
NTSTATUS Status;
#endif
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest;
@ -2541,9 +2536,9 @@ IntAttachConsole(DWORD ProcessId,
goto Quit;
}
#ifdef USE_CONSOLE_INIT_HANDLES
// Is AttachConsoleRequest->ConsoleStartInfo->Events aligned on handle boundary ????
Status = NtWaitForMultipleObjects(2, AttachConsoleRequest->ConsoleStartInfo->Events,
// Is AttachConsoleRequest->ConsoleStartInfo->InitEvents aligned on handle boundary ????
Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS,
AttachConsoleRequest->ConsoleStartInfo->InitEvents,
WaitAny, FALSE, NULL);
if (!NT_SUCCESS(Status))
{
@ -2552,15 +2547,14 @@ IntAttachConsole(DWORD ProcessId,
goto Quit;
}
NtClose(AttachConsoleRequest->ConsoleStartInfo->Events[0]);
NtClose(AttachConsoleRequest->ConsoleStartInfo->Events[1]);
if (Status != STATUS_SUCCESS)
NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
NtClose(AttachConsoleRequest->ConsoleStartInfo->InitEvents[INIT_FAILURE]);
if (Status != INIT_SUCCESS)
{
NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
Success = FALSE;
}
else
#endif
{
RtlCopyMemory(ConsoleStartInfo,
AttachConsoleRequest->ConsoleStartInfo,

View file

@ -308,9 +308,10 @@ ConnectConsole(IN PWSTR SessionDir,
/* Nothing to do if this is not a console app */
if (!ConnectInfo->IsConsoleApp) return TRUE;
#ifdef USE_CONSOLE_INIT_HANDLES
/* Wait for the connection to finish */
Status = NtWaitForMultipleObjects(2, ConnectInfo->ConsoleStartInfo.Events,
// Is ConnectInfo->ConsoleStartInfo.InitEvents aligned on handle boundary ????
Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS,
ConnectInfo->ConsoleStartInfo.InitEvents,
WaitAny, FALSE, NULL);
if (!NT_SUCCESS(Status))
{
@ -318,15 +319,13 @@ ConnectConsole(IN PWSTR SessionDir,
return FALSE;
}
NtClose(ConnectInfo->ConsoleStartInfo.Events[0]);
NtClose(ConnectInfo->ConsoleStartInfo.Events[1]);
if (Status != STATUS_SUCCESS)
NtClose(ConnectInfo->ConsoleStartInfo.InitEvents[INIT_SUCCESS]);
NtClose(ConnectInfo->ConsoleStartInfo.InitEvents[INIT_FAILURE]);
if (Status != INIT_SUCCESS)
{
NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
return FALSE;
}
#endif
return TRUE;
}

View file

@ -14,10 +14,6 @@
#define HANDLE_CREATE_NEW_CONSOLE (HANDLE)-2
#define HANDLE_CREATE_NO_WINDOW (HANDLE)-3
// Enable (and then get rid of) this define when support for
// console initialization handles is implemented in CONSRV.
// #define USE_CONSOLE_INIT_HANDLES
/* FUNCTION PROTOTYPES ********************************************************/

View file

@ -158,6 +158,13 @@ typedef struct _CONSOLE_PROPERTIES
UINT uCodePage;
} CONSOLE_PROPERTIES;
enum
{
INIT_SUCCESS, // STATUS_WAIT_0
INIT_FAILURE, // STATUS_WAIT_1
MAX_INIT_EVENTS
};
typedef struct _CONSOLE_START_INFO
{
HANDLE ConsoleHandle;
@ -165,7 +172,7 @@ typedef struct _CONSOLE_START_INFO
HANDLE InputHandle;
HANDLE OutputHandle;
HANDLE ErrorHandle;
HANDLE Events[2];
HANDLE InitEvents[MAX_INIT_EVENTS];
CONSOLE_PROPERTIES;
} CONSOLE_START_INFO, *PCONSOLE_START_INFO;

View file

@ -170,7 +170,7 @@ AddInputEvents(PCONSOLE Console,
Status = STATUS_SUCCESS;
}
if (SetWaitEvent) SetEvent(Console->InputBuffer.ActiveEvent);
if (SetWaitEvent) NtSetEvent(Console->InputBuffer.ActiveEvent, NULL);
Done:
if (NumEventsWritten) *NumEventsWritten = i;
@ -198,16 +198,24 @@ NTSTATUS NTAPI
ConDrvInitInputBuffer(IN PCONSOLE Console,
IN ULONG InputBufferSize)
{
SECURITY_ATTRIBUTES SecurityAttributes;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
ConSrvInitObject(&Console->InputBuffer.Header, INPUT_BUFFER, Console);
SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
SecurityAttributes.lpSecurityDescriptor = NULL;
SecurityAttributes.bInheritHandle = TRUE;
InitializeObjectAttributes(&ObjectAttributes,
NULL,
OBJ_INHERIT,
NULL,
NULL);
Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
if (Console->InputBuffer.ActiveEvent == NULL) return STATUS_UNSUCCESSFUL;
Status = NtCreateEvent(&Console->InputBuffer.ActiveEvent, EVENT_ALL_ACCESS,
&ObjectAttributes, NotificationEvent, FALSE);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
// return Status;
}
Console->InputBuffer.InputBufferSize = InputBufferSize;
InitializeListHead(&Console->InputBuffer.InputEvents);

View file

@ -80,7 +80,10 @@ VOID NTAPI
ConDrvPause(PCONSOLE Console)
{
if (!Console->UnpauseEvent)
Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
{
NtCreateEvent(&Console->UnpauseEvent, EVENT_ALL_ACCESS,
NULL, NotificationEvent, FALSE);
}
}
VOID NTAPI
@ -88,8 +91,8 @@ ConDrvUnpause(PCONSOLE Console)
{
if (Console->UnpauseEvent)
{
SetEvent(Console->UnpauseEvent);
CloseHandle(Console->UnpauseEvent);
NtSetEvent(Console->UnpauseEvent, NULL);
NtClose(Console->UnpauseEvent);
Console->UnpauseEvent = NULL;
}
}

View file

@ -663,6 +663,27 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
/* Colour table */
memcpy(Console->Colors, ConsoleInfo.Colors, sizeof(ConsoleInfo.Colors));
/* Create the Initialization Events */
Status = NtCreateEvent(&Console->InitEvents[INIT_SUCCESS], EVENT_ALL_ACCESS,
NULL, NotificationEvent, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateEvent(InitEvents[INIT_SUCCESS]) failed: %lu\n", Status);
ConDrvDeleteConsole(Console);
ConSrvDeinitTerminal(&Terminal);
return Status;
}
Status = NtCreateEvent(&Console->InitEvents[INIT_FAILURE], EVENT_ALL_ACCESS,
NULL, NotificationEvent, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtCreateEvent(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
NtClose(Console->InitEvents[INIT_SUCCESS]);
ConDrvDeleteConsole(Console);
ConSrvDeinitTerminal(&Terminal);
return Status;
}
/*
* Attach the ConSrv terminal to the console.
* This call makes a copy of our local Terminal variable.
@ -671,6 +692,8 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to register terminal to the given console, Status = 0x%08lx\n", Status);
NtClose(Console->InitEvents[INIT_FAILURE]);
NtClose(Console->InitEvents[INIT_SUCCESS]);
ConDrvDeleteConsole(Console);
ConSrvDeinitTerminal(&Terminal);
return Status;
@ -680,6 +703,10 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
/* All went right, so add the console to the list */
Status = InsertConsole(&ConsoleHandle, Console);
// FIXME! We do not support at all asynchronous console creation!
NtSetEvent(Console->InitEvents[INIT_SUCCESS], NULL);
// NtSetEvent(Console->InitEvents[INIT_FAILURE], NULL);
/* Return the newly created console to the caller and a success code too */
*NewConsoleHandle = ConsoleHandle;
*NewConsole = Console;
@ -696,6 +723,10 @@ ConSrvDeleteConsole(PCONSRV_CONSOLE Console)
/* Remove the console from the list */
RemoveConsoleByPointer(Console);
/* Destroy the Initialization Events */
NtClose(Console->InitEvents[INIT_FAILURE]);
NtClose(Console->InitEvents[INIT_SUCCESS]);
/* Clean the Input Line Discipline */
if (Console->LineBuffer) ConsoleFreeHeap(Console->LineBuffer);
@ -999,7 +1030,8 @@ CSR_API(SrvAttachConsole)
TRUE,
&AttachConsoleRequest->ConsoleStartInfo->InputHandle,
&AttachConsoleRequest->ConsoleStartInfo->OutputHandle,
&AttachConsoleRequest->ConsoleStartInfo->ErrorHandle);
&AttachConsoleRequest->ConsoleStartInfo->ErrorHandle,
AttachConsoleRequest->ConsoleStartInfo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console inheritance failed\n");

View file

@ -663,7 +663,7 @@ OnNcCreate(HWND hWnd, LPCREATESTRUCTW Create)
{
DPRINT1("GuiConsoleNcCreate: InitFonts failed\n");
GuiData->hWindow = NULL;
SetEvent(GuiData->hGuiInitEvent);
NtSetEvent(GuiData->hGuiInitEvent, NULL);
return FALSE;
}
@ -691,7 +691,7 @@ OnNcCreate(HWND hWnd, LPCREATESTRUCTW Create)
//CreateSysMenu(GuiData->hWindow);
DPRINT("OnNcCreate - setting start event\n");
SetEvent(GuiData->hGuiInitEvent);
NtSetEvent(GuiData->hGuiInitEvent, NULL);
return (BOOL)DefWindowProcW(GuiData->hWindow, WM_NCCREATE, 0, (LPARAM)Create);
}

View file

@ -149,12 +149,12 @@ GuiConsoleInputThread(PVOID Data)
MSG msg;
/*
* This thread dispatches all the console notifications to the notify window.
* It is common for all the console windows.
* This thread dispatches all the console notifications to the
* notification window. It is common for all the console windows.
*/
/* The thread has been initialized, set the event */
SetEvent(*GraphicsStartupEvent);
NtSetEvent(*GraphicsStartupEvent, NULL);
while (GetMessageW(&msg, NULL, 0, 0))
{
@ -250,7 +250,7 @@ GuiConsoleInputThread(PVOID Data)
DestroyWindow(GuiData->hWindow);
PrivateCsrssManualGuiCheck(+1); // RemoveGuiApp
SetEvent(GuiData->hGuiTermEvent);
NtSetEvent(GuiData->hGuiTermEvent, NULL);
if (InterlockedDecrement(&WindowCount) == 0)
{
@ -295,8 +295,12 @@ GuiInit(VOID)
*/
if (hInputThread == NULL)
{
HANDLE GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if (GraphicsStartupEvent == NULL) return FALSE;
HANDLE GraphicsStartupEvent;
NTSTATUS Status;
Status = NtCreateEvent(&GraphicsStartupEvent, EVENT_ALL_ACCESS,
NULL, SynchronizationEvent, FALSE);
if (!NT_SUCCESS(Status)) return FALSE;
hInputThread = CreateThread(NULL,
0,
@ -306,7 +310,7 @@ GuiInit(VOID)
&dwInputThreadId);
if (hInputThread == NULL)
{
CloseHandle(GraphicsStartupEvent);
NtClose(GraphicsStartupEvent);
DPRINT1("CONSRV: Failed to create graphics console thread.\n");
return FALSE;
}
@ -314,7 +318,7 @@ GuiInit(VOID)
CloseHandle(hInputThread);
WaitForSingleObject(GraphicsStartupEvent, INFINITE);
CloseHandle(GraphicsStartupEvent);
NtClose(GraphicsStartupEvent);
}
// ConsInitialized = TRUE;
@ -471,8 +475,10 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
* Ideally we could use SendNotifyMessage for this but its not
* yet implemented.
*/
GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
GuiData->hGuiTermEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
NtCreateEvent(&GuiData->hGuiInitEvent, EVENT_ALL_ACCESS,
NULL, SynchronizationEvent, FALSE);
NtCreateEvent(&GuiData->hGuiTermEvent, EVENT_ALL_ACCESS,
NULL, SynchronizationEvent, FALSE);
DPRINT("GUI - Checkpoint\n");
@ -482,7 +488,7 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
/* Wait until initialization has finished */
WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
DPRINT("OK we created the console window\n");
CloseHandle(GuiData->hGuiInitEvent);
NtClose(GuiData->hGuiInitEvent);
GuiData->hGuiInitEvent = NULL;
/* Check whether we really succeeded in initializing the terminal window */
@ -505,7 +511,7 @@ GuiDeinitFrontEnd(IN OUT PFRONTEND This)
PostThreadMessageW(dwInputThreadId, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
WaitForSingleObject(GuiData->hGuiTermEvent, INFINITE);
DPRINT("hGuiTermEvent set\n");
CloseHandle(GuiData->hGuiTermEvent);
NtClose(GuiData->hGuiTermEvent);
GuiData->hGuiTermEvent = NULL;
DPRINT("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n",

View file

@ -521,6 +521,36 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
return Status;
}
/* Duplicate the Initialization Events */
Status = NtDuplicateObject(NtCurrentProcess(),
Console->InitEvents[INIT_SUCCESS],
ProcessData->Process->ProcessHandle,
&ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS],
EVENT_ALL_ACCESS, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject(InitEvents[INIT_SUCCESS]) failed: %lu\n", Status);
ConSrvFreeHandlesTable(ProcessData);
ConSrvDeleteConsole(Console);
ProcessData->ConsoleHandle = NULL;
return Status;
}
Status = NtDuplicateObject(NtCurrentProcess(),
Console->InitEvents[INIT_FAILURE],
ProcessData->Process->ProcessHandle,
&ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_FAILURE],
EVENT_ALL_ACCESS, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
NtClose(ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
ConSrvFreeHandlesTable(ProcessData);
ConSrvDeleteConsole(Console);
ProcessData->ConsoleHandle = NULL;
return Status;
}
/* Duplicate the Input Event */
Status = NtDuplicateObject(NtCurrentProcess(),
Console->InputBuffer.ActiveEvent,
@ -529,7 +559,9 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
EVENT_ALL_ACCESS, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
DPRINT1("NtDuplicateObject(InputWaitHandle) failed: %lu\n", Status);
NtClose(ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_FAILURE]);
NtClose(ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
ConSrvFreeHandlesTable(ProcessData);
ConSrvDeleteConsole(Console);
ProcessData->ConsoleHandle = NULL;
@ -554,7 +586,8 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
BOOLEAN CreateNewHandlesTable,
PHANDLE pInputHandle,
PHANDLE pOutputHandle,
PHANDLE pErrorHandle)
PHANDLE pErrorHandle,
PCONSOLE_START_INFO ConsoleStartInfo)
{
NTSTATUS Status = STATUS_SUCCESS;
PCONSOLE Console;
@ -599,6 +632,34 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
}
}
/* Duplicate the Initialization Events */
Status = NtDuplicateObject(NtCurrentProcess(),
Console->InitEvents[INIT_SUCCESS],
ProcessData->Process->ProcessHandle,
&ConsoleStartInfo->InitEvents[INIT_SUCCESS],
EVENT_ALL_ACCESS, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject(InitEvents[INIT_SUCCESS]) failed: %lu\n", Status);
ConSrvFreeHandlesTable(ProcessData);
ProcessData->ConsoleHandle = NULL;
goto Quit;
}
Status = NtDuplicateObject(NtCurrentProcess(),
Console->InitEvents[INIT_FAILURE],
ProcessData->Process->ProcessHandle,
&ConsoleStartInfo->InitEvents[INIT_FAILURE],
EVENT_ALL_ACCESS, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
NtClose(ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
ConSrvFreeHandlesTable(ProcessData);
ProcessData->ConsoleHandle = NULL;
goto Quit;
}
/* Duplicate the Input Event */
Status = NtDuplicateObject(NtCurrentProcess(),
Console->InputBuffer.ActiveEvent,
@ -607,7 +668,9 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
EVENT_ALL_ACCESS, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
DPRINT1("NtDuplicateObject(InputWaitHandle) failed: %lu\n", Status);
NtClose(ConsoleStartInfo->InitEvents[INIT_FAILURE]);
NtClose(ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
ConSrvFreeHandlesTable(ProcessData); // NOTE: Always free the handles table.
ProcessData->ConsoleHandle = NULL;
goto Quit;

View file

@ -139,6 +139,8 @@ typedef struct _WINSRV_CONSOLE
// CRITICAL_SECTION Lock;
// CONSOLE_STATE State; /* State of the console */
HANDLE InitEvents[MAX_INIT_EVENTS]; /* Initialization events */
FRONTEND FrontEndIFace; /* Frontend-specific interface */
/******************************* Process support ******************************/

View file

@ -480,9 +480,10 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
Status = ConSrvInheritConsole(ProcessData,
ConnectInfo->ConsoleStartInfo.ConsoleHandle,
FALSE,
NULL, // &ConnectInfo->ConsoleStartInfo.InputHandle,
NULL, // &ConnectInfo->ConsoleStartInfo.OutputHandle,
NULL); // &ConnectInfo->ConsoleStartInfo.ErrorHandle);
NULL, // &ConnectInfo->ConsoleStartInfo.InputHandle,
NULL, // &ConnectInfo->ConsoleStartInfo.OutputHandle,
NULL, // &ConnectInfo->ConsoleStartInfo.ErrorHandle,
&ConnectInfo->ConsoleStartInfo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console inheritance failed\n");

View file

@ -18,5 +18,6 @@ NTSTATUS ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
BOOLEAN CreateNewHandlesTable,
PHANDLE pInputHandle,
PHANDLE pOutputHandle,
PHANDLE pErrorHandle);
PHANDLE pErrorHandle,
PCONSOLE_START_INFO ConsoleStartInfo);
VOID ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData);