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

View file

@ -36,12 +36,9 @@ static BOOL DllInitialized = FALSE;
RTL_CRITICAL_SECTION BaseDllDirectoryLock; RTL_CRITICAL_SECTION BaseDllDirectoryLock;
RTL_CRITICAL_SECTION ConsoleLock; RTL_CRITICAL_SECTION ConsoleLock;
extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
extern DWORD WINAPI ConsoleControlDispatcher(IN LPVOID lpThreadParameter); extern DWORD WINAPI ConsoleControlDispatcher(IN LPVOID lpThreadParameter);
extern PHANDLER_ROUTINE InitialHandler[1]; extern HANDLE InputWaitHandle;
extern PHANDLER_ROUTINE* CtrlHandlers;
extern ULONG NrCtrlHandlers;
extern ULONG NrAllocatedHandlers;
extern BOOL FASTCALL NlsInit(VOID); extern BOOL FASTCALL NlsInit(VOID);
extern VOID FASTCALL NlsUninit(VOID); extern VOID FASTCALL NlsUninit(VOID);
@ -55,9 +52,6 @@ WINAPI
BasepInitConsole(VOID) BasepInitConsole(VOID)
{ {
NTSTATUS Status; NTSTATUS Status;
CONSOLE_API_MESSAGE ApiMessage;
PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest;
BOOLEAN NotConsole = FALSE;
PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
LPCWSTR ExeName; LPCWSTR ExeName;
STARTUPINFO si; STARTUPINFO si;
@ -65,12 +59,8 @@ BasepInitConsole(VOID)
ULONG SessionId = NtCurrentPeb()->SessionId; ULONG SessionId = NtCurrentPeb()->SessionId;
BOOLEAN InServer; BOOLEAN InServer;
// HACK CONSOLE_CONNECTION_INFO ConnectInfo;
/* ULONG ConnectInfoSize = sizeof(ConnectInfo);
CSR_CONNECTION_INFO CsrConnectionInfo;
ULONG ConnectionSize = sizeof(CsrConnectionInfo);
*/
// END HACK
WCHAR lpTest[MAX_PATH]; WCHAR lpTest[MAX_PATH];
GetModuleFileNameW(NULL, lpTest, MAX_PATH); GetModuleFileNameW(NULL, lpTest, MAX_PATH);
@ -79,28 +69,33 @@ BasepInitConsole(VOID)
Parameters->ConsoleHandle, Parameters->StandardInput, Parameters->ConsoleHandle, Parameters->StandardInput,
Parameters->StandardOutput, Parameters->StandardError); 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... */ /* We have nothing to do if this isn't a console app... */
if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem != if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem !=
IMAGE_SUBSYSTEM_WINDOWS_CUI) IMAGE_SUBSYSTEM_WINDOWS_CUI)
{ {
DPRINT("Image is not a console application\n"); DPRINT("Image is not a console application\n");
Parameters->ConsoleHandle = NULL; Parameters->ConsoleHandle = NULL;
AllocConsoleRequest->ConsoleNeeded = FALSE; ConnectInfo.ConsoleNeeded = FALSE; // ConsoleNeeded is used for knowing whether or not this is a CUI app.
} }
else else
{ {
/* Assume one is needed */ /* Assume one is needed */
GetStartupInfo(&si); GetStartupInfo(&si);
AllocConsoleRequest->ConsoleNeeded = TRUE; ConnectInfo.ConsoleNeeded = TRUE;
AllocConsoleRequest->ShowCmd = si.wShowWindow; 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) if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS)
{ {
/* No console to create */ /* No console to create */
DPRINT("No console to create\n"); DPRINT("No console to create\n");
Parameters->ConsoleHandle = NULL; Parameters->ConsoleHandle = NULL;
AllocConsoleRequest->ConsoleNeeded = FALSE; ConnectInfo.ConsoleNeeded = FALSE;
} }
else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE) else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
{ {
@ -113,33 +108,29 @@ BasepInitConsole(VOID)
/* We'll get the real one soon */ /* We'll get the real one soon */
DPRINT("Creating new invisible console\n"); DPRINT("Creating new invisible console\n");
Parameters->ConsoleHandle = NULL; Parameters->ConsoleHandle = NULL;
AllocConsoleRequest->ShowCmd = SW_HIDE; ConnectInfo.ShowCmd = SW_HIDE;
} }
else else
{ {
if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE) if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE)
{ {
Parameters->ConsoleHandle = 0; Parameters->ConsoleHandle = NULL;
} }
DPRINT("Using existing console: %x\n", Parameters->ConsoleHandle); 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 */ /* Initialize Console Ctrl Handler and input EXE name */
ConsoleInitialized = TRUE; InitConsoleCtrlHandling();
RtlInitializeCriticalSection(&ConsoleLock); ConnectInfo.CtrlDispatcher = ConsoleControlDispatcher;
NrAllocatedHandlers = 1;
NrCtrlHandlers = 1;
CtrlHandlers = InitialHandler;
CtrlHandlers[0] = DefaultConsoleCtrlHandler;
ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\'); ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\');
if (ExeName) if (ExeName)
SetConsoleInputExeNameW(ExeName + 1); SetConsoleInputExeNameW(ExeName + 1);
/* Now use the proper console handle */
AllocConsoleRequest->Console = Parameters->ConsoleHandle;
/* Setup the right Object Directory path */ /* Setup the right Object Directory path */
if (!SessionId) if (!SessionId)
{ {
@ -156,61 +147,45 @@ BasepInitConsole(VOID)
WIN_OBJ_DIR); WIN_OBJ_DIR);
} }
/* Connect to the base server */ /* Connect to the Console Server */
DPRINT("Connecting to CSR in BasepInitConsole...\n"); DPRINT("Connecting to the Console Server in BasepInitConsole...\n");
Status = CsrClientConnectToServer(SessionDir, Status = CsrClientConnectToServer(SessionDir,
CONSRV_SERVERDLL_INDEX, CONSRV_SERVERDLL_INDEX,
/* &CsrConnectionInfo, */ NULL, // TODO: Give it a console connection info &ConnectInfo,
/* &ConnectionSize, */ NULL, // TODO: Give it a console connection info &ConnectInfoSize,
&InServer); &InServer);
if (!NT_SUCCESS(Status)) 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; return FALSE;
} }
/* Nothing to do for server-to-server */ /* Nothing to do for server-to-server */
if (InServer) return TRUE; 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 */ /* 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 */ /* 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 we already had some, don't use the new ones */
if (!Parameters->StandardInput) if (!Parameters->StandardInput)
{ {
Parameters->StandardInput = AllocConsoleRequest->InputHandle; Parameters->StandardInput = ConnectInfo.InputHandle;
} }
if (!Parameters->StandardOutput) if (!Parameters->StandardOutput)
{ {
Parameters->StandardOutput = AllocConsoleRequest->OutputHandle; Parameters->StandardOutput = ConnectInfo.OutputHandle;
} }
if (!Parameters->StandardError) if (!Parameters->StandardError)
{ {
Parameters->StandardError = AllocConsoleRequest->OutputHandle; Parameters->StandardError = ConnectInfo.ErrorHandle;
} }
} }
InputWaitHandle = ConnectInfo.InputWaitHandle;
DPRINT("Console setup: %lx, %lx, %lx, %lx\n", DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
Parameters->ConsoleHandle, Parameters->ConsoleHandle,
Parameters->StandardInput, Parameters->StandardInput,
@ -403,9 +378,9 @@ DllMain(HANDLE hDll,
if (ConsoleInitialized == TRUE) if (ConsoleInitialized == TRUE)
{ {
ConsoleInitialized = FALSE; ConsoleInitialized = FALSE;
RtlDeleteCriticalSection (&ConsoleLock); RtlDeleteCriticalSection(&ConsoleLock);
} }
RtlDeleteCriticalSection (&BaseDllDirectoryLock); RtlDeleteCriticalSection(&BaseDllDirectoryLock);
} }
break; break;

