mirror of
https://github.com/reactos/reactos.git
synced 2024-09-28 13:34:53 +00:00
[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. svn path=/trunk/; revision=66662
This commit is contained in:
parent
3ea483bc85
commit
444d33d50b
|
@ -197,7 +197,9 @@ typedef struct _CONSRV_API_CONNECTINFO
|
||||||
ULONG TitleLength;
|
ULONG TitleLength;
|
||||||
WCHAR ConsoleTitle[MAX_PATH + 1]; // Console title or full path to the startup shortcut
|
WCHAR ConsoleTitle[MAX_PATH + 1]; // Console title or full path to the startup shortcut
|
||||||
ULONG DesktopLength;
|
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;
|
ULONG AppNameLength;
|
||||||
WCHAR AppName[128]; // Full path of the launched app
|
WCHAR AppName[128]; // Full path of the launched app
|
||||||
ULONG CurDirLength;
|
ULONG CurDirLength;
|
||||||
|
|
|
@ -100,6 +100,7 @@ list(APPEND SOURCE
|
||||||
user/ntuser/caret.c
|
user/ntuser/caret.c
|
||||||
user/ntuser/class.c
|
user/ntuser/class.c
|
||||||
user/ntuser/clipboard.c
|
user/ntuser/clipboard.c
|
||||||
|
user/ntuser/console.c
|
||||||
user/ntuser/csr.c
|
user/ntuser/csr.c
|
||||||
user/ntuser/cursoricon.c
|
user/ntuser/cursoricon.c
|
||||||
user/ntuser/dde.c
|
user/ntuser/dde.c
|
||||||
|
|
|
@ -1721,11 +1721,18 @@ NtUserCloseWindowStation(
|
||||||
/* Console commands for NtUserConsoleControl */
|
/* Console commands for NtUserConsoleControl */
|
||||||
typedef enum _CONSOLECONTROL
|
typedef enum _CONSOLECONTROL
|
||||||
{
|
{
|
||||||
GuiConsoleWndClassAtom,
|
ConsoleCtrlDesktopConsoleThread = 0,
|
||||||
|
GuiConsoleWndClassAtom = 1,
|
||||||
ConsoleMakePalettePublic = 5,
|
ConsoleMakePalettePublic = 5,
|
||||||
ConsoleAcquireDisplayOwnership,
|
ConsoleAcquireDisplayOwnership,
|
||||||
} CONSOLECONTROL, *PCONSOLECONTROL;
|
} CONSOLECONTROL, *PCONSOLECONTROL;
|
||||||
|
|
||||||
|
typedef struct _DESKTOP_CONSOLE_THREAD
|
||||||
|
{
|
||||||
|
HDESK DesktopHandle;
|
||||||
|
ULONG_PTR ThreadId;
|
||||||
|
} DESKTOP_CONSOLE_THREAD, *PDESKTOP_CONSOLE_THREAD;
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtUserConsoleControl(
|
NtUserConsoleControl(
|
||||||
|
@ -2860,13 +2867,13 @@ NtUserRemoveProp(
|
||||||
HWND hWnd,
|
HWND hWnd,
|
||||||
ATOM Atom);
|
ATOM Atom);
|
||||||
|
|
||||||
DWORD
|
HDESK
|
||||||
NTAPI
|
APIENTRY
|
||||||
NtUserResolveDesktop(
|
NtUserResolveDesktop(
|
||||||
DWORD dwUnknown1,
|
IN HANDLE ProcessHandle,
|
||||||
DWORD dwUnknown2,
|
IN PUNICODE_STRING DesktopPath,
|
||||||
DWORD dwUnknown3,
|
DWORD dwUnknown,
|
||||||
DWORD dwUnknown4);
|
OUT HWINSTA* phWinSta);
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
NTAPI
|
NTAPI
|
||||||
|
|
160
reactos/win32ss/user/ntuser/console.c
Normal file
160
reactos/win32ss/user/ntuser/console.c
Normal file
|
@ -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 */
|
|
@ -1650,6 +1650,103 @@ NtUserPaintDesktop(HDC hDC)
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* NtUserSwitchDesktop
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,6 +23,10 @@ typedef struct _DESKTOP
|
||||||
PWIN32HEAP pheapDesktop;
|
PWIN32HEAP pheapDesktop;
|
||||||
ULONG_PTR ulHeapSize;
|
ULONG_PTR ulHeapSize;
|
||||||
LIST_ENTRY PtiList;
|
LIST_ENTRY PtiList;
|
||||||
|
|
||||||
|
/* One console input thread per desktop, maintained by CONSRV */
|
||||||
|
DWORD dwConsoleThreadId;
|
||||||
|
|
||||||
/* Use for tracking mouse moves. */
|
/* Use for tracking mouse moves. */
|
||||||
PWND spwndTrack;
|
PWND spwndTrack;
|
||||||
DWORD htEx;
|
DWORD htEx;
|
||||||
|
|
|
@ -403,92 +403,6 @@ NtUserYieldTask(VOID)
|
||||||
return 0;
|
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
|
DWORD
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtUserCreateInputContext(
|
NtUserCreateInputContext(
|
||||||
|
@ -738,15 +652,10 @@ NtUserRegisterRawInputDevices(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD APIENTRY
|
||||||
APIENTRY
|
NtUserResolveDesktopForWOW(DWORD Unknown0)
|
||||||
NtUserResolveDesktop(
|
|
||||||
DWORD dwUnknown1,
|
|
||||||
DWORD dwUnknown2,
|
|
||||||
DWORD dwUnknown3,
|
|
||||||
DWORD dwUnknown4)
|
|
||||||
{
|
{
|
||||||
STUB;
|
STUB
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,11 +720,11 @@ NtUserSetInformationThread(IN HANDLE ThreadHandle,
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
Status = _SEH2_GetExceptionCode();
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
_SEH2_YIELD(break);
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
Status = UserInitiateShutdown(Thread, &CapturedFlags);
|
||||||
Status = UserInitiateShutdown(Thread, &CapturedFlags);
|
|
||||||
|
|
||||||
/* Return the modified value to the caller */
|
/* Return the modified value to the caller */
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
|
@ -853,12 +762,11 @@ NtUserSetInformationThread(IN HANDLE ThreadHandle,
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
Status = _SEH2_GetExceptionCode();
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
_SEH2_YIELD(break);
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
Status = UserEndShutdown(Thread, ShutdownStatus);
|
||||||
Status = UserEndShutdown(Thread, ShutdownStatus);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -884,12 +792,11 @@ NtUserSetInformationThread(IN HANDLE ThreadHandle,
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
Status = _SEH2_GetExceptionCode();
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
_SEH2_YIELD(break);
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
Status = InitCsrApiPort(CsrPortHandle);
|
||||||
Status = InitCsrApiPort(CsrPortHandle);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1106,20 +1013,6 @@ NtUserUpdateLayeredWindow(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* NtUserResolveDesktopForWOW
|
|
||||||
*
|
|
||||||
* Status
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
|
|
||||||
DWORD APIENTRY
|
|
||||||
NtUserResolveDesktopForWOW(DWORD Unknown0)
|
|
||||||
{
|
|
||||||
STUB
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -342,7 +342,7 @@ NTSTATUS NTAPI
|
||||||
ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
|
ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
|
||||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||||
IN OUT PVOID ExtraConsoleInfo,
|
IN OUT PVOID ExtraConsoleInfo,
|
||||||
IN ULONG ProcessId);
|
IN PCSR_PROCESS ConsoleLeaderProcess);
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal);
|
ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal);
|
||||||
|
|
||||||
|
@ -513,12 +513,13 @@ NTSTATUS NTAPI
|
||||||
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
|
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
|
||||||
OUT PCONSRV_CONSOLE* NewConsole,
|
OUT PCONSRV_CONSOLE* NewConsole,
|
||||||
IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
|
IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
|
||||||
IN ULONG ConsoleLeaderProcessId)
|
IN PCSR_PROCESS ConsoleLeaderProcess)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
HANDLE ConsoleHandle;
|
HANDLE ConsoleHandle;
|
||||||
PCONSRV_CONSOLE Console;
|
PCONSRV_CONSOLE Console;
|
||||||
CONSOLE_INFO ConsoleInfo;
|
CONSOLE_INFO ConsoleInfo;
|
||||||
|
ULONG ConsoleLeaderProcessId = HandleToUlong(ConsoleLeaderProcess->ClientId.UniqueProcess);
|
||||||
SIZE_T Length = 0;
|
SIZE_T Length = 0;
|
||||||
|
|
||||||
TERMINAL Terminal; /* The ConSrv terminal for this console */
|
TERMINAL Terminal; /* The ConSrv terminal for this console */
|
||||||
|
@ -545,7 +546,7 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
|
||||||
Status = ConSrvInitTerminal(&Terminal,
|
Status = ConSrvInitTerminal(&Terminal,
|
||||||
&ConsoleInfo,
|
&ConsoleInfo,
|
||||||
ConsoleInitInfo,
|
ConsoleInitInfo,
|
||||||
ConsoleLeaderProcessId);
|
ConsoleLeaderProcess);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("CONSRV: Failed to initialize a terminal, Status = 0x%08lx\n", Status);
|
DPRINT1("CONSRV: Failed to initialize a terminal, Status = 0x%08lx\n", Status);
|
||||||
|
|
|
@ -30,7 +30,7 @@ NTSTATUS NTAPI
|
||||||
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
|
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
|
||||||
OUT struct _CONSRV_CONSOLE** /* PCONSRV_CONSOLE* */ NewConsole,
|
OUT struct _CONSRV_CONSOLE** /* PCONSRV_CONSOLE* */ NewConsole,
|
||||||
IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
|
IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
|
||||||
IN ULONG ConsoleLeaderProcessId);
|
IN PCSR_PROCESS ConsoleLeaderProcess);
|
||||||
VOID NTAPI ConSrvDeleteConsole(struct _CONSRV_CONSOLE* /* PCONSRV_CONSOLE */ Console);
|
VOID NTAPI ConSrvDeleteConsole(struct _CONSRV_CONSOLE* /* PCONSRV_CONSOLE */ Console);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -40,6 +40,11 @@ typedef struct _GUI_CONSOLE_DATA
|
||||||
HANDLE hGuiInitEvent;
|
HANDLE hGuiInitEvent;
|
||||||
HANDLE hGuiTermEvent;
|
HANDLE hGuiTermEvent;
|
||||||
|
|
||||||
|
// HANDLE InputThreadHandle;
|
||||||
|
ULONG_PTR InputThreadId;
|
||||||
|
HWINSTA WinSta;
|
||||||
|
HDESK Desktop;
|
||||||
|
|
||||||
BOOLEAN IsWindowVisible;
|
BOOLEAN IsWindowVisible;
|
||||||
|
|
||||||
POINT OldCursor;
|
POINT OldCursor;
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
#define CONGUI_UPDATE_TIME 0
|
#define CONGUI_UPDATE_TIME 0
|
||||||
#define CONGUI_UPDATE_TIMER 1
|
#define CONGUI_UPDATE_TIMER 1
|
||||||
|
|
||||||
#define PM_CREATE_CONSOLE (WM_APP + 1)
|
#define PM_CREATE_CONSOLE (WM_APP + 1)
|
||||||
#define PM_DESTROY_CONSOLE (WM_APP + 2)
|
#define PM_DESTROY_CONSOLE (WM_APP + 2)
|
||||||
|
|
||||||
|
|
||||||
/* GLOBALS ********************************************************************/
|
/* GLOBALS ********************************************************************/
|
||||||
|
@ -33,13 +33,15 @@ typedef struct _GUI_INIT_INFO
|
||||||
{
|
{
|
||||||
PCONSOLE_INFO ConsoleInfo;
|
PCONSOLE_INFO ConsoleInfo;
|
||||||
PCONSOLE_START_INFO ConsoleStartInfo;
|
PCONSOLE_START_INFO ConsoleStartInfo;
|
||||||
ULONG ProcessId;
|
ULONG_PTR ProcessId;
|
||||||
|
HANDLE GuiThreadStartupEvent;
|
||||||
|
ULONG_PTR InputThreadId;
|
||||||
|
HWINSTA WinSta;
|
||||||
|
HDESK Desktop;
|
||||||
BOOLEAN IsWindowVisible;
|
BOOLEAN IsWindowVisible;
|
||||||
} GUI_INIT_INFO, *PGUI_INIT_INFO;
|
} GUI_INIT_INFO, *PGUI_INIT_INFO;
|
||||||
|
|
||||||
static BOOL ConsInitialized = FALSE;
|
static BOOL ConsInitialized = FALSE;
|
||||||
static HANDLE hInputThread = NULL;
|
|
||||||
static DWORD dwInputThreadId = 0;
|
|
||||||
|
|
||||||
extern HICON ghDefaultIcon;
|
extern HICON ghDefaultIcon;
|
||||||
extern HICON ghDefaultIconSm;
|
extern HICON ghDefaultIconSm;
|
||||||
|
@ -137,20 +139,42 @@ SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen);
|
||||||
VOID
|
VOID
|
||||||
CreateSysMenu(HWND hWnd);
|
CreateSysMenu(HWND hWnd);
|
||||||
|
|
||||||
static DWORD NTAPI
|
static ULONG NTAPI
|
||||||
GuiConsoleInputThread(PVOID Param)
|
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;
|
LONG WindowCount = 0;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This thread dispatches all the console notifications to the
|
* 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 */
|
/* The thread has been initialized, set the event */
|
||||||
NtSetEvent(*GraphicsStartupEvent, NULL);
|
NtSetEvent(GuiInitInfo->GuiThreadStartupEvent, NULL);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
while (GetMessageW(&msg, NULL, 0, 0))
|
while (GetMessageW(&msg, NULL, 0, 0))
|
||||||
{
|
{
|
||||||
|
@ -257,7 +281,7 @@ GuiConsoleInputThread(PVOID Param)
|
||||||
|
|
||||||
if (InterlockedDecrement(&WindowCount) == 0)
|
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;
|
goto Quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,19 +294,41 @@ GuiConsoleInputThread(PVOID Param)
|
||||||
}
|
}
|
||||||
|
|
||||||
Quit:
|
Quit:
|
||||||
DPRINT("CONSRV: Quit the Input Thread!!\n");
|
DPRINT("CONSRV: Quit the Input Thread 0x%p, Status = 0x%08lx\n", InputThreadId, Status);
|
||||||
|
|
||||||
hInputThread = NULL;
|
/* Remove this console input thread from this desktop */
|
||||||
dwInputThreadId = 0;
|
// DesktopConsoleThreadInfo.DesktopHandle;
|
||||||
|
DesktopConsoleThreadInfo.ThreadId = 0;
|
||||||
|
NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
|
||||||
|
&DesktopConsoleThreadInfo,
|
||||||
|
sizeof(DesktopConsoleThreadInfo));
|
||||||
|
|
||||||
return 1;
|
/* 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
|
static BOOL
|
||||||
GuiInit(VOID)
|
GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo,
|
||||||
|
IN PCSR_PROCESS ConsoleLeaderProcess,
|
||||||
|
IN OUT PGUI_INIT_INFO GuiInitInfo)
|
||||||
{
|
{
|
||||||
/* Exit if we were already initialized */
|
BOOL Success = TRUE;
|
||||||
// if (ConsInitialized) return 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.
|
* Initialize and register the console window class, if needed.
|
||||||
|
@ -294,39 +340,164 @@ GuiInit(VOID)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set-up the console input thread
|
* Set-up the console input thread. We have
|
||||||
|
* one console input thread per desktop.
|
||||||
*/
|
*/
|
||||||
if (hInputThread == NULL)
|
|
||||||
|
if (!CsrImpersonateClient(NULL))
|
||||||
|
// return STATUS_BAD_IMPERSONATION_LEVEL;
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (ConsoleInitInfo->DesktopLength)
|
||||||
{
|
{
|
||||||
HANDLE GraphicsStartupEvent;
|
DesktopPath.MaximumLength = ConsoleInitInfo->DesktopLength;
|
||||||
NTSTATUS Status;
|
DesktopPath.Length = DesktopPath.MaximumLength - sizeof(UNICODE_NULL);
|
||||||
|
DesktopPath.Buffer = ConsoleInitInfo->Desktop;
|
||||||
Status = NtCreateEvent(&GraphicsStartupEvent, EVENT_ALL_ACCESS,
|
}
|
||||||
NULL, SynchronizationEvent, FALSE);
|
else
|
||||||
if (!NT_SUCCESS(Status)) return FALSE;
|
{
|
||||||
|
RtlInitUnicodeString(&DesktopPath, L"Default");
|
||||||
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;
|
hDesk = NtUserResolveDesktop(ConsoleLeaderProcess->ProcessHandle,
|
||||||
|
&DesktopPath,
|
||||||
|
0,
|
||||||
|
&hWinSta);
|
||||||
|
DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p; hWinSta = 0x%p\n",
|
||||||
|
&DesktopPath, hDesk, hWinSta);
|
||||||
|
|
||||||
return TRUE;
|
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 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
|
||||||
ConsoleStartInfo = GuiInitInfo->ConsoleStartInfo;
|
ConsoleStartInfo = GuiInitInfo->ConsoleStartInfo;
|
||||||
|
|
||||||
/* Terminal data allocation */
|
/* Terminal data allocation */
|
||||||
GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
|
GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiData));
|
||||||
if (!GuiData)
|
if (!GuiData)
|
||||||
{
|
{
|
||||||
DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
|
DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n");
|
||||||
|
@ -471,9 +642,13 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
|
||||||
GuiData->LineSelection = FALSE; // Default to block selection
|
GuiData->LineSelection = FALSE; // Default to block selection
|
||||||
// TODO: Retrieve the selection mode via the registry.
|
// 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 */
|
/* Finally, finish to initialize the frontend structure */
|
||||||
This->Context = GuiData;
|
This->Context = GuiData;
|
||||||
if (This->Context2) ConsoleFreeHeap(This->Context2);
|
ConsoleFreeHeap(This->Context2);
|
||||||
This->Context2 = NULL;
|
This->Context2 = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -490,10 +665,10 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
|
||||||
DPRINT("GUI - Checkpoint\n");
|
DPRINT("GUI - Checkpoint\n");
|
||||||
|
|
||||||
/* Create the terminal window */
|
/* 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 */
|
/* Wait until initialization has finished */
|
||||||
WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
|
NtWaitForSingleObject(GuiData->hGuiInitEvent, FALSE, NULL);
|
||||||
DPRINT("OK we created the console window\n");
|
DPRINT("OK we created the console window\n");
|
||||||
NtClose(GuiData->hGuiInitEvent);
|
NtClose(GuiData->hGuiInitEvent);
|
||||||
GuiData->hGuiInitEvent = NULL;
|
GuiData->hGuiInitEvent = NULL;
|
||||||
|
@ -515,12 +690,15 @@ GuiDeinitFrontEnd(IN OUT PFRONTEND This)
|
||||||
PGUI_CONSOLE_DATA GuiData = This->Context;
|
PGUI_CONSOLE_DATA GuiData = This->Context;
|
||||||
|
|
||||||
DPRINT("Send PM_DESTROY_CONSOLE message and wait on hGuiTermEvent...\n");
|
DPRINT("Send PM_DESTROY_CONSOLE message and wait on hGuiTermEvent...\n");
|
||||||
PostThreadMessageW(dwInputThreadId, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
|
PostThreadMessageW(GuiData->InputThreadId, PM_DESTROY_CONSOLE, 0, (LPARAM)GuiData);
|
||||||
WaitForSingleObject(GuiData->hGuiTermEvent, INFINITE);
|
NtWaitForSingleObject(GuiData->hGuiTermEvent, FALSE, NULL);
|
||||||
DPRINT("hGuiTermEvent set\n");
|
DPRINT("hGuiTermEvent set\n");
|
||||||
NtClose(GuiData->hGuiTermEvent);
|
NtClose(GuiData->hGuiTermEvent);
|
||||||
GuiData->hGuiTermEvent = NULL;
|
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",
|
DPRINT("Destroying icons !! - GuiData->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; GuiData->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n",
|
||||||
GuiData->hIcon, ghDefaultIcon, GuiData->hIconSm, ghDefaultIconSm);
|
GuiData->hIcon, ghDefaultIcon, GuiData->hIconSm, ghDefaultIconSm);
|
||||||
if (GuiData->hIcon != NULL && GuiData->hIcon != ghDefaultIcon)
|
if (GuiData->hIcon != NULL && GuiData->hIcon != ghDefaultIcon)
|
||||||
|
@ -897,9 +1075,9 @@ GuiGetSelectionInfo(IN OUT PFRONTEND This,
|
||||||
|
|
||||||
if (pSelectionInfo == NULL) return FALSE;
|
if (pSelectionInfo == NULL) return FALSE;
|
||||||
|
|
||||||
ZeroMemory(pSelectionInfo, sizeof(CONSOLE_SELECTION_INFO));
|
ZeroMemory(pSelectionInfo, sizeof(*pSelectionInfo));
|
||||||
if (GuiData->Selection.dwFlags != CONSOLE_NO_SELECTION)
|
if (GuiData->Selection.dwFlags != CONSOLE_NO_SELECTION)
|
||||||
RtlCopyMemory(pSelectionInfo, &GuiData->Selection, sizeof(CONSOLE_SELECTION_INFO));
|
RtlCopyMemory(pSelectionInfo, &GuiData->Selection, sizeof(*pSelectionInfo));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +1252,7 @@ NTSTATUS NTAPI
|
||||||
GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||||
IN OUT PVOID ExtraConsoleInfo,
|
IN OUT PVOID ExtraConsoleInfo,
|
||||||
IN ULONG ProcessId)
|
IN PCSR_PROCESS ConsoleLeaderProcess)
|
||||||
{
|
{
|
||||||
PCONSOLE_INIT_INFO ConsoleInitInfo = ExtraConsoleInfo;
|
PCONSOLE_INIT_INFO ConsoleInitInfo = ExtraConsoleInfo;
|
||||||
PGUI_INIT_INFO GuiInitInfo;
|
PGUI_INIT_INFO GuiInitInfo;
|
||||||
|
@ -1082,21 +1260,25 @@ GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||||
if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL)
|
if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
/* Initialize GUI terminal emulator common functionalities */
|
|
||||||
if (!GuiInit()) return STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize a private initialization info structure for later use.
|
* Initialize a private initialization info structure for later use.
|
||||||
* It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
|
* 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;
|
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...
|
// HACK: We suppose that the pointers will be valid in GuiInitFrontEnd...
|
||||||
// If not, then copy exactly what we need in GuiInitInfo.
|
// If not, then copy exactly what we need in GuiInitInfo.
|
||||||
GuiInitInfo->ConsoleInfo = ConsoleInfo;
|
GuiInitInfo->ConsoleInfo = ConsoleInfo;
|
||||||
GuiInitInfo->ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo;
|
GuiInitInfo->ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo;
|
||||||
GuiInitInfo->ProcessId = ProcessId;
|
GuiInitInfo->ProcessId = HandleToUlong(ConsoleLeaderProcess->ClientId.UniqueProcess);
|
||||||
GuiInitInfo->IsWindowVisible = ConsoleInitInfo->IsWindowVisible;
|
GuiInitInfo->IsWindowVisible = ConsoleInitInfo->IsWindowVisible;
|
||||||
|
|
||||||
/* Finally, initialize the frontend structure */
|
/* Finally, initialize the frontend structure */
|
||||||
|
|
|
@ -96,7 +96,7 @@ NTSTATUS NTAPI
|
||||||
TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||||
IN OUT PVOID ExtraConsoleInfo,
|
IN OUT PVOID ExtraConsoleInfo,
|
||||||
IN ULONG ProcessId);
|
IN PCSR_PROCESS ConsoleLeaderProcess);
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
|
TuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
|
||||||
#endif
|
#endif
|
||||||
|
@ -105,7 +105,7 @@ NTSTATUS NTAPI
|
||||||
GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||||
IN OUT PVOID ExtraConsoleInfo,
|
IN OUT PVOID ExtraConsoleInfo,
|
||||||
IN ULONG ProcessId);
|
IN PCSR_PROCESS ConsoleLeaderProcess);
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
|
GuiUnloadFrontEnd(IN OUT PFRONTEND FrontEnd);
|
||||||
/***************/
|
/***************/
|
||||||
|
@ -114,7 +114,7 @@ typedef
|
||||||
NTSTATUS (NTAPI *FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd,
|
NTSTATUS (NTAPI *FRONTEND_LOAD)(IN OUT PFRONTEND FrontEnd,
|
||||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||||
IN OUT PVOID ExtraConsoleInfo,
|
IN OUT PVOID ExtraConsoleInfo,
|
||||||
IN ULONG ProcessId);
|
IN PCSR_PROCESS ConsoleLeaderProcess);
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd);
|
NTSTATUS (NTAPI *FRONTEND_UNLOAD)(IN OUT PFRONTEND FrontEnd);
|
||||||
|
@ -156,7 +156,7 @@ static NTSTATUS
|
||||||
ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||||
IN OUT PVOID ExtraConsoleInfo,
|
IN OUT PVOID ExtraConsoleInfo,
|
||||||
IN ULONG ProcessId)
|
IN PCSR_PROCESS ConsoleLeaderProcess)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
@ -171,7 +171,7 @@ ConSrvLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||||
Status = FrontEndLoadingMethods[i].FrontEndLoad(FrontEnd,
|
Status = FrontEndLoadingMethods[i].FrontEndLoad(FrontEnd,
|
||||||
ConsoleInfo,
|
ConsoleInfo,
|
||||||
ExtraConsoleInfo,
|
ExtraConsoleInfo,
|
||||||
ProcessId);
|
ConsoleLeaderProcess);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Save the unload callback */
|
/* Save the unload callback */
|
||||||
|
@ -206,7 +206,7 @@ NTSTATUS NTAPI
|
||||||
ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
|
ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
|
||||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||||
IN OUT PVOID ExtraConsoleInfo,
|
IN OUT PVOID ExtraConsoleInfo,
|
||||||
IN ULONG ProcessId)
|
IN PCSR_PROCESS ConsoleLeaderProcess)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PFRONTEND FrontEnd;
|
PFRONTEND FrontEnd;
|
||||||
|
@ -218,7 +218,7 @@ ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
|
||||||
Status = ConSrvLoadFrontEnd(FrontEnd,
|
Status = ConSrvLoadFrontEnd(FrontEnd,
|
||||||
ConsoleInfo,
|
ConsoleInfo,
|
||||||
ExtraConsoleInfo,
|
ExtraConsoleInfo,
|
||||||
ProcessId);
|
ConsoleLeaderProcess);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status);
|
DPRINT1("CONSRV: Failed to initialize a frontend, Status = 0x%08lx\n", Status);
|
||||||
|
|
|
@ -942,7 +942,7 @@ NTSTATUS NTAPI
|
||||||
TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
TuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
|
||||||
IN OUT PCONSOLE_INFO ConsoleInfo,
|
IN OUT PCONSOLE_INFO ConsoleInfo,
|
||||||
IN OUT PVOID ExtraConsoleInfo,
|
IN OUT PVOID ExtraConsoleInfo,
|
||||||
IN ULONG ProcessId)
|
IN PCSR_PROCESS ConsoleLeaderProcess)
|
||||||
{
|
{
|
||||||
if (FrontEnd == NULL || ConsoleInfo == NULL)
|
if (FrontEnd == NULL || ConsoleInfo == NULL)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
|
@ -494,10 +494,14 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
||||||
ConSrvFreeHandlesTable(ProcessData);
|
ConSrvFreeHandlesTable(ProcessData);
|
||||||
|
|
||||||
/* Initialize a new Console owned by this process */
|
/* 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,
|
Status = ConSrvInitConsole(&ConsoleHandle,
|
||||||
&Console,
|
&Console,
|
||||||
ConsoleInitInfo,
|
ConsoleInitInfo,
|
||||||
HandleToUlong(ProcessData->Process->ClientId.UniqueProcess));
|
ProcessData->Process);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Console initialization failed\n");
|
DPRINT1("Console initialization failed\n");
|
||||||
|
|
|
@ -414,7 +414,6 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PCONSRV_API_CONNECTINFO ConnectInfo = (PCONSRV_API_CONNECTINFO)ConnectionInfo;
|
PCONSRV_API_CONNECTINFO ConnectInfo = (PCONSRV_API_CONNECTINFO)ConnectionInfo;
|
||||||
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
|
||||||
CONSOLE_INIT_INFO ConsoleInitInfo;
|
|
||||||
|
|
||||||
if ( ConnectionInfo == NULL ||
|
if ( ConnectionInfo == NULL ||
|
||||||
ConnectionInfoLength == NULL ||
|
ConnectionInfoLength == NULL ||
|
||||||
|
@ -433,23 +432,51 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
|
||||||
DPRINT("ConnectInfo->IsConsoleApp = %s\n", ConnectInfo->IsConsoleApp ? "True" : "False");
|
DPRINT("ConnectInfo->IsConsoleApp = %s\n", ConnectInfo->IsConsoleApp ? "True" : "False");
|
||||||
if (!ConnectInfo->IsConsoleApp) return STATUS_SUCCESS;
|
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 we don't inherit from an existing console, then create a new one... */
|
||||||
if (ConnectInfo->ConsoleStartInfo.ConsoleHandle == NULL)
|
if (ConnectInfo->ConsoleStartInfo.ConsoleHandle == NULL)
|
||||||
{
|
{
|
||||||
|
CONSOLE_INIT_INFO ConsoleInitInfo;
|
||||||
|
|
||||||
DPRINT("ConSrvConnect - Allocate a new console\n");
|
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
|
* 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
|
* was called, we didn't know that we wanted to create a new console and
|
||||||
|
@ -467,6 +494,12 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
|
||||||
&ConnectInfo->ConsoleStartInfo.OutputHandle,
|
&ConnectInfo->ConsoleStartInfo.OutputHandle,
|
||||||
&ConnectInfo->ConsoleStartInfo.ErrorHandle,
|
&ConnectInfo->ConsoleStartInfo.ErrorHandle,
|
||||||
&ConsoleInitInfo);
|
&ConsoleInitInfo);
|
||||||
|
|
||||||
|
/* Free our local desktop string if any */
|
||||||
|
if (ConsoleInitInfo.DesktopLength)
|
||||||
|
ConsoleFreeHeap(ConsoleInitInfo.Desktop);
|
||||||
|
|
||||||
|
/* Check for success */
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Console allocation failed\n");
|
DPRINT1("Console allocation failed\n");
|
||||||
|
|
Loading…
Reference in a new issue