[KERNEL32/BASESRV/CONSRV]

- Fix console apps initialization.
- Introduce a helper function InitConsoleCtrlHandling for initializing console control handling.
- We now initialize the new created console when connecting the client (kernel32) to the server (consrv) by calling CsrClientConnectToServer with real parameters (not dummy ones).
- Add/activate some debug prints (will be removed when all things work).

Part 1/2

svn path=/branches/ros-csrss/; revision=58096
This commit is contained in:
Hermès Bélusca-Maïto 2013-01-01 23:36:19 +00:00
parent 0444a3a392
commit d820098fa6
6 changed files with 102 additions and 85 deletions

View file

@ -29,6 +29,8 @@ PHANDLER_ROUTINE* CtrlHandlers;
ULONG NrCtrlHandlers;
ULONG NrAllocatedHandlers;
HANDLE InputWaitHandle = INVALID_HANDLE_VALUE;
#define INPUTEXENAME_BUFLEN 256
static WCHAR InputExeName[INPUTEXENAME_BUFLEN];
@ -76,7 +78,7 @@ ConsoleControlDispatcher(IN LPVOID lpThreadParameter)
UINT i;
EXCEPTION_RECORD erException;
DPRINT("Console Dispatcher Active: %lx %lx\n", CodeAndFlag, nCode);
DPRINT1("Console Dispatcher Active: %lx %lx\n", CodeAndFlag, nCode);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
switch(nCode)
@ -174,6 +176,16 @@ ConsoleControlDispatcher(IN LPVOID lpThreadParameter)
return STATUS_SUCCESS;
}
VOID
WINAPI
InitConsoleCtrlHandling(VOID)
{
/* Initialize Console Ctrl Handler */
NrAllocatedHandlers = NrCtrlHandlers = 1;
CtrlHandlers = InitialHandler;
CtrlHandlers[0] = DefaultConsoleCtrlHandler;
}
/* FUNCTIONS ******************************************************************/
@ -321,10 +333,6 @@ HANDLE
WINAPI
GetConsoleInputWaitHandle(VOID)
{
/// HACK !!!!!!!!!!!!!
ASSERT(FALSE);
return NULL;
#if 0
NTSTATUS Status;
CONSOLE_API_MESSAGE ApiMessage;
@ -341,6 +349,8 @@ GetConsoleInputWaitHandle(VOID)
return ApiMessage.Data.GetConsoleInputWaitHandle.InputWaitHandle;
#endif
return InputWaitHandle;
}
@ -786,9 +796,10 @@ AllocConsole(VOID)
NTSTATUS Status;
CONSOLE_API_MESSAGE ApiMessage;
PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest;
HANDLE hStdError;
STARTUPINFO si;
DPRINT1("AllocConsole called !!!!\n");
if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
{
DPRINT("AllocConsole: Allocate duplicate console to the same Process\n");
@ -798,9 +809,9 @@ AllocConsole(VOID)
GetStartupInfo(&si);
AllocConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher;
AllocConsoleRequest->ConsoleNeeded = TRUE;
AllocConsoleRequest->ShowCmd = si.wShowWindow;
AllocConsoleRequest->Console = NULL;
AllocConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher;
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
@ -814,15 +825,15 @@ AllocConsole(VOID)
NtCurrentPeb()->ProcessParameters->ConsoleHandle = AllocConsoleRequest->Console;
SetStdHandle(STD_INPUT_HANDLE, AllocConsoleRequest->InputHandle);
SetStdHandle(STD_INPUT_HANDLE , AllocConsoleRequest->InputHandle );
SetStdHandle(STD_OUTPUT_HANDLE, AllocConsoleRequest->OutputHandle);
SetStdHandle(STD_ERROR_HANDLE , AllocConsoleRequest->ErrorHandle );
hStdError = DuplicateConsoleHandle(AllocConsoleRequest->OutputHandle,
0,
TRUE,
DUPLICATE_SAME_ACCESS);
/* Initialize Console Ctrl Handler */
InitConsoleCtrlHandling();
InputWaitHandle = AllocConsoleRequest->InputWaitHandle;
SetStdHandle(STD_ERROR_HANDLE, hStdError);
return TRUE;
}
@ -853,6 +864,10 @@ FreeConsole(VOID)
}
NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
CloseHandle(InputWaitHandle);
InputWaitHandle = INVALID_HANDLE_VALUE;
return TRUE;
}