View file

@ -581,6 +581,16 @@ BasepCreateFirstThread(HANDLE ProcessHandle,
CreateProcessRequest->CreationFlags = dwCreationFlags; CreateProcessRequest->CreationFlags = dwCreationFlags;
CreateProcessRequest->bInheritHandles = InheritHandles; 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 */ /* Call CSR */
DPRINT1("Calling CsrClientCallServer from BasepCreateFirstThread...\n"); DPRINT1("Calling CsrClientCallServer from BasepCreateFirstThread...\n");
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
@ -937,19 +947,19 @@ BasePushProcessParameters(IN ULONG ParameterFlags,
ProcessParameters->StandardError = StartupInfo->hStdError; ProcessParameters->StandardError = StartupInfo->hStdError;
} }
/* Use Special Flags for ConDllInitialize in Kernel32 */ /* Use Special Flags for BasepInitConsole in Kernel32 */
if (CreationFlags & DETACHED_PROCESS) if (CreationFlags & DETACHED_PROCESS)
{ {
ProcessParameters->ConsoleHandle = HANDLE_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) else if (CreationFlags & CREATE_NEW_CONSOLE)
{ {
ProcessParameters->ConsoleHandle = HANDLE_CREATE_NEW_CONSOLE; ProcessParameters->ConsoleHandle = HANDLE_CREATE_NEW_CONSOLE;
} }
else if (CreationFlags & CREATE_NO_WINDOW)
{
ProcessParameters->ConsoleHandle = HANDLE_CREATE_NO_WINDOW;
}
else else
{ {
/* Inherit our Console Handle */ /* Inherit our Console Handle */

View file

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

View file

@ -114,7 +114,16 @@ typedef enum _CONSRV_API_NUMBER
typedef struct _CONSOLE_CONNECTION_INFO 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; } CONSOLE_CONNECTION_INFO, *PCONSOLE_CONNECTION_INFO;
@ -157,12 +166,13 @@ typedef struct
typedef struct typedef struct
{ {
LPTHREAD_START_ROUTINE CtrlDispatcher;
BOOL ConsoleNeeded;
INT ShowCmd; INT ShowCmd;
HANDLE Console; HANDLE Console; // ConsoleHandle // In fact, it is a PCSRSS_CONSOLE <-- correct that !!
HANDLE InputHandle; HANDLE InputHandle;
HANDLE OutputHandle; HANDLE OutputHandle;
HANDLE ErrorHandle;
HANDLE InputWaitHandle;
LPTHREAD_START_ROUTINE CtrlDispatcher;
} CSRSS_ALLOC_CONSOLE, *PCSRSS_ALLOC_CONSOLE; } CSRSS_ALLOC_CONSOLE, *PCSRSS_ALLOC_CONSOLE;
typedef struct typedef struct

View file

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