mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[CONSOLE.DLL]
- Fix passing and retrieving gui terminal front-end information. - Fix default (global) console parameters saving. [CONSRV] - PSEH2-protect calls to CreateRemoteThread when 1. calling console app. control handlers and 2. retrieving console settings from console.dll. - Introduce a new way of locking consoles when being used, and store them in a list. svn path=/branches/ros-csrss/; revision=58615
This commit is contained in:
parent
1e1a59fb22
commit
01729482ae
11 changed files with 921 additions and 377 deletions
|
@ -87,6 +87,8 @@ InitConsoleDefaults(PCONSOLE_PROPS pConInfo)
|
|||
{
|
||||
PGUI_CONSOLE_INFO GuiInfo = NULL;
|
||||
|
||||
/* FIXME: Get also the defaults from the registry */
|
||||
|
||||
/* Initialize the default properties */
|
||||
pConInfo->ci.HistoryBufferSize = 50;
|
||||
pConInfo->ci.NumberOfHistoryBuffers = 4;
|
||||
|
@ -108,7 +110,8 @@ InitConsoleDefaults(PCONSOLE_PROPS pConInfo)
|
|||
/* Adapted for holding GUI terminal information */
|
||||
pConInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO);
|
||||
GuiInfo = pConInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pConInfo + 1);
|
||||
GuiInfo->FaceName[0] = L'\0';
|
||||
wcsncpy(GuiInfo->FaceName, L"Fixedsys", LF_FACESIZE); // HACK: !!
|
||||
// GuiInfo->FaceName[0] = L'\0';
|
||||
GuiInfo->FontFamily = FF_DONTCARE;
|
||||
GuiInfo->FontSize = 0;
|
||||
GuiInfo->FontWeight = FW_DONTCARE;
|
||||
|
@ -166,16 +169,35 @@ BOOL
|
|||
ApplyConsoleInfo(HWND hwndDlg,
|
||||
PCONSOLE_PROPS pConInfo)
|
||||
{
|
||||
INT_PTR res = 0;
|
||||
BOOL SetParams = FALSE;
|
||||
BOOL SaveParams = FALSE;
|
||||
|
||||
res = DialogBox(hApplet, MAKEINTRESOURCE(IDD_APPLYOPTIONS), hwndDlg, ApplyProc);
|
||||
if (res == IDCANCEL)
|
||||
/*
|
||||
* If we are setting the default parameters, just save them,
|
||||
* otherwise display the save-confirmation dialog.
|
||||
*/
|
||||
if (pConInfo->ShowDefaultParams)
|
||||
{
|
||||
/* Don't destroy when user presses cancel */
|
||||
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
|
||||
return TRUE;
|
||||
SetParams = TRUE;
|
||||
SaveParams = TRUE;
|
||||
}
|
||||
else if (res == IDC_RADIO_APPLY_ALL || res == IDC_RADIO_APPLY_CURRENT)
|
||||
else
|
||||
{
|
||||
INT_PTR res = DialogBox(hApplet, MAKEINTRESOURCE(IDD_APPLYOPTIONS), hwndDlg, ApplyProc);
|
||||
|
||||
SetParams = (res != IDCANCEL);
|
||||
SaveParams = (res == IDC_RADIO_APPLY_ALL);
|
||||
|
||||
if (SetParams == FALSE)
|
||||
{
|
||||
/* Don't destroy when user presses cancel */
|
||||
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
|
||||
// return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// if (res == IDC_RADIO_APPLY_ALL || res == IDC_RADIO_APPLY_CURRENT)
|
||||
if (SetParams)
|
||||
{
|
||||
HANDLE hSection;
|
||||
PCONSOLE_PROPS pSharedInfo;
|
||||
|
@ -207,10 +229,15 @@ ApplyConsoleInfo(HWND hwndDlg,
|
|||
/* We are applying the chosen configuration */
|
||||
pConInfo->AppliedConfig = TRUE;
|
||||
|
||||
/* Copy the console info into the section */
|
||||
/*
|
||||
* Copy the console information into the section and
|
||||
* offsetize the address of terminal-specific information.
|
||||
* Do not perform the offsetization in pConInfo as it is
|
||||
* likely to be reused later on. Instead, do it in pSharedInfo
|
||||
* after having copied all the data.
|
||||
*/
|
||||
RtlCopyMemory(pSharedInfo, pConInfo, sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO));
|
||||
/* Offsetize */
|
||||
pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pSharedInfo->TerminalInfo.TermInfo - (ULONG_PTR)pSharedInfo);
|
||||
pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)pConInfo->TerminalInfo.TermInfo - (ULONG_PTR)pConInfo);
|
||||
|
||||
/* Unmap it */
|
||||
UnmapViewOfFile(pSharedInfo);
|
||||
|
@ -220,11 +247,10 @@ ApplyConsoleInfo(HWND hwndDlg,
|
|||
SendMessage(pConInfo->hConsoleWindow,
|
||||
PM_APPLY_CONSOLE_INFO,
|
||||
(WPARAM)hSection,
|
||||
(LPARAM)(res == IDC_RADIO_APPLY_ALL));
|
||||
(LPARAM)SaveParams);
|
||||
|
||||
/* Close the section and return */
|
||||
CloseHandle(hSection);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -685,7 +685,6 @@ CSR_API(SrvReadConsole)
|
|||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
|
||||
if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
@ -808,7 +807,7 @@ CSR_API(SrvFlushConsoleInputBuffer)
|
|||
PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FlushInputBufferRequest;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer;
|
||||
ConsoleInput* Input;
|
||||
ConsoleInput* Event;
|
||||
|
||||
DPRINT("SrvFlushConsoleInputBuffer\n");
|
||||
|
||||
|
@ -823,14 +822,12 @@ CSR_API(SrvFlushConsoleInputBuffer)
|
|||
while (!IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
/* Destroy the event */
|
||||
RtlFreeHeap(ConSrvHeap, 0, Input);
|
||||
Event = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
RtlFreeHeap(ConSrvHeap, 0, Event);
|
||||
}
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
|
||||
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,12 +147,27 @@ typedef struct _FRONTEND_IFACE
|
|||
PVOID OldData; /* Reserved */
|
||||
} FRONTEND_IFACE, *PFRONTEND_IFACE;
|
||||
|
||||
#if 0 // Temporarily put in consrv.h
|
||||
/*
|
||||
* WARNING: Change the state of the console ONLY when the console is locked !
|
||||
*/
|
||||
typedef enum _CONSOLE_STATE
|
||||
{
|
||||
CONSOLE_INITIALIZING, /* Console is initializing */
|
||||
CONSOLE_RUNNING , /* Console running */
|
||||
CONSOLE_TERMINATING , /* Console about to be destroyed (but still not) */
|
||||
CONSOLE_IN_DESTRUCTION /* Console in destruction */
|
||||
} CONSOLE_STATE, *PCONSOLE_STATE;
|
||||
#endif
|
||||
|
||||
typedef struct _CONSOLE
|
||||
{
|
||||
LONG ReferenceCount; /* Is incremented each time a handle to a screen-buffer or the input buffer of this console gets referenced, or the console gets locked */
|
||||
LONG ReferenceCount; /* Is incremented each time a handle to something in the console (a screen-buffer or the input buffer of this console) gets referenced */
|
||||
CRITICAL_SECTION Lock;
|
||||
CONSOLE_STATE State; /* State of the console */
|
||||
|
||||
struct _CONSOLE *Prev, *Next; /* Next and Prev consoles in console wheel */
|
||||
// struct _CONSOLE *Prev, *Next; /* Next and Prev consoles in console wheel */
|
||||
LIST_ENTRY Entry; /* Entry in the list of consoles */
|
||||
LIST_ENTRY ProcessList; /* List of processes owning the console. The first one is the so-called "Console Leader Process" */
|
||||
|
||||
FRONTEND_IFACE TermIFace; /* Frontend-specific interface */
|
||||
|
@ -218,11 +233,6 @@ typedef struct _CONSOLE
|
|||
#define PAUSED_FROM_SELECTION 0x4
|
||||
|
||||
/* console.c */
|
||||
VOID WINAPI ConSrvDeleteConsole(PCONSOLE Console);
|
||||
VOID WINAPI ConSrvInitConsoleSupport(VOID);
|
||||
NTSTATUS WINAPI ConSrvInitConsole(OUT PCONSOLE* NewConsole,
|
||||
IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
|
||||
IN PCSR_PROCESS ConsoleLeaderProcess);
|
||||
VOID FASTCALL ConioPause(PCONSOLE Console, UINT Flags);
|
||||
VOID FASTCALL ConioUnpause(PCONSOLE Console, UINT Flags);
|
||||
ULONG FASTCALL ConSrvConsoleProcessCtrlEvent(PCONSOLE Console,
|
||||
|
|
|
@ -1278,15 +1278,18 @@ CSR_API(SrvCreateConsoleScreenBuffer)
|
|||
|
||||
DPRINT("SrvCreateConsoleScreenBuffer\n");
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
// RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
/*
|
||||
if (Console->ActiveBuffer)
|
||||
{
|
||||
ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
|
||||
|
@ -1299,6 +1302,23 @@ CSR_API(SrvCreateConsoleScreenBuffer)
|
|||
IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
|
||||
CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
|
||||
}
|
||||
*/
|
||||
|
||||
// This is Windows' behaviour
|
||||
{
|
||||
ScreenBufferSize = Console->ConsoleSize; // Use the current console size
|
||||
if (ScreenBufferSize.X == 0) ScreenBufferSize.X = 1;
|
||||
if (ScreenBufferSize.Y == 0) ScreenBufferSize.Y = 1;
|
||||
|
||||
if (Console->ActiveBuffer)
|
||||
{
|
||||
ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib;
|
||||
PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib;
|
||||
|
||||
IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
|
||||
CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
|
||||
}
|
||||
}
|
||||
|
||||
Status = ConSrvCreateScreenBuffer(Console,
|
||||
&Buff,
|
||||
|
@ -1309,6 +1329,7 @@ CSR_API(SrvCreateConsoleScreenBuffer)
|
|||
CursorSize);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Insert the new handle inside the process handles table */
|
||||
Status = ConSrvInsertObject(ProcessData,
|
||||
&CreateScreenBufferRequest->OutputHandle,
|
||||
&Buff->Header,
|
||||
|
@ -1317,10 +1338,11 @@ CSR_API(SrvCreateConsoleScreenBuffer)
|
|||
CreateScreenBufferRequest->ShareMode);
|
||||
}
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
// ConSrvReleaseConsole(Console, TRUE);
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,12 +21,19 @@
|
|||
#include "tuiconsole.h"
|
||||
#endif
|
||||
|
||||
#include "console.h"
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
//#define NDEBUG
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
LIST_ENTRY ConsoleList; /* The list of all the allocated consoles */
|
||||
/*static*/ RTL_RESOURCE ListLock;
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
|
@ -44,26 +51,43 @@ ConSrvConsoleCtrlEventTimeout(DWORD Event,
|
|||
DWORD Timeout)
|
||||
{
|
||||
ULONG Status = ERROR_SUCCESS;
|
||||
HANDLE Thread;
|
||||
|
||||
DPRINT("ConSrvConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
|
||||
DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
|
||||
|
||||
if (ProcessData->CtrlDispatcher)
|
||||
{
|
||||
Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
|
||||
ProcessData->CtrlDispatcher,
|
||||
UlongToPtr(Event), 0, NULL);
|
||||
if (NULL == Thread)
|
||||
_SEH2_TRY
|
||||
{
|
||||
Status = GetLastError();
|
||||
DPRINT1("Failed thread creation (Error: 0x%x)\n", Status);
|
||||
HANDLE Thread = NULL;
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
|
||||
ProcessData->CtrlDispatcher,
|
||||
UlongToPtr(Event), 0, NULL);
|
||||
if (NULL == Thread)
|
||||
{
|
||||
Status = GetLastError();
|
||||
DPRINT1("Failed thread creation (Error: 0x%x)\n", Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("ProcessData->CtrlDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
|
||||
WaitForSingleObject(Thread, Timeout);
|
||||
}
|
||||
}
|
||||
_SEH2_FINALLY
|
||||
{
|
||||
CloseHandle(Thread);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
else
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
DPRINT("We succeeded at creating ProcessData->CtrlDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
|
||||
WaitForSingleObject(Thread, Timeout);
|
||||
CloseHandle(Thread);
|
||||
Status = RtlNtStatusToDosError(_SEH2_GetExceptionCode());
|
||||
DPRINT1("ConSrvConsoleCtrlEventTimeout - Caught an exception, Status = %08X\n", Status);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
@ -85,6 +109,10 @@ ConSrvConsoleProcessCtrlEvent(PCONSOLE Console,
|
|||
PLIST_ENTRY current_entry;
|
||||
PCONSOLE_PROCESS_DATA current;
|
||||
|
||||
/* If the console is already being destroyed, just return */
|
||||
if (!ConSrvValidateConsole(Console, CONSOLE_RUNNING, FALSE))
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
/*
|
||||
* Loop through the process list, from the most recent process
|
||||
* (the active one) to the oldest one (the first created, i.e.
|
||||
|
@ -141,6 +169,18 @@ ConioUnpause(PCONSOLE Console, UINT Flags)
|
|||
}
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
ConSrvInitConsoleSupport(VOID)
|
||||
{
|
||||
DPRINT("CONSRV: ConSrvInitConsoleSupport()\n");
|
||||
|
||||
/* Initialize the console list and its lock */
|
||||
InitializeListHead(&ConsoleList);
|
||||
RtlInitializeResource(&ListLock);
|
||||
|
||||
/* Should call LoadKeyboardLayout */
|
||||
}
|
||||
|
||||
static BOOL
|
||||
LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
|
||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||
|
@ -346,6 +386,7 @@ ConSrvInitConsole(OUT PCONSOLE* NewConsole,
|
|||
/*
|
||||
* Initialize the console
|
||||
*/
|
||||
Console->State = CONSOLE_INITIALIZING;
|
||||
InitializeCriticalSection(&Console->Lock);
|
||||
Console->ReferenceCount = 0;
|
||||
InitializeListHead(&Console->ProcessList);
|
||||
|
@ -428,6 +469,9 @@ ConSrvInitConsole(OUT PCONSOLE* NewConsole,
|
|||
RtlCreateUnicodeString(&Console->Title, ConsoleInfo.ConsoleTitle);
|
||||
}
|
||||
|
||||
/* Lock the console until its initialization is finished */
|
||||
// EnterCriticalSection(&Console->Lock);
|
||||
|
||||
/*
|
||||
* If we are not in GUI-mode, start the text-mode terminal emulator.
|
||||
* If we fail, try to start the GUI-mode terminal emulator.
|
||||
|
@ -480,45 +524,134 @@ ConSrvInitConsole(OUT PCONSOLE* NewConsole,
|
|||
RtlFreeUnicodeString(&Console->OriginalTitle);
|
||||
ConioDeleteScreenBuffer(NewBuffer);
|
||||
CloseHandle(Console->InputBuffer.ActiveEvent);
|
||||
// LeaveCriticalSection(&Console->Lock);
|
||||
DeleteCriticalSection(&Console->Lock);
|
||||
RtlFreeHeap(ConSrvHeap, 0, Console);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT1("Terminal initialized\n");
|
||||
|
||||
/* All went right, so add the console to the list */
|
||||
ConSrvLockConsoleListExclusive();
|
||||
DPRINT1("Insert in the list\n");
|
||||
InsertTailList(&ConsoleList, &Console->Entry);
|
||||
|
||||
/* The initialization is finished */
|
||||
DPRINT1("Change state\n");
|
||||
Console->State = CONSOLE_RUNNING;
|
||||
|
||||
/* Unlock the console */
|
||||
// LeaveCriticalSection(&Console->Lock);
|
||||
|
||||
/* Unlock the console list */
|
||||
ConSrvUnlockConsoleList();
|
||||
|
||||
/* Copy buffer contents to screen */
|
||||
ConioDrawConsole(Console);
|
||||
DPRINT1("Console drawn\n");
|
||||
|
||||
/* Return the newly created console to the caller and a success code too */
|
||||
*NewConsole = Console;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
ConSrvInitConsoleSupport(VOID)
|
||||
{
|
||||
DPRINT("CONSRV: ConSrvInitConsoleSupport()\n");
|
||||
|
||||
/* Should call LoadKeyboardLayout */
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
ConSrvDeleteConsole(PCONSOLE Console)
|
||||
{
|
||||
ConsoleInput *Event;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
ConsoleInput* Event;
|
||||
|
||||
DPRINT("ConSrvDeleteConsole\n");
|
||||
DPRINT1("ConSrvDeleteConsole\n");
|
||||
|
||||
/* Drain input event queue */
|
||||
while (Console->InputBuffer.InputEvents.Flink != &Console->InputBuffer.InputEvents)
|
||||
/*
|
||||
* Forbid validation of any console by other threads
|
||||
* during the deletion of this console.
|
||||
*/
|
||||
ConSrvLockConsoleListExclusive();
|
||||
|
||||
/* Check the existence of the console, and if it's ok, continue */
|
||||
if (!ConSrvValidatePointer(Console))
|
||||
{
|
||||
Event = (ConsoleInput *) Console->InputBuffer.InputEvents.Flink;
|
||||
Console->InputBuffer.InputEvents.Flink = Console->InputBuffer.InputEvents.Flink->Flink;
|
||||
Console->InputBuffer.InputEvents.Flink->Flink->Blink = &Console->InputBuffer.InputEvents;
|
||||
/* Unlock the console list and return */
|
||||
ConSrvUnlockConsoleList();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the console is already being destroyed
|
||||
* (thus not running), just return.
|
||||
*/
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
/* Unlock the console list and return */
|
||||
ConSrvUnlockConsoleList();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are about to be destroyed. Signal it to other people
|
||||
* so that they can terminate what they are doing, and that
|
||||
* they cannot longer validate the console.
|
||||
*/
|
||||
Console->State = CONSOLE_TERMINATING;
|
||||
|
||||
/*
|
||||
* Allow other threads to finish their job: basically, unlock
|
||||
* all other calls to EnterCriticalSection(&Console->Lock); by
|
||||
* ConSrvValidateConsole(Unsafe) functions so that they just see
|
||||
* that we are not in CONSOLE_RUNNING state anymore, or unlock
|
||||
* other concurrent calls to ConSrvDeleteConsole so that they
|
||||
* can see that we are in fact already deleting the console.
|
||||
*/
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
ConSrvUnlockConsoleList();
|
||||
|
||||
/* FIXME: Send a terminate message to all the processes owning this console */
|
||||
|
||||
/* Cleanup the UI-oriented part */
|
||||
ConioCleanupConsole(Console);
|
||||
|
||||
/***
|
||||
* Check that the console is in terminating state before continuing
|
||||
* (the cleanup code must not change the state of the console...
|
||||
* ...unless to cancel console deletion ?).
|
||||
***/
|
||||
|
||||
ConSrvLockConsoleListExclusive();
|
||||
|
||||
/* Re-check the existence of the console, and if it's ok, continue */
|
||||
if (!ConSrvValidatePointer(Console))
|
||||
{
|
||||
/* Unlock the console list and return */
|
||||
ConSrvUnlockConsoleList();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_TERMINATING, TRUE))
|
||||
{
|
||||
ConSrvUnlockConsoleList();
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are in destruction */
|
||||
Console->State = CONSOLE_IN_DESTRUCTION;
|
||||
|
||||
/* Remove the console from the list */
|
||||
RemoveEntryList(&Console->Entry);
|
||||
|
||||
/* Reset the count to be sure */
|
||||
Console->ReferenceCount = 0;
|
||||
|
||||
/* Discard all entries in the input event queue */
|
||||
while (!IsListEmpty(&Console->InputBuffer.InputEvents))
|
||||
{
|
||||
CurrentEntry = RemoveHeadList(&Console->InputBuffer.InputEvents);
|
||||
Event = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
RtlFreeHeap(ConSrvHeap, 0, Event);
|
||||
}
|
||||
|
||||
ConioCleanupConsole(Console);
|
||||
if (Console->LineBuffer)
|
||||
RtlFreeHeap(ConSrvHeap, 0, Console->LineBuffer);
|
||||
while (!IsListEmpty(&Console->HistoryBuffers))
|
||||
|
@ -532,12 +665,22 @@ ConSrvDeleteConsole(PCONSOLE Console)
|
|||
|
||||
CloseHandle(Console->InputBuffer.ActiveEvent);
|
||||
if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
|
||||
DeleteCriticalSection(&Console->Lock);
|
||||
|
||||
RtlFreeUnicodeString(&Console->OriginalTitle);
|
||||
RtlFreeUnicodeString(&Console->Title);
|
||||
IntDeleteAllAliases(Console->Aliases);
|
||||
|
||||
DPRINT1("ConSrvDeleteConsole - Unlocking\n");
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
DPRINT1("ConSrvDeleteConsole - Destroying lock\n");
|
||||
DeleteCriticalSection(&Console->Lock);
|
||||
DPRINT1("ConSrvDeleteConsole - Lock destroyed ; freeing console\n");
|
||||
|
||||
RtlFreeHeap(ConSrvHeap, 0, Console);
|
||||
DPRINT1("ConSrvDeleteConsole - Console freed\n");
|
||||
|
||||
/* Unlock the console list and return */
|
||||
ConSrvUnlockConsoleList();
|
||||
}
|
||||
|
||||
|
||||
|
@ -545,56 +688,59 @@ ConSrvDeleteConsole(PCONSOLE Console)
|
|||
|
||||
CSR_API(SrvOpenConsole)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_OPENCONSOLE OpenConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.OpenConsoleRequest;
|
||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
||||
PCONSOLE Console;
|
||||
|
||||
DWORD DesiredAccess = OpenConsoleRequest->Access;
|
||||
DWORD ShareMode = OpenConsoleRequest->ShareMode;
|
||||
Object_t *Object;
|
||||
|
||||
OpenConsoleRequest->ConsoleHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Can't get console\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
if (ProcessData->Console)
|
||||
/*
|
||||
* Open a handle to either the active screen buffer or the input buffer.
|
||||
*/
|
||||
if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT)
|
||||
{
|
||||
DWORD DesiredAccess = OpenConsoleRequest->Access;
|
||||
DWORD ShareMode = OpenConsoleRequest->ShareMode;
|
||||
Object = &Console->ActiveBuffer->Header;
|
||||
}
|
||||
else // HANDLE_INPUT
|
||||
{
|
||||
Object = &Console->InputBuffer.Header;
|
||||
}
|
||||
|
||||
PCONSOLE Console = ProcessData->Console;
|
||||
Object_t *Object;
|
||||
|
||||
EnterCriticalSection(&Console->Lock);
|
||||
|
||||
if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT)
|
||||
{
|
||||
Object = &Console->ActiveBuffer->Header;
|
||||
}
|
||||
else // HANDLE_INPUT
|
||||
{
|
||||
Object = &Console->InputBuffer.Header;
|
||||
}
|
||||
|
||||
if (((DesiredAccess & GENERIC_READ) && Object->ExclusiveRead != 0) ||
|
||||
((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
|
||||
(!(ShareMode & FILE_SHARE_READ) && Object->AccessRead != 0) ||
|
||||
(!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite != 0))
|
||||
{
|
||||
DPRINT1("Sharing violation\n");
|
||||
Status = STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ConSrvInsertObject(ProcessData,
|
||||
&OpenConsoleRequest->ConsoleHandle,
|
||||
Object,
|
||||
DesiredAccess,
|
||||
OpenConsoleRequest->Inheritable,
|
||||
ShareMode);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
if (((DesiredAccess & GENERIC_READ) && Object->ExclusiveRead != 0) ||
|
||||
((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
|
||||
(!(ShareMode & FILE_SHARE_READ) && Object->AccessRead != 0) ||
|
||||
(!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite != 0))
|
||||
{
|
||||
DPRINT1("Sharing violation\n");
|
||||
Status = STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ConSrvInsertObject(ProcessData,
|
||||
&OpenConsoleRequest->ConsoleHandle,
|
||||
Object,
|
||||
DesiredAccess,
|
||||
OpenConsoleRequest->Inheritable,
|
||||
ShareMode);
|
||||
}
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -758,7 +904,6 @@ Quit:
|
|||
|
||||
CSR_API(SrvFreeConsole)
|
||||
{
|
||||
DPRINT1("SrvFreeConsole\n");
|
||||
ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -798,7 +943,6 @@ CSR_API(SrvSetConsoleMode)
|
|||
}
|
||||
|
||||
ConSrvReleaseObject(Object, TRUE);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -831,7 +975,6 @@ CSR_API(SrvGetConsoleMode)
|
|||
}
|
||||
|
||||
ConSrvReleaseObject(Object, TRUE);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
52
win32ss/user/consrv/console.h
Normal file
52
win32ss/user/consrv/console.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Console Server DLL
|
||||
* FILE: win32ss/user/consrv/console.h
|
||||
* PURPOSE: Consoles Management
|
||||
* PROGRAMMERS: Hermes Belusca-Maito
|
||||
*/
|
||||
|
||||
#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 !
|
||||
*/
|
||||
typedef enum _CONSOLE_STATE
|
||||
{
|
||||
CONSOLE_INITIALIZING, /* Console is initializing */
|
||||
CONSOLE_RUNNING , /* Console running */
|
||||
CONSOLE_TERMINATING , /* Console about to be destroyed (but still not) */
|
||||
CONSOLE_IN_DESTRUCTION /* Console in destruction */
|
||||
} CONSOLE_STATE, *PCONSOLE_STATE;
|
||||
#endif
|
||||
|
||||
|
||||
VOID WINAPI ConSrvInitConsoleSupport(VOID);
|
||||
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 ConSrvValidateConsoleState(PCONSOLE Console,
|
||||
CONSOLE_STATE ExpectedState);
|
||||
BOOL FASTCALL ConSrvValidateConsoleUnsafe(PCONSOLE Console,
|
||||
CONSOLE_STATE ExpectedState,
|
||||
BOOL LockConsole);
|
||||
BOOL FASTCALL ConSrvValidateConsole(PCONSOLE Console,
|
||||
CONSOLE_STATE ExpectedState,
|
||||
BOOL LockConsole);
|
||||
|
||||
/* EOF */
|
|
@ -34,6 +34,9 @@
|
|||
/* Public Win32K Headers */
|
||||
#include <ntuser.h>
|
||||
|
||||
/* PSEH for SEH Support */
|
||||
#include <pseh/pseh2.h>
|
||||
|
||||
/* CSRSS Header */
|
||||
#include <csr/csrsrv.h>
|
||||
|
||||
|
@ -93,6 +96,20 @@ typedef struct _CONSOLE_PROCESS_DATA
|
|||
} CONSOLE_PROCESS_DATA, *PCONSOLE_PROCESS_DATA;
|
||||
|
||||
|
||||
#if 1 // Temporarily put there.
|
||||
/*
|
||||
* WARNING: Change the state of the console ONLY when the console is locked !
|
||||
*/
|
||||
typedef enum _CONSOLE_STATE
|
||||
{
|
||||
CONSOLE_INITIALIZING, /* Console is initializing */
|
||||
CONSOLE_RUNNING , /* Console running */
|
||||
CONSOLE_TERMINATING , /* Console about to be destroyed (but still not) */
|
||||
CONSOLE_IN_DESTRUCTION /* Console in destruction */
|
||||
} CONSOLE_STATE, *PCONSOLE_STATE;
|
||||
#endif
|
||||
|
||||
|
||||
/* alias.c */
|
||||
CSR_API(SrvAddConsoleAlias);
|
||||
CSR_API(SrvGetConsoleAlias);
|
||||
|
@ -177,12 +194,12 @@ NTSTATUS FASTCALL ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
PHANDLE pInputHandle,
|
||||
PHANDLE pOutputHandle,
|
||||
PHANDLE pErrorHandle);
|
||||
VOID FASTCALL ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData);
|
||||
NTSTATUS FASTCALL ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
||||
struct _CONSOLE** Console,
|
||||
BOOL LockConsole);
|
||||
VOID FASTCALL ConSrvReleaseConsole(struct _CONSOLE* Console,
|
||||
BOOL IsConsoleLocked);
|
||||
BOOL WasConsoleLocked);
|
||||
VOID FASTCALL ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData);
|
||||
|
||||
NTSTATUS NTAPI ConSrvNewProcess(PCSR_PROCESS SourceProcess,
|
||||
PCSR_PROCESS TargetProcess);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "consrv.h"
|
||||
#include "conio.h"
|
||||
#include "console.h"
|
||||
#include "settings.h"
|
||||
#include "guiconsole.h"
|
||||
#include "guisettings.h"
|
||||
|
@ -212,6 +213,13 @@ static LRESULT
|
|||
GuiConsoleHandleSysMenuCommand(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LRESULT Ret = TRUE;
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
Ret = FALSE;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
switch (wParam)
|
||||
{
|
||||
|
@ -229,7 +237,6 @@ GuiConsoleHandleSysMenuCommand(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM
|
|||
|
||||
case ID_SYSTEM_EDIT_SELECTALL:
|
||||
{
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
COORD bottomRight = { 0, 0 };
|
||||
|
||||
bottomRight.X = Console->ConsoleSize.X - 1;
|
||||
|
@ -255,15 +262,23 @@ GuiConsoleHandleSysMenuCommand(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM
|
|||
break;
|
||||
|
||||
default:
|
||||
Ret = DefWindowProcW(GuiData->hWindow, WM_SYSCOMMAND, wParam, lParam);
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
|
||||
Quit:
|
||||
if (!Ret)
|
||||
Ret = DefWindowProcW(GuiData->hWindow, WM_SYSCOMMAND, wParam, lParam);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static PGUI_CONSOLE_DATA
|
||||
GuiGetGuiData(HWND hWnd)
|
||||
{
|
||||
/* This function ensures that the console pointer is not NULL */
|
||||
PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
|
||||
return ( ((GuiData == NULL) || (GuiData->hWindow == hWnd && GuiData->Console != NULL)) ? GuiData : NULL );
|
||||
}
|
||||
|
@ -342,6 +357,8 @@ GuiConsoleHandleNcCreate(HWND hWnd, LPCREATESTRUCTW Create)
|
|||
TEXTMETRICW Metrics;
|
||||
SIZE CharSize;
|
||||
|
||||
DPRINT1("GuiConsoleHandleNcCreate\n");
|
||||
|
||||
if (NULL == GuiData)
|
||||
{
|
||||
DPRINT1("GuiConsoleNcCreate: No GUI data\n");
|
||||
|
@ -424,12 +441,7 @@ GuiConsoleHandleNcCreate(HWND hWnd, LPCREATESTRUCTW Create)
|
|||
SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL);
|
||||
GuiConsoleCreateSysMenu(GuiData->hWindow);
|
||||
|
||||
/* Move and resize the window to the user's values */
|
||||
GuiConsoleMoveWindow(GuiData);
|
||||
GuiData->WindowSizeLock = TRUE;
|
||||
GuiConsoleResizeWindow(GuiData);
|
||||
GuiData->WindowSizeLock = FALSE;
|
||||
|
||||
DPRINT1("GuiConsoleHandleNcCreate - setting start event\n");
|
||||
SetEvent(GuiData->hGuiInitEvent);
|
||||
|
||||
return (BOOL)DefWindowProcW(GuiData->hWindow, WM_NCCREATE, 0, (LPARAM)Create);
|
||||
|
@ -526,8 +538,6 @@ GuiConsolePaint(PCONSOLE Console,
|
|||
|
||||
Buff = Console->ActiveBuffer;
|
||||
|
||||
/// LOCK /// EnterCriticalSection(&Buff->Header.Console->Lock);
|
||||
|
||||
TopLine = rc->top / GuiData->CharHeight + Buff->ShowY;
|
||||
BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buff->ShowY;
|
||||
LeftChar = rc->left / GuiData->CharWidth + Buff->ShowX;
|
||||
|
@ -618,57 +628,71 @@ GuiConsolePaint(PCONSOLE Console,
|
|||
}
|
||||
}
|
||||
|
||||
/// LOCK /// LeaveCriticalSection(&Buff->Header.Console->Lock);
|
||||
|
||||
SelectObject(hDC, OldFont);
|
||||
}
|
||||
|
||||
static VOID
|
||||
GuiConsoleHandlePaint(PGUI_CONSOLE_DATA GuiData, HDC hDCPaint)
|
||||
GuiConsoleHandlePaint(PGUI_CONSOLE_DATA GuiData)
|
||||
{
|
||||
BOOL Success = TRUE;
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
HDC hDC;
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
if (Console->ActiveBuffer == NULL) return;
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
Success = FALSE;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (Console->ActiveBuffer == NULL ||
|
||||
Console->ActiveBuffer->Buffer == NULL)
|
||||
{
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
hDC = BeginPaint(GuiData->hWindow, &ps);
|
||||
if (hDC != NULL &&
|
||||
ps.rcPaint.left < ps.rcPaint.right &&
|
||||
ps.rcPaint.top < ps.rcPaint.bottom)
|
||||
{
|
||||
if (Console->ActiveBuffer->Buffer != NULL)
|
||||
EnterCriticalSection(&GuiData->Lock);
|
||||
|
||||
GuiConsolePaint(Console,
|
||||
GuiData,
|
||||
hDC,
|
||||
&ps.rcPaint);
|
||||
|
||||
if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
|
||||
{
|
||||
EnterCriticalSection(&GuiData->Lock);
|
||||
RECT rc;
|
||||
SmallRectToRect(GuiData, &rc, &Console->Selection.srSelection);
|
||||
|
||||
GuiConsolePaint(Console,
|
||||
GuiData,
|
||||
hDC,
|
||||
&ps.rcPaint);
|
||||
|
||||
if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
|
||||
/* invert the selection */
|
||||
if (IntersectRect(&rc,
|
||||
&ps.rcPaint,
|
||||
&rc))
|
||||
{
|
||||
RECT rc;
|
||||
SmallRectToRect(GuiData, &rc, &Console->Selection.srSelection);
|
||||
|
||||
/* invert the selection */
|
||||
if (IntersectRect(&rc,
|
||||
&ps.rcPaint,
|
||||
&rc))
|
||||
{
|
||||
PatBlt(hDC,
|
||||
rc.left,
|
||||
rc.top,
|
||||
rc.right - rc.left,
|
||||
rc.bottom - rc.top,
|
||||
DSTINVERT);
|
||||
}
|
||||
PatBlt(hDC,
|
||||
rc.left,
|
||||
rc.top,
|
||||
rc.right - rc.left,
|
||||
rc.bottom - rc.top,
|
||||
DSTINVERT);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&GuiData->Lock);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&GuiData->Lock);
|
||||
}
|
||||
EndPaint(GuiData->hWindow, &ps);
|
||||
|
||||
Quit:
|
||||
if (Success)
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
else
|
||||
DefWindowProcW(GuiData->hWindow, WM_PAINT, 0, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID
|
||||
|
@ -677,6 +701,8 @@ GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM l
|
|||
PCONSOLE Console = GuiData->Console;
|
||||
MSG Message;
|
||||
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
|
||||
|
||||
Message.hwnd = GuiData->hWindow;
|
||||
Message.message = msg;
|
||||
Message.wParam = wParam;
|
||||
|
@ -689,6 +715,8 @@ GuiConsoleHandleKey(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM l
|
|||
}
|
||||
|
||||
ConioProcessKey(Console, &Message);
|
||||
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
}
|
||||
|
||||
static VOID
|
||||
|
@ -706,6 +734,8 @@ GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData)
|
|||
|
||||
SetTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER, CURSOR_BLINK_TIME, NULL);
|
||||
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
|
||||
|
||||
Buff = Console->ActiveBuffer;
|
||||
GuiInvalidateCell(Console, Buff->CursorPosition.X, Buff->CursorPosition.Y);
|
||||
Buff->CursorBlinkOn = !Buff->CursorBlinkOn;
|
||||
|
@ -782,14 +812,15 @@ GuiConsoleHandleTimer(PGUI_CONSOLE_DATA GuiData)
|
|||
GuiData->OldCursor.y = Buff->CursorPosition.Y;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
}
|
||||
|
||||
static VOID
|
||||
GuiConsoleHandleClose(PGUI_CONSOLE_DATA GuiData)
|
||||
{
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
|
||||
/// LOCK /// EnterCriticalSection(&Console->Lock);
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
|
||||
|
||||
/*
|
||||
* FIXME: Windows will wait up to 5 seconds for the thread to exit.
|
||||
|
@ -798,17 +829,23 @@ GuiConsoleHandleClose(PGUI_CONSOLE_DATA GuiData)
|
|||
*/
|
||||
ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_CLOSE_EVENT);
|
||||
|
||||
/// LOCK /// LeaveCriticalSection(&Console->Lock);
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
}
|
||||
|
||||
static VOID
|
||||
GuiConsoleHandleNcDestroy(PGUI_CONSOLE_DATA GuiData)
|
||||
static LRESULT
|
||||
GuiConsoleHandleNcDestroy(HWND hWnd)
|
||||
{
|
||||
KillTimer(GuiData->hWindow, CONGUI_UPDATE_TIMER);
|
||||
GetSystemMenu(GuiData->hWindow, TRUE);
|
||||
// PGUI_CONSOLE_DATA GuiData;
|
||||
|
||||
SetWindowLongPtrW(GuiData->hWindow, GWLP_USERDATA, (DWORD_PTR)NULL);
|
||||
GuiData->hWindow = NULL;
|
||||
KillTimer(hWnd, CONGUI_UPDATE_TIMER);
|
||||
GetSystemMenu(hWnd, TRUE);
|
||||
|
||||
/* Free the GuiData registration */
|
||||
SetWindowLongPtrW(hWnd, GWLP_USERDATA, (DWORD_PTR)NULL);
|
||||
// GuiData->hWindow = NULL;
|
||||
|
||||
// return 0;
|
||||
return DefWindowProcW(hWnd, WM_NCDESTROY, 0, 0);
|
||||
}
|
||||
|
||||
static COORD
|
||||
|
@ -835,43 +872,85 @@ PointToCoord(PGUI_CONSOLE_DATA GuiData, LPARAM lParam)
|
|||
return Coord;
|
||||
}
|
||||
|
||||
static VOID
|
||||
GuiConsoleLeftMouseDown(PGUI_CONSOLE_DATA GuiData, LPARAM lParam)
|
||||
static LRESULT
|
||||
GuiConsoleHandleMouse(PGUI_CONSOLE_DATA GuiData, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LRESULT Ret = TRUE;
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
|
||||
Console->Selection.dwSelectionAnchor = PointToCoord(GuiData, lParam);
|
||||
SetCapture(GuiData->hWindow);
|
||||
Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS | CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
|
||||
GuiConsoleUpdateSelection(Console, &Console->Selection.dwSelectionAnchor);
|
||||
}
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
Ret = FALSE;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
static VOID
|
||||
GuiConsoleLeftMouseUp(PGUI_CONSOLE_DATA GuiData, LPARAM lParam)
|
||||
{
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
COORD c;
|
||||
switch (msg)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
{
|
||||
Console->Selection.dwSelectionAnchor = PointToCoord(GuiData, lParam);
|
||||
SetCapture(GuiData->hWindow);
|
||||
Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS | CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
|
||||
GuiConsoleUpdateSelection(Console, &Console->Selection.dwSelectionAnchor);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) return;
|
||||
case WM_LBUTTONUP:
|
||||
{
|
||||
COORD c;
|
||||
|
||||
c = PointToCoord(GuiData, lParam);
|
||||
Console->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN;
|
||||
GuiConsoleUpdateSelection(Console, &c);
|
||||
ReleaseCapture();
|
||||
}
|
||||
if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
|
||||
|
||||
static VOID
|
||||
GuiConsoleMouseMove(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
COORD c;
|
||||
c = PointToCoord(GuiData, lParam);
|
||||
Console->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN;
|
||||
GuiConsoleUpdateSelection(Console, &c);
|
||||
ReleaseCapture();
|
||||
|
||||
if (!(wParam & MK_LBUTTON)) return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) return;
|
||||
case WM_RBUTTONDOWN:
|
||||
{
|
||||
if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
|
||||
{
|
||||
GuiConsolePaste(GuiData);
|
||||
}
|
||||
else
|
||||
{
|
||||
GuiConsoleCopy(GuiData);
|
||||
|
||||
c = PointToCoord(GuiData, lParam); /* TODO: Scroll buffer to bring c into view */
|
||||
GuiConsoleUpdateSelection(Console, &c);
|
||||
/* Clear the selection */
|
||||
GuiConsoleUpdateSelection(Console, NULL);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
COORD c;
|
||||
|
||||
if (!(wParam & MK_LBUTTON)) break;
|
||||
if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) break;
|
||||
|
||||
c = PointToCoord(GuiData, lParam); /* TODO: Scroll buffer to bring c into view */
|
||||
GuiConsoleUpdateSelection(Console, &c);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
|
||||
Quit:
|
||||
if (!Ret)
|
||||
Ret = DefWindowProcW(GuiData->hWindow, msg, wParam, lParam);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static VOID
|
||||
|
@ -982,30 +1061,14 @@ GuiConsolePaste(PGUI_CONSOLE_DATA GuiData)
|
|||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
GuiConsoleRightMouseDown(PGUI_CONSOLE_DATA GuiData)
|
||||
{
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
|
||||
if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
|
||||
{
|
||||
GuiConsolePaste(GuiData);
|
||||
}
|
||||
else
|
||||
{
|
||||
GuiConsoleCopy(GuiData);
|
||||
|
||||
/* Clear the selection */
|
||||
GuiConsoleUpdateSelection(Console, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
GuiConsoleGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData, PMINMAXINFO minMaxInfo)
|
||||
{
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
DWORD windx, windy;
|
||||
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
|
||||
|
||||
windx = CONGUI_MIN_WIDTH * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
|
||||
windy = CONGUI_MIN_HEIGHT * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
|
||||
|
||||
|
@ -1020,6 +1083,8 @@ GuiConsoleGetMinMaxInfo(PGUI_CONSOLE_DATA GuiData, PMINMAXINFO minMaxInfo)
|
|||
|
||||
minMaxInfo->ptMaxTrackSize.x = windx;
|
||||
minMaxInfo->ptMaxTrackSize.y = windy;
|
||||
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
}
|
||||
|
||||
static VOID
|
||||
|
@ -1027,6 +1092,8 @@ GuiConsoleResize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
|
||||
|
||||
if ((GuiData->WindowSizeLock == FALSE) &&
|
||||
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED))
|
||||
{
|
||||
|
@ -1076,6 +1143,8 @@ GuiConsoleResize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
GuiData->WindowSizeLock = FALSE;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1107,8 +1176,7 @@ GuiConsoleHandleScrollbarMenu(VOID)
|
|||
}
|
||||
*/
|
||||
|
||||
static
|
||||
LRESULT
|
||||
static LRESULT
|
||||
GuiConsoleHandleScroll(PGUI_CONSOLE_DATA GuiData, UINT uMsg, WPARAM wParam)
|
||||
{
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
|
@ -1118,7 +1186,7 @@ GuiConsoleHandleScroll(PGUI_CONSOLE_DATA GuiData, UINT uMsg, WPARAM wParam)
|
|||
int old_pos, Maximum;
|
||||
PUSHORT pShowXY;
|
||||
|
||||
if (GuiData == NULL) return FALSE;
|
||||
if (!ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return 0;
|
||||
|
||||
Buff = Console->ActiveBuffer;
|
||||
|
||||
|
@ -1139,10 +1207,7 @@ GuiConsoleHandleScroll(PGUI_CONSOLE_DATA GuiData, UINT uMsg, WPARAM wParam)
|
|||
sInfo.cbSize = sizeof(SCROLLINFO);
|
||||
sInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS;
|
||||
|
||||
if (!GetScrollInfo(GuiData->hWindow, fnBar, &sInfo))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!GetScrollInfo(GuiData->hWindow, fnBar, &sInfo)) goto Quit;
|
||||
|
||||
old_pos = sInfo.nPos;
|
||||
|
||||
|
@ -1209,6 +1274,8 @@ GuiConsoleHandleScroll(PGUI_CONSOLE_DATA GuiData, UINT uMsg, WPARAM wParam)
|
|||
UpdateWindow(GuiData->hWindow);
|
||||
}
|
||||
|
||||
Quit:
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1217,15 +1284,22 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
LRESULT Result = 0;
|
||||
PGUI_CONSOLE_DATA GuiData = NULL;
|
||||
PCONSOLE Console = NULL;
|
||||
|
||||
/*
|
||||
* If it's the first time we create a window
|
||||
* for the terminal, just initialize it.
|
||||
* - If it's the first time we create a window for the terminal,
|
||||
* just initialize it and return.
|
||||
*
|
||||
* - If we are destroying the window, just do it and return.
|
||||
*/
|
||||
if (msg == WM_NCCREATE)
|
||||
{
|
||||
return (LRESULT)GuiConsoleHandleNcCreate(hWnd, (LPCREATESTRUCTW)lParam);
|
||||
}
|
||||
else if (msg == WM_NCDESTROY)
|
||||
{
|
||||
return GuiConsoleHandleNcDestroy(hWnd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now the terminal window is initialized.
|
||||
|
@ -1235,24 +1309,20 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
GuiData = GuiGetGuiData(hWnd);
|
||||
if (GuiData == NULL) return 0;
|
||||
|
||||
// TODO: If the console is about to be destroyed, leave the loop.
|
||||
/*
|
||||
* Each helper function which needs the console
|
||||
* has to validate and lock it.
|
||||
*/
|
||||
|
||||
/* Lock the console */
|
||||
EnterCriticalSection(&GuiData->Console->Lock);
|
||||
|
||||
/* We have a console, start message dispatching. */
|
||||
/* We have a console, start message dispatching */
|
||||
switch (msg)
|
||||
{
|
||||
case WM_CLOSE:
|
||||
GuiConsoleHandleClose(GuiData);
|
||||
break;
|
||||
|
||||
case WM_NCDESTROY:
|
||||
GuiConsoleHandleNcDestroy(GuiData);
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
GuiConsoleHandlePaint(GuiData, (HDC)wParam);
|
||||
GuiConsoleHandlePaint(GuiData);
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
|
@ -1260,37 +1330,43 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
case WM_CHAR:
|
||||
{
|
||||
GuiConsoleHandleKey(GuiData, msg, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_TIMER:
|
||||
GuiConsoleHandleTimer(GuiData);
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
GuiConsoleLeftMouseDown(GuiData, lParam);
|
||||
break;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
GuiConsoleLeftMouseUp(GuiData, lParam);
|
||||
break;
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
GuiConsoleRightMouseDown(GuiData);
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
GuiConsoleMouseMove(GuiData, wParam, lParam);
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_RBUTTONDBLCLK:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_MBUTTONDBLCLK:
|
||||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
Result = GuiConsoleHandleMouse(GuiData, msg, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
{
|
||||
Result = GuiConsoleHandleSysMenuCommand(GuiData, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_HSCROLL:
|
||||
case WM_VSCROLL:
|
||||
{
|
||||
Result = GuiConsoleHandleScroll(GuiData, msg, wParam);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_GETMINMAXINFO:
|
||||
GuiConsoleGetMinMaxInfo(GuiData, (PMINMAXINFO)lParam);
|
||||
|
@ -1301,26 +1377,30 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
break;
|
||||
|
||||
case PM_APPLY_CONSOLE_INFO:
|
||||
GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam);
|
||||
{
|
||||
Console = GuiData->Console; // Not NULL because checked in GuiGetGuiData.
|
||||
if (ConSrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
GuiApplyUserSettings(GuiData, (HANDLE)wParam, (BOOL)lParam);
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PM_CONSOLE_BEEP:
|
||||
DPRINT1("Beep !!\n");
|
||||
Beep(800, 200);
|
||||
break;
|
||||
|
||||
case PM_CONSOLE_SET_TITLE:
|
||||
SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
|
||||
break;
|
||||
// case PM_CONSOLE_SET_TITLE:
|
||||
// SetWindowText(GuiData->hWindow, GuiData->Console->Title.Buffer);
|
||||
// break;
|
||||
|
||||
default:
|
||||
Result = DefWindowProcW(GuiData->hWindow, msg, wParam, lParam);
|
||||
Result = DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unlock the console */
|
||||
LeaveCriticalSection(&GuiData->Console->Lock);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -1336,8 +1416,6 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
HWND NewWindow;
|
||||
LONG WindowCount;
|
||||
MSG Msg;
|
||||
PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam;
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
|
@ -1349,6 +1427,9 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
case PM_CREATE_CONSOLE:
|
||||
{
|
||||
PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam;
|
||||
PCONSOLE Console = GuiData->Console;
|
||||
|
||||
NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE,
|
||||
GUI_CONSOLE_WINDOW_CLASS,
|
||||
Console->Title.Buffer,
|
||||
|
@ -1381,7 +1462,16 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
SendMessageW(GuiData->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)GuiData->hIconSm);
|
||||
}
|
||||
|
||||
ShowWindow(NewWindow, (int)wParam);
|
||||
/* Move and resize the window to the user's values */
|
||||
/* CAN WE DEADLOCK ?? */
|
||||
GuiConsoleMoveWindow(GuiData);
|
||||
GuiData->WindowSizeLock = TRUE;
|
||||
GuiConsoleResizeWindow(GuiData);
|
||||
GuiData->WindowSizeLock = FALSE;
|
||||
|
||||
// ShowWindow(NewWindow, (int)wParam);
|
||||
ShowWindowAsync(NewWindow, (int)wParam);
|
||||
DPRINT1("Window showed\n");
|
||||
}
|
||||
|
||||
return (LRESULT)NewWindow;
|
||||
|
@ -1389,16 +1479,20 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
case PM_DESTROY_CONSOLE:
|
||||
{
|
||||
PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam;
|
||||
|
||||
/*
|
||||
* Window creation is done using a PostMessage(), so it's possible
|
||||
* that the window that we want to destroy doesn't exist yet.
|
||||
* So first empty the message queue.
|
||||
*/
|
||||
/*
|
||||
while(PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&Msg);
|
||||
DispatchMessageW(&Msg);
|
||||
}
|
||||
}*/
|
||||
while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) ;
|
||||
|
||||
if (GuiData->hWindow != NULL) /* && DestroyWindow(GuiData->hWindow) */
|
||||
{
|
||||
|
@ -1607,6 +1701,8 @@ GuiCleanupConsole(PCONSOLE Console)
|
|||
Console->TermIFace.Data = NULL;
|
||||
DeleteCriticalSection(&GuiData->Lock);
|
||||
RtlFreeHeap(ConSrvHeap, 0, GuiData);
|
||||
|
||||
DPRINT1("Quit GuiCleanupConsole\n");
|
||||
}
|
||||
|
||||
static VOID WINAPI
|
||||
|
@ -1835,7 +1931,8 @@ static VOID WINAPI
|
|||
GuiChangeTitle(PCONSOLE Console)
|
||||
{
|
||||
PGUI_CONSOLE_DATA GuiData = Console->TermIFace.Data;
|
||||
PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0);
|
||||
// PostMessageW(GuiData->hWindow, PM_CONSOLE_SET_TITLE, 0, 0);
|
||||
SetWindowText(GuiData->hWindow, Console->Title.Buffer);
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
|
@ -1916,6 +2013,7 @@ GuiInitConsole(PCONSOLE Console,
|
|||
{
|
||||
PGUI_CONSOLE_DATA GuiData;
|
||||
GUI_CONSOLE_INFO TermInfo;
|
||||
SIZE_T Length = 0;
|
||||
|
||||
if (Console == NULL || ConsoleInfo == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
@ -1984,7 +2082,9 @@ GuiInitConsole(PCONSOLE Console,
|
|||
* Set up the GUI data
|
||||
*/
|
||||
|
||||
Length = min(wcslen(TermInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen
|
||||
wcsncpy(GuiData->GuiInfo.FaceName, TermInfo.FaceName, LF_FACESIZE);
|
||||
GuiData->GuiInfo.FaceName[Length] = L'\0';
|
||||
GuiData->GuiInfo.FontFamily = TermInfo.FontFamily;
|
||||
GuiData->GuiInfo.FontSize = TermInfo.FontSize;
|
||||
GuiData->GuiInfo.FontWeight = TermInfo.FontWeight;
|
||||
|
@ -2034,6 +2134,7 @@ GuiInitConsole(PCONSOLE Console,
|
|||
|
||||
/* Wait until initialization has finished */
|
||||
WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
|
||||
DPRINT1("OK we created the console window\n");
|
||||
CloseHandle(GuiData->hGuiInitEvent);
|
||||
GuiData->hGuiInitEvent = NULL;
|
||||
|
||||
|
|
|
@ -86,7 +86,9 @@ GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
|
|||
|
||||
if (!wcscmp(szValueName, L"FaceName"))
|
||||
{
|
||||
SIZE_T Length = min(wcslen(szValue) + 1, LF_FACESIZE); // wcsnlen
|
||||
wcsncpy(TermInfo->FaceName, szValue, LF_FACESIZE);
|
||||
TermInfo->FaceName[Length] = L'\0';
|
||||
RetVal = TRUE;
|
||||
}
|
||||
else if (!wcscmp(szValueName, L"FontFamily"))
|
||||
|
@ -150,7 +152,7 @@ do {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
SetConsoleSetting(L"FaceName", REG_SZ, (wcslen(TermInfo->FaceName) + 1) * sizeof(WCHAR), TermInfo->FaceName, L'\0');
|
||||
SetConsoleSetting(L"FaceName", REG_SZ, (wcslen(TermInfo->FaceName) + 1) * sizeof(WCHAR), TermInfo->FaceName, L'\0'); // wcsnlen
|
||||
SetConsoleSetting(L"FontFamily", REG_DWORD, sizeof(DWORD), &TermInfo->FontFamily, FF_DONTCARE);
|
||||
SetConsoleSetting(L"FontSize", REG_DWORD, sizeof(DWORD), &TermInfo->FontSize, 0);
|
||||
SetConsoleSetting(L"FontWeight", REG_DWORD, sizeof(DWORD), &TermInfo->FontWeight, FW_DONTCARE);
|
||||
|
@ -269,43 +271,59 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
|
|||
pSharedInfo->hConsoleWindow = GuiData->hWindow;
|
||||
pSharedInfo->ShowDefaultParams = Defaults;
|
||||
|
||||
/* Console information */
|
||||
pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize;
|
||||
pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
|
||||
pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup;
|
||||
pSharedInfo->ci.FullScreen = Console->FullScreen;
|
||||
pSharedInfo->ci.QuickEdit = Console->QuickEdit;
|
||||
pSharedInfo->ci.InsertMode = Console->InsertMode;
|
||||
pSharedInfo->ci.InputBufferSize = 0;
|
||||
pSharedInfo->ci.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
|
||||
pSharedInfo->ci.ConsoleSize = Console->ConsoleSize;
|
||||
pSharedInfo->ci.CursorBlinkOn;
|
||||
pSharedInfo->ci.ForceCursorOff;
|
||||
pSharedInfo->ci.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
|
||||
pSharedInfo->ci.ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib;
|
||||
pSharedInfo->ci.PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib;
|
||||
pSharedInfo->ci.CodePage;
|
||||
/*
|
||||
* We fill-in the fields only if we display
|
||||
* our properties, not the default ones.
|
||||
*/
|
||||
if (!Defaults)
|
||||
{
|
||||
/* Console information */
|
||||
pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize;
|
||||
pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
|
||||
pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup;
|
||||
pSharedInfo->ci.FullScreen = Console->FullScreen;
|
||||
pSharedInfo->ci.QuickEdit = Console->QuickEdit;
|
||||
pSharedInfo->ci.InsertMode = Console->InsertMode;
|
||||
pSharedInfo->ci.InputBufferSize = 0;
|
||||
pSharedInfo->ci.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
|
||||
pSharedInfo->ci.ConsoleSize = Console->ConsoleSize;
|
||||
pSharedInfo->ci.CursorBlinkOn;
|
||||
pSharedInfo->ci.ForceCursorOff;
|
||||
pSharedInfo->ci.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
|
||||
pSharedInfo->ci.ScreenAttrib = Console->ActiveBuffer->ScreenDefaultAttrib;
|
||||
pSharedInfo->ci.PopupAttrib = Console->ActiveBuffer->PopupDefaultAttrib;
|
||||
pSharedInfo->ci.CodePage;
|
||||
|
||||
/* GUI Information */
|
||||
pSharedInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO);
|
||||
GuiInfo = pSharedInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pSharedInfo + 1);
|
||||
wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE);
|
||||
GuiInfo->FontSize = (DWORD)GuiData->GuiInfo.FontSize;
|
||||
GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight;
|
||||
GuiInfo->UseRasterFonts = GuiData->GuiInfo.UseRasterFonts;
|
||||
/// GuiInfo->WindowPosition = GuiData->GuiInfo.WindowPosition;
|
||||
GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition;
|
||||
GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin;
|
||||
/* Offsetize */
|
||||
pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)GuiInfo - (ULONG_PTR)pSharedInfo);
|
||||
/* GUI Information */
|
||||
pSharedInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO);
|
||||
GuiInfo = pSharedInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pSharedInfo + 1);
|
||||
Length = min(wcslen(GuiData->GuiInfo.FaceName) + 1, LF_FACESIZE); // wcsnlen
|
||||
wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE);
|
||||
GuiInfo->FaceName[Length] = L'\0';
|
||||
GuiInfo->FontFamily = GuiData->GuiInfo.FontFamily;
|
||||
GuiInfo->FontSize = GuiData->GuiInfo.FontSize;
|
||||
GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight;
|
||||
GuiInfo->UseRasterFonts = GuiData->GuiInfo.UseRasterFonts;
|
||||
/// GuiInfo->WindowPosition = GuiData->GuiInfo.WindowPosition;
|
||||
GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition;
|
||||
GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin;
|
||||
/* Offsetize */
|
||||
pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)GuiInfo - (ULONG_PTR)pSharedInfo);
|
||||
|
||||
/* Palette */
|
||||
memcpy(pSharedInfo->ci.Colors, Console->Colors, sizeof(Console->Colors));
|
||||
/* Palette */
|
||||
memcpy(pSharedInfo->ci.Colors, Console->Colors, sizeof(Console->Colors));
|
||||
|
||||
/* Title of the console, original one corresponding to the one set by the console leader */
|
||||
Length = min(sizeof(pSharedInfo->ci.ConsoleTitle) / sizeof(pSharedInfo->ci.ConsoleTitle[0]) - 1,
|
||||
Console->OriginalTitle.Length / sizeof(WCHAR));
|
||||
wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length);
|
||||
/* Title of the console, original one corresponding to the one set by the console leader */
|
||||
Length = min(sizeof(pSharedInfo->ci.ConsoleTitle) / sizeof(pSharedInfo->ci.ConsoleTitle[0]) - 1,
|
||||
Console->OriginalTitle.Length / sizeof(WCHAR));
|
||||
wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Length = 0;
|
||||
}
|
||||
|
||||
/* Null-terminate the title */
|
||||
pSharedInfo->ci.ConsoleTitle[Length] = L'\0';
|
||||
|
||||
|
||||
|
@ -326,29 +344,46 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Error: Impossible to duplicate section handle for client ; Status = %lu\n", Status);
|
||||
NtClose(hSection);
|
||||
return;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Start the properties dialog */
|
||||
if (ProcessData->PropDispatcher)
|
||||
{
|
||||
HANDLE Thread;
|
||||
|
||||
Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
|
||||
ProcessData->PropDispatcher,
|
||||
(PVOID)hClientSection, 0, NULL);
|
||||
if (NULL == Thread)
|
||||
_SEH2_TRY
|
||||
{
|
||||
DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
HANDLE Thread = NULL;
|
||||
|
||||
DPRINT1("We succeeded at creating ProcessData->PropDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
|
||||
/// WaitForSingleObject(Thread, INFINITE);
|
||||
CloseHandle(Thread);
|
||||
_SEH2_TRY
|
||||
{
|
||||
Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
|
||||
ProcessData->PropDispatcher,
|
||||
(PVOID)hClientSection, 0, NULL);
|
||||
if (NULL == Thread)
|
||||
{
|
||||
DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("ProcessData->PropDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
|
||||
/// WaitForSingleObject(Thread, INFINITE);
|
||||
}
|
||||
}
|
||||
_SEH2_FINALLY
|
||||
{
|
||||
CloseHandle(Thread);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = %08X\n", Status);
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
Quit:
|
||||
/* We have finished, close the section handle */
|
||||
NtClose(hSection);
|
||||
return;
|
||||
|
@ -369,8 +404,6 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
|
|||
PTERMINAL_INFO TermInfo = NULL;
|
||||
PGUI_CONSOLE_INFO GuiInfo = NULL;
|
||||
|
||||
/// LOCK /// EnterCriticalSection(&Console->Lock);
|
||||
|
||||
/* Get the console leader process, our client */
|
||||
ProcessData = CONTAINING_RECORD(Console->ProcessList.Blink,
|
||||
CONSOLE_PROCESS_DATA,
|
||||
|
@ -406,51 +439,65 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* Check that the section is well-sized */
|
||||
if ( (ViewSize < sizeof(CONSOLE_PROPS)) ||
|
||||
(pConInfo->TerminalInfo.Size != sizeof(GUI_CONSOLE_INFO)) ||
|
||||
(ViewSize < sizeof(CONSOLE_PROPS) + pConInfo->TerminalInfo.Size) )
|
||||
_SEH2_TRY
|
||||
{
|
||||
DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n");
|
||||
Status = STATUS_INVALID_VIEW_SIZE;
|
||||
goto Quit;
|
||||
/* Check that the section is well-sized */
|
||||
if ( (ViewSize < sizeof(CONSOLE_PROPS)) ||
|
||||
(pConInfo->TerminalInfo.Size != sizeof(GUI_CONSOLE_INFO)) ||
|
||||
(ViewSize < sizeof(CONSOLE_PROPS) + pConInfo->TerminalInfo.Size) )
|
||||
{
|
||||
DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n");
|
||||
Status = STATUS_INVALID_VIEW_SIZE;
|
||||
_SEH2_YIELD(goto Quit);
|
||||
}
|
||||
|
||||
// TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow
|
||||
|
||||
/* Retrieve terminal informations */
|
||||
ConInfo = &pConInfo->ci;
|
||||
TermInfo = &pConInfo->TerminalInfo;
|
||||
GuiInfo = TermInfo->TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)TermInfo->TermInfo);
|
||||
|
||||
/*
|
||||
* If we don't set the default parameters,
|
||||
* apply them, otherwise just save them.
|
||||
*/
|
||||
if (pConInfo->ShowDefaultParams == FALSE)
|
||||
{
|
||||
/* Set the console informations */
|
||||
ConSrvApplyUserSettings(Console, ConInfo);
|
||||
|
||||
/* Set the terminal informations */
|
||||
|
||||
// memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO));
|
||||
|
||||
/* Move the window to the user's values */
|
||||
GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition;
|
||||
GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin;
|
||||
GuiConsoleMoveWindow(GuiData);
|
||||
|
||||
InvalidateRect(GuiData->hWindow, NULL, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save settings if needed
|
||||
*/
|
||||
// FIXME: Do it in the console properties applet ??
|
||||
if (SaveSettings)
|
||||
{
|
||||
DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess);
|
||||
ConSrvWriteUserSettings(ConInfo, ProcessId);
|
||||
GuiConsoleWriteUserSettings(GuiInfo, ConInfo->ConsoleTitle, ProcessId);
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow
|
||||
|
||||
/* Set the console informations */
|
||||
ConInfo = &pConInfo->ci;
|
||||
ConSrvApplyUserSettings(Console, ConInfo);
|
||||
|
||||
/* Set the terminal informations - De-offsetization of the pointer */
|
||||
TermInfo = &pConInfo->TerminalInfo;
|
||||
GuiInfo = TermInfo->TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)TermInfo->TermInfo);
|
||||
|
||||
// memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO));
|
||||
|
||||
/* Move the window to the user's values */
|
||||
GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition;
|
||||
GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin;
|
||||
GuiConsoleMoveWindow(GuiData);
|
||||
|
||||
InvalidateRect(GuiData->hWindow, NULL, TRUE);
|
||||
|
||||
|
||||
/*
|
||||
* Save settings if needed
|
||||
*/
|
||||
|
||||
// FIXME: Do it in the console properties applet ??
|
||||
if (SaveSettings)
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess);
|
||||
ConSrvWriteUserSettings(ConInfo, ProcessId);
|
||||
GuiConsoleWriteUserSettings(GuiInfo, ConInfo->ConsoleTitle, ProcessId);
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
DPRINT1("GuiApplyUserSettings - Caught an exception, Status = %08X\n", Status);
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
/// LOCK /// LeaveCriticalSection(&Console->Lock);
|
||||
_SEH2_END;
|
||||
|
||||
Quit:
|
||||
/* Finally, close the section and return */
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
|
||||
#include "consrv.h"
|
||||
#include "conio.h"
|
||||
#include "console.h"
|
||||
|
||||
//#define NDEBUG
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
|
@ -22,7 +23,7 @@ AdjustHandleCounts(PCONSOLE_IO_HANDLE Entry, INT Change)
|
|||
{
|
||||
Object_t *Object = Entry->Object;
|
||||
|
||||
DPRINT1("AdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry, Change, Object, Object->HandleCount, Object->Type);
|
||||
DPRINT("AdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry, Change, Object, Object->HandleCount, Object->Type);
|
||||
|
||||
if (Entry->Access & GENERIC_READ) Object->AccessRead += Change;
|
||||
if (Entry->Access & GENERIC_WRITE) Object->AccessWrite += Change;
|
||||
|
@ -236,8 +237,6 @@ Quit:
|
|||
static VOID
|
||||
ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData)
|
||||
{
|
||||
DPRINT1("ConSrvFreeHandlesTable\n");
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
if (ProcessData->HandleTable != NULL)
|
||||
|
@ -267,12 +266,13 @@ ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
BOOL Inheritable,
|
||||
DWORD ShareMode)
|
||||
{
|
||||
#define IO_HANDLES_INCREMENT 2*3
|
||||
#define IO_HANDLES_INCREMENT 2 * 3
|
||||
|
||||
ULONG i;
|
||||
PCONSOLE_IO_HANDLE Block;
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
// NOTE: Commented out because calling code always lock HandleTableLock before.
|
||||
// RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
for (i = 0; i < ProcessData->HandleTableSize; i++)
|
||||
{
|
||||
|
@ -289,7 +289,7 @@ ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
IO_HANDLES_INCREMENT) * sizeof(CONSOLE_IO_HANDLE));
|
||||
if (Block == NULL)
|
||||
{
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
RtlCopyMemory(Block,
|
||||
|
@ -307,7 +307,7 @@ ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
ConSrvCreateHandleEntry(&ProcessData->HandleTable[i]);
|
||||
*Handle = ULongToHandle((i << 2) | 0x3);
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -329,11 +329,9 @@ ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
DPRINT1("ConSrvRemoveObject - Process 0x%p, Release 0x%p\n", ProcessData->Process, &ProcessData->HandleTable[h]);
|
||||
ConSrvCloseHandleEntry(&ProcessData->HandleTable[h]);
|
||||
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -376,16 +374,24 @@ ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
_InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
if (LockConsole) EnterCriticalSection(&ObjectEntry->Console->Lock);
|
||||
if (ConSrvValidateConsole(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole))
|
||||
{
|
||||
_InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
|
||||
|
||||
/* Return the objects to the caller */
|
||||
*Object = ObjectEntry;
|
||||
if (Entry) *Entry = HandleEntry;
|
||||
/* Return the objects to the caller */
|
||||
*Object = ObjectEntry;
|
||||
if (Entry) *Entry = HandleEntry;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -465,6 +471,13 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
/* Validate and lock the console */
|
||||
if (!ConSrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
// FIXME: Find another status code
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Inherit the console */
|
||||
ProcessData->Console = Console;
|
||||
|
||||
|
@ -479,7 +492,7 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
{
|
||||
DPRINT1("Failed to initialize the handles table\n");
|
||||
ProcessData->Console = NULL;
|
||||
return Status;
|
||||
goto Quit;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,7 +507,7 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
|
||||
ConSrvFreeHandlesTable(ProcessData); // NOTE: Always free the handles table.
|
||||
ProcessData->Console = NULL;
|
||||
return Status;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* Insert the process into the processes list of the console */
|
||||
|
@ -506,30 +519,35 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
/* Update the internal info of the terminal */
|
||||
ConioRefreshInternalInfo(ProcessData->Console);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
Quit:
|
||||
/* Unlock the console and return */
|
||||
LeaveCriticalSection(&Console->Lock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
|
||||
{
|
||||
PCONSOLE Console;
|
||||
PCONSOLE Console = ProcessData->Console;
|
||||
|
||||
DPRINT1("ConSrvRemoveConsole\n");
|
||||
|
||||
/* Close all console handles and free the handle table memory */
|
||||
ConSrvFreeHandlesTable(ProcessData);
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
/* Detach process from console */
|
||||
Console = ProcessData->Console;
|
||||
if (Console != NULL)
|
||||
/* Validate and lock the console */
|
||||
if (ConSrvValidateConsole(Console, CONSOLE_RUNNING, TRUE))
|
||||
{
|
||||
DPRINT1("ConSrvRemoveConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console->ReferenceCount);
|
||||
ProcessData->Console = NULL;
|
||||
|
||||
EnterCriticalSection(&Console->Lock);
|
||||
DPRINT1("ConSrvRemoveConsole - Locking OK\n");
|
||||
|
||||
/* Close all console handles and free the handles table */
|
||||
ConSrvFreeHandlesTable(ProcessData);
|
||||
|
||||
/* Detach the process from the console */
|
||||
ProcessData->Console = NULL;
|
||||
|
||||
/* Remove ourselves from the console's list of processes */
|
||||
RemoveEntryList(&ProcessData->ConsoleLink);
|
||||
|
||||
|
@ -537,10 +555,105 @@ ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
|
|||
ConioRefreshInternalInfo(Console);
|
||||
|
||||
/* Release the console */
|
||||
DPRINT1("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount);
|
||||
ConSrvReleaseConsole(Console, TRUE);
|
||||
//CloseHandle(ProcessData->ConsoleEvent);
|
||||
//ProcessData->ConsoleEvent = NULL;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -549,37 +662,53 @@ ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
|||
PCONSOLE* Console,
|
||||
BOOL LockConsole)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCONSOLE ProcessConsole;
|
||||
|
||||
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
||||
ProcessConsole = ProcessData->Console;
|
||||
|
||||
if (!ProcessConsole)
|
||||
if (ConSrvValidateConsole(ProcessConsole, CONSOLE_RUNNING, LockConsole))
|
||||
{
|
||||
InterlockedIncrement(&ProcessConsole->ReferenceCount);
|
||||
*Console = ProcessConsole;
|
||||
}
|
||||
else
|
||||
{
|
||||
*Console = NULL;
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
return STATUS_INVALID_HANDLE;
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
InterlockedIncrement(&ProcessConsole->ReferenceCount);
|
||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||
|
||||
if (LockConsole) EnterCriticalSection(&ProcessConsole->Lock);
|
||||
|
||||
*Console = ProcessConsole;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID FASTCALL
|
||||
ConSrvReleaseConsole(PCONSOLE Console,
|
||||
BOOL IsConsoleLocked)
|
||||
BOOL WasConsoleLocked)
|
||||
{
|
||||
if (IsConsoleLocked) LeaveCriticalSection(&Console->Lock);
|
||||
LONG RefCount = 0;
|
||||
|
||||
/* Decrement reference count */
|
||||
if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
|
||||
ConSrvDeleteConsole(Console);
|
||||
if (!Console) return;
|
||||
// if (Console->ReferenceCount == 0) return; // This shouldn't happen
|
||||
ASSERT(Console->ReferenceCount > 0);
|
||||
|
||||
/* The console must be locked */
|
||||
// ASSERT(Console_locked);
|
||||
|
||||
/*
|
||||
* Decrement the reference count. Save the new value too,
|
||||
* because Console->ReferenceCount might be modified after
|
||||
* the console gets unlocked but before we check whether we
|
||||
* can destroy it.
|
||||
*/
|
||||
RefCount = _InterlockedDecrement(&Console->ReferenceCount);
|
||||
|
||||
/* Unlock the console if needed */
|
||||
if (WasConsoleLocked) LeaveCriticalSection(&Console->Lock);
|
||||
|
||||
/* Delete the console if needed */
|
||||
if (RefCount <= 0) ConSrvDeleteConsole(Console);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -745,8 +874,6 @@ ConSrvDisconnect(PCSR_PROCESS Process)
|
|||
* This function is called whenever a new process (GUI or CUI) is destroyed.
|
||||
**************************************************************************/
|
||||
|
||||
DPRINT1("ConSrvDisconnect\n");
|
||||
|
||||
if ( ProcessData->Console != NULL ||
|
||||
ProcessData->HandleTable != NULL )
|
||||
{
|
||||
|
@ -828,6 +955,7 @@ CSR_API(SrvDuplicateHandle)
|
|||
}
|
||||
}
|
||||
|
||||
/* Insert the new handle inside the process handles table */
|
||||
ApiMessage->Status = ConSrvInsertObject(ProcessData,
|
||||
&DuplicateHandleRequest->ConsoleHandle, // Use the new handle value!
|
||||
Entry->Object,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "consrv.h"
|
||||
#include "conio.h"
|
||||
#include "console.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
|
Loading…
Reference in a new issue