View file

@ -36,12 +36,9 @@ static BOOL DllInitialized = FALSE;
RTL_CRITICAL_SECTION BaseDllDirectoryLock;
RTL_CRITICAL_SECTION ConsoleLock;
extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
extern DWORD WINAPI ConsoleControlDispatcher(IN LPVOID lpThreadParameter);
extern PHANDLER_ROUTINE InitialHandler[1];
extern PHANDLER_ROUTINE* CtrlHandlers;
extern ULONG NrCtrlHandlers;
extern ULONG NrAllocatedHandlers;
extern HANDLE InputWaitHandle;
extern BOOL FASTCALL NlsInit(VOID);
extern VOID FASTCALL NlsUninit(VOID);
@ -55,9 +52,6 @@ WINAPI
BasepInitConsole(VOID)
{
NTSTATUS Status;
CONSOLE_API_MESSAGE ApiMessage;
PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest;
BOOLEAN NotConsole = FALSE;
PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
LPCWSTR ExeName;
STARTUPINFO si;
@ -65,12 +59,8 @@ BasepInitConsole(VOID)
ULONG SessionId = NtCurrentPeb()->SessionId;
BOOLEAN InServer;
// HACK
/*
CSR_CONNECTION_INFO CsrConnectionInfo;
ULONG ConnectionSize = sizeof(CsrConnectionInfo);
*/
// END HACK
CONSOLE_CONNECTION_INFO ConnectInfo;
ULONG ConnectInfoSize = sizeof(ConnectInfo);
WCHAR lpTest[MAX_PATH];
GetModuleFileNameW(NULL, lpTest, MAX_PATH);
@ -79,28 +69,33 @@ BasepInitConsole(VOID)
Parameters->ConsoleHandle, Parameters->StandardInput,
Parameters->StandardOutput, Parameters->StandardError);
/* Initialize our global console DLL lock */
Status = RtlInitializeCriticalSection(&ConsoleLock);
if (!NT_SUCCESS(Status)) return FALSE;
ConsoleInitialized = TRUE;
/* We have nothing to do if this isn't a console app... */
if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem !=
IMAGE_SUBSYSTEM_WINDOWS_CUI)
{
DPRINT("Image is not a console application\n");
Parameters->ConsoleHandle = NULL;
AllocConsoleRequest->ConsoleNeeded = FALSE;
ConnectInfo.ConsoleNeeded = FALSE; // ConsoleNeeded is used for knowing whether or not this is a CUI app.
}
else
{
/* Assume one is needed */
GetStartupInfo(&si);
AllocConsoleRequest->ConsoleNeeded = TRUE;
AllocConsoleRequest->ShowCmd = si.wShowWindow;
ConnectInfo.ConsoleNeeded = TRUE;
ConnectInfo.ShowCmd = si.wShowWindow;
/* Handle the special flags given to us by BasepInitializeEnvironment */
/* Handle the special flags given to us by BasePushProcessParameters */
if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS)
{
/* No console to create */
DPRINT("No console to create\n");
Parameters->ConsoleHandle = NULL;
AllocConsoleRequest->ConsoleNeeded = FALSE;
ConnectInfo.ConsoleNeeded = FALSE;
}
else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
{
@ -113,33 +108,29 @@ BasepInitConsole(VOID)
/* We'll get the real one soon */
DPRINT("Creating new invisible console\n");
Parameters->ConsoleHandle = NULL;
AllocConsoleRequest->ShowCmd = SW_HIDE;
ConnectInfo.ShowCmd = SW_HIDE;
}
else
{
if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE)
{
Parameters->ConsoleHandle = 0;
Parameters->ConsoleHandle = NULL;
}
DPRINT("Using existing console: %x\n", Parameters->ConsoleHandle);
}
}
/* Now use the proper console handle */
ConnectInfo.Console = Parameters->ConsoleHandle;
/* Initialize Console Ctrl Handler and input EXE name */
ConsoleInitialized = TRUE;
RtlInitializeCriticalSection(&ConsoleLock);
NrAllocatedHandlers = 1;
NrCtrlHandlers = 1;
CtrlHandlers = InitialHandler;
CtrlHandlers[0] = DefaultConsoleCtrlHandler;
InitConsoleCtrlHandling();
ConnectInfo.CtrlDispatcher = ConsoleControlDispatcher;
ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\');
if (ExeName)
SetConsoleInputExeNameW(ExeName + 1);
/* Now use the proper console handle */
AllocConsoleRequest->Console = Parameters->ConsoleHandle;
/* Setup the right Object Directory path */
if (!SessionId)
{
@ -156,61 +147,45 @@ BasepInitConsole(VOID)
WIN_OBJ_DIR);
}
/* Connect to the base server */
DPRINT("Connecting to CSR in BasepInitConsole...\n");
/* Connect to the Console Server */
DPRINT("Connecting to the Console Server in BasepInitConsole...\n");
Status = CsrClientConnectToServer(SessionDir,
CONSRV_SERVERDLL_INDEX,
/* &CsrConnectionInfo, */ NULL, // TODO: Give it a console connection info
/* &ConnectionSize, */ NULL, // TODO: Give it a console connection info
&ConnectInfo,
&ConnectInfoSize,
&InServer);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to connect to CSR (Status %lx)\n", Status);
DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status);
return FALSE;
}
/* Nothing to do for server-to-server */
if (InServer) return TRUE;
/*
* Normally, we should be connecting to the Console CSR Server...
* but we don't have one yet, so we will instead simply send a create
* console message to the Base Server. When we finally have a Console
* Server, this code should be changed to send connection data instead.
*/
AllocConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher;
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc),
sizeof(CSRSS_ALLOC_CONSOLE));
if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status))
{
DPRINT1("CSR Failed to give us a console\n");
/* We're lying here, so at least the process can load... */
return TRUE;
}
/* Nothing to do if not a console app */
if (NotConsole) return TRUE;
if (!ConnectInfo.ConsoleNeeded) return TRUE;
/* We got the handles, let's set them */
if ((Parameters->ConsoleHandle = AllocConsoleRequest->Console))
if ((Parameters->ConsoleHandle = ConnectInfo.Console))
{
/* If we already had some, don't use the new ones */
if (!Parameters->StandardInput)
{
Parameters->StandardInput = AllocConsoleRequest->InputHandle;
Parameters->StandardInput = ConnectInfo.InputHandle;
}
if (!Parameters->StandardOutput)
{
Parameters->StandardOutput = AllocConsoleRequest->OutputHandle;
Parameters->StandardOutput = ConnectInfo.OutputHandle;
}
if (!Parameters->StandardError)
{
Parameters->StandardError = AllocConsoleRequest->OutputHandle;
Parameters->StandardError = ConnectInfo.ErrorHandle;
}
}
InputWaitHandle = ConnectInfo.InputWaitHandle;
DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
Parameters->ConsoleHandle,
Parameters->StandardInput,
@ -403,9 +378,9 @@ DllMain(HANDLE hDll,
if (ConsoleInitialized == TRUE)
{
ConsoleInitialized = FALSE;
RtlDeleteCriticalSection (&ConsoleLock);
RtlDeleteCriticalSection(&ConsoleLock);
}
RtlDeleteCriticalSection (&BaseDllDirectoryLock);
RtlDeleteCriticalSection(&BaseDllDirectoryLock);
}
break;

