+++ /dev/null
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS system libraries
- * FILE: dll/win32/kernel32/client/console/init.c
- * PURPOSE: Console API Client Initialization
- * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
- * Aleksey Bragin (aleksey@reactos.org)
- * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
- */
-
-/* INCLUDES *******************************************************************/
-
-#include <k32.h>
-
-// For Control Panel Applet
-#include <cpl.h>
-
-#define NDEBUG
-#include <debug.h>
-
-
-/* GLOBALS ********************************************************************/
-
-RTL_CRITICAL_SECTION ConsoleLock;
-BOOLEAN ConsoleInitialized = FALSE;
-extern HANDLE InputWaitHandle;
-
-static const PWSTR DefaultConsoleTitle = L"ReactOS Console";
-
-/* FUNCTIONS ******************************************************************/
-
-DWORD
-WINAPI
-PropDialogHandler(IN LPVOID lpThreadParameter)
-{
- // NOTE: lpThreadParameter corresponds to the client shared section handle.
-
- NTSTATUS Status = STATUS_SUCCESS;
- HMODULE hConsoleApplet = NULL;
- APPLET_PROC CPlApplet;
- static BOOL AlreadyDisplayingProps = FALSE;
- WCHAR szBuffer[MAX_PATH];
-
- /*
- * Do not launch more than once the console property dialog applet,
- * or (albeit less probable), if we are not initialized.
- */
- if (!ConsoleInitialized || AlreadyDisplayingProps)
- {
- /* Close the associated client shared section handle if needed */
- if (lpThreadParameter)
- CloseHandle((HANDLE)lpThreadParameter);
-
- return STATUS_UNSUCCESSFUL;
- }
-
- AlreadyDisplayingProps = TRUE;
-
- /* Load the control applet */
- GetSystemDirectoryW(szBuffer, MAX_PATH);
- wcscat(szBuffer, L"\\console.dll");
- hConsoleApplet = LoadLibraryW(szBuffer);
- if (hConsoleApplet == NULL)
- {
- DPRINT1("Failed to load console.dll\n");
- Status = STATUS_UNSUCCESSFUL;
- goto Quit;
- }
-
- /* Load its main function */
- CPlApplet = (APPLET_PROC)GetProcAddress(hConsoleApplet, "CPlApplet");
- if (CPlApplet == NULL)
- {
- DPRINT1("Error: console.dll misses CPlApplet export\n");
- Status = STATUS_UNSUCCESSFUL;
- goto Quit;
- }
-
- /* Initialize the applet */
- if (CPlApplet(NULL, CPL_INIT, 0, 0) == FALSE)
- {
- DPRINT1("Error: failed to initialize console.dll\n");
- Status = STATUS_UNSUCCESSFUL;
- goto Quit;
- }
-
- /* Check the count */
- if (CPlApplet(NULL, CPL_GETCOUNT, 0, 0) != 1)
- {
- DPRINT1("Error: console.dll returned unexpected CPL count\n");
- Status = STATUS_UNSUCCESSFUL;
- goto Quit;
- }
-
- /*
- * Start the applet. For Windows compatibility purposes we need
- * to pass the client shared section handle (lpThreadParameter)
- * via the hWnd parameter of the CPlApplet function.
- */
- CPlApplet((HWND)lpThreadParameter, CPL_DBLCLK, 0, 0);
-
- /* We have finished */
- CPlApplet(NULL, CPL_EXIT, 0, 0);
-
-Quit:
- if (hConsoleApplet) FreeLibrary(hConsoleApplet);
- AlreadyDisplayingProps = FALSE;
- return Status;
-}
-
-
-static INT
-ParseShellInfo(LPCWSTR lpszShellInfo,
- LPCWSTR lpszKeyword)
-{
- DPRINT("ParseShellInfo is UNIMPLEMENTED\n");
- return 0;
-}
-
-
-/*
- * NOTE:
- * The "LPDWORD Length" parameters point on input to the maximum size of
- * the buffers that can hold data (if != 0), and on output they hold the
- * real size of the data. If "Length" are == 0 on input, then on output
- * they receive the full size of the data.
- * The "LPWSTR* lpTitle" parameter has a double meaning:
- * - when "CaptureTitle" is TRUE, data is copied to the buffer pointed
- * by the pointer (*lpTitle).
- * - when "CaptureTitle" is FALSE, "*lpTitle" is set to the address of
- * the source data.
- */
-VOID
-SetUpConsoleInfo(IN BOOLEAN CaptureTitle,
- IN OUT LPDWORD pTitleLength,
- IN OUT LPWSTR* lpTitle OPTIONAL,
- IN OUT LPDWORD pDesktopLength,
- IN OUT LPWSTR* lpDesktop OPTIONAL,
- IN OUT PCONSOLE_START_INFO ConsoleStartInfo)
-{
- PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
- DWORD Length;
-
- /* Initialize the fields */
-
- ConsoleStartInfo->IconIndex = 0;
- ConsoleStartInfo->hIcon = NULL;
- ConsoleStartInfo->hIconSm = NULL;
- ConsoleStartInfo->dwStartupFlags = Parameters->WindowFlags;
- ConsoleStartInfo->nFont = 0;
- ConsoleStartInfo->nInputBufferSize = 0;
- ConsoleStartInfo->uCodePage = GetOEMCP();
-
- if (lpTitle)
- {
- LPWSTR Title;
-
- /* If we don't have any title, use the default one */
- if (Parameters->WindowTitle.Buffer == NULL)
- {
- Title = DefaultConsoleTitle;
- Length = lstrlenW(DefaultConsoleTitle) * sizeof(WCHAR); // sizeof(DefaultConsoleTitle);
- }
- else
- {
- Title = Parameters->WindowTitle.Buffer;
- Length = Parameters->WindowTitle.Length;
- }
-
- /* Retrieve the needed buffer size */
- Length += sizeof(WCHAR);
- if (*pTitleLength > 0) Length = min(Length, *pTitleLength);
- *pTitleLength = Length;
-
- /* Capture the data if needed, or, return a pointer to it */
- if (CaptureTitle)
- {
- /*
- * Length is always >= sizeof(WCHAR). Copy everything but the
- * possible trailing NULL character, and then NULL-terminate.
- */
- Length -= sizeof(WCHAR);
- RtlCopyMemory(*lpTitle, Title, Length);
- (*lpTitle)[Length / sizeof(WCHAR)] = UNICODE_NULL;
- }
- else
- {
- *lpTitle = Title;
- }
- }
- else
- {
- *pTitleLength = 0;
- }
-
- if (lpDesktop && Parameters->DesktopInfo.Buffer && *Parameters->DesktopInfo.Buffer)
- {
- /* Retrieve the needed buffer size */
- Length = Parameters->DesktopInfo.Length + sizeof(WCHAR);
- if (*pDesktopLength > 0) Length = min(Length, *pDesktopLength);
- *pDesktopLength = Length;
-
- /* Return a pointer to the data */
- *lpDesktop = Parameters->DesktopInfo.Buffer;
- }
- else
- {
- *pDesktopLength = 0;
- if (lpDesktop) *lpDesktop = NULL;
- }
-
- if (Parameters->WindowFlags & STARTF_USEFILLATTRIBUTE)
- {
- ConsoleStartInfo->wFillAttribute = (WORD)Parameters->FillAttribute;
- }
- if (Parameters->WindowFlags & STARTF_USECOUNTCHARS)
- {
- ConsoleStartInfo->dwScreenBufferSize.X = (SHORT)Parameters->CountCharsX;
- ConsoleStartInfo->dwScreenBufferSize.Y = (SHORT)Parameters->CountCharsY;
- }
- if (Parameters->WindowFlags & STARTF_USESHOWWINDOW)
- {
- ConsoleStartInfo->wShowWindow = (WORD)Parameters->ShowWindowFlags;
- }
- if (Parameters->WindowFlags & STARTF_USEPOSITION)
- {
- ConsoleStartInfo->dwWindowOrigin.X = (SHORT)Parameters->StartingX;
- ConsoleStartInfo->dwWindowOrigin.Y = (SHORT)Parameters->StartingY;
- }
- if (Parameters->WindowFlags & STARTF_USESIZE)
- {
- ConsoleStartInfo->dwWindowSize.X = (SHORT)Parameters->CountX;
- ConsoleStartInfo->dwWindowSize.Y = (SHORT)Parameters->CountY;
- }
-
- /* Get shell information (ShellInfo.Buffer is NULL-terminated) */
- if (Parameters->ShellInfo.Buffer != NULL)
- {
- ConsoleStartInfo->IconIndex = ParseShellInfo(Parameters->ShellInfo.Buffer, L"dde.");
-
- if ((Parameters->WindowFlags & STARTF_USEHOTKEY) == 0)
- ConsoleStartInfo->dwHotKey = ParseShellInfo(Parameters->ShellInfo.Buffer, L"hotkey.");
- else
- ConsoleStartInfo->dwHotKey = HandleToUlong(Parameters->StandardInput);
- }
-}
-
-
-VOID
-SetUpHandles(IN PCONSOLE_START_INFO ConsoleStartInfo)
-{
- PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
-
- if (ConsoleStartInfo->dwStartupFlags & STARTF_USEHOTKEY)
- {
- Parameters->WindowFlags &= ~STARTF_USEHOTKEY;
- }
- if (ConsoleStartInfo->dwStartupFlags & STARTF_SHELLPRIVATE)
- {
- Parameters->WindowFlags &= ~STARTF_SHELLPRIVATE;
- }
-
- /* We got the handles, let's set them */
- Parameters->ConsoleHandle = ConsoleStartInfo->ConsoleHandle;
-
- if ((ConsoleStartInfo->dwStartupFlags & STARTF_USESTDHANDLES) == 0)
- {
- Parameters->StandardInput = ConsoleStartInfo->InputHandle;
- Parameters->StandardOutput = ConsoleStartInfo->OutputHandle;
- Parameters->StandardError = ConsoleStartInfo->ErrorHandle;
- }
-}
-
-
-static BOOLEAN
-IsConsoleApp(VOID)
-{
- PIMAGE_NT_HEADERS ImageNtHeader = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
- return (ImageNtHeader && (ImageNtHeader->OptionalHeader.Subsystem ==
- IMAGE_SUBSYSTEM_WINDOWS_CUI));
-}
-
-
-static BOOLEAN
-ConnectConsole(IN PWSTR SessionDir,
- IN PCONSRV_API_CONNECTINFO ConnectInfo,
- OUT PBOOLEAN InServerProcess)
-{
- NTSTATUS Status;
- ULONG ConnectInfoSize = sizeof(*ConnectInfo);
-
- ASSERT(SessionDir);
-
- /* Connect to the Console Server */
- DPRINT("Connecting to the Console Server...\n");
- Status = CsrClientConnectToServer(SessionDir,
- CONSRV_SERVERDLL_INDEX,
- ConnectInfo,
- &ConnectInfoSize,
- InServerProcess);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status);
- return FALSE;
- }
-
- /* Nothing to do for server-to-server */
- if (*InServerProcess) return TRUE;
-
- /* Nothing to do if this is not a console app */
- if (!ConnectInfo->IsConsoleApp) return TRUE;
-
- /* Wait for the connection to finish */
- // Is ConnectInfo->ConsoleStartInfo.InitEvents aligned on handle boundary ????
- Status = NtWaitForMultipleObjects(MAX_INIT_EVENTS,
- ConnectInfo->ConsoleStartInfo.InitEvents,
- WaitAny, FALSE, NULL);
- if (!NT_SUCCESS(Status))
- {
- BaseSetLastNTError(Status);
- return FALSE;
- }
-
- NtClose(ConnectInfo->ConsoleStartInfo.InitEvents[INIT_SUCCESS]);
- NtClose(ConnectInfo->ConsoleStartInfo.InitEvents[INIT_FAILURE]);
- if (Status != INIT_SUCCESS)
- {
- NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-BOOLEAN
-WINAPI
-ConDllInitialize(IN ULONG Reason,
- IN PWSTR SessionDir)
-{
- NTSTATUS Status;
- PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
- BOOLEAN InServerProcess = FALSE;
- CONSRV_API_CONNECTINFO ConnectInfo;
- LCID lcid;
-
- if (Reason != DLL_PROCESS_ATTACH)
- {
- if ((Reason == DLL_THREAD_ATTACH) && IsConsoleApp())
- {
- /* Sets the current console locale for the new thread */
- SetTEBLangID(lcid);
- }
- else if (Reason == DLL_PROCESS_DETACH)
- {
- /* Free our resources */
- if (ConsoleInitialized != FALSE)
- {
- ConsoleInitialized = FALSE;
- RtlDeleteCriticalSection(&ConsoleLock);
- }
- }
-
- return TRUE;
- }
-
- DPRINT("ConDllInitialize for: %wZ\n"
- "Our current console handles are: 0x%p, 0x%p, 0x%p 0x%p\n",
- &Parameters->ImagePathName,
- 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;
-
- /* Show by default the console window when applicable */
- ConnectInfo.IsWindowVisible = TRUE;
- /* If this is a console app, a console will be created/opened */
- ConnectInfo.IsConsoleApp = IsConsoleApp();
-
- /* Do nothing if this is not a console app... */
- if (!ConnectInfo.IsConsoleApp)
- {
- DPRINT("Image is not a console application\n");
- }
-
- /*
- * 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");
- /*
- * The new process does not inherit its parent's console and cannot
- * attach to the console of its parent. The new process can call the
- * AllocConsole function at a later time to create a console.
- */
- Parameters->ConsoleHandle = NULL; // Do not inherit the parent's console.
- ConnectInfo.IsConsoleApp = FALSE; // Do not create any console.
- }
- else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
- {
- /* We'll get the real one soon */
- DPRINT("Creating a new separate console\n");
- /*
- * The new process has a new console, instead of inheriting
- * its parent's console.
- */
- Parameters->ConsoleHandle = NULL; // Do not inherit the parent's console.
- }
- else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW)
- {
- /* We'll get the real one soon */
- DPRINT("Creating a new invisible console\n");
- /*
- * The process is a console application that is being run
- * without a console window. Therefore, the console handle
- * for the application is not set.
- */
- Parameters->ConsoleHandle = NULL; // Do not inherit the parent's console.
- ConnectInfo.IsWindowVisible = FALSE; // A console is created but is not shown to the user.
- }
- else
- {
- DPRINT("Using existing console: 0x%p\n", Parameters->ConsoleHandle);
- }
-
- /* Do nothing if this is not a console app... */
- if (!ConnectInfo.IsConsoleApp)
- {
- /* Do not inherit the parent's console if we are not a console app */
- Parameters->ConsoleHandle = NULL;
- }
-
- /* Now use the proper console handle */
- ConnectInfo.ConsoleStartInfo.ConsoleHandle = Parameters->ConsoleHandle;
-
- /* Initialize the console dispatchers */
- ConnectInfo.CtrlRoutine = ConsoleControlDispatcher;
- ConnectInfo.PropRoutine = PropDialogHandler;
- // ConnectInfo.ImeRoutine = ImeRoutine;
-
- /* Set up the console properties */
- if (ConnectInfo.IsConsoleApp && Parameters->ConsoleHandle == NULL)
- {
- /*
- * We can set up the console properties only if we create a new one
- * (we do not inherit it from our parent).
- */
-
- LPWSTR ConsoleTitle = ConnectInfo.ConsoleTitle;
-
- ConnectInfo.TitleLength = sizeof(ConnectInfo.ConsoleTitle);
- ConnectInfo.DesktopLength = 0; // SetUpConsoleInfo will give us the real length.
-
- SetUpConsoleInfo(TRUE,
- &ConnectInfo.TitleLength,
- &ConsoleTitle,
- &ConnectInfo.DesktopLength,
- &ConnectInfo.Desktop,
- &ConnectInfo.ConsoleStartInfo);
- DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n",
- ConsoleTitle, ConnectInfo.Desktop);
- }
- else
- {
- ConnectInfo.TitleLength = 0;
- ConnectInfo.DesktopLength = 0;
- }
-
- /* Initialize the Input EXE name */
- if (ConnectInfo.IsConsoleApp)
- {
- LPWSTR CurDir = ConnectInfo.CurDir;
- LPWSTR AppName = ConnectInfo.AppName;
-
- InitExeName();
-
- ConnectInfo.CurDirLength = sizeof(ConnectInfo.CurDir);
- ConnectInfo.AppNameLength = sizeof(ConnectInfo.AppName);
-
- SetUpAppName(TRUE,
- &ConnectInfo.CurDirLength,
- &CurDir,
- &ConnectInfo.AppNameLength,
- &AppName);
- DPRINT("CurDir = '%S' - AppName = '%S'\n",
- CurDir, AppName);
- }
- else
- {
- ConnectInfo.CurDirLength = 0;
- ConnectInfo.AppNameLength = 0;
- }
-
- /*
- * Initialize Console Ctrl Handling, that needs to be supported by
- * all applications, especially because it is used at shutdown.
- */
- InitializeCtrlHandling();
-
- /* Connect to the Console Server */
- if (!ConnectConsole(SessionDir,
- &ConnectInfo,
- &InServerProcess))
- {
- // DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status);
- return FALSE;
- }
-
- /* If we are not doing server-to-server init and if this is a console app... */
- if (!InServerProcess && ConnectInfo.IsConsoleApp)
- {
- /* ... set the handles that we got */
- if (Parameters->ConsoleHandle == NULL)
- SetUpHandles(&ConnectInfo.ConsoleStartInfo);
-
- InputWaitHandle = ConnectInfo.ConsoleStartInfo.InputWaitHandle;
-
- /* Sets the current console locale for this thread */
- SetTEBLangID(lcid);
- }
-
- DPRINT("Console setup: 0x%p, 0x%p, 0x%p, 0x%p\n",
- Parameters->ConsoleHandle,
- Parameters->StandardInput,
- Parameters->StandardOutput,
- Parameters->StandardError);
-
- return TRUE;
-}
-
-/* EOF */