Author: hbelusca
Date: Wed Jan 2 00:32:20 2013
New Revision: 58098
URL:
http://svn.reactos.org/svn/reactos?rev=58098&view=rev
Log:
[CONSRV]
- Fix console apps initialization.
- Add some debug output (NOTE TO MYSELF: remove them when all things work).
- Rewrite ConsoleNewProcess.
- Reorganize SrvAllocConsole and create ConsoleConnect based on SrvAllocConsole.
- Create ConsoleDisconnect which undoes what ConsoleConnect and ConsoleNewProcess did.
- Rework a little bit CsrInitConsole.
Now the console app. initialization algorithm is the following:
1- A process is created, its type (GUI or CUI) is determined (kernel32 and basesrv).
2- ConsoleNewProcess is called (consrv) and makes this new process inherit the console
handles table from its parent
(NOTE: this is done for all CUI processes, because at this point, we still don't
know whether we must inherit
the handles from the parent or not).
3- (back in kernel32) In BasepInitConsole, we determine whether or not we must create a
new console window or use
the parent's one or not using one at all. We (as a client) connect to the console
server (consrv) (via CsrClientConnectToServer)
which in turn (via CSRSS mechanism) calls ConsoleConnect. For GUI processes we do
nothing. For CUI processes, we initialize
a new console based on properties set in BasepInitConsole.
4- When a process dies, ConsoleDisconnect is called and whether it is a GUI or CUI
process, we revert the actions done previously.
Part 2/2
TODO: - Debug the CSR waits.
- Work on the console properties property-sheet.
- See what can be done on
http://jira.reactos.org/browse/CORE-122
Modified:
branches/ros-csrss/win32ss/user/consrv/conio.h
branches/ros-csrss/win32ss/user/consrv/conoutput.c
branches/ros-csrss/win32ss/user/consrv/console.c
branches/ros-csrss/win32ss/user/consrv/consrv.h
branches/ros-csrss/win32ss/user/consrv/handle.c
branches/ros-csrss/win32ss/user/consrv/init.c
Modified: branches/ros-csrss/win32ss/user/consrv/conio.h
URL:
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/c…
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/conio.h [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/conio.h [iso-8859-1] Wed Jan 2 00:32:20 2013
@@ -9,11 +9,6 @@
#pragma once
#define CSR_DEFAULT_CURSOR_SIZE 25
-
-/* Object type magic numbers */
-
-#define CONIO_CONSOLE_MAGIC 0x00000001
-#define CONIO_SCREEN_BUFFER_MAGIC 0x00000002
/************************************************************************
* Screen buffer structure represents the win32 screen buffer object. *
@@ -29,7 +24,7 @@
* being printed causes another line to scroll down, that the buffer IS *
* memcpy()'s up, and the bottom of the buffer is still displayed, but *
* internally, I just wrap back to the top of the buffer. *
- ***********************************************************************/
+ ************************************************************************/
typedef struct tagCSRSS_SCREEN_BUFFER
{
@@ -149,7 +144,7 @@
/* console.c */
NTSTATUS FASTCALL ConioConsoleFromProcessData(PCONSOLE_PROCESS_DATA ProcessData,
PCSRSS_CONSOLE *Console);
-VOID WINAPI ConioDeleteConsole(Object_t *Object);
+VOID WINAPI ConioDeleteConsole(PCSRSS_CONSOLE Console);
VOID WINAPI CsrInitConsoleSupport(VOID);
VOID FASTCALL ConioPause(PCSRSS_CONSOLE Console, UINT Flags);
VOID FASTCALL ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags);
Modified: branches/ros-csrss/win32ss/user/consrv/conoutput.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/c…
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/conoutput.c [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/conoutput.c [iso-8859-1] Wed Jan 2 00:32:20
2013
@@ -489,58 +489,60 @@
NULL,
NULL))
{
+ /* Fail */
ConioUnlockScreenBuffer(Buff);
return STATUS_NO_MEMORY;
}
}
/* Wait until we un-pause the console */
- ConioUnlockScreenBuffer(Buff);
- return STATUS_PENDING;
- }
-
- if(WriteConsoleRequest->Unicode)
- {
- Length = WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)WriteConsoleRequest->Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- NULL, 0, NULL, NULL);
- Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
+ Status = STATUS_PENDING;
+ }
+ else
+ {
+ if(WriteConsoleRequest->Unicode)
+ {
+ Length = WideCharToMultiByte(Console->OutputCodePage, 0,
+ (PWCHAR)WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->NrCharactersToWrite,
+ NULL, 0, NULL, NULL);
+ Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
+ if (Buffer)
+ {
+ WideCharToMultiByte(Console->OutputCodePage, 0,
+ (PWCHAR)WriteConsoleRequest->Buffer,
+ WriteConsoleRequest->NrCharactersToWrite,
+ Buffer, Length, NULL, NULL);
+ }
+ else
+ {
+ Status = STATUS_NO_MEMORY;
+ }
+ }
+ else
+ {
+ Buffer = (PCHAR)WriteConsoleRequest->Buffer;
+ }
+
if (Buffer)
{
- WideCharToMultiByte(Console->OutputCodePage, 0,
- (PWCHAR)WriteConsoleRequest->Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
- Buffer, Length, NULL, NULL);
- }
- else
- {
- Status = STATUS_NO_MEMORY;
- }
- }
- else
- {
- Buffer = (PCHAR)WriteConsoleRequest->Buffer;
- }
-
- if (Buffer)
- {
- if (NT_SUCCESS(Status))
- {
- Status = ConioWriteConsole(Console, Buff, Buffer,
- WriteConsoleRequest->NrCharactersToWrite,
TRUE);
if (NT_SUCCESS(Status))
{
- Written = WriteConsoleRequest->NrCharactersToWrite;
- }
- }
- if (WriteConsoleRequest->Unicode)
- {
- RtlFreeHeap(GetProcessHeap(), 0, Buffer);
- }
- }
-
- WriteConsoleRequest->NrCharactersWritten = Written;
+ Status = ConioWriteConsole(Console, Buff, Buffer,
+ WriteConsoleRequest->NrCharactersToWrite,
TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ Written = WriteConsoleRequest->NrCharactersToWrite;
+ }
+ }
+ if (WriteConsoleRequest->Unicode)
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, Buffer);
+ }
+ }
+
+ WriteConsoleRequest->NrCharactersWritten = Written;
+ }
ConioUnlockScreenBuffer(Buff);
return Status;
Modified: branches/ros-csrss/win32ss/user/consrv/console.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/c…
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/console.c [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/console.c [iso-8859-1] Wed Jan 2 00:32:20
2013
@@ -12,7 +12,7 @@
#include "guiconsole.h"
#include "tuiconsole.h"
-#define NDEBUG
+//#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
@@ -75,6 +75,7 @@
return;
}
+ DPRINT1("We succeeded at creating ProcessData->CtrlDispatcher remote
thread, ProcessId = %x, Process = 0x%p\n",
ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
WaitForSingleObject(Thread, Timeout);
CloseHandle(Thread);
}
@@ -86,15 +87,29 @@
ConioConsoleCtrlEventTimeout(Event, ProcessData, 0);
}
-static NTSTATUS WINAPI
-CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
+/* static */ NTSTATUS WINAPI
+CsrInitConsole(PCSRSS_CONSOLE* NewConsole, int ShowCmd)
{
NTSTATUS Status;
SECURITY_ATTRIBUTES SecurityAttributes;
+ PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER NewBuffer;
BOOL GuiMode;
WCHAR Title[255];
+ if (NewConsole == NULL) return STATUS_INVALID_PARAMETER;
+
+ *NewConsole = NULL;
+
+ /* Allocate a console structure */
+ Console = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_CONSOLE));
+ if (NULL == Console)
+ {
+ DPRINT1("Not enough memory for console creation.\n");
+ return STATUS_NO_MEMORY;
+ }
+
+ /* Initialize the console */
Console->Title.MaximumLength = Console->Title.Length = 0;
Console->Title.Buffer = NULL;
@@ -112,6 +127,7 @@
Console->Header.Type = CONIO_CONSOLE_MAGIC;
Console->Header.Console = Console;
Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT |
ENABLE_MOUSE_INPUT;
+ InitializeListHead(&Console->ProcessList);
InitializeListHead(&Console->BufferList);
Console->ActiveBuffer = NULL;
InitializeListHead(&Console->ReadWaitQueue);
@@ -129,6 +145,7 @@
if (NULL == Console->ActiveEvent)
{
RtlFreeUnicodeString(&Console->Title);
+ HeapFree(ConSrvHeap, 0, Console);
return STATUS_UNSUCCESSFUL;
}
Console->PrivateData = NULL;
@@ -143,6 +160,7 @@
RtlFreeUnicodeString(&Console->Title);
DeleteCriticalSection(&Console->Lock);
CloseHandle(Console->ActiveEvent);
+ HeapFree(ConSrvHeap, 0, Console);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* init screen buffer with defaults */
@@ -186,6 +204,7 @@
DeleteCriticalSection(&Console->Lock);
CloseHandle(Console->ActiveEvent);
DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status);
+ HeapFree(ConSrvHeap, 0, Console);
return Status;
}
}
@@ -199,11 +218,14 @@
CloseHandle(Console->ActiveEvent);
HeapFree(ConSrvHeap, 0, NewBuffer);
DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
+ HeapFree(ConSrvHeap, 0, Console);
return Status;
}
- /* copy buffer contents to screen */
+ /* Copy buffer contents to screen */
ConioDrawConsole(Console);
+
+ *NewConsole = Console;
return STATUS_SUCCESS;
}
@@ -271,109 +293,116 @@
NTSTATUS Status = STATUS_SUCCESS;
PCSRSS_ALLOC_CONSOLE AllocConsoleRequest =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
PCONSOLE_PROCESS_DATA ProcessData =
ConsoleGetPerProcessData(CsrGetClientThread()->Process);
- PCSRSS_CONSOLE Console;
- BOOLEAN NewConsole = FALSE;
DPRINT("SrvAllocConsole\n");
+ if (ProcessData->Console != NULL)
+ {
+ DPRINT1("Process already has a console\n");
+ return STATUS_INVALID_PARAMETER;
+ }
+
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- if (ProcessData->Console)
- {
- DPRINT1("Process already has a console\n");
+ DPRINT1("SrvAllocConsole - Checkpoint 1\n");
+
+ /* Initialize a new Console */
+ Status = CsrInitConsole(&ProcessData->Console,
AllocConsoleRequest->ShowCmd);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Console initialization failed\n");
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return STATUS_INVALID_PARAMETER;
- }
-
- DPRINT1("SrvAllocConsole - Checkpoint 1\n");
-
- /* If we don't need a console, then get out of here */
- if (!AllocConsoleRequest->ConsoleNeeded)
- {
- DPRINT("No console needed\n");
+ return Status;
+ }
+
+ /* Insert the process into the processes list of the console */
+ InsertHeadList(&ProcessData->Console->ProcessList,
&ProcessData->ConsoleLink);
+
+ /* Return it to the caller */
+ AllocConsoleRequest->Console = ProcessData->Console;
+
+ /* Add a reference count because the process is tied to the console */
+ _InterlockedIncrement(&ProcessData->Console->ReferenceCount);
+
+#if 0000
+ /*
+ * We've just created a new console. However when ConsoleNewProcess 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 our handles table and recreate a new one.
+ */
+
+ ULONG i;
+
+ /* Close all console handles and free the handle table memory */
+ for (i = 0; i < ProcessData->HandleTableSize; i++)
+ {
+ Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
+ }
+ ProcessData->HandleTableSize = 0;
+ RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
+ ProcessData->HandleTable = NULL;
+#endif
+
+ /*
+ * Create a new handle table - Insert the IO handles
+ */
+
+ /* Insert the Input handle */
+ Status = Win32CsrInsertObject(ProcessData,
+ &AllocConsoleRequest->InputHandle,
+ &ProcessData->Console->Header,
+ GENERIC_READ | GENERIC_WRITE,
+ TRUE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to insert the input handle\n");
+ ConioDeleteConsole(ProcessData->Console);
+ ProcessData->Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return STATUS_SUCCESS;
- }
-
- /* If we already have one, then don't create a new one... */
- if (!AllocConsoleRequest->Console ||
- AllocConsoleRequest->Console != ProcessData->ParentConsole)
- {
- /* Allocate a console structure */
- NewConsole = TRUE;
- Console = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_CONSOLE));
- if (NULL == Console)
- {
- DPRINT1("Not enough memory for console\n");
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return STATUS_NO_MEMORY;
- }
-
- /* Initialize list head */
- InitializeListHead(&Console->ProcessList);
-
- /* Insert process data required for GUI initialization */
- InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
-
- /* Initialize the Console */
- Status = CsrInitConsole(Console, AllocConsoleRequest->ShowCmd);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Console init failed\n");
- HeapFree(ConSrvHeap, 0, Console);
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return Status;
- }
- }
- else
- {
- /* Reuse our current console */
- Console = AllocConsoleRequest->Console;
- }
-
- /* Set the Process Console */
- ProcessData->Console = Console;
-
- /* Return it to the caller */
- AllocConsoleRequest->Console = Console;
-
- /* Add a reference count because the process is tied to the console */
- _InterlockedIncrement(&Console->ReferenceCount);
-
- if (NewConsole || !ProcessData->bInheritHandles)
- {
- /* Insert the Objects */
- Status = Win32CsrInsertObject(ProcessData,
- &AllocConsoleRequest->InputHandle,
- &Console->Header,
- GENERIC_READ | GENERIC_WRITE,
- TRUE,
- FILE_SHARE_READ | FILE_SHARE_WRITE);
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed to insert object\n");
- ConioDeleteConsole((Object_t *) Console);
- ProcessData->Console = NULL;
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return Status;
- }
-
- Status = Win32CsrInsertObject(ProcessData,
- &AllocConsoleRequest->OutputHandle,
- &Console->ActiveBuffer->Header,
- GENERIC_READ | GENERIC_WRITE,
- TRUE,
- FILE_SHARE_READ | FILE_SHARE_WRITE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to insert object\n");
- ConioDeleteConsole((Object_t *) Console);
- Win32CsrReleaseObject(ProcessData,
- AllocConsoleRequest->InputHandle);
- ProcessData->Console = NULL;
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return Status;
- }
+ return Status;
+ }
+
+ /* Insert the Output handle */
+ Status = Win32CsrInsertObject(ProcessData,
+ &AllocConsoleRequest->OutputHandle,
+
&ProcessData->Console->ActiveBuffer->Header,
+ GENERIC_READ | GENERIC_WRITE,
+ TRUE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to insert the output handle\n");
+ ConioDeleteConsole(ProcessData->Console);
+ Win32CsrReleaseObject(ProcessData,
+ AllocConsoleRequest->InputHandle);
+ ProcessData->Console = NULL;
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return Status;
+ }
+
+ /* Insert the Error handle */
+ Status = Win32CsrInsertObject(ProcessData,
+ &AllocConsoleRequest->ErrorHandle,
+
&ProcessData->Console->ActiveBuffer->Header,
+ GENERIC_READ | GENERIC_WRITE,
+ TRUE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to insert the error handle\n");
+ ConioDeleteConsole(ProcessData->Console);
+ Win32CsrReleaseObject(ProcessData,
+ AllocConsoleRequest->OutputHandle);
+ Win32CsrReleaseObject(ProcessData,
+ AllocConsoleRequest->InputHandle);
+ ProcessData->Console = NULL;
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return Status;
}
/* Duplicate the Event */
@@ -385,9 +414,11 @@
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
- ConioDeleteConsole((Object_t *) Console);
- if (NewConsole || !ProcessData->bInheritHandles)
- {
+ ConioDeleteConsole(ProcessData->Console);
+ // if (NewConsole /* || !ProcessData->bInheritHandles */)
+ {
+ Win32CsrReleaseObject(ProcessData,
+ AllocConsoleRequest->ErrorHandle);
Win32CsrReleaseObject(ProcessData,
AllocConsoleRequest->OutputHandle);
Win32CsrReleaseObject(ProcessData,
@@ -397,37 +428,30 @@
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
}
+ /* Input Wait Handle */
+ AllocConsoleRequest->InputWaitHandle = ProcessData->ConsoleEvent;
/* Set the Ctrl Dispatcher */
ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
DPRINT("CSRSS:CtrlDispatcher address: %x\n",
ProcessData->CtrlDispatcher);
- if (!NewConsole)
- {
- /* Insert into the list if it has not been added */
- InsertHeadList(&ProcessData->Console->ProcessList,
&ProcessData->ConsoleLink);
- }
-
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
}
CSR_API(SrvFreeConsole)
{
+ DPRINT1("SrvFreeConsole\n");
Win32CsrReleaseConsole(CsrGetClientThread()->Process);
return STATUS_SUCCESS;
}
VOID WINAPI
-ConioDeleteConsole(Object_t *Object)
-{
- PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
+ConioDeleteConsole(PCSRSS_CONSOLE Console)
+{
ConsoleInput *Event;
DPRINT("ConioDeleteConsole\n");
-
- /* TODO: Dereference all the waits in Console->ReadWaitQueue */
- /* TODO: Dereference all the waits in Console->WriteWaitQueue */
/* Drain input event queue */
while (Console->InputEvents.Flink != &Console->InputEvents)
Modified: branches/ros-csrss/win32ss/user/consrv/consrv.h
URL:
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/c…
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/consrv.h [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/consrv.h [iso-8859-1] Wed Jan 2 00:32:20 2013
@@ -35,6 +35,9 @@
// extern HANDLE BaseSrvSharedHeap;
// extern PBASE_STATIC_SERVER_DATA BaseStaticServerData;
+/* Object type magic numbers */
+#define CONIO_CONSOLE_MAGIC 0x00000001 // --> Input-type handles
+#define CONIO_SCREEN_BUFFER_MAGIC 0x00000002 // --> Output-type handles
/* Common things to input/output/console objects */
typedef struct Object_tt
@@ -62,14 +65,17 @@
typedef struct _CONSOLE_PROCESS_DATA
{
LIST_ENTRY ConsoleLink;
- PCSR_PROCESS Process; // Parent process.
+ PCSR_PROCESS Process; // Process owning this structure.
HANDLE ConsoleEvent;
/* PCSRSS_CONSOLE */ struct tagCSRSS_CONSOLE* Console;
/* PCSRSS_CONSOLE */ struct tagCSRSS_CONSOLE* ParentConsole;
- BOOL bInheritHandles;
+
+ // BOOL bInheritHandles;
+ BOOL ConsoleApp; // TRUE if it is a CUI app, FALSE otherwise.
+
RTL_CRITICAL_SECTION HandleTableLock;
ULONG HandleTableSize;
- /* PCSRSS_HANDLE */ struct _CSRSS_HANDLE* HandleTable; // Is it a length-varying
table or length-fixed ??
+ PCSRSS_HANDLE HandleTable; // Length-varying table
LPTHREAD_START_ROUTINE CtrlDispatcher;
} CONSOLE_PROCESS_DATA, *PCONSOLE_PROCESS_DATA;
@@ -128,11 +134,7 @@
CSR_API(SrvCloseHandle);
CSR_API(SrvVerifyConsoleIoHandle);
CSR_API(SrvDuplicateHandle);
-CSR_API(CsrGetInputWaitHandle);
-
-NTSTATUS NTAPI ConsoleNewProcess(PCSR_PROCESS SourceProcess,
- PCSR_PROCESS TargetProcess);
-VOID NTAPI Win32CsrReleaseConsole(PCSR_PROCESS Process);
+/// CSR_API(CsrGetInputWaitHandle);
NTSTATUS FASTCALL Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
PHANDLE Handle,
@@ -149,6 +151,14 @@
NTSTATUS FASTCALL Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData,
HANDLE Handle);
+NTSTATUS NTAPI ConsoleNewProcess(PCSR_PROCESS SourceProcess,
+ PCSR_PROCESS TargetProcess);
+NTSTATUS NTAPI ConsoleConnect(IN PCSR_PROCESS CsrProcess,
+ IN OUT PVOID ConnectionInfo,
+ IN OUT PULONG ConnectionInfoLength);
+VOID NTAPI ConsoleDisconnect(PCSR_PROCESS Process);
+VOID NTAPI Win32CsrReleaseConsole(PCSR_PROCESS Process);
+
/* lineinput.c */
CSR_API(SrvGetConsoleCommandHistoryLength);
CSR_API(SrvGetConsoleCommandHistory);
Modified: branches/ros-csrss/win32ss/user/consrv/handle.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/h…
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/handle.c [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/handle.c [iso-8859-1] Wed Jan 2 00:32:20 2013
@@ -11,7 +11,7 @@
#include "consrv.h"
#include "conio.h"
-#define NDEBUG
+//#define NDEBUG
#include <debug.h>
@@ -21,11 +21,16 @@
AdjustHandleCounts(PCSRSS_HANDLE Entry, INT Change)
{
Object_t *Object = Entry->Object;
+
+ DPRINT1("AdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount =
%d, Object->Type = %lu\n", Entry, Change, Object, Object->HandleCount,
Object->Type);
+
if (Entry->Access & GENERIC_READ) Object->AccessRead += Change;
if (Entry->Access & GENERIC_WRITE) Object->AccessWrite += Change;
if (!(Entry->ShareMode & FILE_SHARE_READ)) Object->ExclusiveRead +=
Change;
if (!(Entry->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite +=
Change;
+
Object->HandleCount += Change;
+
return Object->HandleCount;
}
@@ -46,17 +51,26 @@
{
PCSRSS_CONSOLE Console = Object->Console;
EnterCriticalSection(&Console->Lock);
- /* If the last handle to a screen buffer is closed, delete it */
- if (AdjustHandleCounts(Entry, -1) == 0
- && Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
- {
- PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
- /* ...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)
- ConioDeleteScreenBuffer(Buffer);
- }
+
+ /* If the last handle to a screen buffer is closed, delete it... */
+ if (AdjustHandleCounts(Entry, -1) == 0)
+ {
+ if (Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
+ {
+ PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
+ /* ...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)
+ ConioDeleteScreenBuffer(Buffer);
+ }
+ else if (Object->Type == CONIO_CONSOLE_MAGIC)
+ {
+ /* TODO: FIXME: Destroy here the console ?? */
+ // ConioDeleteConsole(Console);
+ }
+ }
+
LeaveCriticalSection(&Console->Lock);
Entry->Object = NULL;
}
@@ -94,7 +108,7 @@
if (Block == NULL)
{
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return(STATUS_UNSUCCESSFUL);
+ return STATUS_UNSUCCESSFUL;
}
RtlCopyMemory(Block,
ProcessData->HandleTable,
@@ -129,6 +143,8 @@
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
+
+ DPRINT1("Win32CsrReleaseObject - Process 0x%p, Release 0x%p\n",
ProcessData->Process, &ProcessData->HandleTable[h]);
Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
@@ -169,24 +185,43 @@
return STATUS_SUCCESS;
}
+VOID FASTCALL
+Win32CsrUnlockConsole(PCSRSS_CONSOLE Console)
+{
+ LeaveCriticalSection(&Console->Lock);
+
+ /* Decrement reference count */
+ if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
+ ConioDeleteConsole(Console);
+}
+
VOID
FASTCALL
Win32CsrUnlockObject(Object_t *Object)
{
- PCSRSS_CONSOLE Console = Object->Console;
- LeaveCriticalSection(&Console->Lock);
- /* dec ref count */
- if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
- ConioDeleteConsole(&Console->Header);
-}
-
-
-
+ Win32CsrUnlockConsole(Object->Console);
+}
+
+
+
+/** Remark: this function can be called by SrvAttachConsole (not yet implemented) **/
NTSTATUS
NTAPI
ConsoleNewProcess(PCSR_PROCESS SourceProcess,
PCSR_PROCESS TargetProcess)
{
+ /**************************************************************************
+ * This function is called whenever a new process (GUI or CUI) is created.
+ *
+ * Copy the parent's handles table here if both the parent and the child
+ * processes are CUI. If we must actually create our proper console (and
+ * thus do not inherit from the console handles of the parent's), then we
+ * will clean this table in the next ConsoleConnect call. Why we are doing
+ * this? It's because here, we still don't know whether or not we must
create
+ * a new console instead of inherit it from the parent, and, because in
+ * ConsoleConnect we don't have any reference to the parent process anymore.
+ **************************************************************************/
+
PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
ULONG i;
@@ -200,9 +235,22 @@
DPRINT1("ConsoleNewProcess - OK\n");
TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
+ DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData);
+
+ /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
/* Initialize the new (target) process */
TargetProcessData->Process = TargetProcess;
+ TargetProcessData->ConsoleEvent = NULL;
+ TargetProcessData->Console = TargetProcessData->ParentConsole = NULL;
+ // TargetProcessData->bInheritHandles = FALSE;
+ TargetProcessData->ConsoleApp = ((TargetProcess->Flags &
CsrProcessIsConsoleApp) ? TRUE : FALSE);
+
+ // Testing
+ TargetProcessData->HandleTableSize = 0;
+ TargetProcessData->HandleTable = NULL;
+
+ /* HACK */ RtlZeroMemory(&TargetProcessData->HandleTableLock,
sizeof(RTL_CRITICAL_SECTION));
RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
/* Do nothing if the source process is NULL */
@@ -210,51 +258,256 @@
return STATUS_SUCCESS;
SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
-
- // TODO: Check if one of the processes is really a CONSOLE.
+ DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData);
+
/*
- if (!(CreateProcessRequest->CreationFlags & (CREATE_NEW_CONSOLE |
DETACHED_PROCESS)))
- {
- // NewProcess == TargetProcess.
- NewProcess->ParentConsole = Process->Console;
- NewProcess->bInheritHandles = CreateProcessRequest->bInheritHandles;
- }
- */
-
- /* Only inherit if the if the flag was set */
- if (!TargetProcessData->bInheritHandles) return STATUS_SUCCESS;
-
- if (TargetProcessData->HandleTableSize)
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
-
- TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap,
- HEAP_ZERO_MEMORY,
-
SourceProcessData->HandleTableSize
- * sizeof(CSRSS_HANDLE));
- if (TargetProcessData->HandleTable == NULL)
- {
+ * If both of the processes (parent and new child) are console applications,
+ * then try to inherit handles from the parent process.
+ */
+ if ( SourceProcessData->Console != NULL && /*
SourceProcessData->ConsoleApp */
+ TargetProcessData->ConsoleApp )
+ {
+/*
+ if (TargetProcessData->HandleTableSize)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+*/
+
+ DPRINT1("ConsoleNewProcess - Copy the handle table (1)\n");
+ /* Temporary "inherit" the console from the parent */
+ TargetProcessData->ParentConsole = SourceProcessData->Console;
+ RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
+ DPRINT1("ConsoleNewProcess - Copy the handle table (2)\n");
+
+ /* Allocate a new handle table for the child process */
+ TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap,
+ HEAP_ZERO_MEMORY,
+
SourceProcessData->HandleTableSize
+ *
sizeof(CSRSS_HANDLE));
+ if (TargetProcessData->HandleTable == NULL)
+ {
+ RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ 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.
+ */
+ for (i = 0; i < SourceProcessData->HandleTableSize; i++)
+ {
+ if (SourceProcessData->HandleTable[i].Object != NULL &&
+ SourceProcessData->HandleTable[i].Inheritable)
+ {
+ /*
+ * Copy the handle data and increment the reference count of the
+ * pointed object (via the call to Win32CsrCreateHandleEntry).
+ */
+ TargetProcessData->HandleTable[i] =
SourceProcessData->HandleTable[i];
+ Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
+ }
+ }
+
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
+ }
+ else
+ {
+ DPRINT1("ConsoleNewProcess - We don't launch a Console process :
SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n",
SourceProcessData->Console, TargetProcess->Flags);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+// Temporary ; move it to a header.
+NTSTATUS WINAPI CsrInitConsole(PCSRSS_CONSOLE* NewConsole, int ShowCmd);
+
+NTSTATUS
+NTAPI
+ConsoleConnect(IN PCSR_PROCESS CsrProcess,
+ IN OUT PVOID ConnectionInfo,
+ IN OUT PULONG ConnectionInfoLength)
+{
+ /**************************************************************************
+ * This function is called whenever a CUI new process is created.
+ **************************************************************************/
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
+ BOOLEAN NewConsole = FALSE;
+ // PCSRSS_CONSOLE Console = NULL;
+
+ DPRINT1("ConsoleConnect\n");
+
+ if ( ConnectionInfo == NULL ||
+ ConnectionInfoLength == NULL ||
+ *ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
+ {
+ DPRINT1("CONSRV: Connection failed\n");
return STATUS_UNSUCCESSFUL;
}
- TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
-
- for (i = 0; i < SourceProcessData->HandleTableSize; i++)
- {
- if (SourceProcessData->HandleTable[i].Object != NULL &&
- SourceProcessData->HandleTable[i].Inheritable)
- {
- TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
- Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
- }
- }
-
- RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
-
+ /* If we don't need a console, then get out of here */
+ if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is
for GUI apps.
+ {
+ DPRINT("ConsoleConnect - No console needed\n");
+ return STATUS_SUCCESS;
+ }
+
+ RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+
+ /* If we don't have a console, then create a new one... */
+ if (!ConnectInfo->Console ||
+ ConnectInfo->Console != ProcessData->ParentConsole)
+ {
+ // PCSRSS_CONSOLE Console;
+
+ DPRINT1("ConsoleConnect - Allocate a new console\n");
+
+ /* Initialize a new Console */
+ NewConsole = TRUE;
+ Status = CsrInitConsole(&ProcessData->Console, ConnectInfo->ShowCmd);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Console initialization failed\n");
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return Status;
+ }
+ }
+ else /* We inherit it from the parent */
+ {
+ DPRINT1("ConsoleConnect - Reuse current (parent's) console\n");
+
+ /* Reuse our current console */
+ NewConsole = FALSE;
+ ProcessData->Console = ConnectInfo->Console;
+ }
+
+ /* Insert the process into the processes list of the console */
+ InsertHeadList(&ProcessData->Console->ProcessList,
&ProcessData->ConsoleLink);
+
+ /* Return it to the caller */
+ ConnectInfo->Console = ProcessData->Console;
+
+ /* Add a reference count because the process is tied to the console */
+ _InterlockedIncrement(&ProcessData->Console->ReferenceCount);
+
+ if (NewConsole /* || !ProcessData->bInheritHandles */)
+ {
+ /*
+ * We've just created a new console. However when ConsoleNewProcess 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 our handles table and recreate a new one.
+ */
+
+ ULONG i;
+
+ /* Close all console handles and free the handle table memory */
+ for (i = 0; i < ProcessData->HandleTableSize; i++)
+ {
+ Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
+ }
+ ProcessData->HandleTableSize = 0;
+ RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
+ ProcessData->HandleTable = NULL;
+
+ /*
+ * Create a new handle table - Insert the IO handles
+ */
+
+ /* Insert the Input handle */
+ Status = Win32CsrInsertObject(ProcessData,
+ &ConnectInfo->InputHandle,
+ &ProcessData->Console->Header,
+ GENERIC_READ | GENERIC_WRITE,
+ TRUE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to insert the input handle\n");
+ ConioDeleteConsole(ProcessData->Console);
+ ProcessData->Console = NULL;
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return Status;
+ }
+
+ /* Insert the Output handle */
+ Status = Win32CsrInsertObject(ProcessData,
+ &ConnectInfo->OutputHandle,
+
&ProcessData->Console->ActiveBuffer->Header,
+ GENERIC_READ | GENERIC_WRITE,
+ TRUE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to insert the output handle\n");
+ ConioDeleteConsole(ProcessData->Console);
+ Win32CsrReleaseObject(ProcessData,
+ ConnectInfo->InputHandle);
+ ProcessData->Console = NULL;
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return Status;
+ }
+
+ /* Insert the Error handle */
+ Status = Win32CsrInsertObject(ProcessData,
+ &ConnectInfo->ErrorHandle,
+
&ProcessData->Console->ActiveBuffer->Header,
+ GENERIC_READ | GENERIC_WRITE,
+ TRUE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to insert the error handle\n");
+ ConioDeleteConsole(ProcessData->Console);
+ Win32CsrReleaseObject(ProcessData,
+ ConnectInfo->OutputHandle);
+ Win32CsrReleaseObject(ProcessData,
+ ConnectInfo->InputHandle);
+ ProcessData->Console = NULL;
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return Status;
+ }
+ }
+
+ /* Duplicate the Event */
+ Status = NtDuplicateObject(NtCurrentProcess(),
+ ProcessData->Console->ActiveEvent,
+ ProcessData->Process->ProcessHandle,
+ &ProcessData->ConsoleEvent,
+ EVENT_ALL_ACCESS, 0, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
+ ConioDeleteConsole(ProcessData->Console);
+ if (NewConsole /* || !ProcessData->bInheritHandles */)
+ {
+ Win32CsrReleaseObject(ProcessData,
+ ConnectInfo->ErrorHandle);
+ Win32CsrReleaseObject(ProcessData,
+ ConnectInfo->OutputHandle);
+ Win32CsrReleaseObject(ProcessData,
+ ConnectInfo->InputHandle);
+ }
+ ProcessData->Console = NULL;
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return Status;
+ }
+ /* Input Wait Handle */
+ ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent;
+
+ /* Set the Ctrl Dispatcher */
+ ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
+ DPRINT("CSRSS:CtrlDispatcher address: %x\n",
ProcessData->CtrlDispatcher);
+
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
}
@@ -266,29 +519,62 @@
PCSRSS_CONSOLE Console;
ULONG i;
- /* Close all console handles and detach process from console */
+ DPRINT1("Win32CsrReleaseConsole\n");
+
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+ /* Close all console handles and free the handle table memory */
for (i = 0; i < ProcessData->HandleTableSize; i++)
+ {
Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
+ }
ProcessData->HandleTableSize = 0;
RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
ProcessData->HandleTable = NULL;
+ /* Detach process from console */
Console = ProcessData->Console;
if (Console != NULL)
{
+ DPRINT1("Win32CsrReleaseConsole - Console->ReferenceCount = %lu - We are
going to decrement it !\n", Console->ReferenceCount);
ProcessData->Console = NULL;
EnterCriticalSection(&Console->Lock);
RemoveEntryList(&ProcessData->ConsoleLink);
- LeaveCriticalSection(&Console->Lock);
- if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
- ConioDeleteConsole(&Console->Header);
+ Win32CsrUnlockConsole(Console);
//CloseHandle(ProcessData->ConsoleEvent);
//ProcessData->ConsoleEvent = NULL;
}
+
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
}
+
+VOID
+WINAPI
+ConsoleDisconnect(PCSR_PROCESS Process)
+{
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
+
+ /**************************************************************************
+ * This function is called whenever a new process (GUI or CUI) is destroyed.
+ *
+ * Only do something if the process is a CUI. <-- modify this behaviour if
+ * we deal with a GUI which
+ * quits and acquired a
+ * console...
+ **************************************************************************/
+
+ DPRINT1("ConsoleDisconnect called\n");
+ // if (ProcessData->Console != NULL)
+ if (ProcessData->ConsoleApp)
+ {
+ DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
+ Win32CsrReleaseConsole(Process);
+ }
+
+ RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
+}
+
+
CSR_API(SrvCloseHandle)
{
@@ -374,6 +660,7 @@
return ApiMessage->Status;
}
+/**
CSR_API(CsrGetInputWaitHandle)
{
PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle =
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
@@ -383,5 +670,6 @@
return STATUS_SUCCESS;
}
+**/
/* EOF */
Modified: branches/ros-csrss/win32ss/user/consrv/init.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/i…
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/init.c [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/init.c [iso-8859-1] Wed Jan 2 00:32:20 2013
@@ -460,8 +460,8 @@
LoadedServerDll->ValidTable = ConsoleServerApiServerValidTable;
LoadedServerDll->NameTable = ConsoleServerApiNameTable;
LoadedServerDll->SizeOfProcessData = sizeof(CONSOLE_PROCESS_DATA);
- LoadedServerDll->ConnectCallback = NULL;
- LoadedServerDll->DisconnectCallback = Win32CsrReleaseConsole;
+ LoadedServerDll->ConnectCallback = ConsoleConnect;
+ LoadedServerDll->DisconnectCallback = ConsoleDisconnect;
LoadedServerDll->NewProcessCallback = ConsoleNewProcess;
// LoadedServerDll->HardErrorCallback = Win32CsrHardError;