View file

@ -581,6 +581,16 @@ BasepCreateFirstThread(HANDLE ProcessHandle,
CreateProcessRequest->CreationFlags = dwCreationFlags;
CreateProcessRequest->bInheritHandles = InheritHandles;
/*
* For GUI applications we turn on the 2nd bit. This also allows
* us to know whether or not the application is a GUI or CUI app.
*/
if (IMAGE_SUBSYSTEM_WINDOWS_GUI == SectionImageInfo->SubSystemType)
{
CreateProcessRequest->ProcessHandle = (HANDLE)
((ULONG_PTR)CreateProcessRequest->ProcessHandle | 2);
}
/* Call CSR */
DPRINT1("Calling CsrClientCallServer from BasepCreateFirstThread...\n");
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
@ -937,19 +947,19 @@ BasePushProcessParameters(IN ULONG ParameterFlags,
ProcessParameters->StandardError = StartupInfo->hStdError;
}
/* Use Special Flags for ConDllInitialize in Kernel32 */
/* Use Special Flags for BasepInitConsole in Kernel32 */
if (CreationFlags & DETACHED_PROCESS)
{
ProcessParameters->ConsoleHandle = HANDLE_DETACHED_PROCESS;
}
else if (CreationFlags & CREATE_NO_WINDOW)
{
ProcessParameters->ConsoleHandle = HANDLE_CREATE_NO_WINDOW;
}
else if (CreationFlags & CREATE_NEW_CONSOLE)
{
ProcessParameters->ConsoleHandle = HANDLE_CREATE_NEW_CONSOLE;
}
else if (CreationFlags & CREATE_NO_WINDOW)
{
ProcessParameters->ConsoleHandle = HANDLE_CREATE_NO_WINDOW;
}
else
{
/* Inherit our Console Handle */

View file

@ -186,6 +186,8 @@ VOID
NTAPI
BaseDllInitializeMemoryManager(VOID);
VOID WINAPI InitConsoleCtrlHandling(VOID);
BOOL WINAPI VerifyConsoleIoHandle(HANDLE Handle);
BOOL WINAPI CloseConsoleHandle(HANDLE Handle);

View file

@ -114,7 +114,16 @@ typedef enum _CONSRV_API_NUMBER
typedef struct _CONSOLE_CONNECTION_INFO
{
ULONG Dummy;
BOOL ConsoleNeeded; // Used for GUI apps only.
/* Copied from CSRSS_ALLOC_CONSOLE */
INT ShowCmd;
HANDLE Console; // ConsoleHandle // In fact, it is a PCSRSS_CONSOLE <-- correct that !!
HANDLE InputHandle;
HANDLE OutputHandle;
HANDLE ErrorHandle;
HANDLE InputWaitHandle;
LPTHREAD_START_ROUTINE CtrlDispatcher;
} CONSOLE_CONNECTION_INFO, *PCONSOLE_CONNECTION_INFO;
@ -157,12 +166,13 @@ typedef struct
typedef struct
{
LPTHREAD_START_ROUTINE CtrlDispatcher;
BOOL ConsoleNeeded;
INT ShowCmd;
HANDLE Console;
HANDLE Console; // ConsoleHandle // In fact, it is a PCSRSS_CONSOLE <-- correct that !!
HANDLE InputHandle;
HANDLE OutputHandle;
HANDLE ErrorHandle;
HANDLE InputWaitHandle;
LPTHREAD_START_ROUTINE CtrlDispatcher;
} CSRSS_ALLOC_CONSOLE, *PCSRSS_ALLOC_CONSOLE;
typedef struct

View file

@ -81,6 +81,11 @@ CSR_API(BaseSrvCreateProcess)
{
DebugFlags |= CsrProcessCreateNewGroup;
}
if ((Flags & 2) == 0)
{
DPRINT1("BaseSrvCreateProcess - Launching a Console process\n");
DebugFlags |= CsrProcessIsConsoleApp;
}
/* FIXME: SxS Stuff */
@ -129,8 +134,8 @@ CSR_API(BaseSrvCreateThread)
if (!CurrentThread)
{
DPRINT1("Server Thread TID: [%lx.%lx]\n",
CreateThreadRequest->ClientId.UniqueProcess,
CreateThreadRequest->ClientId.UniqueThread);
CreateThreadRequest->ClientId.UniqueProcess,
CreateThreadRequest->ClientId.UniqueThread);
return STATUS_SUCCESS; // server-to-server
}