Author: hbelusca
Date: Wed Mar 11 01:21:29 2015
New Revision: 66662
URL:
http://svn.reactos.org/svn/reactos?rev=66662&view=rev
Log:
[WIN32K]
- Implement NtUserResolveDesktop, which opens a desktop and a window station based on a
desktop path string (format: "WinSta\Desktop").
- Move NtUserConsoleControl to a more suitable file, and implement the control code that
allows CSRSS to assign console input threads to given desktops.
- Simplify a bit the code in NtUserSetInformationThread.
[CONSRV]
Turn the console input thread to a real one. There should be one such thread per desktop.
When a console process is started, we open the desktop on which the process is going to
start, we create a new input thread (attach it to the desktop) if needed, or reuse the
existing one, and then we open the terminal on the correct desktop.
CORE-9346 #resolve #comment Fixed in revision 66662.
Added:
trunk/reactos/win32ss/user/ntuser/console.c (with props)
Modified:
trunk/reactos/include/reactos/subsys/win/conmsg.h
trunk/reactos/win32ss/CMakeLists.txt
trunk/reactos/win32ss/include/ntuser.h
trunk/reactos/win32ss/user/ntuser/desktop.c
trunk/reactos/win32ss/user/ntuser/desktop.h
trunk/reactos/win32ss/user/ntuser/ntstubs.c
trunk/reactos/win32ss/user/winsrv/consrv/console.c
trunk/reactos/win32ss/user/winsrv/consrv/console.h
trunk/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.h
trunk/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
trunk/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c
trunk/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c
trunk/reactos/win32ss/user/winsrv/consrv/handle.c
trunk/reactos/win32ss/user/winsrv/consrv/init.c
Modified: trunk/reactos/include/reactos/subsys/win/conmsg.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/subsys/win…
==============================================================================
--- trunk/reactos/include/reactos/subsys/win/conmsg.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/subsys/win/conmsg.h [iso-8859-1] Wed Mar 11 01:21:29
2015
@@ -197,7 +197,9 @@
ULONG TitleLength;
WCHAR ConsoleTitle[MAX_PATH + 1]; // Console title or full path to the startup
shortcut
ULONG DesktopLength;
- PWCHAR Desktop;
+ PWCHAR Desktop; // Contrary to the case of CONSOLE_ALLOCCONSOLE,
the
+ // desktop string is allocated in the
process' heap,
+ // and CSR will read it via NtReadVirtualMemory.
ULONG AppNameLength;
WCHAR AppName[128]; // Full path of the launched app
ULONG CurDirLength;
Modified: trunk/reactos/win32ss/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/CMakeLists.txt?rev…
==============================================================================
--- trunk/reactos/win32ss/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/win32ss/CMakeLists.txt [iso-8859-1] Wed Mar 11 01:21:29 2015
@@ -100,6 +100,7 @@
user/ntuser/caret.c
user/ntuser/class.c
user/ntuser/clipboard.c
+ user/ntuser/console.c
user/ntuser/csr.c
user/ntuser/cursoricon.c
user/ntuser/dde.c
Modified: trunk/reactos/win32ss/include/ntuser.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/include/ntuser.h?r…
==============================================================================
--- trunk/reactos/win32ss/include/ntuser.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/include/ntuser.h [iso-8859-1] Wed Mar 11 01:21:29 2015
@@ -1721,10 +1721,17 @@
/* Console commands for NtUserConsoleControl */
typedef enum _CONSOLECONTROL
{
- GuiConsoleWndClassAtom,
+ ConsoleCtrlDesktopConsoleThread = 0,
+ GuiConsoleWndClassAtom = 1,
ConsoleMakePalettePublic = 5,
ConsoleAcquireDisplayOwnership,
} CONSOLECONTROL, *PCONSOLECONTROL;
+
+typedef struct _DESKTOP_CONSOLE_THREAD
+{
+ HDESK DesktopHandle;
+ ULONG_PTR ThreadId;
+} DESKTOP_CONSOLE_THREAD, *PDESKTOP_CONSOLE_THREAD;
NTSTATUS
APIENTRY
@@ -2860,13 +2867,13 @@
HWND hWnd,
ATOM Atom);
-DWORD
-NTAPI
+HDESK
+APIENTRY
NtUserResolveDesktop(
- DWORD dwUnknown1,
- DWORD dwUnknown2,
- DWORD dwUnknown3,
- DWORD dwUnknown4);
+ IN HANDLE ProcessHandle,
+ IN PUNICODE_STRING DesktopPath,
+ DWORD dwUnknown,
+ OUT HWINSTA* phWinSta);
DWORD
NTAPI
Added: trunk/reactos/win32ss/user/ntuser/console.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/consol…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/console.c (added)
+++ trunk/reactos/win32ss/user/ntuser/console.c [iso-8859-1] Wed Mar 11 01:21:29 2015
@@ -0,0 +1,160 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Win32k subsystem
+ * PURPOSE: Console support functions for CONSRV
+ * FILE: subsystems/win32/win32k/ntuser/console.c
+ * PROGRAMMER: Hermes Belusca-Maito (hermes.belusca(a)sfr.fr)
+ */
+
+#include <win32k.h>
+DBG_DEFAULT_CHANNEL(UserMisc);
+
+NTSTATUS
+APIENTRY
+NtUserConsoleControl(
+ IN CONSOLECONTROL ConsoleCtrl,
+ IN PVOID ConsoleCtrlInfo,
+ IN ULONG ConsoleCtrlInfoLength)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* Allow only the Console Server to perform this operation (via CSRSS) */
+ if (PsGetCurrentProcess() != gpepCSRSS)
+ return STATUS_ACCESS_DENIED;
+
+ UserEnterExclusive();
+
+ switch (ConsoleCtrl)
+ {
+ case ConsoleCtrlDesktopConsoleThread:
+ {
+ DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo;
+ PDESKTOP Desktop = NULL;
+ ULONG_PTR OldThreadId;
+
+ if (ConsoleCtrlInfoLength != sizeof(DesktopConsoleThreadInfo))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForWrite(ConsoleCtrlInfo, ConsoleCtrlInfoLength, sizeof(USHORT));
+ DesktopConsoleThreadInfo = *(PDESKTOP_CONSOLE_THREAD)ConsoleCtrlInfo;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Reference the desktop */
+ Status = ObReferenceObjectByHandle(DesktopConsoleThreadInfo.DesktopHandle,
+ 0,
+ ExDesktopObjectType,
+ UserMode,
+ (PVOID*)&Desktop,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Save the old thread ID, it is always returned to the caller */
+ OldThreadId = Desktop->dwConsoleThreadId;
+
+ /* Set the new console input thread ID for this desktop if required */
+ if (DesktopConsoleThreadInfo.ThreadId != (ULONG_PTR)INVALID_HANDLE_VALUE)
+ {
+ Desktop->dwConsoleThreadId = DesktopConsoleThreadInfo.ThreadId;
+ }
+
+ /* Always return the old thread ID */
+ DesktopConsoleThreadInfo.ThreadId = OldThreadId;
+
+ /* Dereference the desktop */
+ ObDereferenceObject(Desktop);
+
+ /* Return the information back to the caller */
+ _SEH2_TRY
+ {
+ *(PDESKTOP_CONSOLE_THREAD)ConsoleCtrlInfo = DesktopConsoleThreadInfo;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ break;
+ }
+
+ case GuiConsoleWndClassAtom:
+ {
+ if (ConsoleCtrlInfoLength != sizeof(ATOM))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForRead(ConsoleCtrlInfo, ConsoleCtrlInfoLength, sizeof(USHORT));
+ gaGuiConsoleWndClass = *(ATOM*)ConsoleCtrlInfo;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ break;
+ }
+
+ case ConsoleMakePalettePublic:
+ {
+ HPALETTE hPalette;
+
+ if (ConsoleCtrlInfoLength != sizeof(hPalette))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForRead(ConsoleCtrlInfo, ConsoleCtrlInfoLength, sizeof(USHORT));
+ hPalette = *(HPALETTE*)ConsoleCtrlInfo;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Make the palette handle public */
+ GreSetObjectOwnerEx(hPalette,
+ GDI_OBJ_HMGR_PUBLIC,
+ GDIOBJFLAG_IGNOREPID);
+ break;
+ }
+
+ case ConsoleAcquireDisplayOwnership:
+ {
+ ERR("NtUserConsoleControl - ConsoleAcquireDisplayOwnership is
UNIMPLEMENTED\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+
+ default:
+ ERR("Calling invalid control %d in NtUserConsoleControl\n",
ConsoleCtrl);
+ Status = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ UserLeave();
+
+ return Status;
+}
+
+/* EOF */
Propchange: trunk/reactos/win32ss/user/ntuser/console.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/win32ss/user/ntuser/desktop.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/deskto…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/desktop.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/desktop.c [iso-8859-1] Wed Mar 11 01:21:29 2015
@@ -1651,6 +1651,103 @@
}
/*
+ * NtUserResolveDesktop
+ *
+ * The NtUserResolveDesktop function retrieves handles to the desktop and
+ * the window station specified by the desktop path string.
+ *
+ * Parameters
+ * ProcessHandle
+ * Handle to a user process.
+ *
+ * DesktopPath
+ * The desktop path string.
+ *
+ * Return Value
+ * Handle to the desktop (direct return value) and
+ * handle to the associated window station (by pointer).
+ * NULL in case of failure.
+ *
+ * Remarks
+ * Callable by CSRSS only.
+ *
+ * Status
+ * @implemented
+ */
+
+HDESK
+APIENTRY
+NtUserResolveDesktop(
+ IN HANDLE ProcessHandle,
+ IN PUNICODE_STRING DesktopPath,
+ DWORD dwUnknown,
+ OUT HWINSTA* phWinSta)
+{
+ NTSTATUS Status;
+ PEPROCESS Process = NULL;
+ HWINSTA hWinSta = NULL;
+ HDESK hDesktop = NULL;
+
+ /* Allow only the Console Server to perform this operation (via CSRSS) */
+ if (PsGetCurrentProcess() != gpepCSRSS)
+ return NULL;
+
+ /* Get the process object the user handle was referencing */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ *PsProcessType,
+ UserMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) return NULL;
+
+ // UserEnterShared();
+
+ _SEH2_TRY
+ {
+ UNICODE_STRING CapturedDesktopPath;
+
+ /* Capture the user desktop path string */
+ Status = IntSafeCopyUnicodeStringTerminateNULL(&CapturedDesktopPath,
+ DesktopPath);
+ if (!NT_SUCCESS(Status)) _SEH2_YIELD(goto Quit);
+
+ /* Call the internal function */
+ Status = IntParseDesktopPath(Process,
+ &CapturedDesktopPath,
+ &hWinSta,
+ &hDesktop);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("IntParseDesktopPath failed, Status = 0x%08lx\n", Status);
+ hWinSta = NULL;
+ hDesktop = NULL;
+ }
+
+ /* Return the window station handle */
+ *phWinSta = hWinSta;
+
+ /* Free the captured string */
+ if (CapturedDesktopPath.Buffer)
+ ExFreePoolWithTag(CapturedDesktopPath.Buffer, TAG_STRING);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+Quit:
+ // UserLeave();
+
+ /* Dereference the process object */
+ ObDereferenceObject(Process);
+
+ /* Return the desktop handle */
+ return hDesktop;
+}
+
+/*
* NtUserSwitchDesktop
*
* Sets the current input (interactive) desktop.
Modified: trunk/reactos/win32ss/user/ntuser/desktop.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/deskto…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/desktop.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/desktop.h [iso-8859-1] Wed Mar 11 01:21:29 2015
@@ -23,6 +23,10 @@
PWIN32HEAP pheapDesktop;
ULONG_PTR ulHeapSize;
LIST_ENTRY PtiList;
+
+ /* One console input thread per desktop, maintained by CONSRV */
+ DWORD dwConsoleThreadId;
+
/* Use for tracking mouse moves. */
PWND spwndTrack;
DWORD htEx;
Modified: trunk/reactos/win32ss/user/ntuser/ntstubs.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/ntstub…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/ntstubs.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/ntstubs.c [iso-8859-1] Wed Mar 11 01:21:29 2015
@@ -403,92 +403,6 @@
return 0;
}
-NTSTATUS
-APIENTRY
-NtUserConsoleControl(
- IN CONSOLECONTROL ConsoleCtrl,
- IN PVOID ConsoleCtrlInfo,
- IN ULONG ConsoleCtrlInfoLength)
-{
- NTSTATUS Status = STATUS_SUCCESS;
-
- /* Allow only the Console Server to perform this operation (via CSRSS) */
- if (PsGetCurrentProcess() != gpepCSRSS)
- return STATUS_ACCESS_DENIED;
-
- UserEnterExclusive();
-
- switch (ConsoleCtrl)
- {
- case GuiConsoleWndClassAtom:
- {
- if (ConsoleCtrlInfoLength != sizeof(ATOM))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- break;
- }
-
- _SEH2_TRY
- {
- ProbeForRead(ConsoleCtrlInfo, ConsoleCtrlInfoLength, 1);
- gaGuiConsoleWndClass = *(ATOM*)ConsoleCtrlInfo;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- break;
- }
-
- case ConsoleMakePalettePublic:
- {
- HPALETTE hPalette;
-
- if (ConsoleCtrlInfoLength != sizeof(HPALETTE))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- break;
- }
-
- _SEH2_TRY
- {
- ProbeForRead(ConsoleCtrlInfo, ConsoleCtrlInfoLength, 1);
- hPalette = *(HPALETTE*)ConsoleCtrlInfo;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- /* Make the palette handle public */
- GreSetObjectOwnerEx(hPalette,
- GDI_OBJ_HMGR_PUBLIC,
- GDIOBJFLAG_IGNOREPID);
-
- break;
- }
-
- case ConsoleAcquireDisplayOwnership:
- {
- ERR("NtUserConsoleControl - ConsoleAcquireDisplayOwnership is
UNIMPLEMENTED\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
- }
-
- default:
- ERR("Calling invalid control %d in NtUserConsoleControl\n",
ConsoleCtrl);
- Status = STATUS_INVALID_INFO_CLASS;
- break;
- }
-
- UserLeave();
-
- return Status;
-}
-
DWORD
APIENTRY
NtUserCreateInputContext(
@@ -738,15 +652,10 @@
return 0;
}
-DWORD
-APIENTRY
-NtUserResolveDesktop(
- DWORD dwUnknown1,
- DWORD dwUnknown2,
- DWORD dwUnknown3,
- DWORD dwUnknown4)
-{
- STUB;
+DWORD APIENTRY
+NtUserResolveDesktopForWOW(DWORD Unknown0)
+{
+ STUB
return 0;
}
@@ -811,11 +720,11 @@
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (NT_SUCCESS(Status))
- Status = UserInitiateShutdown(Thread, &CapturedFlags);
+ Status = UserInitiateShutdown(Thread, &CapturedFlags);
/* Return the modified value to the caller */
_SEH2_TRY
@@ -853,12 +762,11 @@
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (NT_SUCCESS(Status))
- Status = UserEndShutdown(Thread, ShutdownStatus);
-
+ Status = UserEndShutdown(Thread, ShutdownStatus);
break;
}
@@ -884,12 +792,11 @@
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (NT_SUCCESS(Status))
- Status = InitCsrApiPort(CsrPortHandle);
-
+ Status = InitCsrApiPort(CsrPortHandle);
break;
}
@@ -1103,20 +1010,6 @@
{
STUB
- return 0;
-}
-
-/*
- * NtUserResolveDesktopForWOW
- *
- * Status
- * @unimplemented
- */
-
-DWORD APIENTRY
-NtUserResolveDesktopForWOW(DWORD Unknown0)
-{
- STUB
return 0;
}
Modified: trunk/reactos/win32ss/user/winsrv/consrv/console.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/console.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/console.c [iso-8859-1] Wed Mar 11 01:21:29
2015
@@ -342,7 +342,7 @@
ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
IN OUT PCONSOLE_INFO ConsoleInfo,
IN OUT PVOID ExtraConsoleInfo,
- IN ULONG ProcessId);
+ IN PCSR_PROCESS ConsoleLeaderProcess);
NTSTATUS NTAPI
ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal);
@@ -513,12 +513,13 @@
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
OUT PCONSRV_CONSOLE* NewConsole,
IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
- IN ULONG ConsoleLeaderProcessId)
+ IN PCSR_PROCESS ConsoleLeaderProcess)
{
NTSTATUS Status;
HANDLE ConsoleHandle;
PCONSRV_CONSOLE Console;
CONSOLE_INFO ConsoleInfo;
+ ULONG ConsoleLeaderProcessId =
HandleToUlong(ConsoleLeaderProcess->ClientId.UniqueProcess);
SIZE_T Length = 0;
TERMINAL Terminal; /* The ConSrv terminal for this console */
@@ -545,7 +546,7 @@
Status = ConSrvInitTerminal(&Terminal,
&ConsoleInfo,
ConsoleInitInfo,
- ConsoleLeaderProcessId);
+ ConsoleLeaderProcess);
if (!NT_SUCCESS(Status))
{
DPRINT1("CONSRV: Failed to initialize a terminal, Status = 0x%08lx\n",
Status);
Modified: trunk/reactos/win32ss/user/winsrv/consrv/console.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/console.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/console.h [iso-8859-1] Wed Mar 11 01:21:29
2015
@@ -30,7 +30,7 @@
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
OUT struct _CONSRV_CONSOLE** /* PCONSRV_CONSOLE* */ NewConsole,
IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
- IN ULONG ConsoleLeaderProcessId);
+ IN PCSR_PROCESS ConsoleLeaderProcess);
VOID NTAPI ConSrvDeleteConsole(struct _CONSRV_CONSOLE* /* PCONSRV_CONSOLE */ Console);
NTSTATUS
Modified: trunk/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.h [iso-8859-1]
(original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.h [iso-8859-1] Wed Mar
11 01:21:29 2015
@@ -39,6 +39,11 @@
BOOL WindowSizeLock;
HANDLE hGuiInitEvent;
HANDLE hGuiTermEvent;
+
+ // HANDLE InputThreadHandle;
+ ULONG_PTR InputThreadId;
+ HWINSTA WinSta;
+ HDESK Desktop;
BOOLEAN IsWindowVisible;
Modified: trunk/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c [iso-8859-1]
(original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c [iso-8859-1] Wed Mar
11 01:21:29 2015
@@ -23,8 +23,8 @@
#define CONGUI_UPDATE_TIME 0
#define CONGUI_UPDATE_TIMER 1
-#define PM_CREATE_CONSOLE (WM_APP + 1)
-#define PM_DESTROY_CONSOLE (WM_APP + 2)
+#define PM_CREATE_CONSOLE (WM_APP + 1)
+#define PM_DESTROY_CONSOLE (WM_APP + 2)
/* GLOBALS ********************************************************************/
@@ -33,13 +33,15 @@
{
PCONSOLE_INFO ConsoleInfo;
PCONSOLE_START_INFO ConsoleStartInfo;
- ULONG ProcessId;
+ ULONG_PTR ProcessId;
+ HANDLE GuiThreadStartupEvent;
+ ULONG_PTR InputThreadId;
+ HWINSTA WinSta;
+ HDESK Desktop;
BOOLEAN IsWindowVisible;
} GUI_INIT_INFO, *PGUI_INIT_INFO;
-static BOOL ConsInitialized = FALSE;
-static HANDLE hInputThread = NULL;
-static DWORD dwInputThreadId = 0;
+static BOOL ConsInitialized = FALSE;
extern HICON ghDefaultIcon;
extern HICON ghDefaultIconSm;
@@ -137,20 +139,42 @@
VOID
CreateSysMenu(HWND hWnd);
-static DWORD NTAPI
+static ULONG NTAPI
GuiConsoleInputThread(PVOID Param)
{
- PHANDLE GraphicsStartupEvent = (PHANDLE)Param;
+ NTSTATUS Status;
+ PCSR_THREAD pcsrt = NULL;
+ PGUI_INIT_INFO GuiInitInfo = (PGUI_INIT_INFO)Param;
+ DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo;
+ ULONG_PTR InputThreadId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
+
LONG WindowCount = 0;
MSG msg;
/*
* This thread dispatches all the console notifications to the
- * notification window. It is common for all the console windows.
- */
+ * notification window. It is common for all the console windows
+ * in a given desktop in a window station.
+ */
+
+ /* Assign this console input thread to this desktop */
+ DesktopConsoleThreadInfo.DesktopHandle = GuiInitInfo->Desktop; // Duplicated
desktop handle
+ DesktopConsoleThreadInfo.ThreadId = InputThreadId;
+ Status = NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
+ &DesktopConsoleThreadInfo,
+ sizeof(DesktopConsoleThreadInfo));
+ if (!NT_SUCCESS(Status)) goto Quit;
+
+ /* Connect this CSR thread to the USER subsystem */
+ pcsrt = CsrConnectToUser();
+ if (pcsrt == NULL) goto Quit;
+
+ /* Assign the desktop to this thread */
+ if (!SetThreadDesktop(DesktopConsoleThreadInfo.DesktopHandle)) goto Quit;
/* The thread has been initialized, set the event */
- NtSetEvent(*GraphicsStartupEvent, NULL);
+ NtSetEvent(GuiInitInfo->GuiThreadStartupEvent, NULL);
+ Status = STATUS_SUCCESS;
while (GetMessageW(&msg, NULL, 0, 0))
{
@@ -257,7 +281,7 @@
if (InterlockedDecrement(&WindowCount) == 0)
{
- DPRINT("CONSRV: Going to quit the Input Thread!!\n");
+ DPRINT("CONSRV: Going to quit the Input Thread 0x%p\n",
InputThreadId);
goto Quit;
}
@@ -270,19 +294,41 @@
}
Quit:
- DPRINT("CONSRV: Quit the Input Thread!!\n");
-
- hInputThread = NULL;
- dwInputThreadId = 0;
-
- return 1;
-}
-
+ DPRINT("CONSRV: Quit the Input Thread 0x%p, Status = 0x%08lx\n",
InputThreadId, Status);
+
+ /* Remove this console input thread from this desktop */
+ // DesktopConsoleThreadInfo.DesktopHandle;
+ DesktopConsoleThreadInfo.ThreadId = 0;
+ NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
+ &DesktopConsoleThreadInfo,
+ sizeof(DesktopConsoleThreadInfo));
+
+ /* Close the duplicated desktop handle */
+ CloseDesktop(DesktopConsoleThreadInfo.DesktopHandle); // NtUserCloseDesktop
+
+ /* Cleanup CSR thread */
+ if (pcsrt) CsrDereferenceThread(pcsrt);
+
+ /* Exit the thread */
+ RtlExitUserThread(Status);
+ return 0;
+}
+
+// FIXME: Maybe return a NTSTATUS
static BOOL
-GuiInit(VOID)
-{
- /* Exit if we were already initialized */
- // if (ConsInitialized) return TRUE;
+GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo,
+ IN PCSR_PROCESS ConsoleLeaderProcess,
+ IN OUT PGUI_INIT_INFO GuiInitInfo)
+{
+ BOOL Success = TRUE;
+ UNICODE_STRING DesktopPath;
+ DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo;
+ HWINSTA hWinSta;
+ HDESK hDesk;
+
+ NTSTATUS Status;
+ HANDLE hInputThread;
+ CLIENT_ID ClientId;
/*
* Initialize and register the console window class, if needed.
@@ -294,39 +340,164 @@
}
/*
- * Set-up the console input thread
- */
- if (hInputThread == NULL)
- {
- HANDLE GraphicsStartupEvent;
- NTSTATUS Status;
-
- Status = NtCreateEvent(&GraphicsStartupEvent, EVENT_ALL_ACCESS,
- NULL, SynchronizationEvent, FALSE);
- if (!NT_SUCCESS(Status)) return FALSE;
-
- hInputThread = CreateThread(NULL,
- 0,
- GuiConsoleInputThread,
- (PVOID)&GraphicsStartupEvent,
- 0,
- &dwInputThreadId);
- if (hInputThread == NULL)
- {
- NtClose(GraphicsStartupEvent);
- DPRINT1("CONSRV: Failed to create graphics console thread.\n");
- return FALSE;
- }
- SetThreadPriority(hInputThread, THREAD_PRIORITY_HIGHEST);
- CloseHandle(hInputThread);
-
- WaitForSingleObject(GraphicsStartupEvent, INFINITE);
- NtClose(GraphicsStartupEvent);
- }
-
- // ConsInitialized = TRUE;
-
- return TRUE;
+ * Set-up the console input thread. We have
+ * one console input thread per desktop.
+ */
+
+ if (!CsrImpersonateClient(NULL))
+ // return STATUS_BAD_IMPERSONATION_LEVEL;
+ return FALSE;
+
+ if (ConsoleInitInfo->DesktopLength)
+ {
+ DesktopPath.MaximumLength = ConsoleInitInfo->DesktopLength;
+ DesktopPath.Length = DesktopPath.MaximumLength - sizeof(UNICODE_NULL);
+ DesktopPath.Buffer = ConsoleInitInfo->Desktop;
+ }
+ else
+ {
+ RtlInitUnicodeString(&DesktopPath, L"Default");
+ }
+
+ hDesk = NtUserResolveDesktop(ConsoleLeaderProcess->ProcessHandle,
+ &DesktopPath,
+ 0,
+ &hWinSta);
+ DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p;
hWinSta = 0x%p\n",
+ &DesktopPath, hDesk, hWinSta);
+
+ CsrRevertToSelf();
+
+ if (hDesk == NULL) return FALSE;
+
+ /*
+ * We need to see whether we need to create a
+ * new console input thread for this desktop.
+ */
+ DesktopConsoleThreadInfo.DesktopHandle = hDesk;
+ DesktopConsoleThreadInfo.ThreadId = (ULONG_PTR)INVALID_HANDLE_VALUE; // Special value
to say we just want to retrieve the thread ID.
+ NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
+ &DesktopConsoleThreadInfo,
+ sizeof(DesktopConsoleThreadInfo));
+ DPRINT("NtUserConsoleControl returned ThreadId = 0x%p\n",
DesktopConsoleThreadInfo.ThreadId);
+
+ /*
+ * Save the opened window station and desktop handles in the initialization
+ * structure. They will be used later on, and released, by the GUI frontend.
+ */
+ GuiInitInfo->WinSta = hWinSta;
+ GuiInitInfo->Desktop = hDesk;
+
+ /* Here GuiInitInfo contains original handles */
+
+ /* If we already have a console input thread on this desktop... */
+ if (DesktopConsoleThreadInfo.ThreadId != 0)
+ {
+ /* ... just use it... */
+ DPRINT("Using input thread InputThreadId = 0x%p\n",
DesktopConsoleThreadInfo.ThreadId);
+ GuiInitInfo->InputThreadId = DesktopConsoleThreadInfo.ThreadId;
+ goto Quit;
+ }
+
+ /* ... otherwise create a new one. */
+
+ /* Initialize a startup event for the thread to signal it */
+ Status = NtCreateEvent(&GuiInitInfo->GuiThreadStartupEvent, EVENT_ALL_ACCESS,
+ NULL, SynchronizationEvent, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ Success = FALSE;
+ goto Quit;
+ }
+
+ /*
+ * Duplicate the desktop handle for the console input thread internal needs.
+ * If it happens to need also a window station handle in the future, then
+ * it is there that you also need to duplicate the window station handle!
+ *
+ * Note also that we are going to temporarily overwrite the stored handles
+ * in GuiInitInfo because it happens that we use also this structure to give
+ * the duplicated handles to the input thread that is going to initialize.
+ * After the input thread finishes its initialization, we restore the handles
+ * in GuiInitInfo to their old values.
+ */
+ Status = NtDuplicateObject(NtCurrentProcess(),
+ hDesk,
+ NtCurrentProcess(),
+ (PHANDLE)&GuiInitInfo->Desktop,
+ 0, 0, DUPLICATE_SAME_ACCESS);
+ if (!NT_SUCCESS(Status))
+ {
+ Success = FALSE;
+ goto Quit;
+ }
+
+ /* Here GuiInitInfo contains duplicated handles */
+
+ Status = RtlCreateUserThread(NtCurrentProcess(),
+ NULL,
+ TRUE, // Start the thread in suspended state
+ 0,
+ 0,
+ 0,
+ (PVOID)GuiConsoleInputThread,
+ (PVOID)GuiInitInfo,
+ &hInputThread,
+ &ClientId);
+ if (NT_SUCCESS(Status))
+ {
+ /* Add it as a static server thread and resume it */
+ CsrAddStaticServerThread(hInputThread, &ClientId, 0);
+ Status = NtResumeThread(hInputThread, NULL);
+ }
+ DPRINT("Thread creation hInputThread = 0x%p, InputThreadId = 0x%p, Status =
0x%08lx\n",
+ hInputThread, ClientId.UniqueThread, Status);
+
+ if (!NT_SUCCESS(Status) || hInputThread == NULL)
+ {
+ /* Close the thread's handle */
+ if (hInputThread) NtClose(hInputThread);
+
+ /* We need to close here the duplicated desktop handle */
+ CloseDesktop(GuiInitInfo->Desktop); // NtUserCloseDesktop
+
+ /* Close the startup event and bail out */
+ NtClose(GuiInitInfo->GuiThreadStartupEvent);
+
+ DPRINT1("CONSRV: Failed to create graphics console thread.\n");
+ Success = FALSE;
+ goto Quit;
+ }
+
+ /* No need to close hInputThread, this is done by CSR automatically */
+
+ /* Wait for the thread to finish its initialization, and close the startup event */
+ NtWaitForSingleObject(GuiInitInfo->GuiThreadStartupEvent, FALSE, NULL);
+ NtClose(GuiInitInfo->GuiThreadStartupEvent);
+
+ /*
+ * Save the input thread ID for later use, and restore the original handles.
+ * The copies are held by the console input thread.
+ */
+ GuiInitInfo->InputThreadId = (ULONG_PTR)ClientId.UniqueThread;
+ GuiInitInfo->WinSta = hWinSta;
+ GuiInitInfo->Desktop = hDesk;
+
+ /* Here GuiInitInfo contains again original handles */
+
+Quit:
+ if (!Success)
+ {
+ /*
+ * Close the original handles. Do not use the copies in GuiInitInfo
+ * because we may have failed in the middle of the duplicate operation
+ * and the handles stored in GuiInitInfo may have changed.
+ */
+ CloseDesktop(hDesk); // NtUserCloseDesktop
+ CloseWindowStation(hWinSta); // NtUserCloseWindowStation
+ }
+
+ return Success;
}
@@ -362,7 +533,7 @@
ConsoleStartInfo = GuiInitInfo->ConsoleStartInfo;
/* Terminal data allocation */
- GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
+ GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiData));
if (!GuiData)
{
DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
@@ -471,9 +642,13 @@
GuiData->LineSelection = FALSE; // Default to block selection
// TODO: Retrieve the selection mode via the registry.
+ GuiData->InputThreadId = GuiInitInfo->InputThreadId;
+ GuiData->WinSta = GuiInitInfo->WinSta;
+ GuiData->Desktop = GuiInitInfo->Desktop;
+
/* Finally, finish to initialize the frontend structure */
This->Context = GuiData;
- if (This->Context2) ConsoleFreeHeap(This->Context2);
+ ConsoleFreeHeap(This->Context2);
This->Context2 = NULL;
/*
@@ -490,10 +665,10 @@
DPRINT("GUI - Checkpoint\n");
/* Create the terminal window */
- PostThreadMessageW(dwInputThreadId, PM_CREATE_CONSOLE, 0, (LPARAM)GuiData);
+ PostThreadMessageW(GuiData->InputThreadId, PM_CREATE_CONSOLE, 0,
(LPARAM)GuiData);
/* Wait until initialization has finished */
- WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
+ NtWaitForSingleObject(GuiData->hGuiInitEvent, FALSE, NULL);
DPRINT("OK we created the console window\n");
NtClose(GuiData->hGuiInitEvent);
GuiData->hGuiInitEvent = NULL;
@@ -515,11 +690,14 @@
PGUI_CONSOLE_DATA GuiData = This->Context;
DPRINT("Send PM_DESTROY_CONSOLE message and wait on hGuiTermEvent...\n");
- PostThreadMessageW(dwInputThreadId, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
- WaitForSingleObject(GuiData->hGuiTermEvent, INFINITE);
+ PostThreadMessageW(GuiData->InputThreadId, PM_DESTROY_CONSOLE, 0,
(LPARAM)GuiData);
+ NtWaitForSingleObject(GuiData->hGuiTermEvent, FALSE, NULL);
DPRINT("hGuiTermEvent set\n");
NtClose(GuiData->hGuiTermEvent);
GuiData->hGuiTermEvent = NULL;
+
+ CloseDesktop(GuiData->Desktop); // NtUserCloseDesktop
+ CloseWindowStation(GuiData->WinSta); // NtUserCloseWindowStation
DPRINT("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ;
GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n",
GuiData->hIcon, ghDefaultIcon, GuiData->hIconSm, ghDefaultIconSm);
@@ -897,9 +1075,9 @@
if (pSelectionInfo == NULL) return FALSE;
- ZeroMemory(pSelectionInfo, sizeof(CONSOLE_SELECTION_INFO));
+ ZeroMemory(pSelectionInfo, sizeof(*pSelectionInfo));
if (GuiData->Selection.dwFlags != CONSOLE_NO_SELECTION)
- RtlCopyMemory(pSelectionInfo, &GuiData->Selection,
sizeof(CONSOLE_SELECTION_INFO));
+ RtlCopyMemory(pSelectionInfo, &GuiData->Selection,
sizeof(*pSelectionInfo));
return TRUE;
}
@@ -1074,7 +1252,7 @@
GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
IN OUT PCONSOLE_INFO ConsoleInfo,
IN OUT PVOID ExtraConsoleInfo,
- IN ULONG ProcessId)
+ IN PCSR_PROCESS ConsoleLeaderProcess)
{
PCONSOLE_INIT_INFO ConsoleInitInfo = ExtraConsoleInfo;
PGUI_INIT_INFO GuiInitInfo;
@@ -1082,21 +1260,25 @@
if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL)
return STATUS_INVALID_PARAMETER;
- /* Initialize GUI terminal emulator common functionalities */
- if (!GuiInit()) return STATUS_UNSUCCESSFUL;
-
/*
* Initialize a private initialization info structure for later use.
* It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
*/
- GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_INIT_INFO));
+ GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiInitInfo));
if (GuiInitInfo == NULL) return STATUS_NO_MEMORY;
+
+ /* Initialize GUI terminal emulator common functionalities */
+ if (!GuiInit(ConsoleInitInfo, ConsoleLeaderProcess, GuiInitInfo))
+ {
+ ConsoleFreeHeap(GuiInitInfo);
+ return STATUS_UNSUCCESSFUL;
+ }
// HACK: We suppose that the pointers will be valid in GuiInitFrontEnd...
// If not, then copy exactly what we need in GuiInitInfo.
GuiInitInfo->ConsoleInfo = ConsoleInfo;
GuiInitInfo->ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo;
- GuiInitInfo->ProcessId = ProcessId;
+ GuiInitInfo->ProcessId =
HandleToUlong(ConsoleLeaderProcess->ClientId.UniqueProcess);
GuiInitInfo->IsWindowVisible = ConsoleInitInfo->IsWindowVisible;
/* Finally, initialize the frontend structure */
Modified: trunk/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/frontends/terminal.c [iso-8859-1] Wed Mar 11
01:21:29 2015
@@ -96,7 +96,7 @@
TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
IN OUT PCONSOLE_INFO ConsoleInfo,
IN OUT PVOID ExtraConsoleInfo,
- IN ULONG ProcessId);
+ IN PCSR_PROCESS ConsoleLeaderProcess);
NTSTATUS NTAPI
TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
#endif
@@ -105,7 +105,7 @@
GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
IN OUT PCONSOLE_INFO ConsoleInfo,
IN OUT PVOID ExtraConsoleInfo,
- IN ULONG ProcessId);
+ IN PCSR_PROCESS ConsoleLeaderProcess);
NTSTATUS NTAPI
GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
/***************/
@@ -114,7 +114,7 @@
NTSTATUS (NTAPI *FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd,
IN OUT PCONSOLE_INFO ConsoleInfo,
IN OUT PVOID ExtraConsoleInfo,
- IN ULONG ProcessId);
+ IN PCSR_PROCESS ConsoleLeaderProcess);
typedef
NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd);
@@ -156,7 +156,7 @@
ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
IN OUT PCONSOLE_INFO ConsoleInfo,
IN OUT PVOID ExtraConsoleInfo,
- IN ULONG ProcessId)
+ IN PCSR_PROCESS ConsoleLeaderProcess)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG i;
@@ -171,7 +171,7 @@
Status = FrontEndLoadingMethods[i].FrontEndLoad(FrontEnd,
ConsoleInfo,
ExtraConsoleInfo,
- ProcessId);
+ ConsoleLeaderProcess);
if (NT_SUCCESS(Status))
{
/* Save the unload callback */
@@ -206,7 +206,7 @@
ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
IN OUT PCONSOLE_INFO ConsoleInfo,
IN OUT PVOID ExtraConsoleInfo,
- IN ULONG ProcessId)
+ IN PCSR_PROCESS ConsoleLeaderProcess)
{
NTSTATUS Status;
PFRONTEND FrontEnd;
@@ -218,7 +218,7 @@
Status = ConSrvLoadFrontEnd(FrontEnd,
ConsoleInfo,
ExtraConsoleInfo,
- ProcessId);
+ ConsoleLeaderProcess);
if (!NT_SUCCESS(Status))
{
DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n",
Status);
Modified: trunk/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c [iso-8859-1]
(original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c [iso-8859-1] Wed Mar
11 01:21:29 2015
@@ -942,7 +942,7 @@
TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
IN OUT PCONSOLE_INFO ConsoleInfo,
IN OUT PVOID ExtraConsoleInfo,
- IN ULONG ProcessId)
+ IN PCSR_PROCESS ConsoleLeaderProcess)
{
if (FrontEnd == NULL || ConsoleInfo == NULL)
return STATUS_INVALID_PARAMETER;
Modified: trunk/reactos/win32ss/user/winsrv/consrv/handle.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/handle.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/handle.c [iso-8859-1] Wed Mar 11 01:21:29
2015
@@ -494,10 +494,14 @@
ConSrvFreeHandlesTable(ProcessData);
/* Initialize a new Console owned by this process */
+ DPRINT("Initialization of console '%S' for process '%S' on
desktop '%S'\n",
+ ConsoleInitInfo->ConsoleTitle ? ConsoleInitInfo->ConsoleTitle :
L"n/a",
+ ConsoleInitInfo->AppName ? ConsoleInitInfo->AppName : L"n/a",
+ ConsoleInitInfo->Desktop ? ConsoleInitInfo->Desktop :
L"n/a");
Status = ConSrvInitConsole(&ConsoleHandle,
&Console,
ConsoleInitInfo,
-
HandleToUlong(ProcessData->Process->ClientId.UniqueProcess));
+ ProcessData->Process);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console initialization failed\n");
Modified: trunk/reactos/win32ss/user/winsrv/consrv/init.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/init.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/init.c [iso-8859-1] Wed Mar 11 01:21:29 2015
@@ -414,7 +414,6 @@
NTSTATUS Status = STATUS_SUCCESS;
PCONSRV_API_CONNECTINFO ConnectInfo = (PCONSRV_API_CONNECTINFO)ConnectionInfo;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
- CONSOLE_INIT_INFO ConsoleInitInfo;
if ( ConnectionInfo == NULL ||
ConnectionInfoLength == NULL ||
@@ -433,22 +432,50 @@
DPRINT("ConnectInfo->IsConsoleApp = %s\n", ConnectInfo->IsConsoleApp
? "True" : "False");
if (!ConnectInfo->IsConsoleApp) return STATUS_SUCCESS;
- /* Initialize the console initialization info structure */
- ConsoleInitInfo.ConsoleStartInfo = &ConnectInfo->ConsoleStartInfo;
- ConsoleInitInfo.IsWindowVisible = ConnectInfo->IsWindowVisible;
- ConsoleInitInfo.TitleLength = ConnectInfo->TitleLength;
- ConsoleInitInfo.ConsoleTitle = ConnectInfo->ConsoleTitle;
- ConsoleInitInfo.DesktopLength = ConnectInfo->DesktopLength;
- ConsoleInitInfo.Desktop = ConnectInfo->Desktop;
- ConsoleInitInfo.AppNameLength = ConnectInfo->AppNameLength;
- ConsoleInitInfo.AppName = ConnectInfo->AppName;
- ConsoleInitInfo.CurDirLength = ConnectInfo->CurDirLength;
- ConsoleInitInfo.CurDir = ConnectInfo->CurDir;
-
/* If we don't inherit from an existing console, then create a new one... */
if (ConnectInfo->ConsoleStartInfo.ConsoleHandle == NULL)
{
+ CONSOLE_INIT_INFO ConsoleInitInfo;
+
DPRINT("ConSrvConnect - Allocate a new console\n");
+
+ /* Initialize the console initialization info structure */
+ ConsoleInitInfo.ConsoleStartInfo = &ConnectInfo->ConsoleStartInfo;
+ ConsoleInitInfo.IsWindowVisible = ConnectInfo->IsWindowVisible;
+ ConsoleInitInfo.TitleLength = ConnectInfo->TitleLength;
+ ConsoleInitInfo.ConsoleTitle = ConnectInfo->ConsoleTitle;
+ ConsoleInitInfo.DesktopLength = 0;
+ ConsoleInitInfo.Desktop = NULL;
+ ConsoleInitInfo.AppNameLength = ConnectInfo->AppNameLength;
+ ConsoleInitInfo.AppName = ConnectInfo->AppName;
+ ConsoleInitInfo.CurDirLength = ConnectInfo->CurDirLength;
+ ConsoleInitInfo.CurDir = ConnectInfo->CurDir;
+
+ /*
+ * Contrary to the case of SrvAllocConsole, the desktop string is
+ * allocated in the process' heap, so we need to retrieve it by
+ * using NtReadVirtualMemory.
+ */
+ if (ConnectInfo->DesktopLength)
+ {
+ ConsoleInitInfo.DesktopLength = ConnectInfo->DesktopLength;
+
+ ConsoleInitInfo.Desktop = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
+ ConsoleInitInfo.DesktopLength);
+ if (ConsoleInitInfo.Desktop == NULL)
+ return STATUS_NO_MEMORY;
+
+ Status = NtReadVirtualMemory(ProcessData->Process->ProcessHandle,
+ ConnectInfo->Desktop,
+ ConsoleInitInfo.Desktop,
+ ConsoleInitInfo.DesktopLength,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ConsoleFreeHeap(ConsoleInitInfo.Desktop);
+ return Status;
+ }
+ }
/*
* We are about to create a new console. However when ConSrvNewProcess
@@ -467,6 +494,12 @@
&ConnectInfo->ConsoleStartInfo.OutputHandle,
&ConnectInfo->ConsoleStartInfo.ErrorHandle,
&ConsoleInitInfo);
+
+ /* Free our local desktop string if any */
+ if (ConsoleInitInfo.DesktopLength)
+ ConsoleFreeHeap(ConsoleInitInfo.Desktop);
+
+ /* Check for success */
if (!NT_SUCCESS(Status))
{
DPRINT1("Console allocation failed\n");