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?re... ============================================================================== --- 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/console... ============================================================================== --- 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@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/desktop... ============================================================================== --- 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/desktop... ============================================================================== --- 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/ntstubs... ============================================================================== --- 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");