2012-10-23 22:31:36 +00:00
|
|
|
/*
|
2012-10-25 20:40:41 +00:00
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS Console Server DLL
|
2015-10-05 12:21:25 +00:00
|
|
|
* FILE: win32ss/user/winsrv/consrv/handle.c
|
2013-01-18 22:31:16 +00:00
|
|
|
* PURPOSE: Console I/O Handles functions
|
2013-04-10 20:22:30 +00:00
|
|
|
* PROGRAMMERS: David Welch
|
|
|
|
* Jeffrey Morlan
|
|
|
|
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
1999-12-26 15:50:53 +00:00
|
|
|
*/
|
|
|
|
|
2013-03-19 22:05:38 +00:00
|
|
|
/* INCLUDES *******************************************************************/
|
1999-12-26 15:50:53 +00:00
|
|
|
|
2012-10-23 22:31:36 +00:00
|
|
|
#include "consrv.h"
|
2014-02-04 19:54:42 +00:00
|
|
|
|
|
|
|
#include <win/console.h>
|
1999-12-26 15:50:53 +00:00
|
|
|
|
2013-03-30 18:44:56 +00:00
|
|
|
#define NDEBUG
|
2003-03-09 21:41:00 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
2013-04-07 23:18:59 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
2014-08-11 13:31:22 +00:00
|
|
|
/* Console handle */
|
2013-04-07 23:18:59 +00:00
|
|
|
typedef struct _CONSOLE_IO_HANDLE
|
|
|
|
{
|
|
|
|
PCONSOLE_IO_OBJECT Object; /* The object on which the handle points to */
|
2014-08-11 13:31:22 +00:00
|
|
|
ULONG Access;
|
|
|
|
ULONG ShareMode;
|
|
|
|
BOOLEAN Inheritable;
|
2013-04-07 23:18:59 +00:00
|
|
|
} CONSOLE_IO_HANDLE, *PCONSOLE_IO_HANDLE;
|
|
|
|
|
|
|
|
|
2013-03-19 22:05:38 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
2005-05-30 20:13:35 +00:00
|
|
|
|
2014-08-11 13:31:22 +00:00
|
|
|
static LONG
|
|
|
|
AdjustHandleCounts(IN PCONSOLE_IO_HANDLE Handle,
|
|
|
|
IN LONG Change)
|
2010-05-23 09:10:02 +00:00
|
|
|
{
|
2014-08-11 13:31:22 +00:00
|
|
|
PCONSOLE_IO_OBJECT Object = Handle->Object;
|
2013-01-02 00:32:20 +00:00
|
|
|
|
2014-08-11 13:31:22 +00:00
|
|
|
DPRINT("AdjustHandleCounts(0x%p, %d), Object = 0x%p\n",
|
|
|
|
Handle, Change, Object);
|
|
|
|
DPRINT("\tAdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->ReferenceCount = %d, Object->Type = %lu\n",
|
|
|
|
Handle, Change, Object, Object->ReferenceCount, Object->Type);
|
2013-01-02 00:32:20 +00:00
|
|
|
|
2014-08-11 13:31:22 +00:00
|
|
|
if (Handle->Access & GENERIC_READ) Object->AccessRead += Change;
|
|
|
|
if (Handle->Access & GENERIC_WRITE) Object->AccessWrite += Change;
|
|
|
|
if (!(Handle->ShareMode & FILE_SHARE_READ)) Object->ExclusiveRead += Change;
|
|
|
|
if (!(Handle->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change;
|
2013-01-02 00:32:20 +00:00
|
|
|
|
2014-08-11 13:31:22 +00:00
|
|
|
Object->ReferenceCount += Change;
|
2013-01-02 00:32:20 +00:00
|
|
|
|
2014-08-11 13:31:22 +00:00
|
|
|
return Object->ReferenceCount;
|
2010-05-23 09:10:02 +00:00
|
|
|
}
|
|
|
|
|
2010-05-23 05:33:21 +00:00
|
|
|
static VOID
|
2014-08-11 13:31:22 +00:00
|
|
|
ConSrvCloseHandle(IN PCONSOLE_IO_HANDLE Handle)
|
1999-12-30 01:51:42 +00:00
|
|
|
{
|
2014-08-11 13:31:22 +00:00
|
|
|
PCONSOLE_IO_OBJECT Object = Handle->Object;
|
2010-05-23 05:33:21 +00:00
|
|
|
if (Object != NULL)
|
2003-12-02 11:38:47 +00:00
|
|
|
{
|
2013-01-24 20:48:42 +00:00
|
|
|
/*
|
|
|
|
* If this is a input handle, notify and dereference
|
|
|
|
* all the waits related to this handle.
|
|
|
|
*/
|
2013-04-07 23:18:59 +00:00
|
|
|
if (Object->Type == INPUT_BUFFER)
|
2013-01-24 20:48:42 +00:00
|
|
|
{
|
2014-05-02 16:46:13 +00:00
|
|
|
// PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
|
|
|
|
PCONSOLE Console = Object->Console;
|
2013-01-24 20:48:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Wake up all the writing waiters related to this handle for this
|
|
|
|
* input buffer, if any, then dereference them and purge them all
|
|
|
|
* from the list.
|
|
|
|
* To select them amongst all the waiters for this input buffer,
|
|
|
|
* pass the handle pointer to the waiters, then they will check
|
|
|
|
* whether or not they are related to this handle and if so, they
|
|
|
|
* return.
|
|
|
|
*/
|
2014-05-02 16:46:13 +00:00
|
|
|
CsrNotifyWait(&Console->ReadWaitQueue,
|
2013-10-05 22:17:34 +00:00
|
|
|
TRUE,
|
2013-01-24 20:48:42 +00:00
|
|
|
NULL,
|
2014-08-11 13:31:22 +00:00
|
|
|
(PVOID)Handle);
|
2014-05-02 16:46:13 +00:00
|
|
|
if (!IsListEmpty(&Console->ReadWaitQueue))
|
2013-01-26 16:12:05 +00:00
|
|
|
{
|
2014-05-02 16:46:13 +00:00
|
|
|
CsrDereferenceWait(&Console->ReadWaitQueue);
|
2013-01-26 16:12:05 +00:00
|
|
|
}
|
2013-01-24 20:48:42 +00:00
|
|
|
}
|
2013-01-02 00:32:20 +00:00
|
|
|
|
|
|
|
/* If the last handle to a screen buffer is closed, delete it... */
|
2014-08-11 13:31:22 +00:00
|
|
|
if (AdjustHandleCounts(Handle, -1) == 0)
|
2003-12-02 11:38:47 +00:00
|
|
|
{
|
2013-05-29 00:29:07 +00:00
|
|
|
if (Object->Type == TEXTMODE_BUFFER || Object->Type == GRAPHICS_BUFFER)
|
2013-01-02 00:32:20 +00:00
|
|
|
{
|
2013-01-05 23:37:04 +00:00
|
|
|
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
|
2013-01-02 00:32:20 +00:00
|
|
|
/* ...unless it's the only buffer left. Windows allows deletion
|
|
|
|
* even of the last buffer, but having to deal with a lack of
|
|
|
|
* any active buffer might be error-prone. */
|
|
|
|
if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
|
2014-09-05 21:08:15 +00:00
|
|
|
ConDrvDeleteScreenBuffer(Buffer);
|
2013-01-02 00:32:20 +00:00
|
|
|
}
|
2013-04-07 23:18:59 +00:00
|
|
|
else if (Object->Type == INPUT_BUFFER)
|
2013-01-02 00:32:20 +00:00
|
|
|
{
|
2013-04-06 13:40:34 +00:00
|
|
|
DPRINT("Closing the input buffer\n");
|
2013-01-02 00:32:20 +00:00
|
|
|
}
|
2013-05-29 00:29:07 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Invalid object type %d\n", Object->Type);
|
|
|
|
}
|
2003-12-02 11:38:47 +00:00
|
|
|
}
|
2013-01-02 00:32:20 +00:00
|
|
|
|
2013-05-12 00:20:15 +00:00
|
|
|
/* Invalidate (zero-out) this handle entry */
|
2014-08-11 13:31:22 +00:00
|
|
|
// Handle->Object = NULL;
|
|
|
|
// RtlZeroMemory(Handle, sizeof(*Handle));
|
2003-12-02 11:38:47 +00:00
|
|
|
}
|
2014-08-11 13:31:22 +00:00
|
|
|
RtlZeroMemory(Handle, sizeof(*Handle)); // Be sure the whole entry is invalidated.
|
2003-12-02 11:38:47 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 21:02:12 +00:00
|
|
|
|
2014-08-11 13:31:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-03-19 22:05:38 +00:00
|
|
|
/* Forward declaration, used in ConSrvInitHandlesTable */
|
|
|
|
static VOID ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData);
|
2012-12-30 21:02:12 +00:00
|
|
|
|
2013-03-19 22:05:38 +00:00
|
|
|
static NTSTATUS
|
2013-01-24 22:41:33 +00:00
|
|
|
ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData,
|
2013-07-06 19:47:53 +00:00
|
|
|
IN PCONSOLE Console,
|
2013-01-24 22:41:33 +00:00
|
|
|
OUT PHANDLE pInputHandle,
|
|
|
|
OUT PHANDLE pOutputHandle,
|
|
|
|
OUT PHANDLE pErrorHandle)
|
2013-01-16 22:25:12 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE InputHandle = INVALID_HANDLE_VALUE,
|
|
|
|
OutputHandle = INVALID_HANDLE_VALUE,
|
|
|
|
ErrorHandle = INVALID_HANDLE_VALUE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize the handles table. Use temporary variables to store
|
|
|
|
* the handles values in such a way that, if we fail, we don't
|
|
|
|
* return to the caller invalid handle values.
|
|
|
|
*
|
|
|
|
* Insert the IO handles.
|
|
|
|
*/
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
|
|
|
|
/* Insert the Input handle */
|
2013-01-24 22:41:33 +00:00
|
|
|
Status = ConSrvInsertObject(ProcessData,
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
&InputHandle,
|
2013-07-06 19:47:53 +00:00
|
|
|
&Console->InputBuffer.Header,
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
|
|
TRUE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
2013-01-16 22:25:12 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to insert the input handle\n");
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2013-01-24 22:41:33 +00:00
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
2013-01-16 22:25:12 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Insert the Output handle */
|
2013-01-24 22:41:33 +00:00
|
|
|
Status = ConSrvInsertObject(ProcessData,
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
&OutputHandle,
|
2013-07-06 19:47:53 +00:00
|
|
|
&Console->ActiveBuffer->Header,
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
|
|
TRUE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
2013-01-16 22:25:12 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to insert the output handle\n");
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2013-01-24 22:41:33 +00:00
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
2013-01-16 22:25:12 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Insert the Error handle */
|
2013-01-24 22:41:33 +00:00
|
|
|
Status = ConSrvInsertObject(ProcessData,
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
&ErrorHandle,
|
2013-07-06 19:47:53 +00:00
|
|
|
&Console->ActiveBuffer->Header,
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
|
|
TRUE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
2013-01-16 22:25:12 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to insert the error handle\n");
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2013-01-24 22:41:33 +00:00
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
2013-01-16 22:25:12 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the newly created handles */
|
|
|
|
*pInputHandle = InputHandle;
|
|
|
|
*pOutputHandle = OutputHandle;
|
|
|
|
*pErrorHandle = ErrorHandle;
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2013-03-30 21:25:27 +00:00
|
|
|
NTSTATUS
|
2013-01-24 22:41:33 +00:00
|
|
|
ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
|
|
|
|
IN PCONSOLE_PROCESS_DATA TargetProcessData)
|
2013-01-13 17:07:25 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2013-05-12 00:20:15 +00:00
|
|
|
ULONG i, j;
|
2013-01-13 17:07:25 +00:00
|
|
|
|
|
|
|
RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
|
|
|
|
|
|
|
|
/* Inherit a handles table only if there is no already */
|
|
|
|
if (TargetProcessData->HandleTable != NULL /* || TargetProcessData->HandleTableSize != 0 */)
|
|
|
|
{
|
2013-05-12 00:20:15 +00:00
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
2013-01-13 17:07:25 +00:00
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate a new handle table for the child process */
|
2013-05-12 00:20:15 +00:00
|
|
|
TargetProcessData->HandleTable = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
|
|
|
|
SourceProcessData->HandleTableSize
|
|
|
|
* sizeof(CONSOLE_IO_HANDLE));
|
2013-01-13 17:07:25 +00:00
|
|
|
if (TargetProcessData->HandleTable == NULL)
|
|
|
|
{
|
|
|
|
Status = STATUS_NO_MEMORY;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the parent process' handles table and, for each handle,
|
|
|
|
* do a copy of it and reference it, if the handle is inheritable.
|
|
|
|
*/
|
2013-05-12 00:20:15 +00:00
|
|
|
for (i = 0, j = 0; i < SourceProcessData->HandleTableSize; i++)
|
2013-01-13 17:07:25 +00:00
|
|
|
{
|
|
|
|
if (SourceProcessData->HandleTable[i].Object != NULL &&
|
|
|
|
SourceProcessData->HandleTable[i].Inheritable)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Copy the handle data and increment the reference count of the
|
2014-08-11 13:31:22 +00:00
|
|
|
* pointed object (via the call to ConSrvCreateHandleEntry == AdjustHandleCounts).
|
2013-01-13 17:07:25 +00:00
|
|
|
*/
|
2013-05-12 00:20:15 +00:00
|
|
|
TargetProcessData->HandleTable[j] = SourceProcessData->HandleTable[i];
|
2014-08-11 13:31:22 +00:00
|
|
|
AdjustHandleCounts(&TargetProcessData->HandleTable[j], +1);
|
2013-05-12 00:20:15 +00:00
|
|
|
++j;
|
2013-01-13 17:07:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2013-03-19 22:05:38 +00:00
|
|
|
static VOID
|
2014-08-11 13:31:22 +00:00
|
|
|
ConSrvFreeHandlesTable(IN PCONSOLE_PROCESS_DATA ProcessData)
|
2013-01-13 17:07:25 +00:00
|
|
|
{
|
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
|
|
|
|
if (ProcessData->HandleTable != NULL)
|
|
|
|
{
|
|
|
|
ULONG i;
|
|
|
|
|
2013-05-12 00:20:15 +00:00
|
|
|
/*
|
2013-07-06 19:47:53 +00:00
|
|
|
* ProcessData->ConsoleHandle is NULL (and the assertion fails) when
|
2013-05-12 00:20:15 +00:00
|
|
|
* ConSrvFreeHandlesTable is called in ConSrvConnect during the
|
|
|
|
* allocation of a new console.
|
|
|
|
*/
|
2013-07-06 19:47:53 +00:00
|
|
|
// ASSERT(ProcessData->ConsoleHandle);
|
|
|
|
if (ProcessData->ConsoleHandle != NULL)
|
2013-01-13 17:07:25 +00:00
|
|
|
{
|
2013-05-12 00:20:15 +00:00
|
|
|
/* Close all the console handles */
|
|
|
|
for (i = 0; i < ProcessData->HandleTableSize; i++)
|
|
|
|
{
|
2014-08-11 13:31:22 +00:00
|
|
|
ConSrvCloseHandle(&ProcessData->HandleTable[i]);
|
2013-05-12 00:20:15 +00:00
|
|
|
}
|
2013-01-13 17:07:25 +00:00
|
|
|
}
|
2013-05-12 00:20:15 +00:00
|
|
|
/* Free the handles table memory */
|
|
|
|
ConsoleFreeHeap(ProcessData->HandleTable);
|
2013-01-13 17:07:25 +00:00
|
|
|
ProcessData->HandleTable = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ProcessData->HandleTableSize = 0;
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
}
|
|
|
|
|
2014-08-11 13:31:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ConSrvCreateObject
|
2013-05-12 00:20:15 +00:00
|
|
|
VOID
|
|
|
|
ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object,
|
|
|
|
IN CONSOLE_IO_OBJECT_TYPE Type,
|
|
|
|
IN PCONSOLE Console)
|
|
|
|
{
|
|
|
|
ASSERT(Object);
|
|
|
|
// if (!Object) return;
|
|
|
|
|
|
|
|
Object->Type = Type;
|
|
|
|
Object->Console = Console;
|
2014-08-11 13:31:22 +00:00
|
|
|
Object->ReferenceCount = 0;
|
|
|
|
|
2013-05-12 00:20:15 +00:00
|
|
|
Object->AccessRead = Object->AccessWrite = 0;
|
|
|
|
Object->ExclusiveRead = Object->ExclusiveWrite = 0;
|
|
|
|
}
|
|
|
|
|
2012-12-30 21:02:12 +00:00
|
|
|
NTSTATUS
|
2014-08-11 13:31:22 +00:00
|
|
|
ConSrvInsertObject(IN PCONSOLE_PROCESS_DATA ProcessData,
|
|
|
|
OUT PHANDLE Handle,
|
|
|
|
IN PCONSOLE_IO_OBJECT Object,
|
|
|
|
IN ULONG Access,
|
|
|
|
IN BOOLEAN Inheritable,
|
|
|
|
IN ULONG ShareMode)
|
2012-12-30 21:02:12 +00:00
|
|
|
{
|
2013-03-30 18:44:56 +00:00
|
|
|
#define IO_HANDLES_INCREMENT 2 * 3
|
2013-01-18 22:31:16 +00:00
|
|
|
|
2013-05-12 00:20:15 +00:00
|
|
|
ULONG i = 0;
|
2013-01-05 23:37:04 +00:00
|
|
|
PCONSOLE_IO_HANDLE Block;
|
2012-12-30 21:02:12 +00:00
|
|
|
|
2013-03-30 18:44:56 +00:00
|
|
|
// NOTE: Commented out because calling code always lock HandleTableLock before.
|
|
|
|
// RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
2012-12-30 21:02:12 +00:00
|
|
|
|
2013-05-12 00:20:15 +00:00
|
|
|
ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
|
|
|
|
(ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
|
|
|
|
|
|
|
|
if (ProcessData->HandleTable)
|
2012-12-30 21:02:12 +00:00
|
|
|
{
|
2013-05-12 00:20:15 +00:00
|
|
|
for (i = 0; i < ProcessData->HandleTableSize; i++)
|
2012-12-30 21:02:12 +00:00
|
|
|
{
|
2013-05-12 00:20:15 +00:00
|
|
|
if (ProcessData->HandleTable[i].Object == NULL)
|
|
|
|
break;
|
2012-12-30 21:02:12 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-12 00:20:15 +00:00
|
|
|
|
2012-12-30 21:02:12 +00:00
|
|
|
if (i >= ProcessData->HandleTableSize)
|
|
|
|
{
|
2013-05-12 00:20:15 +00:00
|
|
|
/* Allocate a new handles table */
|
|
|
|
Block = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
|
|
|
|
(ProcessData->HandleTableSize +
|
2013-01-18 22:31:16 +00:00
|
|
|
IO_HANDLES_INCREMENT) * sizeof(CONSOLE_IO_HANDLE));
|
2012-12-30 21:02:12 +00:00
|
|
|
if (Block == NULL)
|
|
|
|
{
|
2013-03-30 18:44:56 +00:00
|
|
|
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2013-01-02 00:32:20 +00:00
|
|
|
return STATUS_UNSUCCESSFUL;
|
2012-12-30 21:02:12 +00:00
|
|
|
}
|
2013-05-12 00:20:15 +00:00
|
|
|
|
|
|
|
/* If we previously had a handles table, free it and use the new one */
|
|
|
|
if (ProcessData->HandleTable)
|
|
|
|
{
|
|
|
|
/* Copy the handles from the old table to the new one */
|
|
|
|
RtlCopyMemory(Block,
|
|
|
|
ProcessData->HandleTable,
|
|
|
|
ProcessData->HandleTableSize * sizeof(CONSOLE_IO_HANDLE));
|
|
|
|
ConsoleFreeHeap(ProcessData->HandleTable);
|
|
|
|
}
|
2012-12-30 21:02:12 +00:00
|
|
|
ProcessData->HandleTable = Block;
|
2013-01-18 22:31:16 +00:00
|
|
|
ProcessData->HandleTableSize += IO_HANDLES_INCREMENT;
|
2012-12-30 21:02:12 +00:00
|
|
|
}
|
2013-01-18 22:31:16 +00:00
|
|
|
|
2012-12-30 21:02:12 +00:00
|
|
|
ProcessData->HandleTable[i].Object = Object;
|
|
|
|
ProcessData->HandleTable[i].Access = Access;
|
|
|
|
ProcessData->HandleTable[i].Inheritable = Inheritable;
|
|
|
|
ProcessData->HandleTable[i].ShareMode = ShareMode;
|
2014-08-11 13:31:22 +00:00
|
|
|
AdjustHandleCounts(&ProcessData->HandleTable[i], +1);
|
2013-01-13 17:07:25 +00:00
|
|
|
*Handle = ULongToHandle((i << 2) | 0x3);
|
|
|
|
|
2013-03-30 18:44:56 +00:00
|
|
|
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2013-01-18 22:31:16 +00:00
|
|
|
|
2012-12-30 21:02:12 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2009-02-18 03:07:20 +00:00
|
|
|
NTSTATUS
|
2014-08-11 13:31:22 +00:00
|
|
|
ConSrvRemoveObject(IN PCONSOLE_PROCESS_DATA ProcessData,
|
|
|
|
IN HANDLE Handle)
|
2003-12-02 11:38:47 +00:00
|
|
|
{
|
2013-07-06 19:47:53 +00:00
|
|
|
ULONG Index = HandleToULong(Handle) >> 2;
|
2003-12-02 11:38:47 +00:00
|
|
|
|
2009-02-18 03:07:20 +00:00
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
2012-12-30 21:02:12 +00:00
|
|
|
|
2013-05-12 00:20:15 +00:00
|
|
|
ASSERT(ProcessData->HandleTable);
|
2013-08-06 19:10:36 +00:00
|
|
|
// ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
|
|
|
|
// (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
|
2013-05-12 00:20:15 +00:00
|
|
|
|
2013-07-06 19:47:53 +00:00
|
|
|
if (Index >= ProcessData->HandleTableSize ||
|
2014-04-20 14:39:38 +00:00
|
|
|
ProcessData->HandleTable[Index].Object == NULL)
|
2003-12-02 11:38:47 +00:00
|
|
|
{
|
2009-02-18 03:07:20 +00:00
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
return STATUS_INVALID_HANDLE;
|
2003-12-02 11:38:47 +00:00
|
|
|
}
|
2013-01-03 17:47:34 +00:00
|
|
|
|
2013-07-06 19:47:53 +00:00
|
|
|
ASSERT(ProcessData->ConsoleHandle);
|
2014-08-11 13:31:22 +00:00
|
|
|
ConSrvCloseHandle(&ProcessData->HandleTable[Index]);
|
2012-12-30 21:02:12 +00:00
|
|
|
|
2009-02-18 03:07:20 +00:00
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2010-05-23 05:33:21 +00:00
|
|
|
return STATUS_SUCCESS;
|
2010-05-23 00:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2014-08-11 13:31:22 +00:00
|
|
|
ConSrvGetObject(IN PCONSOLE_PROCESS_DATA ProcessData,
|
|
|
|
IN HANDLE Handle,
|
|
|
|
OUT PCONSOLE_IO_OBJECT* Object,
|
|
|
|
OUT PVOID* Entry OPTIONAL,
|
|
|
|
IN ULONG Access,
|
|
|
|
IN BOOLEAN LockConsole,
|
|
|
|
IN CONSOLE_IO_OBJECT_TYPE Type)
|
2010-05-23 00:51:29 +00:00
|
|
|
{
|
2013-07-06 19:47:53 +00:00
|
|
|
// NTSTATUS Status;
|
|
|
|
ULONG Index = HandleToULong(Handle) >> 2;
|
2013-01-24 20:48:42 +00:00
|
|
|
PCONSOLE_IO_HANDLE HandleEntry = NULL;
|
2013-04-07 23:18:59 +00:00
|
|
|
PCONSOLE_IO_OBJECT ObjectEntry = NULL;
|
2013-07-06 19:47:53 +00:00
|
|
|
// PCONSOLE ObjectConsole;
|
2013-01-24 20:48:42 +00:00
|
|
|
|
|
|
|
ASSERT(Object);
|
|
|
|
if (Entry) *Entry = NULL;
|
2010-05-23 00:51:29 +00:00
|
|
|
|
2013-06-30 19:21:42 +00:00
|
|
|
DPRINT("ConSrvGetObject -- Object: 0x%x, Handle: 0x%x\n", Object, Handle);
|
2010-05-23 00:51:29 +00:00
|
|
|
|
2010-05-23 05:33:21 +00:00
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
2012-12-30 21:02:12 +00:00
|
|
|
|
2013-01-24 20:48:42 +00:00
|
|
|
if ( IsConsoleHandle(Handle) &&
|
2013-07-06 19:47:53 +00:00
|
|
|
Index < ProcessData->HandleTableSize )
|
2013-01-24 20:48:42 +00:00
|
|
|
{
|
2013-07-06 19:47:53 +00:00
|
|
|
HandleEntry = &ProcessData->HandleTable[Index];
|
2013-01-24 20:48:42 +00:00
|
|
|
ObjectEntry = HandleEntry->Object;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( HandleEntry == NULL ||
|
|
|
|
ObjectEntry == NULL ||
|
|
|
|
(HandleEntry->Access & Access) == 0 ||
|
2013-05-29 00:29:07 +00:00
|
|
|
/*(Type != 0 && ObjectEntry->Type != Type)*/
|
|
|
|
(Type != 0 && (ObjectEntry->Type & Type) == 0) )
|
2010-05-23 00:51:29 +00:00
|
|
|
{
|
2014-02-08 22:30:45 +00:00
|
|
|
DPRINT("ConSrvGetObject -- Invalid handle 0x%x of type %lu with access %lu ; retrieved object 0x%x (handle 0x%x) of type %lu with access %lu\n",
|
|
|
|
Handle, Type, Access, ObjectEntry, HandleEntry, (ObjectEntry ? ObjectEntry->Type : 0), (HandleEntry ? HandleEntry->Access : 0));
|
2013-06-30 19:21:42 +00:00
|
|
|
|
2010-05-23 05:33:21 +00:00
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2010-05-23 00:51:29 +00:00
|
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
}
|
2012-12-30 21:02:12 +00:00
|
|
|
|
2010-05-23 05:33:21 +00:00
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2010-05-23 00:51:29 +00:00
|
|
|
|
2014-05-04 00:01:48 +00:00
|
|
|
// Status = ConSrvGetConsole(ProcessData, &ObjectConsole, LockConsole);
|
2013-07-06 19:47:53 +00:00
|
|
|
// if (NT_SUCCESS(Status))
|
|
|
|
if (ConDrvValidateConsoleUnsafe(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole))
|
2013-03-30 18:44:56 +00:00
|
|
|
{
|
|
|
|
_InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
|
2013-01-24 20:48:42 +00:00
|
|
|
|
2013-03-30 18:44:56 +00:00
|
|
|
/* Return the objects to the caller */
|
|
|
|
*Object = ObjectEntry;
|
|
|
|
if (Entry) *Entry = HandleEntry;
|
2013-01-22 23:28:51 +00:00
|
|
|
|
2013-03-30 18:44:56 +00:00
|
|
|
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
}
|
2010-05-23 00:51:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
2014-08-11 13:31:22 +00:00
|
|
|
ConSrvReleaseObject(IN PCONSOLE_IO_OBJECT Object,
|
|
|
|
IN BOOLEAN IsConsoleLocked)
|
2010-05-23 00:51:29 +00:00
|
|
|
{
|
2013-01-24 22:41:33 +00:00
|
|
|
ConSrvReleaseConsole(Object->Console, IsConsoleLocked);
|
1999-12-30 01:51:42 +00:00
|
|
|
}
|
|
|
|
|
2014-08-11 13:31:22 +00:00
|
|
|
|
|
|
|
|
2013-01-16 22:25:12 +00:00
|
|
|
NTSTATUS
|
2013-01-24 22:41:33 +00:00
|
|
|
ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
|
|
|
PHANDLE pInputHandle,
|
|
|
|
PHANDLE pOutputHandle,
|
|
|
|
PHANDLE pErrorHandle,
|
2014-09-07 22:53:49 +00:00
|
|
|
PCONSOLE_INIT_INFO ConsoleInitInfo)
|
2013-01-16 22:25:12 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2013-07-06 19:47:53 +00:00
|
|
|
HANDLE ConsoleHandle;
|
2014-08-12 14:59:13 +00:00
|
|
|
PCONSRV_CONSOLE Console;
|
2013-01-16 22:25:12 +00:00
|
|
|
|
2013-05-12 00:20:15 +00:00
|
|
|
/*
|
|
|
|
* We are about to create a new console. However when ConSrvNewProcess
|
|
|
|
* was called, we didn't know that we wanted to create a new console and
|
|
|
|
* therefore, we by default inherited the handles table from our parent
|
|
|
|
* process. It's only now that we notice that in fact we do not need
|
|
|
|
* them, because we've created a new console and thus we must use it.
|
|
|
|
*
|
|
|
|
* Therefore, free the handles table so that we can recreate
|
|
|
|
* a new one later on.
|
|
|
|
*/
|
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
|
|
|
|
2013-02-10 12:36:57 +00:00
|
|
|
/* Initialize a new Console owned by this process */
|
2015-03-11 01:21:29 +00:00
|
|
|
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");
|
2013-07-06 19:47:53 +00:00
|
|
|
Status = ConSrvInitConsole(&ConsoleHandle,
|
|
|
|
&Console,
|
2014-09-07 22:53:49 +00:00
|
|
|
ConsoleInitInfo,
|
2015-03-11 01:21:29 +00:00
|
|
|
ProcessData->Process);
|
2013-01-16 22:25:12 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Console initialization failed\n");
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2013-07-06 19:47:53 +00:00
|
|
|
/* Assign the new console handle */
|
|
|
|
ProcessData->ConsoleHandle = ConsoleHandle;
|
|
|
|
|
2013-01-16 22:25:12 +00:00
|
|
|
/* Initialize the handles table */
|
2013-01-24 22:41:33 +00:00
|
|
|
Status = ConSrvInitHandlesTable(ProcessData,
|
2013-07-06 19:47:53 +00:00
|
|
|
Console,
|
2013-02-01 23:36:23 +00:00
|
|
|
pInputHandle,
|
|
|
|
pOutputHandle,
|
|
|
|
pErrorHandle);
|
2013-01-16 22:25:12 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to initialize the handles table\n");
|
2013-07-06 19:47:53 +00:00
|
|
|
ConSrvDeleteConsole(Console);
|
|
|
|
ProcessData->ConsoleHandle = NULL;
|
2013-02-01 23:36:23 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2013-01-16 22:25:12 +00:00
|
|
|
|
2014-11-22 22:13:08 +00:00
|
|
|
/* Duplicate the Initialization Events */
|
|
|
|
Status = NtDuplicateObject(NtCurrentProcess(),
|
|
|
|
Console->InitEvents[INIT_SUCCESS],
|
|
|
|
ProcessData->Process->ProcessHandle,
|
|
|
|
&ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS],
|
|
|
|
EVENT_ALL_ACCESS, 0, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtDuplicateObject(InitEvents[INIT_SUCCESS]) failed: %lu\n", Status);
|
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
|
|
|
ConSrvDeleteConsole(Console);
|
|
|
|
ProcessData->ConsoleHandle = NULL;
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = NtDuplicateObject(NtCurrentProcess(),
|
|
|
|
Console->InitEvents[INIT_FAILURE],
|
|
|
|
ProcessData->Process->ProcessHandle,
|
|
|
|
&ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_FAILURE],
|
|
|
|
EVENT_ALL_ACCESS, 0, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtDuplicateObject(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
|
2015-11-14 16:20:00 +00:00
|
|
|
NtDuplicateObject(ProcessData->Process->ProcessHandle,
|
|
|
|
ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS],
|
|
|
|
NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
|
2014-11-22 22:13:08 +00:00
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
|
|
|
ConSrvDeleteConsole(Console);
|
|
|
|
ProcessData->ConsoleHandle = NULL;
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2013-02-01 23:36:23 +00:00
|
|
|
/* Duplicate the Input Event */
|
|
|
|
Status = NtDuplicateObject(NtCurrentProcess(),
|
2013-07-06 19:47:53 +00:00
|
|
|
Console->InputBuffer.ActiveEvent,
|
2013-02-01 23:36:23 +00:00
|
|
|
ProcessData->Process->ProcessHandle,
|
2014-11-23 14:26:37 +00:00
|
|
|
&ConsoleInitInfo->ConsoleStartInfo->InputWaitHandle,
|
2013-02-01 23:36:23 +00:00
|
|
|
EVENT_ALL_ACCESS, 0, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-11-22 22:13:08 +00:00
|
|
|
DPRINT1("NtDuplicateObject(InputWaitHandle) failed: %lu\n", Status);
|
2015-11-14 16:20:00 +00:00
|
|
|
NtDuplicateObject(ProcessData->Process->ProcessHandle,
|
|
|
|
ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_FAILURE],
|
|
|
|
NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
|
|
|
|
NtDuplicateObject(ProcessData->Process->ProcessHandle,
|
|
|
|
ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS],
|
|
|
|
NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
|
2013-02-01 23:36:23 +00:00
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
2013-07-06 19:47:53 +00:00
|
|
|
ConSrvDeleteConsole(Console);
|
|
|
|
ProcessData->ConsoleHandle = NULL;
|
2013-02-01 23:36:23 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
/* Mark the process as having a console */
|
|
|
|
ProcessData->ConsoleApp = TRUE;
|
|
|
|
ProcessData->Process->Flags |= CsrProcessIsConsoleApp;
|
|
|
|
|
|
|
|
/* Return the console handle to the caller */
|
|
|
|
ConsoleInitInfo->ConsoleStartInfo->ConsoleHandle = ProcessData->ConsoleHandle;
|
|
|
|
|
2015-08-15 17:05:13 +00:00
|
|
|
/*
|
|
|
|
* Insert the process into the processes list of the console,
|
|
|
|
* and set its foreground priority.
|
|
|
|
*/
|
2013-07-06 19:47:53 +00:00
|
|
|
InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
|
2015-08-15 17:05:13 +00:00
|
|
|
ConSrvSetProcessFocus(ProcessData->Process, Console->HasFocus);
|
2013-02-01 23:36:23 +00:00
|
|
|
|
|
|
|
/* Add a reference count because the process is tied to the console */
|
2013-07-06 19:47:53 +00:00
|
|
|
_InterlockedIncrement(&Console->ReferenceCount);
|
2013-01-16 22:25:12 +00:00
|
|
|
|
2013-03-20 00:41:47 +00:00
|
|
|
/* Update the internal info of the terminal */
|
2013-10-10 01:16:02 +00:00
|
|
|
TermRefreshInternalInfo(Console);
|
2013-03-20 00:41:47 +00:00
|
|
|
|
2013-02-01 23:36:23 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
|
2013-07-06 19:47:53 +00:00
|
|
|
HANDLE ConsoleHandle,
|
2014-08-11 13:31:22 +00:00
|
|
|
BOOLEAN CreateNewHandlesTable,
|
2013-02-01 23:36:23 +00:00
|
|
|
PHANDLE pInputHandle,
|
|
|
|
PHANDLE pOutputHandle,
|
2014-11-22 22:13:08 +00:00
|
|
|
PHANDLE pErrorHandle,
|
|
|
|
PCONSOLE_START_INFO ConsoleStartInfo)
|
2013-02-01 23:36:23 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2013-07-06 19:47:53 +00:00
|
|
|
PCONSOLE Console;
|
2013-02-01 23:36:23 +00:00
|
|
|
|
2013-03-30 18:44:56 +00:00
|
|
|
/* Validate and lock the console */
|
2014-05-04 00:01:48 +00:00
|
|
|
if (!ConSrvValidateConsole(&Console,
|
2013-07-06 19:47:53 +00:00
|
|
|
ConsoleHandle,
|
|
|
|
CONSOLE_RUNNING, TRUE))
|
2013-03-30 18:44:56 +00:00
|
|
|
{
|
|
|
|
// FIXME: Find another status code
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
|
2013-02-01 23:36:23 +00:00
|
|
|
/* Inherit the console */
|
2013-07-06 19:47:53 +00:00
|
|
|
ProcessData->ConsoleHandle = ConsoleHandle;
|
2013-02-01 23:36:23 +00:00
|
|
|
|
|
|
|
if (CreateNewHandlesTable)
|
|
|
|
{
|
2013-05-12 00:20:15 +00:00
|
|
|
/*
|
|
|
|
* We are about to create a new console. However when ConSrvNewProcess
|
|
|
|
* was called, we didn't know that we wanted to create a new console and
|
|
|
|
* therefore, we by default inherited the handles table from our parent
|
|
|
|
* process. It's only now that we notice that in fact we do not need
|
|
|
|
* them, because we've created a new console and thus we must use it.
|
|
|
|
*
|
|
|
|
* Therefore, free the handles table so that we can recreate
|
|
|
|
* a new one later on.
|
|
|
|
*/
|
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
|
|
|
|
2013-02-01 23:36:23 +00:00
|
|
|
/* Initialize the handles table */
|
|
|
|
Status = ConSrvInitHandlesTable(ProcessData,
|
2013-07-06 19:47:53 +00:00
|
|
|
Console,
|
2013-02-01 23:36:23 +00:00
|
|
|
pInputHandle,
|
|
|
|
pOutputHandle,
|
|
|
|
pErrorHandle);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to initialize the handles table\n");
|
2013-07-06 19:47:53 +00:00
|
|
|
ProcessData->ConsoleHandle = NULL;
|
2013-03-30 18:44:56 +00:00
|
|
|
goto Quit;
|
2013-02-01 23:36:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-22 22:13:08 +00:00
|
|
|
/* Duplicate the Initialization Events */
|
|
|
|
Status = NtDuplicateObject(NtCurrentProcess(),
|
|
|
|
Console->InitEvents[INIT_SUCCESS],
|
|
|
|
ProcessData->Process->ProcessHandle,
|
|
|
|
&ConsoleStartInfo->InitEvents[INIT_SUCCESS],
|
|
|
|
EVENT_ALL_ACCESS, 0, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtDuplicateObject(InitEvents[INIT_SUCCESS]) failed: %lu\n", Status);
|
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
|
|
|
ProcessData->ConsoleHandle = NULL;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = NtDuplicateObject(NtCurrentProcess(),
|
|
|
|
Console->InitEvents[INIT_FAILURE],
|
|
|
|
ProcessData->Process->ProcessHandle,
|
|
|
|
&ConsoleStartInfo->InitEvents[INIT_FAILURE],
|
|
|
|
EVENT_ALL_ACCESS, 0, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("NtDuplicateObject(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
|
2015-11-14 16:20:00 +00:00
|
|
|
NtDuplicateObject(ProcessData->Process->ProcessHandle,
|
|
|
|
ConsoleStartInfo->InitEvents[INIT_SUCCESS],
|
|
|
|
NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
|
2014-11-22 22:13:08 +00:00
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
|
|
|
ProcessData->ConsoleHandle = NULL;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
2013-02-01 23:36:23 +00:00
|
|
|
/* Duplicate the Input Event */
|
|
|
|
Status = NtDuplicateObject(NtCurrentProcess(),
|
2013-07-06 19:47:53 +00:00
|
|
|
Console->InputBuffer.ActiveEvent,
|
2013-02-01 23:36:23 +00:00
|
|
|
ProcessData->Process->ProcessHandle,
|
2014-11-23 14:26:37 +00:00
|
|
|
&ConsoleStartInfo->InputWaitHandle,
|
2013-02-01 23:36:23 +00:00
|
|
|
EVENT_ALL_ACCESS, 0, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-11-22 22:13:08 +00:00
|
|
|
DPRINT1("NtDuplicateObject(InputWaitHandle) failed: %lu\n", Status);
|
2015-11-14 16:20:00 +00:00
|
|
|
NtDuplicateObject(ProcessData->Process->ProcessHandle,
|
|
|
|
ConsoleStartInfo->InitEvents[INIT_FAILURE],
|
|
|
|
NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
|
|
|
|
NtDuplicateObject(ProcessData->Process->ProcessHandle,
|
|
|
|
ConsoleStartInfo->InitEvents[INIT_SUCCESS],
|
|
|
|
NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
|
2013-02-01 23:36:23 +00:00
|
|
|
ConSrvFreeHandlesTable(ProcessData); // NOTE: Always free the handles table.
|
2013-07-06 19:47:53 +00:00
|
|
|
ProcessData->ConsoleHandle = NULL;
|
2013-03-30 18:44:56 +00:00
|
|
|
goto Quit;
|
2013-01-16 22:25:12 +00:00
|
|
|
}
|
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
/* Mark the process as having a console */
|
|
|
|
ProcessData->ConsoleApp = TRUE;
|
|
|
|
ProcessData->Process->Flags |= CsrProcessIsConsoleApp;
|
|
|
|
|
|
|
|
/* Return the console handle to the caller */
|
|
|
|
ConsoleStartInfo->ConsoleHandle = ProcessData->ConsoleHandle;
|
|
|
|
|
2015-08-15 17:05:13 +00:00
|
|
|
/*
|
|
|
|
* Insert the process into the processes list of the console,
|
|
|
|
* and set its foreground priority.
|
|
|
|
*/
|
2013-07-06 19:47:53 +00:00
|
|
|
InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
|
2015-08-15 17:05:13 +00:00
|
|
|
ConSrvSetProcessFocus(ProcessData->Process, Console->HasFocus);
|
2013-02-01 23:36:23 +00:00
|
|
|
|
|
|
|
/* Add a reference count because the process is tied to the console */
|
2013-07-06 19:47:53 +00:00
|
|
|
_InterlockedIncrement(&Console->ReferenceCount);
|
2013-02-01 23:36:23 +00:00
|
|
|
|
2013-03-20 00:41:47 +00:00
|
|
|
/* Update the internal info of the terminal */
|
2013-10-10 01:16:02 +00:00
|
|
|
TermRefreshInternalInfo(Console);
|
2013-03-20 00:41:47 +00:00
|
|
|
|
2013-03-30 18:44:56 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
/* Unlock the console and return */
|
|
|
|
LeaveCriticalSection(&Console->Lock);
|
|
|
|
return Status;
|
2013-01-16 22:25:12 +00:00
|
|
|
}
|
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
NTSTATUS
|
2013-01-24 22:41:33 +00:00
|
|
|
ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
|
2013-01-13 17:07:25 +00:00
|
|
|
{
|
2013-07-06 19:47:53 +00:00
|
|
|
PCONSOLE Console;
|
2014-11-23 14:26:37 +00:00
|
|
|
PCONSOLE_PROCESS_DATA ConsoleLeaderProcess;
|
2013-01-13 17:07:25 +00:00
|
|
|
|
2013-04-06 13:40:34 +00:00
|
|
|
DPRINT("ConSrvRemoveConsole\n");
|
2013-01-13 17:07:25 +00:00
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
/* Mark the process as not having a console anymore */
|
|
|
|
ProcessData->ConsoleApp = FALSE;
|
|
|
|
ProcessData->Process->Flags &= ~CsrProcessIsConsoleApp;
|
2013-01-13 17:07:25 +00:00
|
|
|
|
2013-03-30 18:44:56 +00:00
|
|
|
/* Validate and lock the console */
|
2014-11-23 14:26:37 +00:00
|
|
|
if (!ConSrvValidateConsole(&Console,
|
|
|
|
ProcessData->ConsoleHandle,
|
|
|
|
CONSOLE_RUNNING, TRUE))
|
2013-01-13 17:07:25 +00:00
|
|
|
{
|
2014-11-23 14:26:37 +00:00
|
|
|
// FIXME: Find another status code
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2014-04-22 00:46:49 +00:00
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
DPRINT("ConSrvRemoveConsole - Locking OK\n");
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
/* Retrieve the console leader process */
|
|
|
|
ConsoleLeaderProcess = ConSrvGetConsoleLeaderProcess(Console);
|
2013-03-30 18:44:56 +00:00
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
/* Close all console handles and free the handles table */
|
|
|
|
ConSrvFreeHandlesTable(ProcessData);
|
|
|
|
|
|
|
|
/* Detach the process from the console */
|
|
|
|
ProcessData->ConsoleHandle = NULL;
|
2013-03-30 18:44:56 +00:00
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
/* Remove the process from the console's list of processes */
|
|
|
|
RemoveEntryList(&ProcessData->ConsoleLink);
|
[CONSOLE.DLL-KERNEL32-CONSRV]
Fix the console properties dialog, when launching and transmitting console properties. Before, the properties dialog was directly launched by the console server (consrv), running with CSRSS (System) privileges, what constituted a security hole. Now, I create a remote thread in the running process owning the console for launching the properties dialog (thus it has only user privileges, and not System ones anymore). For that purpose, I basically took the technique described in the following paper (Cesar Cerrudo, "Story of a dumb patch", http://www.argeniss.com/research/MSBugPaper.pdf or http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf), where basically the console server shares the console properties via a shared memory section with the console properties dialog dll. The address of the thread which launches the dialog in the context of the console app is given to the console server the same way as we do for the control handler (called e.g. when you press Ctrl-C, etc...)
Of course this is quite hackish, because you have the GUI interface split between the console server and the console properties dialog dll. Something far more elegant would be to put all the GUI thingie into a dedicated dll or exe, running with the same privileges as the console program itself (a kind of console -- or terminal -- emulator).
[CONSOLE.DLL]
Fix retriving / setting colors.c and other things.
[CONSRV.DLL]
- Fix retrieving / setting console properties from the registry (via the HKCU\Console\* keys), via the shell shortcuts (not totally done at the moment, because somebody has to implement properly that thing : http://msdn.microsoft.com/en-us/library/windows/desktop/bb773359(v=vs.85).aspx (NT_CONSOLE_PROPS structure stored as a shortcut data block) (at application launching time), and via the console properties dialog.
- Few DPRINTs removed.
svn path=/branches/ros-csrss/; revision=58415
2013-03-03 15:35:12 +00:00
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
/* Check whether the console should send a last close notification */
|
|
|
|
if (Console->NotifyLastClose)
|
|
|
|
{
|
|
|
|
/* If we are removing the process which wants the last close notification... */
|
|
|
|
if (ProcessData == Console->NotifiedLastCloseProcess)
|
|
|
|
{
|
|
|
|
/* ... just reset the flag and the pointer... */
|
|
|
|
Console->NotifyLastClose = FALSE;
|
|
|
|
Console->NotifiedLastCloseProcess = NULL;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* ... otherwise, if we are removing the console leader process
|
|
|
|
* (that cannot be the process wanting the notification, because
|
|
|
|
* the previous case already dealt with it)...
|
|
|
|
*/
|
|
|
|
else if (ProcessData == ConsoleLeaderProcess)
|
2014-04-21 01:22:17 +00:00
|
|
|
{
|
2014-04-22 00:46:49 +00:00
|
|
|
/*
|
2014-11-23 14:26:37 +00:00
|
|
|
* ... reset the flag first (so that we avoid multiple notifications)
|
|
|
|
* and then send the last close notification.
|
2014-04-22 00:46:49 +00:00
|
|
|
*/
|
2014-11-23 14:26:37 +00:00
|
|
|
Console->NotifyLastClose = FALSE;
|
|
|
|
ConSrvConsoleCtrlEvent(CTRL_LAST_CLOSE_EVENT, Console->NotifiedLastCloseProcess);
|
|
|
|
|
|
|
|
/* Only now, reset the pointer */
|
|
|
|
Console->NotifiedLastCloseProcess = NULL;
|
2014-04-21 01:22:17 +00:00
|
|
|
}
|
2014-11-23 14:26:37 +00:00
|
|
|
}
|
2014-04-21 01:22:17 +00:00
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
/* Update the internal info of the terminal */
|
|
|
|
TermRefreshInternalInfo(Console);
|
2014-04-22 00:46:49 +00:00
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
/* Release the console */
|
|
|
|
DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount);
|
|
|
|
ConSrvReleaseConsole(Console, TRUE);
|
2013-03-30 18:44:56 +00:00
|
|
|
|
2014-11-23 14:26:37 +00:00
|
|
|
return STATUS_SUCCESS;
|
2013-03-30 18:44:56 +00:00
|
|
|
}
|
|
|
|
|
2013-04-07 23:18:59 +00:00
|
|
|
|
|
|
|
/* PUBLIC SERVER APIS *********************************************************/
|
|
|
|
|
|
|
|
CSR_API(SrvOpenConsole)
|
2013-01-18 22:31:16 +00:00
|
|
|
{
|
2013-04-07 23:18:59 +00:00
|
|
|
/*
|
|
|
|
* This API opens a handle to either the input buffer or to
|
|
|
|
* a screen-buffer of the console of the current process.
|
|
|
|
*/
|
|
|
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
PCONSOLE_OPENCONSOLE OpenConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.OpenConsoleRequest;
|
|
|
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
|
|
|
PCONSOLE Console;
|
|
|
|
|
2014-04-20 11:25:38 +00:00
|
|
|
DWORD DesiredAccess = OpenConsoleRequest->DesiredAccess;
|
2013-04-07 23:18:59 +00:00
|
|
|
DWORD ShareMode = OpenConsoleRequest->ShareMode;
|
|
|
|
PCONSOLE_IO_OBJECT Object;
|
|
|
|
|
2014-04-20 11:25:38 +00:00
|
|
|
OpenConsoleRequest->Handle = INVALID_HANDLE_VALUE;
|
2013-04-07 23:18:59 +00:00
|
|
|
|
|
|
|
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-03-27 10:10:42 +00:00
|
|
|
DPRINT1("Can't get console, status %lx\n", Status);
|
2013-04-07 23:18:59 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2013-01-18 22:31:16 +00:00
|
|
|
|
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
|
2013-04-07 23:18:59 +00:00
|
|
|
/*
|
|
|
|
* Open a handle to either the active screen buffer or the input buffer.
|
|
|
|
*/
|
|
|
|
if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT)
|
|
|
|
{
|
|
|
|
Object = &Console->ActiveBuffer->Header;
|
|
|
|
}
|
|
|
|
else // HANDLE_INPUT
|
2013-03-30 18:44:56 +00:00
|
|
|
{
|
2013-04-07 23:18:59 +00:00
|
|
|
Object = &Console->InputBuffer.Header;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((DesiredAccess & GENERIC_READ) && Object->ExclusiveRead != 0) ||
|
|
|
|
((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
|
|
|
|
(!(ShareMode & FILE_SHARE_READ) && Object->AccessRead != 0) ||
|
|
|
|
(!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite != 0))
|
|
|
|
{
|
|
|
|
DPRINT1("Sharing violation\n");
|
|
|
|
Status = STATUS_SHARING_VIOLATION;
|
2013-03-30 18:44:56 +00:00
|
|
|
}
|
|
|
|
else
|
2013-01-18 22:31:16 +00:00
|
|
|
{
|
2013-04-07 23:18:59 +00:00
|
|
|
Status = ConSrvInsertObject(ProcessData,
|
2014-04-20 11:25:38 +00:00
|
|
|
&OpenConsoleRequest->Handle,
|
2013-04-07 23:18:59 +00:00
|
|
|
Object,
|
|
|
|
DesiredAccess,
|
2014-04-20 11:25:38 +00:00
|
|
|
OpenConsoleRequest->InheritHandle,
|
2013-04-07 23:18:59 +00:00
|
|
|
ShareMode);
|
2013-01-18 22:31:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2013-03-30 18:44:56 +00:00
|
|
|
|
2013-04-07 23:18:59 +00:00
|
|
|
ConSrvReleaseConsole(Console, TRUE);
|
|
|
|
return Status;
|
2013-01-24 22:41:33 +00:00
|
|
|
}
|
|
|
|
|
2012-10-22 23:55:51 +00:00
|
|
|
CSR_API(SrvDuplicateHandle)
|
2010-05-22 23:47:54 +00:00
|
|
|
{
|
2013-05-12 00:20:15 +00:00
|
|
|
NTSTATUS Status;
|
2013-01-05 23:10:12 +00:00
|
|
|
PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.DuplicateHandleRequest;
|
2012-11-07 22:23:36 +00:00
|
|
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
2013-05-12 00:20:15 +00:00
|
|
|
PCONSOLE Console;
|
|
|
|
|
2014-04-20 11:25:38 +00:00
|
|
|
HANDLE SourceHandle = DuplicateHandleRequest->SourceHandle;
|
|
|
|
ULONG Index = HandleToULong(SourceHandle) >> 2;
|
2013-05-12 00:20:15 +00:00
|
|
|
PCONSOLE_IO_HANDLE Entry;
|
|
|
|
DWORD DesiredAccess;
|
|
|
|
|
2014-04-20 11:25:38 +00:00
|
|
|
DuplicateHandleRequest->TargetHandle = INVALID_HANDLE_VALUE;
|
|
|
|
|
2013-05-12 00:20:15 +00:00
|
|
|
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-03-27 10:10:42 +00:00
|
|
|
DPRINT1("Can't get console, status %lx\n", Status);
|
2013-05-12 00:20:15 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2010-05-22 23:47:54 +00:00
|
|
|
|
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
2012-12-30 21:02:12 +00:00
|
|
|
|
2013-08-06 19:10:36 +00:00
|
|
|
// ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
|
|
|
|
// (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
|
|
|
|
|
2014-04-20 11:25:38 +00:00
|
|
|
if ( /** !IsConsoleHandle(SourceHandle) || **/
|
2012-12-30 21:02:12 +00:00
|
|
|
Index >= ProcessData->HandleTableSize ||
|
|
|
|
(Entry = &ProcessData->HandleTable[Index])->Object == NULL)
|
2010-05-22 23:47:54 +00:00
|
|
|
{
|
2014-04-20 11:25:38 +00:00
|
|
|
DPRINT1("Couldn't duplicate invalid handle 0x%p\n", SourceHandle);
|
2013-05-12 00:20:15 +00:00
|
|
|
Status = STATUS_INVALID_HANDLE;
|
|
|
|
goto Quit;
|
2010-05-22 23:47:54 +00:00
|
|
|
}
|
|
|
|
|
2012-10-23 22:31:36 +00:00
|
|
|
if (DuplicateHandleRequest->Options & DUPLICATE_SAME_ACCESS)
|
2010-05-22 23:47:54 +00:00
|
|
|
{
|
|
|
|
DesiredAccess = Entry->Access;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-04-20 11:25:38 +00:00
|
|
|
DesiredAccess = DuplicateHandleRequest->DesiredAccess;
|
2010-05-22 23:47:54 +00:00
|
|
|
/* Make sure the source handle has all the desired flags */
|
2013-01-22 23:28:51 +00:00
|
|
|
if ((Entry->Access & DesiredAccess) == 0)
|
2010-05-22 23:47:54 +00:00
|
|
|
{
|
2014-04-20 11:25:38 +00:00
|
|
|
DPRINT1("Handle 0x%p only has access %X; requested %X\n",
|
|
|
|
SourceHandle, Entry->Access, DesiredAccess);
|
2013-05-12 00:20:15 +00:00
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
goto Quit;
|
2010-05-22 23:47:54 +00:00
|
|
|
}
|
|
|
|
}
|
2010-05-30 20:00:17 +00:00
|
|
|
|
2013-03-30 18:44:56 +00:00
|
|
|
/* Insert the new handle inside the process handles table */
|
2013-05-12 00:20:15 +00:00
|
|
|
Status = ConSrvInsertObject(ProcessData,
|
2014-04-20 11:25:38 +00:00
|
|
|
&DuplicateHandleRequest->TargetHandle,
|
2013-05-12 00:20:15 +00:00
|
|
|
Entry->Object,
|
|
|
|
DesiredAccess,
|
2014-04-20 11:25:38 +00:00
|
|
|
DuplicateHandleRequest->InheritHandle,
|
2013-05-12 00:20:15 +00:00
|
|
|
Entry->ShareMode);
|
|
|
|
if (NT_SUCCESS(Status) &&
|
|
|
|
(DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE))
|
|
|
|
{
|
|
|
|
/* Close the original handle if needed */
|
2014-08-11 13:31:22 +00:00
|
|
|
ConSrvCloseHandle(Entry);
|
2010-05-22 23:47:54 +00:00
|
|
|
}
|
|
|
|
|
2013-05-12 00:20:15 +00:00
|
|
|
Quit:
|
2010-05-22 23:47:54 +00:00
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
2013-05-12 00:20:15 +00:00
|
|
|
|
|
|
|
ConSrvReleaseConsole(Console, TRUE);
|
|
|
|
return Status;
|
2010-05-22 23:47:54 +00:00
|
|
|
}
|
|
|
|
|
2013-08-30 17:53:45 +00:00
|
|
|
CSR_API(SrvGetHandleInformation)
|
|
|
|
{
|
2014-04-20 14:39:38 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PCONSOLE_GETHANDLEINFO GetHandleInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetHandleInfoRequest;
|
|
|
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
|
|
|
PCONSOLE Console;
|
|
|
|
|
|
|
|
HANDLE Handle = GetHandleInfoRequest->Handle;
|
|
|
|
ULONG Index = HandleToULong(Handle) >> 2;
|
|
|
|
PCONSOLE_IO_HANDLE Entry;
|
|
|
|
|
|
|
|
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-03-27 10:10:42 +00:00
|
|
|
DPRINT1("Can't get console, status %lx\n", Status);
|
2014-04-20 14:39:38 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
|
|
|
|
ASSERT(ProcessData->HandleTable);
|
|
|
|
// ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
|
|
|
|
// (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
|
|
|
|
|
|
|
|
if (!IsConsoleHandle(Handle) ||
|
|
|
|
Index >= ProcessData->HandleTableSize ||
|
|
|
|
(Entry = &ProcessData->HandleTable[Index])->Object == NULL)
|
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_HANDLE;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Retrieve the handle information flags. The console server
|
|
|
|
* doesn't support HANDLE_FLAG_PROTECT_FROM_CLOSE.
|
|
|
|
*/
|
|
|
|
GetHandleInfoRequest->Flags = 0;
|
|
|
|
if (Entry->Inheritable) GetHandleInfoRequest->Flags |= HANDLE_FLAG_INHERIT;
|
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
|
|
|
|
ConSrvReleaseConsole(Console, TRUE);
|
|
|
|
return Status;
|
2013-08-30 17:53:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CSR_API(SrvSetHandleInformation)
|
|
|
|
{
|
2014-04-20 14:39:38 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PCONSOLE_SETHANDLEINFO SetHandleInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetHandleInfoRequest;
|
|
|
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
|
|
|
PCONSOLE Console;
|
|
|
|
|
|
|
|
HANDLE Handle = SetHandleInfoRequest->Handle;
|
|
|
|
ULONG Index = HandleToULong(Handle) >> 2;
|
|
|
|
PCONSOLE_IO_HANDLE Entry;
|
|
|
|
|
|
|
|
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-03-27 10:10:42 +00:00
|
|
|
DPRINT1("Can't get console, status %lx\n", Status);
|
2014-04-20 14:39:38 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
|
|
|
|
ASSERT(ProcessData->HandleTable);
|
|
|
|
// ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
|
|
|
|
// (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
|
|
|
|
|
|
|
|
if (!IsConsoleHandle(Handle) ||
|
|
|
|
Index >= ProcessData->HandleTableSize ||
|
|
|
|
(Entry = &ProcessData->HandleTable[Index])->Object == NULL)
|
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_HANDLE;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Modify the handle information flags. The console server
|
|
|
|
* doesn't support HANDLE_FLAG_PROTECT_FROM_CLOSE.
|
|
|
|
*/
|
|
|
|
if (SetHandleInfoRequest->Mask & HANDLE_FLAG_INHERIT)
|
|
|
|
{
|
|
|
|
Entry->Inheritable = ((SetHandleInfoRequest->Flags & HANDLE_FLAG_INHERIT) != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
|
|
|
|
ConSrvReleaseConsole(Console, TRUE);
|
|
|
|
return Status;
|
2013-08-30 17:53:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CSR_API(SrvCloseHandle)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PCONSOLE_CLOSEHANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
|
|
|
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
|
|
|
PCONSOLE Console;
|
|
|
|
|
|
|
|
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-03-27 10:10:42 +00:00
|
|
|
DPRINT1("Can't get console, status %lx\n", Status);
|
2013-08-30 17:53:45 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2014-03-08 15:31:05 +00:00
|
|
|
Status = ConSrvRemoveObject(ProcessData, CloseHandleRequest->Handle);
|
2013-08-30 17:53:45 +00:00
|
|
|
|
|
|
|
ConSrvReleaseConsole(Console, TRUE);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
CSR_API(SrvVerifyConsoleIoHandle)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PCONSOLE_VERIFYHANDLE VerifyHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.VerifyHandleRequest;
|
|
|
|
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
|
|
|
|
PCONSOLE Console;
|
|
|
|
|
2014-03-08 15:31:05 +00:00
|
|
|
HANDLE IoHandle = VerifyHandleRequest->Handle;
|
|
|
|
ULONG Index = HandleToULong(IoHandle) >> 2;
|
|
|
|
|
|
|
|
VerifyHandleRequest->IsValid = FALSE;
|
2013-08-30 17:53:45 +00:00
|
|
|
|
|
|
|
Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2015-03-27 10:10:42 +00:00
|
|
|
DPRINT1("Can't get console, status %lx\n", Status);
|
2013-08-30 17:53:45 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
|
|
|
|
// ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
|
|
|
|
// (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
|
|
|
|
|
2014-03-08 15:31:05 +00:00
|
|
|
if (!IsConsoleHandle(IoHandle) ||
|
2013-08-30 17:53:45 +00:00
|
|
|
Index >= ProcessData->HandleTableSize ||
|
|
|
|
ProcessData->HandleTable[Index].Object == NULL)
|
|
|
|
{
|
|
|
|
DPRINT("SrvVerifyConsoleIoHandle failed\n");
|
2014-03-08 15:31:05 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VerifyHandleRequest->IsValid = TRUE;
|
2013-08-30 17:53:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
|
|
|
|
|
|
ConSrvReleaseConsole(Console, TRUE);
|
2014-03-08 15:31:05 +00:00
|
|
|
return STATUS_SUCCESS;
|
2013-08-30 17:53:45 +00:00
|
|
|
}
|
|
|
|
|
2001-08-14 12:57:16 +00:00
|
|
|
/* EOF */
|