* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
* FILE: win32ss/user/consrv/console.c
- * PURPOSE: Console I/O functions
- * PROGRAMMERS:
+ * PURPOSE: Console Management Functions
+ * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
+
+#define COBJMACROS
+#define NONAMELESSUNION
#include "consrv.h"
-#include "guiconsole.h"
-#include "tuiconsole.h"
+#include "include/conio.h"
+#include "conio.h"
+#include "handle.h"
+#include "procinit.h"
+#include "alias.h"
+#include "coninput.h"
+#include "conoutput.h"
+#include "lineinput.h"
+#include "include/settings.h"
+
+#include "frontends/gui/guiterm.h"
+
+#ifdef TUI_CONSOLE
+ #include "frontends/tui/tuiterm.h"
+#endif
+
+#include "include/console.h"
+#include "console.h"
+#include "resource.h"
+
+#include <shlwapi.h>
+#include <shlobj.h>
#define NDEBUG
#include <debug.h>
-/* FUNCTIONS *****************************************************************/
+/* GLOBALS ********************************************************************/
-/*** Taken from win32ss/user/win32csr/desktopbg.c ***/
-BOOL FASTCALL
+static LIST_ENTRY ConsoleList; /* The list of all the allocated consoles */
+static RTL_RESOURCE ListLock;
+
+#define ConSrvLockConsoleListExclusive() \
+ RtlAcquireResourceExclusive(&ListLock, TRUE)
+
+#define ConSrvLockConsoleListShared() \
+ RtlAcquireResourceShared(&ListLock, TRUE)
+
+#define ConSrvUnlockConsoleList() \
+ RtlReleaseResource(&ListLock)
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+#ifdef TUI_CONSOLE
+static BOOL
DtbgIsDesktopVisible(VOID)
{
- HWND VisibleDesktopWindow = GetDesktopWindow(); // DESKTOPWNDPROC
+ return !((BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_ISCONSOLEMODE));
+}
+#endif
+
+static ULONG
+ConSrvConsoleCtrlEventTimeout(DWORD Event,
+ PCONSOLE_PROCESS_DATA ProcessData,
+ DWORD Timeout)
+{
+ ULONG Status = ERROR_SUCCESS;
- if (VisibleDesktopWindow != NULL &&
- !IsWindowVisible(VisibleDesktopWindow))
+ DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
+
+ if (ProcessData->CtrlDispatcher)
{
- VisibleDesktopWindow = NULL;
+ _SEH2_TRY
+ {
+ 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;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = RtlNtStatusToDosError(_SEH2_GetExceptionCode());
+ DPRINT1("ConSrvConsoleCtrlEventTimeout - Caught an exception, Status = %08X\n", Status);
+ }
+ _SEH2_END;
}
- return VisibleDesktopWindow != NULL;
+ return Status;
}
-/****************************************************/
-NTSTATUS FASTCALL
-ConioConsoleFromProcessData(PCSR_PROCESS ProcessData, PCSRSS_CONSOLE *Console)
+static ULONG
+ConSrvConsoleCtrlEvent(DWORD Event,
+ PCONSOLE_PROCESS_DATA ProcessData)
{
- PCSRSS_CONSOLE ProcessConsole;
+ return ConSrvConsoleCtrlEventTimeout(Event, ProcessData, 0);
+}
- RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- ProcessConsole = ProcessData->Console;
+ULONG FASTCALL
+ConSrvConsoleProcessCtrlEvent(PCONSOLE Console,
+ ULONG ProcessGroupId,
+ DWORD Event)
+{
+ ULONG Status = ERROR_SUCCESS;
+ 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;
- if (!ProcessConsole)
+ /*
+ * Loop through the process list, from the most recent process
+ * (the active one) to the oldest one (the first created, i.e.
+ * the console leader process), and for each, send an event
+ * (new processes are inserted at the head of the console process list).
+ */
+ current_entry = Console->ProcessList.Flink;
+ while (current_entry != &Console->ProcessList)
{
- *Console = NULL;
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return STATUS_INVALID_HANDLE;
+ current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
+ current_entry = current_entry->Flink;
+
+ /*
+ * Only processes belonging to the same process group are signaled.
+ * If the process group ID is zero, then all the processes are signaled.
+ */
+ if (ProcessGroupId == 0 || current->Process->ProcessGroupId == ProcessGroupId)
+ {
+ Status = ConSrvConsoleCtrlEvent(Event, current);
+ }
}
- InterlockedIncrement(&ProcessConsole->ReferenceCount);
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- EnterCriticalSection(&(ProcessConsole->Lock));
- *Console = ProcessConsole;
-
- return STATUS_SUCCESS;
+ return Status;
}
VOID FASTCALL
-ConioConsoleCtrlEventTimeout(DWORD Event, PCSR_PROCESS ProcessData, DWORD Timeout)
+ConioPause(PCONSOLE Console, UINT Flags)
{
- HANDLE Thread;
+ Console->PauseFlags |= Flags;
+ if (!Console->UnpauseEvent)
+ Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+}
- DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->ClientId.UniqueProcess);
+VOID FASTCALL
+ConioUnpause(PCONSOLE Console, UINT Flags)
+{
+ Console->PauseFlags &= ~Flags;
- if (ProcessData->CtrlDispatcher)
+ // if ((Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) == 0)
+ if (Console->PauseFlags == 0 && Console->UnpauseEvent)
{
+ SetEvent(Console->UnpauseEvent);
+ CloseHandle(Console->UnpauseEvent);
+ Console->UnpauseEvent = NULL;
- Thread = CreateRemoteThread(ProcessData->ProcessHandle, NULL, 0,
- (LPTHREAD_START_ROUTINE) ProcessData->CtrlDispatcher,
- UlongToPtr(Event), 0, NULL);
- if (NULL == Thread)
+ CsrNotifyWait(&Console->WriteWaitQueue,
+ WaitAll,
+ NULL,
+ NULL);
+ if (!IsListEmpty(&Console->WriteWaitQueue))
{
- DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
- return;
+ CsrDereferenceWait(&Console->WriteWaitQueue);
}
- WaitForSingleObject(Thread, Timeout);
- CloseHandle(Thread);
}
}
-VOID FASTCALL
-ConioConsoleCtrlEvent(DWORD Event, PCSR_PROCESS ProcessData)
+BOOL FASTCALL
+ConSrvValidateConsolePointer(PCONSOLE Console)
{
- ConioConsoleCtrlEventTimeout(Event, ProcessData, 0);
+ 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;
}
-static NTSTATUS WINAPI
-CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
+BOOL FASTCALL
+ConSrvValidateConsoleState(PCONSOLE Console,
+ CONSOLE_STATE ExpectedState)
{
- NTSTATUS Status;
- SECURITY_ATTRIBUTES SecurityAttributes;
- PCSRSS_SCREEN_BUFFER NewBuffer;
- BOOL GuiMode;
- WCHAR Title[255];
- HINSTANCE hInst;
+ // if (!Console) return FALSE;
- Console->Title.MaximumLength = Console->Title.Length = 0;
- Console->Title.Buffer = NULL;
+ /* The console must be locked */
+ // ASSERT(Console_locked);
- hInst = GetModuleHandleW(L"win32csr");
- if (LoadStringW(hInst,IDS_COMMAND_PROMPT,Title,sizeof(Title)/sizeof(Title[0])))
+ 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))
{
- RtlCreateUnicodeString(&Console->Title, Title);
+ if (LockConsole) LeaveCriticalSection(&Console->Lock);
+ return FALSE;
}
- else
+
+ return TRUE;
+}
+
+BOOL FASTCALL
+ConSrvValidateConsole(PCONSOLE Console,
+ CONSOLE_STATE ExpectedState,
+ BOOL LockConsole)
+{
+ BOOL RetVal = FALSE;
+
+ if (!Console) return FALSE;
+
+ /*
+ * Forbid creation or deletion of consoles when
+ * checking for the existence of a console.
+ */
+ ConSrvLockConsoleListShared();
+
+ if (ConSrvValidateConsolePointer(Console))
{
- RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
+ RetVal = ConSrvValidateConsoleUnsafe(Console,
+ ExpectedState,
+ LockConsole);
}
- Console->ReferenceCount = 0;
- Console->LineBuffer = NULL;
- Console->Header.Type = CONIO_CONSOLE_MAGIC;
- Console->Header.Console = Console;
- Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
- InitializeListHead(&Console->BufferList);
- Console->ActiveBuffer = NULL;
- InitializeListHead(&Console->InputEvents);
- InitializeListHead(&Console->HistoryBuffers);
- Console->CodePage = GetOEMCP();
- Console->OutputCodePage = GetOEMCP();
+ /* Unlock the console list and return */
+ ConSrvUnlockConsoleList();
+ return RetVal;
+}
- SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- SecurityAttributes.lpSecurityDescriptor = NULL;
- SecurityAttributes.bInheritHandle = TRUE;
+NTSTATUS
+FASTCALL
+ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
+ PCONSOLE* Console,
+ BOOL LockConsole)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCONSOLE ProcessConsole;
+
+ RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+ ProcessConsole = ProcessData->Console;
- Console->ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
- if (NULL == Console->ActiveEvent)
+ if (ConSrvValidateConsole(ProcessConsole, CONSOLE_RUNNING, LockConsole))
{
- RtlFreeUnicodeString(&Console->Title);
- return STATUS_UNSUCCESSFUL;
+ InterlockedIncrement(&ProcessConsole->ReferenceCount);
+ *Console = ProcessConsole;
+ }
+ else
+ {
+ *Console = NULL;
+ Status = STATUS_INVALID_HANDLE;
}
- Console->PrivateData = NULL;
- InitializeCriticalSection(&Console->Lock);
- GuiMode = DtbgIsDesktopVisible();
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return Status;
+}
+
+VOID FASTCALL
+ConSrvReleaseConsole(PCONSOLE Console,
+ BOOL WasConsoleLocked)
+{
+ LONG RefCount = 0;
+
+ 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);
- /* allocate console screen buffer */
- NewBuffer = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER));
- if (NULL == NewBuffer)
+ /* Delete the console if needed */
+ if (RefCount <= 0) ConSrvDeleteConsole(Console);
+}
+
+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,
+ OUT LPWSTR IconPath,
+ IN SIZE_T IconPathLength,
+ OUT PINT piIcon)
+{
+#define PATH_SEPARATOR L'\\'
+
+ BOOL RetVal = FALSE;
+ LPWSTR LinkName = NULL;
+ SIZE_T Length = 0;
+
+ if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+ return FALSE;
+
+ if (IconPath == NULL || piIcon == NULL)
+ return FALSE;
+
+ IconPath[0] = L'\0';
+ *piIcon = 0;
+
+ /* 1- Find the last path separator if any */
+ LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR);
+ if (LinkName == NULL)
{
- RtlFreeUnicodeString(&Console->Title);
- DeleteCriticalSection(&Console->Lock);
- CloseHandle(Console->ActiveEvent);
- return STATUS_INSUFFICIENT_RESOURCES;
+ LinkName = ConsoleStartInfo->ConsoleTitle;
}
- /* init screen buffer with defaults */
- NewBuffer->CursorInfo.bVisible = TRUE;
- NewBuffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE;
- /* make console active, and insert into console list */
- Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
+ else
+ {
+ /* Skip the path separator */
+ ++LinkName;
+ }
+
+ /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
+ Length = wcslen(LinkName);
+ if ( (Length <= 4) || (wcsicmp(LinkName + (Length - 4), L".lnk") != 0) )
+ return FALSE;
- if (! GuiMode)
+ /* 3- It may be a link. Try to retrieve some properties */
+ HRESULT hRes = CoInitialize(NULL);
+ if (SUCCEEDED(hRes))
{
- Status = TuiInitConsole(Console);
- if (! NT_SUCCESS(Status))
+ /* Get a pointer to the IShellLink interface */
+ IShellLinkW* pshl = NULL;
+ hRes = CoCreateInstance(&CLSID_ShellLink,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ &IID_IShellLinkW,
+ (LPVOID*)&pshl);
+ if (SUCCEEDED(hRes))
{
- DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
- GuiMode = TRUE;
+ /* Get a pointer to the IPersistFile interface */
+ IPersistFile* ppf = NULL;
+ hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
+ if (SUCCEEDED(hRes))
+ {
+ /* Load the shortcut */
+ hRes = IPersistFile_Load(ppf, ConsoleStartInfo->ConsoleTitle, STGM_READ);
+ if (SUCCEEDED(hRes))
+ {
+ /*
+ * Finally we can get the properties !
+ * Update the old ones if needed.
+ */
+ INT ShowCmd = 0;
+ // WORD HotKey = 0;
+
+ /* Reset the name of the console with the name of the shortcut */
+ Length = min(/*Length*/ Length - 4, // 4 == len(".lnk")
+ sizeof(ConsoleInfo->ConsoleTitle) / sizeof(ConsoleInfo->ConsoleTitle[0]) - 1);
+ wcsncpy(ConsoleInfo->ConsoleTitle, LinkName, Length);
+ ConsoleInfo->ConsoleTitle[Length] = L'\0';
+
+ /* Get the window showing command */
+ hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd);
+ if (SUCCEEDED(hRes)) ConsoleStartInfo->ShowWindow = (WORD)ShowCmd;
+
+ /* Get the hotkey */
+ // hRes = pshl->GetHotkey(&ShowCmd);
+ // if (SUCCEEDED(hRes)) ConsoleStartInfo->HotKey = HotKey;
+
+ /* Get the icon location, if any */
+ hRes = IShellLinkW_GetIconLocation(pshl, IconPath, IconPathLength, piIcon);
+ if (!SUCCEEDED(hRes))
+ {
+ IconPath[0] = L'\0';
+ }
+
+ // FIXME: Since we still don't load console properties from the shortcut,
+ // return false. When this will be done, we will return true instead.
+ RetVal = FALSE;
+ }
+ IPersistFile_Release(ppf);
+ }
+ IShellLinkW_Release(pshl);
}
}
- else /* GuiMode */
+ CoUninitialize();
+
+ return RetVal;
+}
+
+NTSTATUS WINAPI
+ConSrvInitConsole(OUT PCONSOLE* NewConsole,
+ IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
+ IN PCSR_PROCESS ConsoleLeaderProcess)
+{
+ NTSTATUS Status;
+ SECURITY_ATTRIBUTES SecurityAttributes;
+ CONSOLE_INFO ConsoleInfo;
+ SIZE_T Length = 0;
+ DWORD ProcessId = HandleToUlong(ConsoleLeaderProcess->ClientId.UniqueProcess);
+ PCONSOLE Console;
+ PCONSOLE_SCREEN_BUFFER NewBuffer;
+ BOOL GuiMode;
+ WCHAR Title[128];
+ WCHAR IconPath[MAX_PATH + 1] = L"";
+ INT iIcon = 0;
+
+ if (NewConsole == NULL) return STATUS_INVALID_PARAMETER;
+ *NewConsole = NULL;
+
+ /*
+ * Allocate a console structure
+ */
+ Console = RtlAllocateHeap(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CONSOLE));
+ if (NULL == Console)
{
- Status = GuiInitConsole(Console, ShowCmd);
- if (! NT_SUCCESS(Status))
+ DPRINT1("Not enough memory for console creation.\n");
+ return STATUS_NO_MEMORY;
+ }
+
+ /*
+ * Load the console settings
+ */
+
+ /* 1. Load the default settings */
+ ConSrvGetDefaultSettings(&ConsoleInfo, ProcessId);
+
+ /* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */
+ Length = min(wcslen(ConsoleStartInfo->ConsoleTitle),
+ sizeof(ConsoleInfo.ConsoleTitle) / sizeof(ConsoleInfo.ConsoleTitle[0]) - 1);
+ wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length);
+ ConsoleInfo.ConsoleTitle[Length] = L'\0';
+
+ /*
+ * 3. Check whether the process creating the console was launched
+ * via a shell-link. ConsoleInfo.ConsoleTitle may be updated by
+ * the name of the shortcut.
+ */
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME)
+ {
+ if (!LoadShellLinkConsoleInfo(ConsoleStartInfo,
+ &ConsoleInfo,
+ IconPath,
+ MAX_PATH,
+ &iIcon))
{
- HeapFree(ConSrvHeap,0, NewBuffer);
- RtlFreeUnicodeString(&Console->Title);
- DeleteCriticalSection(&Console->Lock);
- CloseHandle(Console->ActiveEvent);
- DPRINT1("GuiInitConsole: failed\n");
- return Status;
+ ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
}
}
- Status = CsrInitConsoleScreenBuffer(Console, NewBuffer);
- if (! NT_SUCCESS(Status))
+ /*
+ * 4. Load the remaining console settings via the registry.
+ */
+ if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
{
- ConioCleanupConsole(Console);
- RtlFreeUnicodeString(&Console->Title);
- DeleteCriticalSection(&Console->Lock);
- CloseHandle(Console->ActiveEvent);
- HeapFree(ConSrvHeap, 0, NewBuffer);
- DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
- return Status;
+ /*
+ * Either we weren't created by an app launched via a shell-link,
+ * or we failed to load shell-link console properties.
+ * Therefore, load the console infos for the application from the registry.
+ */
+ ConSrvReadUserSettings(&ConsoleInfo, ProcessId);
+
+ /*
+ * Now, update them with the properties the user might gave to us
+ * via the STARTUPINFO structure before calling CreateProcess
+ * (and which was transmitted via the ConsoleStartInfo structure).
+ * We therefore overwrite the values read in the registry.
+ */
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE)
+ {
+ ConsoleInfo.ScreenAttrib = ConsoleStartInfo->FillAttribute;
+ }
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS)
+ {
+ ConsoleInfo.ScreenBufferSize = ConsoleStartInfo->ScreenBufferSize;
+ }
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
+ {
+ // ConsoleInfo->ConsoleSize = ConsoleStartInfo->ConsoleWindowSize;
+ ConsoleInfo.ConsoleSize.X = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cx;
+ ConsoleInfo.ConsoleSize.Y = (SHORT)ConsoleStartInfo->ConsoleWindowSize.cy;
+ }
+ /*
+ if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN)
+ {
+ ConsoleInfo.FullScreen = TRUE;
+ }
+ */
}
- /* copy buffer contents to screen */
- ConioDrawConsole(Console);
-
- return STATUS_SUCCESS;
-}
-
-CSR_API(SrvAllocConsole)
-{
- PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
- PCSRSS_CONSOLE Console;
- NTSTATUS Status = STATUS_SUCCESS;
- BOOLEAN NewConsole = FALSE;
+ /*
+ * Initialize the console
+ */
+ Console->State = CONSOLE_INITIALIZING;
+ InitializeCriticalSection(&Console->Lock);
+ Console->ReferenceCount = 0;
+ InitializeListHead(&Console->ProcessList);
+ memcpy(Console->Colors, ConsoleInfo.Colors, sizeof(ConsoleInfo.Colors));
+ Console->ConsoleSize = ConsoleInfo.ConsoleSize;
- DPRINT("SrvAllocConsole\n");
+ /*
+ * Initialize the input buffer
+ */
+ Console->InputBuffer.Header.Type = INPUT_BUFFER;
+ Console->InputBuffer.Header.Console = Console;
- RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- if (ProcessData->Console)
+ SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ SecurityAttributes.lpSecurityDescriptor = NULL;
+ SecurityAttributes.bInheritHandle = TRUE;
+ Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
+ if (NULL == Console->InputBuffer.ActiveEvent)
{
- DPRINT1("Process already has a console\n");
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return STATUS_INVALID_PARAMETER;
+ DeleteCriticalSection(&Console->Lock);
+ RtlFreeHeap(ConSrvHeap, 0, Console);
+ return STATUS_UNSUCCESSFUL;
}
- /* If we don't need a console, then get out of here */
- if (!AllocConsoleRequest->ConsoleNeeded)
+ Console->InputBuffer.Mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
+ ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
+ Console->QuickEdit = ConsoleInfo.QuickEdit;
+ Console->InsertMode = ConsoleInfo.InsertMode;
+ InitializeListHead(&Console->InputBuffer.ReadWaitQueue);
+ InitializeListHead(&Console->InputBuffer.InputEvents);
+ Console->LineBuffer = NULL;
+ Console->CodePage = GetOEMCP();
+ Console->OutputCodePage = GetOEMCP();
+
+ /* Initialize a new screen buffer with default settings */
+ InitializeListHead(&Console->BufferList);
+ Status = ConSrvCreateScreenBuffer(Console,
+ &NewBuffer,
+ ConsoleInfo.ScreenBufferSize,
+ ConsoleInfo.ScreenAttrib,
+ ConsoleInfo.PopupAttrib,
+ (ConsoleInfo.FullScreen ? CONSOLE_FULLSCREEN_MODE
+ : CONSOLE_WINDOWED_MODE),
+ TRUE,
+ ConsoleInfo.CursorSize);
+ if (!NT_SUCCESS(Status))
{
- DPRINT("No console needed\n");
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return STATUS_SUCCESS;
+ DPRINT1("ConSrvCreateScreenBuffer: failed, Status = 0x%08lx\n", Status);
+ CloseHandle(Console->InputBuffer.ActiveEvent);
+ DeleteCriticalSection(&Console->Lock);
+ RtlFreeHeap(ConSrvHeap, 0, Console);
+ return Status;
}
+ /* Make the new screen buffer active */
+ Console->ActiveBuffer = NewBuffer;
+ InitializeListHead(&Console->WriteWaitQueue);
- /* If we already have one, then don't create a new one... */
- if (!AllocConsoleRequest->Console ||
- AllocConsoleRequest->Console != ProcessData->ParentConsole)
+ /*
+ * Initialize the history buffers
+ */
+ InitializeListHead(&Console->HistoryBuffers);
+ Console->HistoryBufferSize = ConsoleInfo.HistoryBufferSize;
+ Console->NumberOfHistoryBuffers = ConsoleInfo.NumberOfHistoryBuffers;
+ Console->HistoryNoDup = ConsoleInfo.HistoryNoDup;
+
+ /* Initialize the console title */
+ RtlCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo.ConsoleTitle);
+ if (ConsoleInfo.ConsoleTitle[0] == L'\0')
{
- /* Allocate a console structure */
- NewConsole = TRUE;
- Console = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_CONSOLE));
- if (NULL == Console)
+ if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, Title, sizeof(Title) / sizeof(Title[0])))
{
- DPRINT1("Not enough memory for console\n");
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return STATUS_NO_MEMORY;
+ RtlCreateUnicodeString(&Console->Title, Title);
}
- /* initialize list head */
- InitializeListHead(&Console->ProcessList);
- /* insert process data required for GUI initialization */
- InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
- /* Initialize the Console */
- Status = CsrInitConsole(Console, AllocConsoleRequest->ShowCmd);
- if (!NT_SUCCESS(Status))
+ else
{
- DPRINT1("Console init failed\n");
- HeapFree(ConSrvHeap, 0, Console);
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return Status;
+ RtlCreateUnicodeString(&Console->Title, L"ReactOS Console");
}
}
else
{
- /* Reuse our current console */
- Console = AllocConsoleRequest->Console;
+ RtlCreateUnicodeString(&Console->Title, ConsoleInfo.ConsoleTitle);
}
- /* Set the Process Console */
- ProcessData->Console = Console;
-
- /* Return it to the caller */
- AllocConsoleRequest->Console = Console;
+ /* Lock the console until its initialization is finished */
+ // EnterCriticalSection(&Console->Lock);
- /* Add a reference count because the process is tied to the console */
- _InterlockedIncrement(&Console->ReferenceCount);
+ /*
+ * If we are not in GUI-mode, start the text-mode terminal emulator.
+ * If we fail, try to start the GUI-mode terminal emulator.
+ */
+#ifdef TUI_CONSOLE
+ GuiMode = DtbgIsDesktopVisible();
+#else
+ GuiMode = TRUE;
+#endif
- if (NewConsole || !ProcessData->bInheritHandles)
+#ifdef TUI_CONSOLE
+ if (!GuiMode)
{
- /* Insert the Objects */
- Status = Win32CsrInsertObject(ProcessData,
- &AllocConsoleRequest->InputHandle,
- &Console->Header,
- GENERIC_READ | GENERIC_WRITE,
- TRUE,
- FILE_SHARE_READ | FILE_SHARE_WRITE);
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed to insert object\n");
- ConioDeleteConsole((Object_t *) Console);
- ProcessData->Console = 0;
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return Status;
- }
-
- Status = Win32CsrInsertObject(ProcessData,
- &AllocConsoleRequest->OutputHandle,
- &Console->ActiveBuffer->Header,
- GENERIC_READ | GENERIC_WRITE,
- TRUE,
- FILE_SHARE_READ | FILE_SHARE_WRITE);
+ DPRINT1("CONSRV: Opening text-mode terminal emulator\n");
+ Status = TuiInitConsole(Console,
+ ConsoleStartInfo,
+ &ConsoleInfo,
+ ProcessId);
if (!NT_SUCCESS(Status))
{
- DPRINT1("Failed to insert object\n");
- ConioDeleteConsole((Object_t *) Console);
- Win32CsrReleaseObject(ProcessData,
- AllocConsoleRequest->InputHandle);
- ProcessData->Console = 0;
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return Status;
+ DPRINT1("Failed to open text-mode terminal emulator, switching to gui-mode, Status = 0x%08lx\n", Status);
+ GuiMode = TRUE;
}
}
-
- /* Duplicate the Event */
- if (!DuplicateHandle(GetCurrentProcess(),
- ProcessData->Console->ActiveEvent,
- ProcessData->ProcessHandle,
- &ProcessData->ConsoleEvent,
- EVENT_ALL_ACCESS,
- FALSE,
- 0))
+#endif
+
+ /*
+ * Try to open the GUI-mode terminal emulator. Two cases are possible:
+ * - We are in GUI-mode, therefore GuiMode == TRUE, the previous test-case
+ * failed and we start GUI-mode terminal emulator.
+ * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case
+ * succeeded BUT we failed at starting text-mode terminal emulator.
+ * Then GuiMode was switched to TRUE in order to try to open the GUI-mode
+ * terminal emulator (Win32k will automatically switch to graphical mode,
+ * therefore no additional code is needed).
+ */
+ if (GuiMode)
{
- DPRINT1("DuplicateHandle() failed: %lu\n", GetLastError());
- ConioDeleteConsole((Object_t *) Console);
- if (NewConsole || !ProcessData->bInheritHandles)
+ DPRINT1("CONSRV: Opening GUI-mode terminal emulator\n");
+ Status = GuiInitConsole(Console,
+ ConsoleStartInfo,
+ &ConsoleInfo,
+ ProcessId,
+ IconPath,
+ iIcon);
+ if (!NT_SUCCESS(Status))
{
- Win32CsrReleaseObject(ProcessData,
- AllocConsoleRequest->OutputHandle);
- Win32CsrReleaseObject(ProcessData,
- AllocConsoleRequest->InputHandle);
+ DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status);
+ RtlFreeUnicodeString(&Console->Title);
+ RtlFreeUnicodeString(&Console->OriginalTitle);
+ ConioDeleteScreenBuffer(NewBuffer);
+ CloseHandle(Console->InputBuffer.ActiveEvent);
+ // LeaveCriticalSection(&Console->Lock);
+ DeleteCriticalSection(&Console->Lock);
+ RtlFreeHeap(ConSrvHeap, 0, Console);
+ return Status;
}
- ProcessData->Console = 0;
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return Status;
}
- /* Set the Ctrl Dispatcher */
- ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
- DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
+ DPRINT("Terminal initialized\n");
- if (!NewConsole)
- {
- /* Insert into the list if it has not been added */
- InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
- }
+ /* All went right, so add the console to the list */
+ ConSrvLockConsoleListExclusive();
+ DPRINT("Insert in the list\n");
+ InsertTailList(&ConsoleList, &Console->Entry);
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return STATUS_SUCCESS;
-}
+ /* The initialization is finished */
+ DPRINT("Change state\n");
+ Console->State = CONSOLE_RUNNING;
-CSR_API(SrvFreeConsole)
-{
- Win32CsrReleaseConsole(CsrGetClientThread()->Process);
+ /* Unlock the console */
+ // LeaveCriticalSection(&Console->Lock);
+
+ /* Unlock the console list */
+ ConSrvUnlockConsoleList();
+
+ /* Copy buffer contents to screen */
+ ConioDrawConsole(Console);
+ DPRINT("Console drawn\n");
+
+ /* Return the newly created console to the caller and a success code too */
+ *NewConsole = Console;
return STATUS_SUCCESS;
}
VOID WINAPI
-ConioDeleteConsole(Object_t *Object)
+ConSrvDeleteConsole(PCONSOLE Console)
{
- PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
- ConsoleInput *Event;
+ DPRINT("ConSrvDeleteConsole\n");
- DPRINT("ConioDeleteConsole\n");
+ /*
+ * Forbid validation of any console by other threads
+ * during the deletion of this console.
+ */
+ ConSrvLockConsoleListExclusive();
- /* Drain input event queue */
- while (Console->InputEvents.Flink != &Console->InputEvents)
+ /* Check the existence of the console, and if it's ok, continue */
+ if (!ConSrvValidateConsolePointer(Console))
{
- Event = (ConsoleInput *) Console->InputEvents.Flink;
- Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
- Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents;
- HeapFree(ConSrvHeap, 0, Event);
+ /* 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);
- if (Console->LineBuffer)
- RtlFreeHeap(ConSrvHeap, 0, Console->LineBuffer);
- while (!IsListEmpty(&Console->HistoryBuffers))
- HistoryDeleteBuffer((struct tagHISTORY_BUFFER *)Console->HistoryBuffers.Flink);
+
+ /***
+ * 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 (!ConSrvValidateConsolePointer(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 */
+ PurgeInputBuffer(Console);
+
+ if (Console->LineBuffer) RtlFreeHeap(ConSrvHeap, 0, Console->LineBuffer);
+
+ IntDeleteAllAliases(Console);
+ HistoryDeleteBuffers(Console);
ConioDeleteScreenBuffer(Console->ActiveBuffer);
if (!IsListEmpty(&Console->BufferList))
DPRINT1("BUG: screen buffer list not empty\n");
}
- CloseHandle(Console->ActiveEvent);
+ // CloseHandle(Console->InputBuffer.ActiveEvent);
if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
- DeleteCriticalSection(&Console->Lock);
+
+ RtlFreeUnicodeString(&Console->OriginalTitle);
RtlFreeUnicodeString(&Console->Title);
- IntDeleteAllAliases(Console->Aliases);
- HeapFree(ConSrvHeap, 0, Console);
-}
-VOID WINAPI
-CsrInitConsoleSupport(VOID)
-{
- DPRINT("CSR: CsrInitConsoleSupport()\n");
+ DPRINT("ConSrvDeleteConsole - Unlocking\n");
+ LeaveCriticalSection(&Console->Lock);
+ DPRINT("ConSrvDeleteConsole - Destroying lock\n");
+ DeleteCriticalSection(&Console->Lock);
+ DPRINT("ConSrvDeleteConsole - Lock destroyed ; freeing console\n");
- /* Should call LoadKeyboardLayout */
-}
+ RtlFreeHeap(ConSrvHeap, 0, Console);
+ DPRINT("ConSrvDeleteConsole - Console freed\n");
-VOID FASTCALL
-ConioPause(PCSRSS_CONSOLE Console, UINT Flags)
-{
- Console->PauseFlags |= Flags;
- if (!Console->UnpauseEvent)
- Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ /* Unlock the console list and return */
+ ConSrvUnlockConsoleList();
}
-VOID FASTCALL
-ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags)
+
+/* PUBLIC SERVER APIS *********************************************************/
+
+CSR_API(SrvAllocConsole)
{
- Console->PauseFlags &= ~Flags;
- if (Console->PauseFlags == 0 && Console->UnpauseEvent)
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
+ PCSR_PROCESS CsrProcess = CsrGetClientThread()->Process;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
+
+ if (ProcessData->Console != NULL)
{
- SetEvent(Console->UnpauseEvent);
- CloseHandle(Console->UnpauseEvent);
- Console->UnpauseEvent = NULL;
+ DPRINT1("Process already has a console\n");
+ return STATUS_ACCESS_DENIED;
+ }
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&AllocConsoleRequest->ConsoleStartInfo,
+ 1,
+ sizeof(CONSOLE_START_INFO)))
+ {
+ return STATUS_INVALID_PARAMETER;
}
+
+ /*
+ * We are about to create a new console. However when ConSrvNewProcess
+ * was called, we didn't know that we wanted to create a new console and
+ * therefore, we by default inherited the handles table from our parent
+ * process. It's only now that we notice that in fact we do not need
+ * them, because we've created a new console and thus we must use it.
+ *
+ * Therefore, free the console we can have and our handles table,
+ * and recreate a new one later on.
+ */
+ ConSrvRemoveConsole(ProcessData);
+
+ /* Initialize a new Console owned by the Console Leader Process */
+ Status = ConSrvAllocateConsole(ProcessData,
+ &AllocConsoleRequest->InputHandle,
+ &AllocConsoleRequest->OutputHandle,
+ &AllocConsoleRequest->ErrorHandle,
+ AllocConsoleRequest->ConsoleStartInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Console allocation failed\n");
+ return Status;
+ }
+
+ /* Return it to the caller */
+ AllocConsoleRequest->Console = ProcessData->Console;
+
+ /* Input Wait Handle */
+ AllocConsoleRequest->InputWaitHandle = ProcessData->ConsoleEvent;
+
+ /* Set the Property Dialog Handler */
+ ProcessData->PropDispatcher = AllocConsoleRequest->PropDispatcher;
+
+ /* Set the Ctrl Dispatcher */
+ ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
+
+ return STATUS_SUCCESS;
}
-CSR_API(SrvSetConsoleMode)
+CSR_API(SrvAttachConsole)
{
- NTSTATUS Status;
- PCSRSS_SET_CONSOLE_MODE SetConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleModeRequest;
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AttachConsoleRequest;
+ PCSR_PROCESS SourceProcess = NULL; // The parent process.
+ PCSR_PROCESS TargetProcess = CsrGetClientThread()->Process; // Ourselves.
+ HANDLE ProcessId = ULongToHandle(AttachConsoleRequest->ProcessId);
+ PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
- DPRINT("SrvSetConsoleMode\n");
+ TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
- Status = Win32CsrLockObject(CsrGetClientThread()->Process,
- SetConsoleModeRequest->ConsoleHandle,
- (Object_t **) &Console, GENERIC_WRITE, 0);
- if (! NT_SUCCESS(Status))
+ if (TargetProcessData->Console != NULL)
{
- return Status;
+ DPRINT1("Process already has a console\n");
+ return STATUS_ACCESS_DENIED;
}
- Buff = (PCSRSS_SCREEN_BUFFER)Console;
- if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
+ /* Check whether we try to attach to the parent's console */
+ if (ProcessId == ULongToHandle(ATTACH_PARENT_PROCESS))
{
- Console->Mode = SetConsoleModeRequest->Mode & CONSOLE_INPUT_MODE_VALID;
+ PROCESS_BASIC_INFORMATION ProcessInfo;
+ ULONG Length = sizeof(ProcessInfo);
+
+ /* Get the real parent's ID */
+
+ Status = NtQueryInformationProcess(TargetProcess->ProcessHandle,
+ ProcessBasicInformation,
+ &ProcessInfo,
+ Length, &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, Status = %lu\n", Status);
+ return Status;
+ }
+
+ ProcessId = ULongToHandle(ProcessInfo.InheritedFromUniqueProcessId);
}
- else if (CONIO_SCREEN_BUFFER_MAGIC == Console->Header.Type)
+
+ /* Lock the source process via its PID */
+ Status = CsrLockProcessByClientId(ProcessId, &SourceProcess);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
+
+ if (SourceProcessData->Console == NULL)
{
- Buff->Mode = SetConsoleModeRequest->Mode & CONSOLE_OUTPUT_MODE_VALID;
+ Status = STATUS_INVALID_HANDLE;
+ goto Quit;
}
- else
+
+ /*
+ * We are about to create a new console. However when ConSrvNewProcess
+ * was called, we didn't know that we wanted to create a new console and
+ * therefore, we by default inherited the handles table from our parent
+ * process. It's only now that we notice that in fact we do not need
+ * them, because we've created a new console and thus we must use it.
+ *
+ * Therefore, free the console we can have and our handles table,
+ * and recreate a new one later on.
+ */
+ ConSrvRemoveConsole(TargetProcessData);
+
+ /*
+ * Inherit the console from the parent,
+ * if any, otherwise return an error.
+ */
+ Status = ConSrvInheritConsole(TargetProcessData,
+ SourceProcessData->Console,
+ TRUE,
+ &AttachConsoleRequest->InputHandle,
+ &AttachConsoleRequest->OutputHandle,
+ &AttachConsoleRequest->ErrorHandle);
+ if (!NT_SUCCESS(Status))
{
- Status = STATUS_INVALID_HANDLE;
+ DPRINT1("Console inheritance failed\n");
+ goto Quit;
}
- Win32CsrUnlockObject((Object_t *)Console);
+ /* Return it to the caller */
+ AttachConsoleRequest->Console = TargetProcessData->Console;
+
+ /* Input Wait Handle */
+ AttachConsoleRequest->InputWaitHandle = TargetProcessData->ConsoleEvent;
+
+ /* Set the Property Dialog Handler */
+ TargetProcessData->PropDispatcher = AttachConsoleRequest->PropDispatcher;
+
+ /* Set the Ctrl Dispatcher */
+ TargetProcessData->CtrlDispatcher = AttachConsoleRequest->CtrlDispatcher;
+
+ Status = STATUS_SUCCESS;
+Quit:
+ /* Unlock the "source" process and exit */
+ CsrUnlockProcess(SourceProcess);
return Status;
}
+CSR_API(SrvFreeConsole)
+{
+ ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process));
+ return STATUS_SUCCESS;
+}
+
CSR_API(SrvGetConsoleMode)
{
NTSTATUS Status;
- PCSRSS_GET_CONSOLE_MODE GetConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleModeRequest;
- PCSRSS_CONSOLE Console;
- PCSRSS_SCREEN_BUFFER Buff;
+ PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
+ PCONSOLE_IO_OBJECT Object = NULL;
- DPRINT("SrvGetConsoleMode\n");
+ Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ ConsoleModeRequest->ConsoleHandle,
+ &Object, NULL, GENERIC_READ, TRUE, 0);
+ if (!NT_SUCCESS(Status)) return Status;
- Status = Win32CsrLockObject(CsrGetClientThread()->Process, GetConsoleModeRequest->ConsoleHandle,
- (Object_t **) &Console, GENERIC_READ, 0);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
Status = STATUS_SUCCESS;
- Buff = (PCSRSS_SCREEN_BUFFER) Console;
- if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
+
+ if (INPUT_BUFFER == Object->Type)
{
- GetConsoleModeRequest->ConsoleMode = Console->Mode;
+ PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
+ PCONSOLE Console = InputBuffer->Header.Console;
+ DWORD ConsoleMode = InputBuffer->Mode;
+
+ if (Console->QuickEdit || Console->InsertMode)
+ {
+ // Windows does this, even if it's not documented on MSDN
+ ConsoleMode |= ENABLE_EXTENDED_FLAGS;
+
+ if (Console->QuickEdit ) ConsoleMode |= ENABLE_QUICK_EDIT_MODE;
+ if (Console->InsertMode) ConsoleMode |= ENABLE_INSERT_MODE;
+ }
+
+ ConsoleModeRequest->ConsoleMode = ConsoleMode;
}
- else if (CONIO_SCREEN_BUFFER_MAGIC == Buff->Header.Type)
+ else if (SCREEN_BUFFER == Object->Type)
{
- GetConsoleModeRequest->ConsoleMode = Buff->Mode;
+ PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
+ ConsoleModeRequest->ConsoleMode = Buffer->Mode;
}
else
{
Status = STATUS_INVALID_HANDLE;
}
- Win32CsrUnlockObject((Object_t *)Console);
+ ConSrvReleaseObject(Object, TRUE);
return Status;
}
-CSR_API(SrvSetConsoleTitle)
+CSR_API(SrvSetConsoleMode)
{
+#define CONSOLE_VALID_CONTROL_MODES ( ENABLE_EXTENDED_FLAGS | ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE )
+#define CONSOLE_VALID_INPUT_MODES ( ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | \
+ ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | \
+ ENABLE_MOUSE_INPUT )
+#define CONSOLE_VALID_OUTPUT_MODES ( ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT )
+
NTSTATUS Status;
- PCSRSS_SET_TITLE SetTitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetTitleRequest;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
- PCSRSS_CONSOLE Console;
- PWCHAR Buffer;
+ PCONSOLE_GETSETCONSOLEMODE ConsoleModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleModeRequest;
+ DWORD ConsoleMode = ConsoleModeRequest->ConsoleMode;
+ PCONSOLE_IO_OBJECT Object = NULL;
- DPRINT("SrvSetConsoleTitle\n");
+ Status = ConSrvGetObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ ConsoleModeRequest->ConsoleHandle,
+ &Object, NULL, GENERIC_WRITE, TRUE, 0);
+ if (!NT_SUCCESS(Status)) return Status;
- if (!Win32CsrValidateBuffer(ProcessData, SetTitleRequest->Title,
- SetTitleRequest->Length, 1))
+ Status = STATUS_SUCCESS;
+
+ if (INPUT_BUFFER == Object->Type)
{
- return STATUS_ACCESS_VIOLATION;
- }
+ PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
+ PCONSOLE Console = InputBuffer->Header.Console;
+
+ DPRINT("SetConsoleMode(Input, %d)\n", ConsoleMode);
+
+ /*
+ * 1. Only the presence of valid mode flags is allowed.
+ */
+ if (ConsoleMode & ~(CONSOLE_VALID_INPUT_MODES | CONSOLE_VALID_CONTROL_MODES))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quit;
+ }
- Status = ConioConsoleFromProcessData(ProcessData, &Console);
- if(NT_SUCCESS(Status))
+ /*
+ * 2. If we use control mode flags without ENABLE_EXTENDED_FLAGS,
+ * then consider the flags invalid.
+ *
+ if ( (ConsoleMode & CONSOLE_VALID_CONTROL_MODES) &&
+ (ConsoleMode & ENABLE_EXTENDED_FLAGS) == 0 )
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quit;
+ }
+ */
+
+ /*
+ * 3. Now we can continue.
+ */
+ if (ConsoleMode & CONSOLE_VALID_CONTROL_MODES)
+ {
+ Console->QuickEdit = !!(ConsoleMode & ENABLE_QUICK_EDIT_MODE);
+ Console->InsertMode = !!(ConsoleMode & ENABLE_INSERT_MODE);
+ }
+ InputBuffer->Mode = (ConsoleMode & CONSOLE_VALID_INPUT_MODES);
+ }
+ else if (SCREEN_BUFFER == Object->Type)
{
- Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, SetTitleRequest->Length);
- if (Buffer)
+ PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
+
+ DPRINT("SetConsoleMode(Output, %d)\n", ConsoleMode);
+
+ if (ConsoleMode & ~CONSOLE_VALID_OUTPUT_MODES)
{
- /* copy title to console */
- RtlFreeUnicodeString(&Console->Title);
- Console->Title.Buffer = Buffer;
- Console->Title.Length = Console->Title.MaximumLength = SetTitleRequest->Length;
- memcpy(Console->Title.Buffer, SetTitleRequest->Title, Console->Title.Length);
- if (! ConioChangeTitle(Console))
- {
- Status = STATUS_UNSUCCESSFUL;
- }
- else
- {
- Status = STATUS_SUCCESS;
- }
+ Status = STATUS_INVALID_PARAMETER;
}
else
{
- Status = STATUS_NO_MEMORY;
+ Buffer->Mode = (ConsoleMode & CONSOLE_VALID_OUTPUT_MODES);
}
- ConioUnlockConsole(Console);
+ }
+ else
+ {
+ Status = STATUS_INVALID_HANDLE;
}
+Quit:
+ ConSrvReleaseObject(Object, TRUE);
return Status;
}
CSR_API(SrvGetConsoleTitle)
{
NTSTATUS Status;
- PCSRSS_GET_TITLE GetTitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetTitleRequest;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
- PCSRSS_CONSOLE Console;
+ PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
+ // PCSR_PROCESS Process = CsrGetClientThread()->Process;
+ PCONSOLE Console;
DWORD Length;
- DPRINT("SrvGetConsoleTitle\n");
-
- if (!Win32CsrValidateBuffer(ProcessData, GetTitleRequest->Title,
- GetTitleRequest->Length, 1))
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID)&TitleRequest->Title,
+ TitleRequest->Length,
+ sizeof(BYTE)))
{
- return STATUS_ACCESS_VIOLATION;
+ return STATUS_INVALID_PARAMETER;
}
- Status = ConioConsoleFromProcessData(ProcessData, &Console);
- if (! NT_SUCCESS(Status))
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status))
{
DPRINT1("Can't get console\n");
return Status;
}
/* Copy title of the console to the user title buffer */
- if (GetTitleRequest->Length >= sizeof(WCHAR))
+ if (TitleRequest->Length >= sizeof(WCHAR))
{
- Length = min(GetTitleRequest->Length - sizeof(WCHAR), Console->Title.Length);
- memcpy(GetTitleRequest->Title, Console->Title.Buffer, Length);
- GetTitleRequest->Title[Length / sizeof(WCHAR)] = L'\0';
+ Length = min(TitleRequest->Length - sizeof(WCHAR), Console->Title.Length);
+ memcpy(TitleRequest->Title, Console->Title.Buffer, Length);
+ TitleRequest->Title[Length / sizeof(WCHAR)] = L'\0';
}
- GetTitleRequest->Length = Console->Title.Length;
+ TitleRequest->Length = Console->Title.Length;
- ConioUnlockConsole(Console);
+ ConSrvReleaseConsole(Console, TRUE);
return STATUS_SUCCESS;
}
+CSR_API(SrvSetConsoleTitle)
+{
+ NTSTATUS Status;
+ PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
+ // PCSR_PROCESS Process = CsrGetClientThread()->Process;
+ PCONSOLE Console;
+ PWCHAR Buffer;
+
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID)&TitleRequest->Title,
+ TitleRequest->Length,
+ sizeof(BYTE)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Can't get console\n");
+ return Status;
+ }
+
+ /* Allocate a new buffer to hold the new title (NULL-terminated) */
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest->Length + sizeof(WCHAR));
+ if (Buffer)
+ {
+ /* Free the old title */
+ RtlFreeUnicodeString(&Console->Title);
+
+ /* Copy title to console */
+ Console->Title.Buffer = Buffer;
+ Console->Title.Length = TitleRequest->Length;
+ Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR);
+ RtlCopyMemory(Console->Title.Buffer,
+ TitleRequest->Title,
+ Console->Title.Length);
+ Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
+
+ ConioChangeTitle(Console);
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_NO_MEMORY;
+ }
+
+ ConSrvReleaseConsole(Console, TRUE);
+ return Status;
+}
+
/**********************************************************************
- * HardwareStateProperty
+ * HardwareStateProperty
*
- * DESCRIPTION
- * Set/Get the value of the HardwareState and switch
- * between direct video buffer ouput and GDI windowed
- * output.
- * ARGUMENTS
- * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
- * object. We use the same object to Request.
- * NOTE
- * ConsoleHwState has the correct size to be compatible
- * with NT's, but values are not.
+ * DESCRIPTION
+ * Set/Get the value of the HardwareState and switch
+ * between direct video buffer ouput and GDI windowed
+ * output.
+ * ARGUMENTS
+ * Client hands us a CONSOLE_GETSETHWSTATE object.
+ * We use the same object to Request.
+ * NOTE
+ * ConsoleHwState has the correct size to be compatible
+ * with NT's, but values are not.
*/
static NTSTATUS FASTCALL
-SetConsoleHardwareState(PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
+SetConsoleHardwareState(PCONSOLE Console, ULONG ConsoleHwState)
{
DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
CSR_API(SrvGetConsoleHardwareState)
{
- PCSRSS_SETGET_CONSOLE_HW_STATE ConsoleHardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleHardwareStateRequest;
- PCSRSS_CONSOLE Console;
NTSTATUS Status;
-
- DPRINT("SrvGetConsoleHardwareState\n");
-
- Status = ConioLockConsole(CsrGetClientThread()->Process,
- ConsoleHardwareStateRequest->ConsoleHandle,
- &Console,
- GENERIC_READ);
- if (! NT_SUCCESS(Status))
+ PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
+ PCONSOLE_SCREEN_BUFFER Buff;
+ PCONSOLE Console;
+
+ Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ HardwareStateRequest->OutputHandle,
+ &Buff,
+ GENERIC_READ,
+ TRUE);
+ if (!NT_SUCCESS(Status))
{
- DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
+ DPRINT1("Failed to get console handle in SrvGetConsoleHardwareState\n");
return Status;
}
- switch (ConsoleHardwareStateRequest->SetGet)
- {
- case CONSOLE_HARDWARE_STATE_GET:
- ConsoleHardwareStateRequest->State = Console->HardwareState;
- break;
-
- case CONSOLE_HARDWARE_STATE_SET:
- DPRINT("Setting console hardware state.\n");
- Status = SetConsoleHardwareState(Console, ConsoleHardwareStateRequest->State);
- break;
-
- default:
- Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
- break;
- }
-
- ConioUnlockConsole(Console);
+ Console = Buff->Header.Console;
+ HardwareStateRequest->State = Console->HardwareState;
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
return Status;
}
CSR_API(SrvSetConsoleHardwareState)
{
- PCSRSS_SETGET_CONSOLE_HW_STATE ConsoleHardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleHardwareStateRequest;
- PCSRSS_CONSOLE Console;
NTSTATUS Status;
-
- DPRINT("SrvSetConsoleHardwareState\n");
-
- Status = ConioLockConsole(CsrGetClientThread()->Process,
- ConsoleHardwareStateRequest->ConsoleHandle,
- &Console,
- GENERIC_READ);
- if (! NT_SUCCESS(Status))
+ PCONSOLE_GETSETHWSTATE HardwareStateRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.HardwareStateRequest;
+ PCONSOLE_SCREEN_BUFFER Buff;
+ PCONSOLE Console;
+
+ Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ HardwareStateRequest->OutputHandle,
+ &Buff,
+ GENERIC_WRITE,
+ TRUE);
+ if (!NT_SUCCESS(Status))
{
- DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
+ DPRINT1("Failed to get console handle in SrvSetConsoleHardwareState\n");
return Status;
}
- switch (ConsoleHardwareStateRequest->SetGet)
- {
- case CONSOLE_HARDWARE_STATE_GET:
- ConsoleHardwareStateRequest->State = Console->HardwareState;
- break;
-
- case CONSOLE_HARDWARE_STATE_SET:
- DPRINT("Setting console hardware state.\n");
- Status = SetConsoleHardwareState(Console, ConsoleHardwareStateRequest->State);
- break;
-
- default:
- Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
- break;
- }
-
- ConioUnlockConsole(Console);
+ DPRINT("Setting console hardware state.\n");
+ Console = Buff->Header.Console;
+ Status = SetConsoleHardwareState(Console, HardwareStateRequest->State);
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
return Status;
}
-CSR_API(SrvGetConsoleWindow)
+CSR_API(SrvGetConsoleDisplayMode)
{
- PCSRSS_GET_CONSOLE_WINDOW GetConsoleWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleWindowRequest;
- PCSRSS_CONSOLE Console;
NTSTATUS Status;
+ PCONSOLE_GETDISPLAYMODE GetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetDisplayModeRequest;
+ PCONSOLE Console;
+ ULONG DisplayMode = 0;
- DPRINT("SrvGetConsoleWindow\n");
-
- Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
- if (! NT_SUCCESS(Status))
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ &Console, TRUE);
+ if (!NT_SUCCESS(Status))
{
+ DPRINT1("Failed to get console handle in SrvGetConsoleDisplayMode\n");
return Status;
}
- GetConsoleWindowRequest->WindowHandle = Console->hWindow;
- ConioUnlockConsole(Console);
+ if (Console->ActiveBuffer->DisplayMode & CONSOLE_FULLSCREEN_MODE)
+ DisplayMode |= CONSOLE_FULLSCREEN_HARDWARE; // CONSOLE_FULLSCREEN
+ else if (Console->ActiveBuffer->DisplayMode & CONSOLE_WINDOWED_MODE)
+ DisplayMode |= CONSOLE_WINDOWED;
- return STATUS_SUCCESS;
+ GetDisplayModeRequest->DisplayMode = DisplayMode;
+ Status = STATUS_SUCCESS;
+
+ ConSrvReleaseConsole(Console, TRUE);
+ return Status;
}
-CSR_API(SrvSetConsoleIcon)
+CSR_API(SrvSetConsoleDisplayMode)
{
- PCSRSS_SET_CONSOLE_ICON SetConsoleIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleIconRequest;
- PCSRSS_CONSOLE Console;
NTSTATUS Status;
-
- DPRINT("SrvSetConsoleIcon\n");
-
- Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
- if (! NT_SUCCESS(Status))
+ PCONSOLE_SETDISPLAYMODE SetDisplayModeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetDisplayModeRequest;
+ PCONSOLE_SCREEN_BUFFER Buff;
+
+ Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ SetDisplayModeRequest->OutputHandle,
+ &Buff,
+ GENERIC_WRITE,
+ TRUE);
+ if (!NT_SUCCESS(Status))
{
+ DPRINT1("Failed to get console handle in SrvSetConsoleDisplayMode\n");
return Status;
}
- Status = (ConioChangeIcon(Console, SetConsoleIconRequest->WindowIcon)
- ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
- ConioUnlockConsole(Console);
+ if (SetDisplayModeRequest->DisplayMode & ~(CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ Buff->DisplayMode = SetDisplayModeRequest->DisplayMode;
+ // TODO: Change the display mode
+ SetDisplayModeRequest->NewSBDim = Buff->ScreenBufferSize;
+ Status = STATUS_SUCCESS;
+ }
+
+ ConSrvReleaseScreenBuffer(Buff, TRUE);
return Status;
}
-CSR_API(SrvGetConsoleCP)
+CSR_API(SrvGetConsoleWindow)
{
- PCSRSS_GET_CONSOLE_CP GetConsoleCodePage = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleCodePage;
- PCSRSS_CONSOLE Console;
NTSTATUS Status;
+ PCONSOLE_GETWINDOW GetWindowRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetWindowRequest;
+ PCONSOLE Console;
- DPRINT("SrvGetConsoleCP\n");
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
- Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
+ GetWindowRequest->WindowHandle = ConioGetConsoleWindowHandle(Console);
+ ConSrvReleaseConsole(Console, TRUE);
- GetConsoleCodePage->CodePage = Console->CodePage;
- ConioUnlockConsole(Console);
return STATUS_SUCCESS;
}
-CSR_API(CsrGetConsoleOutputCodePage) // TODO: Merge this function with the other one.
+CSR_API(SrvSetConsoleIcon)
{
- PCSRSS_GET_CONSOLE_OUTPUT_CP GetConsoleOutputCodePage = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleOutputCodePage;
- PCSRSS_CONSOLE Console;
NTSTATUS Status;
+ PCONSOLE_SETICON SetIconRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetIconRequest;
+ PCONSOLE Console;
- DPRINT("CsrGetConsoleOutputCodePage\n");
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
- Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
+ Status = (ConioChangeIcon(Console, SetIconRequest->WindowIcon)
+ ? STATUS_SUCCESS
+ : STATUS_UNSUCCESSFUL);
- GetConsoleOutputCodePage->CodePage = Console->OutputCodePage;
- ConioUnlockConsole(Console);
- return STATUS_SUCCESS;
+ ConSrvReleaseConsole(Console, TRUE);
+
+ return Status;
}
-CSR_API(SrvSetConsoleCP)
+CSR_API(SrvGetConsoleCP)
{
- PCSRSS_SET_CONSOLE_CP SetConsoleCodePage = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleCodePage;
- PCSRSS_CONSOLE Console;
NTSTATUS Status;
+ PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
+ PCONSOLE Console;
- DPRINT("SrvSetConsoleCP\n");
+ DPRINT("SrvGetConsoleCP, getting %s Code Page\n",
+ ConsoleCPRequest->InputCP ? "Input" : "Output");
- Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
- if (IsValidCodePage(SetConsoleCodePage->CodePage))
- {
- Console->CodePage = SetConsoleCodePage->CodePage;
- ConioUnlockConsole(Console);
- return STATUS_SUCCESS;
- }
-
- ConioUnlockConsole(Console);
- return STATUS_INVALID_PARAMETER;
+ ConsoleCPRequest->CodePage = (ConsoleCPRequest->InputCP ? Console->CodePage
+ : Console->OutputCodePage);
+ ConSrvReleaseConsole(Console, TRUE);
+ return STATUS_SUCCESS;
}
-CSR_API(CsrSetConsoleOutputCodePage) // TODO: Merge this function with the other one.
+CSR_API(SrvSetConsoleCP)
{
- PCSRSS_SET_CONSOLE_OUTPUT_CP SetConsoleOutputCodePage = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetConsoleOutputCodePage;
- PCSRSS_CONSOLE Console;
NTSTATUS Status;
+ PCONSOLE_GETSETINPUTOUTPUTCP ConsoleCPRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ConsoleCPRequest;
+ PCONSOLE Console;
- DPRINT("CsrSetConsoleOutputCodePage\n");
+ DPRINT("SrvSetConsoleCP, setting %s Code Page\n",
+ ConsoleCPRequest->InputCP ? "Input" : "Output");
- Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
- if (IsValidCodePage(SetConsoleOutputCodePage->CodePage))
+ if (IsValidCodePage(ConsoleCPRequest->CodePage))
{
- Console->OutputCodePage = SetConsoleOutputCodePage->CodePage;
- ConioUnlockConsole(Console);
+ if (ConsoleCPRequest->InputCP)
+ Console->CodePage = ConsoleCPRequest->CodePage;
+ else
+ Console->OutputCodePage = ConsoleCPRequest->CodePage;
+
+ ConSrvReleaseConsole(Console, TRUE);
return STATUS_SUCCESS;
}
- ConioUnlockConsole(Console);
+ ConSrvReleaseConsole(Console, TRUE);
return STATUS_INVALID_PARAMETER;
}
CSR_API(SrvGetConsoleProcessList)
{
- PCSRSS_GET_PROCESS_LIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
+ NTSTATUS Status;
+ PCONSOLE_GETPROCESSLIST GetProcessListRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetProcessListRequest;
PDWORD Buffer;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
- PCSRSS_CONSOLE Console;
- PCSR_PROCESS current;
+ // PCSR_PROCESS Process = CsrGetClientThread()->Process;
+ PCONSOLE Console;
+ PCONSOLE_PROCESS_DATA current;
PLIST_ENTRY current_entry;
ULONG nItems = 0;
- NTSTATUS Status;
- DPRINT("SrvGetConsoleProcessList\n");
-
- Buffer = GetProcessListRequest->ProcessId;
- if (!Win32CsrValidateBuffer(ProcessData, Buffer, GetProcessListRequest->nMaxIds, sizeof(DWORD)))
- return STATUS_ACCESS_VIOLATION;
-
- Status = ConioConsoleFromProcessData(ProcessData, &Console);
- if (! NT_SUCCESS(Status))
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID)&GetProcessListRequest->pProcessIds,
+ GetProcessListRequest->nMaxIds,
+ sizeof(DWORD)))
{
- return Status;
+ return STATUS_INVALID_PARAMETER;
}
+ Buffer = GetProcessListRequest->pProcessIds;
+
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
for (current_entry = Console->ProcessList.Flink;
current_entry != &Console->ProcessList;
current_entry = current_entry->Flink)
{
- current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
+ current = CONTAINING_RECORD(current_entry, CONSOLE_PROCESS_DATA, ConsoleLink);
if (++nItems <= GetProcessListRequest->nMaxIds)
{
- *Buffer++ = HandleToUlong(current->ClientId.UniqueProcess);
+ *Buffer++ = HandleToUlong(current->Process->ClientId.UniqueProcess);
}
}
- ConioUnlockConsole(Console);
+ ConSrvReleaseConsole(Console, TRUE);
GetProcessListRequest->nProcessIdsTotal = nItems;
return STATUS_SUCCESS;
CSR_API(SrvGenerateConsoleCtrlEvent)
{
- PCSRSS_GENERATE_CTRL_EVENT GenerateCtrlEvent = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GenerateCtrlEvent;
- PCSRSS_CONSOLE Console;
- PCSR_PROCESS current;
- PLIST_ENTRY current_entry;
- DWORD Group;
NTSTATUS Status;
+ PCONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GenerateCtrlEventRequest;
+ PCONSOLE Console;
- Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Group = GenerateCtrlEvent->ProcessGroup;
- Status = STATUS_INVALID_PARAMETER;
- for (current_entry = Console->ProcessList.Flink;
- current_entry != &Console->ProcessList;
- current_entry = current_entry->Flink)
- {
- current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
- if (Group == 0 || current->ProcessGroupId == Group)
- {
- ConioConsoleCtrlEvent(GenerateCtrlEvent->Event, current);
- Status = STATUS_SUCCESS;
- }
- }
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
- ConioUnlockConsole(Console);
+ Status = ConSrvConsoleProcessCtrlEvent(Console,
+ GenerateCtrlEventRequest->ProcessGroup,
+ GenerateCtrlEventRequest->Event);
+ ConSrvReleaseConsole(Console, TRUE);
return Status;
}
CSR_API(SrvGetConsoleSelectionInfo)
{
NTSTATUS Status;
- PCSRSS_GET_CONSOLE_SELECTION_INFO GetConsoleSelectionInfo = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleSelectionInfo;
- PCSRSS_CONSOLE Console;
+ PCONSOLE_GETSELECTIONINFO GetSelectionInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetSelectionInfoRequest;
+ PCONSOLE Console;
- Status = ConioConsoleFromProcessData(CsrGetClientThread()->Process, &Console);
+ Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE);
if (NT_SUCCESS(Status))
{
- memset(&GetConsoleSelectionInfo->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
+ memset(&GetSelectionInfoRequest->Info, 0, sizeof(CONSOLE_SELECTION_INFO));
if (Console->Selection.dwFlags != 0)
- GetConsoleSelectionInfo->Info = Console->Selection;
- ConioUnlockConsole(Console);
+ GetSelectionInfoRequest->Info = Console->Selection;
+ ConSrvReleaseConsole(Console, TRUE);
}
+
return Status;
}