- Make CONSRV_API_CONNECTINFO, CONSOLE_ALLOCCONSOLE and CONSOLE_ATTACHCONSOLE Windows 2k3-compatible, so that using either their kernel32 in ROS or our kernel32 in windows, works.
For that, complete and fix also the CONSOLE_START_INFO and CONSOLE_PROPERTIES structures.
- Rewrite Alloc/AttachConsole and the console initialization functions to match what Windows expects when connecting to the console server, and make them compatible with the fixed structures.
- Fix SrvAllocConsole and SrvAttachConsole accordingly, and few other console initialization functions in consrv.
- Fix input EXE name support and store also the current directory from which we were started.
- Use a temporarily define USE_CONSOLE_INIT_HANDLES that is not enabled yet because we do not use console initialization events (used by Windows for Alloc/AttachConsole and console initialization functions). Until this gets implemented in ReactOS, putting windows' kernel32 in ReactOS will fail when it will try to wait on those events.
- For SrvAlloc/SrvAttach/SrvFreeConsole, ConSrvConnect and ConSrvDisconnect: correctly mark the process as console app.
- Fix process initialization in ConSrvNewProcess.
- Get rid of CONSOLE_PROCESS_DATA::ParentConsoleHandle member.
- Temporarily move the link settings retrieval in console.c and hack a bit icon setting.
[CONSRV]
- Move console title setting from condrv back to consrv where it should belong in fact.
CORE-7931 #resolve #comment ConsolepAlloc and ConsolepAttach finally fixed in revision 64079.
svn path=/branches/condrv_restructure/; revision=64079
/* GLOBALS ********************************************************************/
extern RTL_CRITICAL_SECTION ConsoleLock;
-extern BOOL ConsoleInitialized;
-extern BOOL WINAPI IsDebuggerPresent(VOID);
+extern BOOLEAN ConsoleInitialized;
/* Console reserved "file" names */
static LPCWSTR BaseConFileName = CONSOLE_FILE_NAME;
static LPCWSTR BaseConInputFileName = CONSOLE_INPUT_FILE_NAME;
static LPCWSTR BaseConOutputFileName = CONSOLE_OUTPUT_FILE_NAME;
-PHANDLER_ROUTINE InitialHandler[1];
-PHANDLER_ROUTINE* CtrlHandlers;
-ULONG NrCtrlHandlers;
-ULONG NrAllocatedHandlers;
-BOOL LastCloseNotify = FALSE;
+/* Console Control handling */
+static PHANDLER_ROUTINE InitialHandler[1];
+static PHANDLER_ROUTINE* CtrlHandlers;
+static ULONG NrCtrlHandlers;
+static ULONG NrAllocatedHandlers;
+static BOOLEAN LastCloseNotify = FALSE;
+
+extern BOOL WINAPI IsDebuggerPresent(VOID);
+/* Console Input facilities */
HANDLE InputWaitHandle = INVALID_HANDLE_VALUE;
-#define INPUTEXENAME_BUFLEN 256
-static WCHAR InputExeName[INPUTEXENAME_BUFLEN];
+#define EXENAME_LENGTH 255 + 1
+static RTL_CRITICAL_SECTION ExeNameLock;
+static BOOLEAN ExeNameInitialized;
+static WCHAR ExeNameBuffer[EXENAME_LENGTH]; // NULL-terminated
+static USHORT ExeNameLength; // Count in number of characters without NULL
+static WCHAR StartDirBuffer[MAX_PATH + 1]; // NULL-terminated
+static USHORT StartDirLength; // Count in number of characters without NULL
/* Default Console Control Handler ********************************************/
-BOOL
+static BOOL
WINAPI
DefaultConsoleCtrlHandler(DWORD Event)
{
}
VOID
-WINAPI
-InitConsoleCtrlHandling(VOID)
+InitializeCtrlHandling(VOID)
{
/* Initialize Console Ctrl Handler */
NrAllocatedHandlers = NrCtrlHandlers = 1;
}
+/* Input EXE Name Support *****************************************************/
+
+VOID
+InitExeName(VOID)
+{
+ NTSTATUS Status;
+ PPEB Peb = NtCurrentPeb();
+ PCURDIR CurrentDirectory = &Peb->ProcessParameters->CurrentDirectory;
+ PLDR_DATA_TABLE_ENTRY ImageEntry;
+
+ if (ExeNameInitialized) return;
+
+ /* Initialize the EXE name lock */
+ Status = RtlInitializeCriticalSection(&ExeNameLock);
+ if (!NT_SUCCESS(Status)) return;
+ ExeNameInitialized = TRUE;
+
+ ImageEntry = CONTAINING_RECORD(Peb->Ldr->InLoadOrderModuleList.Flink,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+
+ /* Retrieve the EXE name, NULL-terminate it... */
+ ExeNameLength = min(sizeof(ExeNameBuffer)/sizeof(ExeNameBuffer[0]),
+ ImageEntry->BaseDllName.Length / sizeof(WCHAR));
+ RtlCopyMemory(ExeNameBuffer,
+ ImageEntry->BaseDllName.Buffer,
+ ImageEntry->BaseDllName.Length);
+ ExeNameBuffer[ExeNameLength] = UNICODE_NULL;
+
+ /* ... and retrieve the current directory path and NULL-terminate it. */
+ StartDirLength = min(sizeof(StartDirBuffer)/sizeof(StartDirBuffer[0]),
+ CurrentDirectory->DosPath.Length / sizeof(WCHAR));
+ RtlCopyMemory(StartDirBuffer,
+ CurrentDirectory->DosPath.Buffer,
+ CurrentDirectory->DosPath.Length);
+ StartDirBuffer[StartDirLength] = UNICODE_NULL;
+}
+
+/*
+ * 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* String" parameters have a double meaning:
+ * - when "CaptureStrings" is TRUE, data is copied to the buffers pointed
+ * by the pointers (*String).
+ * - when "CaptureStrings" is FALSE, "*String" are set to the addresses of
+ * the source data.
+ */
+VOID
+SetUpAppName(IN BOOLEAN CaptureStrings,
+ IN OUT LPDWORD CurDirLength,
+ IN OUT LPWSTR* CurDir,
+ IN OUT LPDWORD AppNameLength,
+ IN OUT LPWSTR* AppName)
+{
+ DWORD Length;
+
+ /* Retrieve the needed buffer size */
+ Length = (StartDirLength + 1) * sizeof(WCHAR);
+ if (*CurDirLength > 0) Length = min(Length, *CurDirLength);
+ *CurDirLength = Length;
+
+ /* Capture the data if needed, or, return a pointer to it */
+ if (CaptureStrings)
+ {
+ /*
+ * Length is always >= sizeof(WCHAR). Copy everything but the
+ * possible trailing NULL character, and then NULL-terminate.
+ */
+ Length -= sizeof(WCHAR);
+ RtlCopyMemory(*CurDir, StartDirBuffer, Length);
+ (*CurDir)[Length / sizeof(WCHAR)] = UNICODE_NULL;
+ }
+ else
+ {
+ *CurDir = StartDirBuffer;
+ }
+
+ /* Retrieve the needed buffer size */
+ Length = (ExeNameLength + 1) * sizeof(WCHAR);
+ if (*AppNameLength > 0) Length = min(Length, *AppNameLength);
+ *AppNameLength = Length;
+
+ /* Capture the data if needed, or, return a pointer to it */
+ if (CaptureStrings)
+ {
+ /*
+ * Length is always >= sizeof(WCHAR). Copy everything but the
+ * possible trailing NULL character, and then NULL-terminate.
+ */
+ Length -= sizeof(WCHAR);
+ RtlCopyMemory(*AppName, ExeNameBuffer, Length);
+ (*AppName)[Length / sizeof(WCHAR)] = UNICODE_NULL;
+ }
+ else
+ {
+ *AppName = ExeNameBuffer;
+ }
+}
+
+USHORT
+GetCurrentExeName(OUT PWCHAR ExeName,
+ IN USHORT BufferSize)
+{
+ USHORT ExeLength;
+
+ if (ExeNameInitialized)
+ {
+ RtlEnterCriticalSection(&ExeNameLock);
+
+ if (BufferSize > ExeNameLength * sizeof(WCHAR))
+ BufferSize = ExeNameLength * sizeof(WCHAR);
+
+ RtlCopyMemory(ExeName, ExeNameBuffer, BufferSize);
+
+ RtlLeaveCriticalSection(&ExeNameLock);
+ ExeLength = BufferSize;
+ }
+ else
+ {
+ *ExeName = UNICODE_NULL;
+ ExeLength = 0;
+ }
+
+ return ExeLength;
+}
+
/* FUNCTIONS ******************************************************************/
LPCWSTR
}
-/*--------------------------------------------------------------
- * AllocConsole
- *
+/*
* @implemented
*/
-BOOL
-WINAPI
-AllocConsole(VOID)
-{
+static BOOL
+IntAllocConsole(LPWSTR Title,
+ DWORD TitleLength,
+ LPWSTR Desktop,
+ DWORD DesktopLength,
+ LPWSTR CurDir,
+ DWORD CurDirLength,
+ LPWSTR AppName,
+ DWORD AppNameLength,
+ LPTHREAD_START_ROUTINE CtrlRoutine,
+ LPTHREAD_START_ROUTINE PropRoutine,
+ PCONSOLE_START_INFO ConsoleStartInfo)
+{
+ BOOL Success = TRUE;
+#ifdef USE_CONSOLE_INIT_HANDLES
NTSTATUS Status;
- PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
+#endif
+
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest;
PCSR_CAPTURE_BUFFER CaptureBuffer;
- if (Parameters->ConsoleHandle)
- {
- DPRINT1("AllocConsole: Allocating a console to a process already having one\n");
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
+ AllocConsoleRequest->CtrlRoutine = CtrlRoutine;
+ AllocConsoleRequest->PropRoutine = PropRoutine;
- CaptureBuffer = CsrAllocateCaptureBuffer(1, sizeof(CONSOLE_START_INFO));
+ CaptureBuffer = CsrAllocateCaptureBuffer(5, TitleLength +
+ DesktopLength +
+ CurDirLength +
+ AppNameLength +
+ sizeof(CONSOLE_START_INFO));
if (CaptureBuffer == NULL)
{
- DPRINT1("CsrAllocateCaptureBuffer failed!\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
+ Success = FALSE;
+ goto Quit;
}
- CsrAllocateMessagePointer(CaptureBuffer,
- sizeof(CONSOLE_START_INFO),
- (PVOID*)&AllocConsoleRequest->ConsoleStartInfo);
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ ConsoleStartInfo,
+ sizeof(CONSOLE_START_INFO),
+ (PVOID*)&AllocConsoleRequest->ConsoleStartInfo);
- InitConsoleInfo(AllocConsoleRequest->ConsoleStartInfo,
- &Parameters->ImagePathName);
+ AllocConsoleRequest->TitleLength = TitleLength;
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ Title,
+ TitleLength,
+ (PVOID*)&AllocConsoleRequest->ConsoleTitle);
- AllocConsoleRequest->ConsoleHandle = NULL;
- AllocConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher;
- AllocConsoleRequest->PropDispatcher = PropDialogHandler;
+ AllocConsoleRequest->DesktopLength = DesktopLength;
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ Desktop,
+ DesktopLength,
+ (PVOID*)&AllocConsoleRequest->Desktop);
- Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
- CaptureBuffer,
- CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc),
- sizeof(CONSOLE_ALLOCCONSOLE));
+ AllocConsoleRequest->CurDirLength = CurDirLength;
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ CurDir,
+ CurDirLength,
+ (PVOID*)&AllocConsoleRequest->CurDir);
- CsrFreeCaptureBuffer(CaptureBuffer);
+ AllocConsoleRequest->AppNameLength = AppNameLength;
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ AppName,
+ AppNameLength,
+ (PVOID*)&AllocConsoleRequest->AppName);
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ CaptureBuffer,
+ CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc),
+ sizeof(*AllocConsoleRequest));
+ if (!NT_SUCCESS(ApiMessage.Status))
+ {
+ BaseSetLastNTError(ApiMessage.Status);
+ Success = FALSE;
+ goto Quit;
+ }
+
+#ifdef USE_CONSOLE_INIT_HANDLES
+ // Is AllocConsoleRequest->ConsoleStartInfo->Events aligned on handle boundary ????
+ Status = NtWaitForMultipleObjects(2, AllocConsoleRequest->ConsoleStartInfo->Events,
+ WaitAny, FALSE, NULL);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
- return FALSE;
+ Success = FALSE;
+ goto Quit;
}
- Parameters->ConsoleHandle = AllocConsoleRequest->ConsoleHandle;
- SetStdHandle(STD_INPUT_HANDLE , AllocConsoleRequest->InputHandle );
- SetStdHandle(STD_OUTPUT_HANDLE, AllocConsoleRequest->OutputHandle);
- SetStdHandle(STD_ERROR_HANDLE , AllocConsoleRequest->ErrorHandle );
+ NtClose(AllocConsoleRequest->ConsoleStartInfo->Events[0]);
+ NtClose(AllocConsoleRequest->ConsoleStartInfo->Events[1]);
+ if (Status != STATUS_SUCCESS)
+ {
+ NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
+ Success = FALSE;
+ }
+ else
+#endif
+ {
+ RtlCopyMemory(ConsoleStartInfo,
+ AllocConsoleRequest->ConsoleStartInfo,
+ sizeof(CONSOLE_START_INFO));
+ Success = TRUE;
+ }
- /* Initialize Console Ctrl Handler */
- InitConsoleCtrlHandling();
+Quit:
+ if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
+ return Success;
+}
+
+BOOL
+WINAPI
+AllocConsole(VOID)
+{
+ BOOL Success;
+ CONSOLE_START_INFO ConsoleStartInfo;
- InputWaitHandle = AllocConsoleRequest->InputWaitHandle;
+ PWCHAR ConsoleTitle;
+ PWCHAR Desktop;
+ PWCHAR AppName;
+ PWCHAR CurDir;
- return TRUE;
+ ULONG TitleLength = (MAX_PATH + 1) * sizeof(WCHAR);
+ ULONG DesktopLength = (MAX_PATH + 1) * sizeof(WCHAR);
+ ULONG AppNameLength = 128 * sizeof(WCHAR);
+ ULONG CurDirLength = (MAX_PATH + 1) * sizeof(WCHAR);
+
+ LCID lcid;
+
+ RtlEnterCriticalSection(&ConsoleLock);
+
+ if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
+ {
+ DPRINT1("AllocConsole: Allocating a console to a process already having one\n");
+ SetLastError(ERROR_ACCESS_DENIED);
+ Success = FALSE;
+ goto Quit;
+ }
+
+ /* Set up the console properties */
+ SetUpConsoleInfo(FALSE,
+ &TitleLength,
+ &ConsoleTitle,
+ &DesktopLength,
+ &Desktop,
+ &ConsoleStartInfo);
+ DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n",
+ ConsoleTitle, Desktop);
+
+ /* Initialize the Input EXE name */
+ InitExeName();
+ SetUpAppName(FALSE,
+ &CurDirLength,
+ &CurDir,
+ &AppNameLength,
+ &AppName);
+ DPRINT("CurDir = '%S' - AppName = '%S'\n",
+ CurDir, AppName);
+
+ Success = IntAllocConsole(ConsoleTitle,
+ TitleLength,
+ Desktop,
+ DesktopLength,
+ CurDir,
+ CurDirLength,
+ AppName,
+ AppNameLength,
+ ConsoleControlDispatcher,
+ PropDialogHandler,
+ &ConsoleStartInfo);
+ if (Success)
+ {
+ /* Set up the handles */
+ SetUpHandles(&ConsoleStartInfo);
+ InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
+
+ /* Initialize Console Ctrl Handling */
+ InitializeCtrlHandling();
+
+ SetTEBLangID(lcid);
+ }
+
+Quit:
+ RtlLeaveCriticalSection(&ConsoleLock);
+ return Success;
}
-/*--------------------------------------------------------------
- * FreeConsole
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * GetConsoleScreenBufferInfo
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * SetConsoleCursorPosition
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * GetConsoleMode
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * SetConsoleMode
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * GetNumberOfConsoleInputEvents
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * GetLargestConsoleWindowSize
- *
+/*
* @implemented
*/
COORD
}
-/*--------------------------------------------------------------
- * GetConsoleCursorInfo
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * SetConsoleCursorInfo
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * GetNumberOfConsoleMouseButtons
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * SetConsoleActiveScreenBuffer
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * FlushConsoleInputBuffer
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * SetConsoleScreenBufferSize
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * ScrollConsoleScreenBufferA
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * ScrollConsoleScreenBufferW
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * SetConsoleWindowInfo
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * SetConsoleTextAttribute
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * GenerateConsoleCtrlEvent
- *
+/*
* @implemented
*/
BOOL
memcpy(lpConsoleTitle, TitleRequest->Title, TitleRequest->Length);
if (bUnicode)
- ((LPWSTR)lpConsoleTitle)[dwNumChars] = L'\0';
+ ((LPWSTR)lpConsoleTitle)[dwNumChars] = UNICODE_NULL;
else
- ((LPSTR)lpConsoleTitle)[dwNumChars] = '\0';
+ ((LPSTR)lpConsoleTitle)[dwNumChars] = ANSI_NULL;
}
CsrFreeCaptureBuffer(CaptureBuffer);
}
-/*--------------------------------------------------------------
- * GetConsoleTitleW
- *
+/*
* @implemented
*/
DWORD
}
-/*--------------------------------------------------------------
- * GetConsoleTitleA
- *
+/*
* @implemented
*/
DWORD
return TRUE;
}
-/*--------------------------------------------------------------
- * SetConsoleTitleW
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * SetConsoleTitleA
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * CreateConsoleScreenBuffer
- *
+/*
* @implemented
*/
HANDLE
}
-/*--------------------------------------------------------------
- * GetConsoleCP
- *
+/*
* @implemented
*/
UINT
}
-/*--------------------------------------------------------------
- * SetConsoleCP
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * GetConsoleOutputCP
- *
+/*
* @implemented
*/
UINT
}
-/*--------------------------------------------------------------
- * SetConsoleOutputCP
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * GetConsoleProcessList
- *
+/*
* @implemented
*/
DWORD
}
-/*--------------------------------------------------------------
- * GetConsoleSelectionInfo
- *
+/*
* @implemented
*/
BOOL
}
-/*--------------------------------------------------------------
- * AttachConsole
- *
+/*
* @implemented
- *
* @note Strongly inspired by AllocConsole.
*/
-BOOL
-WINAPI
-AttachConsole(DWORD dwProcessId)
+static BOOL
+IntAttachConsole(DWORD ProcessId,
+ LPTHREAD_START_ROUTINE CtrlRoutine,
+ LPTHREAD_START_ROUTINE PropRoutine,
+ PCONSOLE_START_INFO ConsoleStartInfo)
{
+ BOOL Success = TRUE;
+#ifdef USE_CONSOLE_INIT_HANDLES
NTSTATUS Status;
- PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
+#endif
+
CONSOLE_API_MESSAGE ApiMessage;
PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest;
+ PCSR_CAPTURE_BUFFER CaptureBuffer;
+
+ AttachConsoleRequest->ProcessId = ProcessId;
+ AttachConsoleRequest->CtrlRoutine = CtrlRoutine;
+ AttachConsoleRequest->PropRoutine = PropRoutine;
- if (Parameters->ConsoleHandle)
+ CaptureBuffer = CsrAllocateCaptureBuffer(1, sizeof(CONSOLE_START_INFO));
+ if (CaptureBuffer == NULL)
{
- DPRINT1("AttachConsole: Attaching a console to a process already having one\n");
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ Success = FALSE;
+ goto Quit;
}
- AttachConsoleRequest->ProcessId = dwProcessId;
- AttachConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher;
- AttachConsoleRequest->PropDispatcher = PropDialogHandler;
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ ConsoleStartInfo,
+ sizeof(CONSOLE_START_INFO),
+ (PVOID*)&AttachConsoleRequest->ConsoleStartInfo);
+
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ CaptureBuffer,
+ CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAttach),
+ sizeof(*AttachConsoleRequest));
+ if (!NT_SUCCESS(ApiMessage.Status))
+ {
+ BaseSetLastNTError(ApiMessage.Status);
+ Success = FALSE;
+ goto Quit;
+ }
- Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
- NULL,
- CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAttach),
- sizeof(CONSOLE_ATTACHCONSOLE));
+#ifdef USE_CONSOLE_INIT_HANDLES
+ // Is AttachConsoleRequest->ConsoleStartInfo->Events aligned on handle boundary ????
+ Status = NtWaitForMultipleObjects(2, AttachConsoleRequest->ConsoleStartInfo->Events,
+ WaitAny, FALSE, NULL);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
- return FALSE;
+ Success = FALSE;
+ goto Quit;
}
- Parameters->ConsoleHandle = AttachConsoleRequest->ConsoleHandle;
- SetStdHandle(STD_INPUT_HANDLE , AttachConsoleRequest->InputHandle );
- SetStdHandle(STD_OUTPUT_HANDLE, AttachConsoleRequest->OutputHandle);
- SetStdHandle(STD_ERROR_HANDLE , AttachConsoleRequest->ErrorHandle );
+ NtClose(AttachConsoleRequest->ConsoleStartInfo->Events[0]);
+ NtClose(AttachConsoleRequest->ConsoleStartInfo->Events[1]);
+ if (Status != STATUS_SUCCESS)
+ {
+ NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
+ Success = FALSE;
+ }
+ else
+#endif
+ {
+ RtlCopyMemory(ConsoleStartInfo,
+ AttachConsoleRequest->ConsoleStartInfo,
+ sizeof(CONSOLE_START_INFO));
+ Success = TRUE;
+ }
- /* Initialize Console Ctrl Handler */
- InitConsoleCtrlHandling();
+Quit:
+ if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
+ return Success;
+}
- InputWaitHandle = AttachConsoleRequest->InputWaitHandle;
+BOOL
+WINAPI
+AttachConsole(DWORD dwProcessId)
+{
+ BOOL Success;
+ CONSOLE_START_INFO ConsoleStartInfo;
- return TRUE;
+ DWORD dummy;
+ LCID lcid;
+
+ RtlEnterCriticalSection(&ConsoleLock);
+
+ if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
+ {
+ DPRINT1("AttachConsole: Attaching a console to a process already having one\n");
+ SetLastError(ERROR_ACCESS_DENIED);
+ Success = FALSE;
+ goto Quit;
+ }
+
+ /* Set up the console properties */
+ SetUpConsoleInfo(FALSE,
+ &dummy,
+ NULL,
+ &dummy,
+ NULL,
+ &ConsoleStartInfo);
+
+ Success = IntAttachConsole(dwProcessId,
+ ConsoleControlDispatcher,
+ PropDialogHandler,
+ &ConsoleStartInfo);
+ if (Success)
+ {
+ /* Set up the handles */
+ SetUpHandles(&ConsoleStartInfo);
+ InputWaitHandle = ConsoleStartInfo.InputWaitHandle;
+
+ /* Initialize Console Ctrl Handling */
+ InitializeCtrlHandling();
+
+ SetTEBLangID(lcid);
+ }
+
+Quit:
+ RtlLeaveCriticalSection(&ConsoleLock);
+ return Success;
}
-/*--------------------------------------------------------------
- * GetConsoleWindow
- *
+/*
* @implemented
*/
HWND
}
-/*--------------------------------------------------------------
- * SetConsoleIcon
- *
+/*
* @implemented
*/
BOOL
/******************************************************************************
* \name SetConsoleInputExeNameW
* \brief Sets the console input file name from a unicode string.
- * \param lpInputExeName Pointer to a unicode string with the name.
+ * \param lpExeName Pointer to a unicode string with the name.
* \return TRUE if successful, FALSE if unsuccsedful.
- * \remarks If lpInputExeName is 0 or the string length is 0 or greater than 255,
+ * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
* the function fails and sets last error to ERROR_INVALID_PARAMETER.
*/
BOOL
WINAPI
-SetConsoleInputExeNameW(LPCWSTR lpInputExeName)
+SetConsoleInputExeNameW(IN LPWSTR lpExeName)
{
- int lenName;
+ DWORD ExeLength;
- if ( !lpInputExeName ||
- (lenName = lstrlenW(lpInputExeName)) == 0 ||
- lenName > INPUTEXENAME_BUFLEN - 1 )
+ ExeLength = lstrlenW(lpExeName);
+ if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
{
/* Fail if string is empty or too long */
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
- RtlEnterCriticalSection(&ConsoleLock);
+ RtlEnterCriticalSection(&ExeNameLock);
_SEH2_TRY
{
- RtlCopyMemory(InputExeName, lpInputExeName, lenName * sizeof(WCHAR));
- InputExeName[lenName] = L'\0';
+ /* Set the input EXE name, not NULL terminated */
+ RtlCopyMemory(ExeNameBuffer, lpExeName, ExeLength * sizeof(WCHAR));
+ ExeNameLength = (USHORT)ExeLength;
}
_SEH2_FINALLY
{
- RtlLeaveCriticalSection(&ConsoleLock);
+ RtlLeaveCriticalSection(&ExeNameLock);
}
_SEH2_END;
/******************************************************************************
* \name SetConsoleInputExeNameA
* \brief Sets the console input file name from an ansi string.
- * \param lpInputExeName Pointer to an ansi string with the name.
+ * \param lpExeName Pointer to an ansi string with the name.
* \return TRUE if successful, FALSE if unsuccsedful.
- * \remarks If lpInputExeName is 0 or the string length is 0 or greater than 255,
+ * \remarks If lpExeName is 0 or the string length is 0 or greater than 255,
* the function fails and sets last error to ERROR_INVALID_PARAMETER.
*/
BOOL
WINAPI
-SetConsoleInputExeNameA(LPCSTR lpInputExeName)
+SetConsoleInputExeNameA(IN LPSTR lpExeName)
{
- WCHAR Buffer[INPUTEXENAME_BUFLEN];
- ANSI_STRING InputExeNameA;
- UNICODE_STRING InputExeNameU;
NTSTATUS Status;
+#ifdef USE_TEB_STATIC_USTR
+ PUNICODE_STRING ExeNameU;
+#else
+ UNICODE_STRING ExeNameU;
+#endif
+ ANSI_STRING ExeNameA;
+#ifndef USE_TEB_STATIC_USTR
+ WCHAR Buffer[EXENAME_LENGTH];
+#endif
+
+#ifdef USE_TEB_STATIC_USTR
+ /*
+ * Use the TEB static UNICODE string for storage. It is already
+ * initialized at process creation time by the Memory Manager.
+ */
+ ExeNameU = &NtCurrentTeb()->StaticUnicodeString;
+#endif
- RtlInitAnsiString(&InputExeNameA, lpInputExeName);
+ /* Initialize string for conversion */
+ RtlInitAnsiString(&ExeNameA, lpExeName);
- if ( InputExeNameA.Length == 0 ||
- InputExeNameA.Length > INPUTEXENAME_BUFLEN - 1 )
+#if 1
+ if ((ExeNameA.Length == 0) || (ExeNameA.Length >= EXENAME_LENGTH))
{
/* Fail if string is empty or too long */
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
-
- InputExeNameU.Buffer = Buffer;
- InputExeNameU.MaximumLength = sizeof(Buffer);
- InputExeNameU.Length = 0;
-
- Status = RtlAnsiStringToUnicodeString(&InputExeNameU, &InputExeNameA, FALSE);
+#endif
+#ifndef USE_TEB_STATIC_USTR
+ ExeNameU.Length = 0;
+ ExeNameU.MaximumLength = (USHORT)sizeof(Buffer);
+ ExeNameU.Buffer = Buffer;
+#endif
+
+#ifdef USE_TEB_STATIC_USTR
+ Status = RtlAnsiStringToUnicodeString(ExeNameU, &ExeNameA, FALSE);
+#else
+ Status = RtlAnsiStringToUnicodeString(&ExeNameU, &ExeNameA, FALSE);
+#endif
if (!NT_SUCCESS(Status))
{
- BaseSetLastNTError(Status);
+ /* Fail if string is empty or too long */
+ if (Status == STATUS_BUFFER_OVERFLOW)
+ SetLastError(ERROR_FILENAME_EXCED_RANGE);
+ else
+ SetLastError(ERROR_INVALID_PARAMETER);
+
return FALSE;
}
- return SetConsoleInputExeNameW(InputExeNameU.Buffer);
+#ifdef USE_TEB_STATIC_USTR
+ return SetConsoleInputExeNameW(ExeNameU->Buffer);
+#else
+ return SetConsoleInputExeNameW(ExeNameU.Buffer);
+#endif
}
*/
DWORD
WINAPI
-GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer)
+GetConsoleInputExeNameW(IN DWORD nBufferLength,
+ OUT LPWSTR lpExeName)
{
- ULONG lenName = lstrlenW(InputExeName);
-
- if (nBufferLength == 0)
+ if (nBufferLength <= ExeNameLength)
{
- /* Buffer size is requested, return it */
- return lenName + 1;
- }
-
- if (lenName + 1 > nBufferLength)
- {
- /* Buffer is not large enough! */
+ /* Buffer is not large enough! Return the correct size. */
SetLastError(ERROR_BUFFER_OVERFLOW);
- return 2;
+ return ExeNameLength + 1;
}
- RtlEnterCriticalSection(&ConsoleLock);
+ RtlEnterCriticalSection(&ExeNameLock);
_SEH2_TRY
{
- RtlCopyMemory(lpBuffer, InputExeName, lenName * sizeof(WCHAR));
- lpBuffer[lenName] = '\0';
+ /* Copy the input EXE name and NULL-terminate it */
+ RtlCopyMemory(lpExeName, ExeNameBuffer, ExeNameLength * sizeof(WCHAR));
+ lpExeName[ExeNameLength] = UNICODE_NULL;
}
_SEH2_FINALLY
{
- RtlLeaveCriticalSection(&ConsoleLock);
+ RtlLeaveCriticalSection(&ExeNameLock);
}
_SEH2_END;
- /* Success, return 1 */
- return 1;
+ return TRUE;
}
*/
DWORD
WINAPI
-GetConsoleInputExeNameA(DWORD nBufferLength, LPSTR lpBuffer)
+GetConsoleInputExeNameA(IN DWORD nBufferLength,
+ OUT LPSTR lpExeName)
{
- WCHAR Buffer[INPUTEXENAME_BUFLEN];
- DWORD Ret;
+ NTSTATUS Status;
+ DWORD ExeLength;
UNICODE_STRING BufferU;
ANSI_STRING BufferA;
+ WCHAR Buffer[EXENAME_LENGTH];
- /* Get the unicode name */
- Ret = GetConsoleInputExeNameW(sizeof(Buffer) / sizeof(Buffer[0]), Buffer);
+ /* Get the UNICODE name */
+ ExeLength = GetConsoleInputExeNameW(EXENAME_LENGTH, Buffer);
- /* Initialize strings for conversion */
+ if ((ExeLength == 0) || (ExeLength >= EXENAME_LENGTH))
+ return ExeLength;
+
+ /* Initialize the strings for conversion */
RtlInitUnicodeString(&BufferU, Buffer);
BufferA.Length = 0;
BufferA.MaximumLength = (USHORT)nBufferLength;
- BufferA.Buffer = lpBuffer;
-
- /* Convert unicode name to ansi, copying as much chars as fit */
- RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE);
+ BufferA.Buffer = lpExeName;
- /* Error handling */
- if (nBufferLength <= BufferU.Length / sizeof(WCHAR))
+ /* Convert UNICODE name to ANSI, copying as much chars as it can fit */
+ Status = RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE);
+ if (!NT_SUCCESS(Status))
{
- SetLastError(ERROR_BUFFER_OVERFLOW);
- return 2;
+ if (Status == STATUS_BUFFER_OVERFLOW)
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return ExeLength + 1;
+ }
+ SetLastError(ERROR_INVALID_PARAMETER);
}
- return Ret;
+ return ExeLength;
}
BOOL
/* GLOBALS ********************************************************************/
RTL_CRITICAL_SECTION ConsoleLock;
-BOOL ConsoleInitialized = FALSE;
+BOOLEAN ConsoleInitialized = FALSE;
extern HANDLE InputWaitHandle;
static HMODULE ConsoleLibrary = NULL;
static BOOL AlreadyDisplayingProps = FALSE;
-#define WIN_OBJ_DIR L"\\Windows"
-#define SESSION_DIR L"\\Sessions"
+static const PWSTR DefaultConsoleTitle = L"ReactOS Console";
/* FUNCTIONS ******************************************************************/
{
// NOTE: lpThreadParameter corresponds to the client shared section handle.
+ NTSTATUS Status = STATUS_SUCCESS;
APPLET_PROC CPLFunc;
/*
GetSystemDirectoryW(szBuffer, MAX_PATH);
wcscat(szBuffer, L"\\console.dll");
ConsoleLibrary = LoadLibraryW(szBuffer);
-
if (ConsoleLibrary == NULL)
{
DPRINT1("Failed to load console.dll\n");
- AlreadyDisplayingProps = FALSE;
- return STATUS_UNSUCCESSFUL;
+ Status = STATUS_UNSUCCESSFUL;
+ goto Quit;
}
}
CPLFunc = (APPLET_PROC)GetProcAddress(ConsoleLibrary, "CPlApplet");
if (CPLFunc == NULL)
{
- DPRINT("Error: Console.dll misses CPlApplet export\n");
- AlreadyDisplayingProps = FALSE;
- return STATUS_UNSUCCESSFUL;
+ DPRINT1("Error: Console.dll misses CPlApplet export\n");
+ Status = STATUS_UNSUCCESSFUL;
+ goto Quit;
}
if (CPLFunc(NULL, CPL_INIT, 0, 0) == FALSE)
{
- DPRINT("Error: failed to initialize console.dll\n");
- AlreadyDisplayingProps = FALSE;
- return STATUS_UNSUCCESSFUL;
+ DPRINT1("Error: failed to initialize console.dll\n");
+ Status = STATUS_UNSUCCESSFUL;
+ goto Quit;
}
if (CPLFunc(NULL, CPL_GETCOUNT, 0, 0) != 1)
{
- DPRINT("Error: console.dll returned unexpected CPL count\n");
- AlreadyDisplayingProps = FALSE;
- return STATUS_UNSUCCESSFUL;
+ DPRINT1("Error: console.dll returned unexpected CPL count\n");
+ Status = STATUS_UNSUCCESSFUL;
+ goto Quit;
}
CPLFunc(NULL, CPL_DBLCLK, (LPARAM)lpThreadParameter, 0);
CPLFunc(NULL, CPL_EXIT , 0, 0);
+Quit:
AlreadyDisplayingProps = FALSE;
- return STATUS_SUCCESS;
+ return Status;
}
-VOID
-InitConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
- IN PUNICODE_STRING ImagePathName)
+static INT
+ParseShellInfo(LPCWSTR lpszShellInfo,
+ LPCWSTR lpszKeyword)
{
- STARTUPINFOW si;
- SIZE_T Length;
+ DPRINT1("ParseShellInfo is UNIMPLEMENTED\n");
+ return 0;
+}
- /* Get the startup information */
- GetStartupInfoW(&si);
+
+/*
+ * 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->dwStartupFlags = si.dwFlags;
- if (si.dwFlags & STARTF_USEFILLATTRIBUTE)
+
+ ConsoleStartInfo->IconIndex = 0;
+ ConsoleStartInfo->hIcon = NULL;
+ ConsoleStartInfo->hIconSm = NULL;
+ ConsoleStartInfo->dwStartupFlags = Parameters->WindowFlags;
+ ConsoleStartInfo->nFont = 0;
+ ConsoleStartInfo->nInputBufferSize = 0;
+ ConsoleStartInfo->uCodePage = GetOEMCP();
+
+ if (lpTitle)
{
- ConsoleStartInfo->wFillAttribute = (WORD)si.dwFillAttribute;
+ 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 (si.dwFlags & STARTF_USECOUNTCHARS)
+
+ if (lpDesktop && Parameters->DesktopInfo.Buffer && *Parameters->DesktopInfo.Buffer)
{
- ConsoleStartInfo->dwScreenBufferSize.X = (SHORT)(si.dwXCountChars);
- ConsoleStartInfo->dwScreenBufferSize.Y = (SHORT)(si.dwYCountChars);
+ /* 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;
}
- if (si.dwFlags & STARTF_USESHOWWINDOW)
+ else
{
- ConsoleStartInfo->wShowWindow = si.wShowWindow;
+ *pDesktopLength = 0;
+ if (lpDesktop) *lpDesktop = NULL;
}
- if (si.dwFlags & STARTF_USEPOSITION)
+
+ if (Parameters->WindowFlags & STARTF_USEFILLATTRIBUTE)
+ {
+ ConsoleStartInfo->wFillAttribute = (WORD)Parameters->FillAttribute;
+ }
+ if (Parameters->WindowFlags & STARTF_USECOUNTCHARS)
{
- ConsoleStartInfo->dwWindowOrigin.X = (SHORT)(si.dwX);
- ConsoleStartInfo->dwWindowOrigin.Y = (SHORT)(si.dwY);
+ ConsoleStartInfo->dwScreenBufferSize.X = (SHORT)Parameters->CountCharsX;
+ ConsoleStartInfo->dwScreenBufferSize.Y = (SHORT)Parameters->CountCharsY;
}
- if (si.dwFlags & STARTF_USESIZE)
+ if (Parameters->WindowFlags & STARTF_USESHOWWINDOW)
{
- ConsoleStartInfo->dwWindowSize.X = (SHORT)(si.dwXSize);
- ConsoleStartInfo->dwWindowSize.Y = (SHORT)(si.dwYSize);
+ 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;
}
- /* Set up the title for the console */
- if (si.lpTitle)
+ /* Get shell information (ShellInfo.Buffer is NULL-terminated) */
+ if (Parameters->ShellInfo.Buffer != NULL)
{
- wcsncpy(ConsoleStartInfo->ConsoleTitle, si.lpTitle, MAX_PATH + 1);
+ 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);
}
- else
+}
+
+
+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))
{
- ConsoleStartInfo->ConsoleTitle[0] = L'\0';
+ Parameters->StandardInput = ConsoleStartInfo->InputHandle;
+ Parameters->StandardOutput = ConsoleStartInfo->OutputHandle;
+ Parameters->StandardError = ConsoleStartInfo->ErrorHandle;
}
+}
- /* Retrieve the application path name */
- Length = min(sizeof(ConsoleStartInfo->AppPath) / sizeof(ConsoleStartInfo->AppPath[0]) - 1,
- ImagePathName->Length / sizeof(WCHAR));
- wcsncpy(ConsoleStartInfo->AppPath, ImagePathName->Buffer, Length);
- ConsoleStartInfo->AppPath[Length] = L'\0';
- /* The Console Server will use these fields to set up the console icon */
- ConsoleStartInfo->IconPath[0] = L'\0';
- ConsoleStartInfo->IconIndex = 0;
+static BOOLEAN
+IsConsoleApp(VOID)
+{
+ PIMAGE_NT_HEADERS ImageNtHeader = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
+ return (ImageNtHeader && (ImageNtHeader->OptionalHeader.Subsystem ==
+ IMAGE_SUBSYSTEM_WINDOWS_CUI));
}
-BOOL
+static BOOLEAN
+ConnectConsole(IN PWSTR SessionDir,
+ IN PCONSRV_API_CONNECTINFO ConnectInfo,
+ OUT PBOOLEAN IsServerProcess)
+{
+ 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,
+ IsServerProcess);
+ 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 (*IsServerProcess) return TRUE;
+
+ /* Nothing to do if this is not a console app */
+ if (!ConnectInfo->IsConsoleApp) return TRUE;
+
+#ifdef USE_CONSOLE_INIT_HANDLES
+ /* Wait for the connection to finish */
+ Status = NtWaitForMultipleObjects(2, ConnectInfo->ConsoleStartInfo.Events,
+ WaitAny, FALSE, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ return FALSE;
+ }
+
+ NtClose(ConnectInfo->ConsoleStartInfo.Events[0]);
+ NtClose(ConnectInfo->ConsoleStartInfo.Events[1]);
+
+ if (Status != STATUS_SUCCESS)
+ {
+ NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL;
+ return FALSE;
+ }
+#endif
+
+ return TRUE;
+}
+
+
+BOOLEAN
WINAPI
-BasepInitConsole(VOID)
+ConDllInitialize(IN ULONG Reason,
+ IN PWSTR SessionDir)
{
NTSTATUS Status;
PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
- WCHAR SessionDir[256];
- ULONG SessionId = NtCurrentPeb()->SessionId;
- BOOLEAN InServer;
-
+ BOOLEAN IsServerProcess;
CONSRV_API_CONNECTINFO ConnectInfo;
- ULONG ConnectInfoSize = sizeof(ConnectInfo);
+ LCID lcid;
- DPRINT("BasepInitConsole for : %wZ\n", &Parameters->ImagePathName);
- DPRINT("Our current console handles are: %p, %p, %p %p\n",
- Parameters->ConsoleHandle, Parameters->StandardInput,
- Parameters->StandardOutput, Parameters->StandardError);
+ if (Reason != DLL_PROCESS_ATTACH)
+ {
+ if (Reason != DLL_THREAD_ATTACH || !IsConsoleApp())
+ return TRUE;
+
+ // Reason == DLL_THREAD_ATTACH and IsConsoleApp;
+ goto Exit;
+ }
+
+ 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;
- /* Do nothing if this isn't a console app... */
- if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem !=
- IMAGE_SUBSYSTEM_WINDOWS_CUI)
+ /* 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");
- Parameters->ConsoleHandle = NULL;
- ConnectInfo.ConsoleStartInfo.ConsoleNeeded = FALSE; // ConsoleNeeded is used for knowing whether or not this is a CUI app.
+ }
- ConnectInfo.ConsoleStartInfo.ConsoleTitle[0] = L'\0';
- ConnectInfo.ConsoleStartInfo.AppPath[0] = L'\0';
+ /*
+ * 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
{
- LPCWSTR ExeName;
+ DPRINT("Using existing console: 0x%p\n", Parameters->ConsoleHandle);
+ }
- InitConsoleInfo(&ConnectInfo.ConsoleStartInfo,
- &Parameters->ImagePathName);
+ /* 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;
+ }
- /* Initialize Input EXE name */
- ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\');
- if (ExeName) SetConsoleInputExeNameW(ExeName + 1);
+ /* Now use the proper console handle */
+ ConnectInfo.ConsoleStartInfo.ConsoleHandle = Parameters->ConsoleHandle;
- /* Assume one is needed */
- ConnectInfo.ConsoleStartInfo.ConsoleNeeded = TRUE;
+ /* Initialize the console dispatchers */
+ ConnectInfo.CtrlRoutine = ConsoleControlDispatcher;
+ ConnectInfo.PropRoutine = PropDialogHandler;
+ // ConnectInfo.ImeRoutine = ImeRoutine;
- /* 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;
- ConnectInfo.ConsoleStartInfo.ConsoleNeeded = FALSE;
- }
- else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
- {
- /* We'll get the real one soon */
- DPRINT("Creating new console\n");
- Parameters->ConsoleHandle = NULL;
- }
- else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW)
- {
- /* We'll get the real one soon */
- DPRINT("Creating new invisible console\n");
- Parameters->ConsoleHandle = NULL;
- ConnectInfo.ConsoleStartInfo.wShowWindow = SW_HIDE;
- }
- else
- {
- if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE)
- {
- Parameters->ConsoleHandle = NULL;
- }
- DPRINT("Using existing console: %p\n", Parameters->ConsoleHandle);
- }
+ /* 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;
}
- /* Now use the proper console handle */
- ConnectInfo.ConsoleHandle = Parameters->ConsoleHandle;
+ /* Initialize the Input EXE name */
+ if (ConnectInfo.IsConsoleApp)
+ {
+ LPWSTR CurDir = ConnectInfo.CurDir;
+ LPWSTR AppName = ConnectInfo.AppName;
- /* Initialize the Console Ctrl Handler */
- InitConsoleCtrlHandling();
- ConnectInfo.ConsoleStartInfo.CtrlDispatcher = ConsoleControlDispatcher;
+ InitExeName();
- /* Initialize the Property Dialog Handler */
- ConnectInfo.ConsoleStartInfo.PropDispatcher = PropDialogHandler;
+ ConnectInfo.CurDirLength = sizeof(ConnectInfo.CurDir);
+ ConnectInfo.AppNameLength = sizeof(ConnectInfo.AppName);
- /* Setup the right Object Directory path */
- if (!SessionId)
- {
- /* Use the raw path */
- wcscpy(SessionDir, WIN_OBJ_DIR);
+ SetUpAppName(TRUE,
+ &ConnectInfo.CurDirLength,
+ &CurDir,
+ &ConnectInfo.AppNameLength,
+ &AppName);
+ DPRINT("CurDir = '%S' - AppName = '%S'\n",
+ CurDir, AppName);
}
else
{
- /* Use the session path */
- swprintf(SessionDir,
- L"%ws\\%ld%ws",
- SESSION_DIR,
- SessionId,
- WIN_OBJ_DIR);
+ 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 */
- DPRINT("Connecting to the Console Server in BasepInitConsole...\n");
- Status = CsrClientConnectToServer(SessionDir,
- CONSRV_SERVERDLL_INDEX,
- &ConnectInfo,
- &ConnectInfoSize,
- &InServer);
- if (!NT_SUCCESS(Status))
+ if (!ConnectConsole(SessionDir,
+ &ConnectInfo,
+ &IsServerProcess))
{
- DPRINT1("Failed to connect to the Console Server (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;
-
- /* Nothing to do if not a console app */
- if (!ConnectInfo.ConsoleStartInfo.ConsoleNeeded) return TRUE;
-
- /* We got the handles, let's set them */
- if ((Parameters->ConsoleHandle = ConnectInfo.ConsoleHandle))
+ /* If we are not doing server-to-server init and if this is a console app... */
+ if (!IsServerProcess && ConnectInfo.IsConsoleApp)
{
- /* If we already had some, don't use the new ones */
- if (!Parameters->StandardInput)
- {
- Parameters->StandardInput = ConnectInfo.InputHandle;
- }
- if (!Parameters->StandardOutput)
- {
- Parameters->StandardOutput = ConnectInfo.OutputHandle;
- }
- if (!Parameters->StandardError)
- {
- Parameters->StandardError = ConnectInfo.ErrorHandle;
- }
+ /* ... set the handles that we got */
+ if (Parameters->ConsoleHandle == NULL)
+ SetUpHandles(&ConnectInfo.ConsoleStartInfo);
+
+ InputWaitHandle = ConnectInfo.ConsoleStartInfo.InputWaitHandle;
+Exit:
+ SetTEBLangID(lcid);
}
- InputWaitHandle = ConnectInfo.InputWaitHandle;
+ DPRINT("Console setup: 0x%p, 0x%p, 0x%p, 0x%p\n",
+ Parameters->ConsoleHandle,
+ Parameters->StandardInput,
+ Parameters->StandardOutput,
+ Parameters->StandardError);
- DPRINT("Console setup: %p, %p, %p, %p\n",
- Parameters->ConsoleHandle,
- Parameters->StandardInput,
- Parameters->StandardOutput,
- Parameters->StandardError);
return TRUE;
}
* Read functions *
******************/
-DWORD
-WINAPI
-GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer);
-
static
BOOL
IntReadConsole(IN HANDLE hConsoleInput,
ReadConsoleRequest->Unicode = bUnicode;
/*
- * Retrieve the current console executable name string and length (always
- * in UNICODE format).
- * FIXME: Do not use GetConsoleInputExeNameW but use something else...
+ * Retrieve the (current) Input EXE name string and length,
+ * not NULL-terminated (always in UNICODE format).
*/
- // 1- Get the exe name length in characters, including NULL character.
ReadConsoleRequest->ExeLength =
- (USHORT)GetConsoleInputExeNameW(0, (PWCHAR)ReadConsoleRequest->StaticBuffer);
- // 2- Get the exe name (GetConsoleInputExeNameW returns 1 in case of success).
- if (GetConsoleInputExeNameW(ReadConsoleRequest->ExeLength,
- (PWCHAR)ReadConsoleRequest->StaticBuffer) != 1)
- {
- // Nothing
- ReadConsoleRequest->ExeLength = 0;
- }
- else
- {
- // Remove the NULL character, and convert in number of bytes.
- ReadConsoleRequest->ExeLength--;
- ReadConsoleRequest->ExeLength *= sizeof(WCHAR);
- }
+ GetCurrentExeName((PWCHAR)ReadConsoleRequest->StaticBuffer,
+ sizeof(ReadConsoleRequest->StaticBuffer));
/*** For DEBUGGING purposes ***/
{
}
/* Initialize Console Support */
- if (!BasepInitConsole())
+ if (!ConDllInitialize(dwReason, SessionDir))
{
DPRINT1("Failed to set up console\n");
return FALSE;
ProcessParameters->StandardError = StartupInfo->hStdError;
}
- /* Use Special Flags for BasepInitConsole in Kernel32 */
+ /* Use Special Flags for ConDllInitialize in Kernel32 */
if (CreationFlags & DETACHED_PROCESS)
{
ProcessParameters->ConsoleHandle = HANDLE_DETACHED_PROCESS;
/* CONSTANTS ******************************************************************/
-#define HANDLE_DETACHED_PROCESS (HANDLE)-2
-#define HANDLE_CREATE_NEW_CONSOLE (HANDLE)-3
-#define HANDLE_CREATE_NO_WINDOW (HANDLE)-4
+#define HANDLE_DETACHED_PROCESS (HANDLE)-1
+#define HANDLE_CREATE_NEW_CONSOLE (HANDLE)-2
+#define HANDLE_CREATE_NO_WINDOW (HANDLE)-3
+
+// Enable (and then get rid of) this define when support for
+// console initialization handles is implemented in CONSRV.
+// #define USE_CONSOLE_INIT_HANDLES
/* FUNCTION PROTOTYPES ********************************************************/
-BOOL WINAPI
-BasepInitConsole(VOID);
+BOOLEAN
+WINAPI
+ConDllInitialize(IN ULONG Reason,
+ IN PWSTR SessionDir);
-VOID WINAPI
+VOID
+WINAPI
BasepUninitConsole(VOID);
-VOID WINAPI
-InitConsoleCtrlHandling(VOID);
+VOID
+InitializeCtrlHandling(VOID);
-DWORD WINAPI
+DWORD
+WINAPI
ConsoleControlDispatcher(IN LPVOID lpThreadParameter);
-DWORD WINAPI
+DWORD
+WINAPI
PropDialogHandler(IN LPVOID lpThreadParameter);
HANDLE WINAPI
HANDLE
TranslateStdHandle(HANDLE hHandle);
+#define SetTEBLangID(p) (p)
+
+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);
+
VOID
-InitConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
- IN PUNICODE_STRING ImagePathName);
+SetUpHandles(IN PCONSOLE_START_INFO ConsoleStartInfo);
+
+VOID
+InitExeName(VOID);
+
+VOID
+SetUpAppName(IN BOOLEAN CaptureStrings,
+ IN OUT LPDWORD CurDirLength,
+ IN OUT LPWSTR* CurDir,
+ IN OUT LPDWORD AppNameLength,
+ IN OUT LPWSTR* AppName);
+
+USHORT
+GetCurrentExeName(OUT PWCHAR ExeName,
+ IN USHORT BufferSize);
LPCWSTR
IntCheckForConsoleFileName(IN LPCWSTR pszName,
BOOL bInheritHandle,
DWORD dwShareMode);
-BOOL WINAPI
-SetConsoleInputExeNameW(LPCWSTR lpInputExeName);
-
/* EOF */
//
typedef struct _CONSOLE_PROPERTIES
{
+ INT IconIndex;
+ HICON hIcon;
+ HICON hIconSm;
+ DWORD dwHotKey;
+ DWORD dwStartupFlags;
+
+ // NT_CONSOLE_PROPS
WORD wFillAttribute;
WORD wPopupFillAttribute;
DWORD nFont;
DWORD nInputBufferSize;
COORD dwFontSize;
- UINT uFontFamily;
- UINT uFontWeight;
+ UINT uFontFamily;
+ UINT uFontWeight;
WCHAR FaceName[LF_FACESIZE];
- UINT uCursorSize;
- BOOL bFullScreen;
- BOOL bQuickEdit;
- BOOL bInsertMode;
- BOOL bAutoPosition;
- UINT uHistoryBufferSize;
- UINT uNumberOfHistoryBuffers;
- BOOL bHistoryNoDup;
+ UINT uCursorSize;
+ BOOL bFullScreen;
+ BOOL bQuickEdit;
+ BOOL bInsertMode;
+ BOOL bAutoPosition;
+ UINT uHistoryBufferSize;
+ UINT uNumberOfHistoryBuffers;
+ BOOL bHistoryNoDup;
COLORREF ColorTable[16];
- //NT_FE_CONSOLE_PROPS
+ // NT_FE_CONSOLE_PROPS
UINT uCodePage;
} CONSOLE_PROPERTIES;
-//
-// To minimize code changes, some fields were put here even though they really only belong in
-// CONSRV_API_CONNECTINFO. Do not change the ordering however, as it's required for Windows
-// compatibility.
-//
typedef struct _CONSOLE_START_INFO
-{
- INT IconIndex;
- HICON IconHandle1;
- HICON IconHandle2;
- DWORD dwHotKey;
- DWORD dwStartupFlags;
- CONSOLE_PROPERTIES;
-
- BOOLEAN ConsoleNeeded; // Used for GUI apps only.
- LPTHREAD_START_ROUTINE CtrlDispatcher;
- LPTHREAD_START_ROUTINE ImeDispatcher;
- LPTHREAD_START_ROUTINE PropDispatcher;
- ULONG TitleLength;
- WCHAR ConsoleTitle[MAX_PATH + 1]; // Console title or full path to the startup shortcut
- ULONG DesktopLength;
- PWCHAR DesktopPath;
- ULONG AppNameLength;
- WCHAR AppPath[128]; // Full path of the launched app
- ULONG IconPathLength;
- WCHAR IconPath[MAX_PATH + 1]; // Path to the file containing the icon
-} CONSOLE_START_INFO, *PCONSOLE_START_INFO;
-
-typedef struct _CONSRV_API_CONNECTINFO
{
HANDLE ConsoleHandle;
HANDLE InputWaitHandle;
HANDLE InputHandle;
HANDLE OutputHandle;
HANDLE ErrorHandle;
- HANDLE Event1;
- HANDLE Event2;
- /* Adapted from CONSOLE_ALLOCCONSOLE */
+ HANDLE Events[2];
+
+ CONSOLE_PROPERTIES;
+} CONSOLE_START_INFO, *PCONSOLE_START_INFO;
+
+#if defined(_M_IX86)
+C_ASSERT(sizeof(CONSOLE_START_INFO) == 0xFC);
+#endif
+
+typedef struct _CONSRV_API_CONNECTINFO
+{
CONSOLE_START_INFO ConsoleStartInfo;
+
+ BOOLEAN IsConsoleApp;
+ BOOLEAN IsWindowVisible;
+
+ // USHORT Padding;
+
+ LPTHREAD_START_ROUTINE CtrlRoutine;
+ LPTHREAD_START_ROUTINE PropRoutine;
+ LPTHREAD_START_ROUTINE ImeRoutine;
+
+ ULONG TitleLength;
+ WCHAR ConsoleTitle[MAX_PATH + 1]; // Console title or full path to the startup shortcut
+ ULONG DesktopLength;
+ PWCHAR Desktop;
+ ULONG AppNameLength;
+ WCHAR AppName[128]; // Full path of the launched app
+ ULONG CurDirLength;
+ WCHAR CurDir[MAX_PATH + 1];
} CONSRV_API_CONNECTINFO, *PCONSRV_API_CONNECTINFO;
#if defined(_M_IX86)
{
PCONSOLE_START_INFO ConsoleStartInfo;
- HANDLE ConsoleHandle;
- HANDLE InputHandle;
- HANDLE OutputHandle;
- HANDLE ErrorHandle;
- HANDLE InputWaitHandle;
- LPTHREAD_START_ROUTINE CtrlDispatcher;
- LPTHREAD_START_ROUTINE PropDispatcher;
+ ULONG TitleLength;
+ PWCHAR ConsoleTitle; // Console title or full path to the startup shortcut
+ ULONG DesktopLength;
+ PWCHAR Desktop;
+ ULONG AppNameLength;
+ PWCHAR AppName; // Full path of the launched app
+ ULONG CurDirLength;
+ PWCHAR CurDir;
+
+ LPTHREAD_START_ROUTINE CtrlRoutine;
+ LPTHREAD_START_ROUTINE PropRoutine;
} CONSOLE_ALLOCCONSOLE, *PCONSOLE_ALLOCCONSOLE;
typedef struct _CONSOLE_ATTACHCONSOLE
{
- DWORD ProcessId; // If ProcessId == ATTACH_PARENT_PROCESS == -1, then attach the current process to its parent process console.
- HANDLE ConsoleHandle;
- HANDLE InputHandle;
- HANDLE OutputHandle;
- HANDLE ErrorHandle;
- HANDLE InputWaitHandle;
- LPTHREAD_START_ROUTINE CtrlDispatcher;
- LPTHREAD_START_ROUTINE PropDispatcher;
+ /*
+ * If ProcessId == ATTACH_PARENT_PROCESS == -1, then attach
+ * the current process to its parent process console.
+ */
+ DWORD ProcessId;
+
+ PCONSOLE_START_INFO ConsoleStartInfo;
+
+ LPTHREAD_START_ROUTINE CtrlRoutine;
+ LPTHREAD_START_ROUTINE PropRoutine;
} CONSOLE_ATTACHCONSOLE, *PCONSOLE_ATTACHCONSOLE;
typedef struct _CONSOLE_FREECONSOLE
/* PRIVATE FUNCTIONS **********************************************************/
-// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180
-static BOOLEAN
-ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest,
- IN PCWSTR Source)
-{
- SIZE_T Size = (wcslen(Source) + 1) * sizeof(WCHAR);
- if (Size > MAXUSHORT) return FALSE;
-
- UniDest->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size);
- if (UniDest->Buffer == NULL) return FALSE;
-
- RtlCopyMemory(UniDest->Buffer, Source, Size);
- UniDest->MaximumLength = (USHORT)Size;
- UniDest->Length = (USHORT)Size - sizeof(WCHAR);
-
- return TRUE;
-}
-
-// Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431
-static VOID
-ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
-{
- if (UnicodeString->Buffer)
- {
- ConsoleFreeHeap(UnicodeString->Buffer);
- RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
- }
-}
-
VOID NTAPI
ConDrvPause(PCONSOLE Console)
{
TEXTMODE_BUFFER_INFO ScreenBufferInfo;
PCONSOLE Console;
PCONSOLE_SCREEN_BUFFER NewBuffer;
-#if 0
- WCHAR DefaultTitle[128];
-#endif
if (NewConsole == NULL || ConsoleInfo == NULL)
return STATUS_INVALID_PARAMETER;
Console->ActiveBuffer = NewBuffer;
Console->UnpauseEvent = NULL;
- /* Initialize the console title */
- ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo->ConsoleTitle);
-#if 0
- if (ConsoleInfo.ConsoleTitle[0] == L'\0')
- {
- if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0])))
- {
- ConsoleCreateUnicodeString(&Console->Title, DefaultTitle);
- }
- else
- {
- ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console");
- }
- }
- else
- {
-#endif
- ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo->ConsoleTitle);
-#if 0
- }
-#endif
-
DPRINT("Console initialized\n");
/* All went right, so add the console to the list */
if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
- ConsoleFreeUnicodeString(&Console->OriginalTitle);
- ConsoleFreeUnicodeString(&Console->Title);
-
DPRINT("ConDrvDeleteConsole - Unlocking\n");
LeaveCriticalSection(&Console->Lock);
DPRINT("ConDrvDeleteConsole - Destroying lock\n");
return Status;
}
-NTSTATUS NTAPI
-ConDrvGetConsoleTitle(IN PCONSOLE Console,
- IN BOOLEAN Unicode,
- IN OUT PVOID TitleBuffer,
- IN OUT PULONG BufLength)
-{
- ULONG Length;
-
- if (Console == NULL || TitleBuffer == NULL || BufLength == NULL)
- return STATUS_INVALID_PARAMETER;
-
- /* Copy title of the console to the user title buffer */
- if (Unicode)
- {
- if (*BufLength >= sizeof(WCHAR))
- {
- Length = min(*BufLength - sizeof(WCHAR), Console->Title.Length);
- RtlCopyMemory(TitleBuffer, Console->Title.Buffer, Length);
- ((PWCHAR)TitleBuffer)[Length / sizeof(WCHAR)] = L'\0';
- *BufLength = Length;
- }
- else
- {
- *BufLength = Console->Title.Length;
- }
- }
- else
- {
- if (*BufLength >= sizeof(CHAR))
- {
- Length = min(*BufLength - sizeof(CHAR), Console->Title.Length / sizeof(WCHAR));
- Length = WideCharToMultiByte(Console->InputCodePage, 0,
- Console->Title.Buffer, Length,
- TitleBuffer, Length,
- NULL, NULL);
- ((PCHAR)TitleBuffer)[Length] = '\0';
- *BufLength = Length;
- }
- else
- {
- *BufLength = Console->Title.Length / sizeof(WCHAR);
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS NTAPI
-ConDrvSetConsoleTitle(IN PCONSOLE Console,
- IN BOOLEAN Unicode,
- IN PVOID TitleBuffer,
- IN ULONG BufLength)
-{
- PWCHAR Buffer;
- ULONG Length;
-
- if (Console == NULL || TitleBuffer == NULL)
- return STATUS_INVALID_PARAMETER;
-
- if (Unicode)
- {
- /* Length is in bytes */
- Length = BufLength;
- }
- else
- {
- /* Use the console input CP for the conversion */
- Length = MultiByteToWideChar(Console->InputCodePage, 0,
- TitleBuffer, BufLength,
- NULL, 0);
- /* The returned Length was in number of wchars, convert it in bytes */
- Length *= sizeof(WCHAR);
- }
-
- /* Allocate a new buffer to hold the new title (NULL-terminated) */
- Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Length + sizeof(WCHAR));
- if (!Buffer) return STATUS_NO_MEMORY;
-
- /* Free the old title */
- ConsoleFreeUnicodeString(&Console->Title);
-
- /* Copy title to console */
- Console->Title.Buffer = Buffer;
- Console->Title.Length = Length;
- Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR);
-
- if (Unicode)
- {
- RtlCopyMemory(Console->Title.Buffer, TitleBuffer, Console->Title.Length);
- }
- else
- {
- MultiByteToWideChar(Console->InputCodePage, 0,
- TitleBuffer, BufLength,
- Console->Title.Buffer,
- Console->Title.Length / sizeof(WCHAR));
- }
-
- /* NULL-terminate */
- Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
-
- // TermChangeTitle(Console);
- return STATUS_SUCCESS;
-}
-
NTSTATUS NTAPI
ConDrvGetConsoleCP(IN PCONSOLE Console,
OUT PUINT CodePage,
{
}
-static VOID NTAPI
-DummyChangeTitle(IN OUT PTERMINAL This)
-{
-}
-
static VOID NTAPI
DummyGetLargestConsoleWindowSize(IN OUT PTERMINAL This,
PCOORD pSize)
DummyResizeTerminal,
DummySetActiveScreenBuffer,
DummyReleaseScreenBuffer,
- DummyChangeTitle,
DummyGetLargestConsoleWindowSize,
DummySetPalette,
DummyShowMouseCursor,
#include <ndk/psfuncs.h>
+/* This is for COM usage */
+#define COBJMACROS
+#include <shlobj.h>
+
+
#include <alias.h>
#include <history.h>
#include "procinit.h"
/* PRIVATE FUNCTIONS **********************************************************/
+// Adapted from reactos/lib/rtl/unicode.c, RtlCreateUnicodeString line 2180
+static BOOLEAN
+ConsoleCreateUnicodeString(IN OUT PUNICODE_STRING UniDest,
+ IN PCWSTR Source)
+{
+ SIZE_T Size = (wcslen(Source) + 1) * sizeof(WCHAR);
+ if (Size > MAXUSHORT) return FALSE;
+
+ UniDest->Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Size);
+ if (UniDest->Buffer == NULL) return FALSE;
+
+ RtlCopyMemory(UniDest->Buffer, Source, Size);
+ UniDest->MaximumLength = (USHORT)Size;
+ UniDest->Length = (USHORT)Size - sizeof(WCHAR);
+
+ return TRUE;
+}
+
+// Adapted from reactos/lib/rtl/unicode.c, RtlFreeUnicodeString line 431
+static VOID
+ConsoleFreeUnicodeString(IN PUNICODE_STRING UnicodeString)
+{
+ if (UnicodeString->Buffer)
+ {
+ ConsoleFreeHeap(UnicodeString->Buffer);
+ RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING));
+ }
+}
+
VOID
ConioPause(PCONSRV_CONSOLE Console, UINT Flags)
{
NTSTATUS NTAPI
ConSrvDeinitTerminal(IN OUT PTERMINAL Terminal);
+
+static BOOL
+LoadShellLinkConsoleInfo(IN OUT PCONSOLE_INFO ConsoleInfo,
+ IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo)
+{
+#define PATH_SEPARATOR L'\\'
+
+ BOOL RetVal = FALSE;
+ HRESULT hRes = S_OK;
+ SIZE_T Length = 0;
+ LPWSTR LinkName = NULL;
+ LPWSTR IconPath = NULL;
+ WCHAR Buffer[MAX_PATH + 1];
+
+ ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0;
+
+ if ((ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+ {
+ // return FALSE; // FIXME!! (for icon loading)
+ RetVal = TRUE;
+ goto Finish;
+ }
+
+ /* 1- Find the last path separator if any */
+ LinkName = wcsrchr(ConsoleInfo->ConsoleTitle, PATH_SEPARATOR);
+ if (LinkName == NULL)
+ LinkName = ConsoleInfo->ConsoleTitle;
+ else
+ ++LinkName; // Skip the path separator
+
+ /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
+ Length = wcslen(LinkName);
+ if ( (Length <= 4) || (wcsicmp(LinkName + (Length - 4), L".lnk") != 0) )
+ return FALSE;
+
+ /* 3- It may be a link. Try to retrieve some properties */
+ hRes = CoInitialize(NULL);
+ if (SUCCEEDED(hRes))
+ {
+ /* Get a pointer to the IShellLink interface */
+ IShellLinkW* pshl = NULL;
+ hRes = CoCreateInstance(&CLSID_ShellLink,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ &IID_IShellLinkW,
+ (LPVOID*)&pshl);
+ if (SUCCEEDED(hRes))
+ {
+ /* Get a pointer to the IPersistFile interface */
+ IPersistFile* ppf = NULL;
+ hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
+ if (SUCCEEDED(hRes))
+ {
+ /* Load the shortcut */
+ hRes = IPersistFile_Load(ppf, ConsoleInfo->ConsoleTitle, STGM_READ);
+ if (SUCCEEDED(hRes))
+ {
+ /*
+ * Finally we can get the properties !
+ * Update the old ones if needed.
+ */
+ INT ShowCmd = 0;
+ // WORD HotKey = 0;
+
+ /* Reset the name of the console with the name of the shortcut */
+ Length = min(/*Length*/ Length - 4, // 4 == len(".lnk")
+ sizeof(ConsoleInfo->ConsoleTitle) / sizeof(ConsoleInfo->ConsoleTitle[0]) - 1);
+ wcsncpy(ConsoleInfo->ConsoleTitle, LinkName, Length);
+ ConsoleInfo->ConsoleTitle[Length] = L'\0';
+
+ /* Get the window showing command */
+ hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd);
+ if (SUCCEEDED(hRes)) ConsoleInitInfo->ConsoleStartInfo->wShowWindow = (WORD)ShowCmd;
+
+ /* Get the hotkey */
+ // hRes = pshl->GetHotkey(&ShowCmd);
+ // if (SUCCEEDED(hRes)) ConsoleInitInfo->ConsoleStartInfo->HotKey = HotKey;
+
+ /* Get the icon location, if any */
+ hRes = IShellLinkW_GetIconLocation(pshl,
+ Buffer,
+ sizeof(Buffer)/sizeof(Buffer[0]) - 1, // == MAX_PATH
+ &ConsoleInitInfo->ConsoleStartInfo->IconIndex);
+ if (!SUCCEEDED(hRes))
+ {
+ ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0;
+ }
+ else
+ {
+ IconPath = Buffer;
+ }
+
+ // FIXME: Since we still don't load console properties from the shortcut,
+ // return false. When this will be done, we will return true instead.
+ RetVal = TRUE; // FALSE;
+ }
+ IPersistFile_Release(ppf);
+ }
+ IShellLinkW_Release(pshl);
+ }
+ }
+ CoUninitialize();
+
+Finish:
+
+ if (RetVal)
+ {
+ /* Get the associated icon, if any */
+ if (IconPath == NULL)
+ {
+ // Question: How to retrieve the full path name
+ // of the app we are going to run??
+ Length = RtlDosSearchPath_U(ConsoleInitInfo->CurDir,
+ ConsoleInitInfo->AppName,
+ NULL,
+ sizeof(Buffer),
+ Buffer,
+ NULL);
+ if (Length > 0 && Length < sizeof(Buffer))
+ IconPath = Buffer;
+ else
+ IconPath = ConsoleInitInfo->AppName;
+
+ // ConsoleInitInfo->ConsoleStartInfo->IconIndex = 0;
+ }
+ DPRINT1("IconPath = '%S' ; IconIndex = %lu\n",
+ IconPath, ConsoleInitInfo->ConsoleStartInfo->IconIndex);
+ if (IconPath && *IconPath)
+ {
+ HICON hIcon = NULL, hIconSm = NULL;
+ PrivateExtractIconExW(IconPath,
+ ConsoleInitInfo->ConsoleStartInfo->IconIndex,
+ &hIcon,
+ &hIconSm,
+ 1);
+ DPRINT1("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm);
+ if (hIcon != NULL) ConsoleInitInfo->ConsoleStartInfo->hIcon = hIcon;
+ if (hIconSm != NULL) ConsoleInitInfo->ConsoleStartInfo->hIconSm = hIconSm;
+ }
+ }
+
+ // FIXME: See the previous FIXME above.
+ RetVal = FALSE;
+
+ return RetVal;
+}
+
NTSTATUS NTAPI
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
OUT PCONSRV_CONSOLE* NewConsole,
- IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
+ IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
IN ULONG ConsoleLeaderProcessId)
{
NTSTATUS Status;
TERMINAL Terminal; /* The ConSrv terminal for this console */
- if (NewConsole == NULL || ConsoleStartInfo == NULL)
+ if (NewConsole == NULL || ConsoleInitInfo == NULL)
return STATUS_INVALID_PARAMETER;
*NewConsole = NULL;
ConSrvGetDefaultSettings(&ConsoleInfo, ConsoleLeaderProcessId);
/* 2. Get the title of the console (initialize ConsoleInfo.ConsoleTitle) */
- Length = min(wcslen(ConsoleStartInfo->ConsoleTitle),
+ Length = min(ConsoleInitInfo->TitleLength,
sizeof(ConsoleInfo.ConsoleTitle) / sizeof(ConsoleInfo.ConsoleTitle[0]) - 1);
- wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleStartInfo->ConsoleTitle, Length);
- ConsoleInfo.ConsoleTitle[Length] = L'\0';
+ wcsncpy(ConsoleInfo.ConsoleTitle, ConsoleInitInfo->ConsoleTitle, Length);
+ ConsoleInfo.ConsoleTitle[Length] = L'\0'; // NULL-terminate it.
/* 3. Initialize the ConSrv terminal */
Status = ConSrvInitTerminal(&Terminal,
&ConsoleInfo,
- ConsoleStartInfo,
+ ConsoleInitInfo,
ConsoleLeaderProcessId);
if (!NT_SUCCESS(Status))
{
}
DPRINT("CONSRV: Terminal initialized\n");
+ /*
+ * Load per-application terminal settings.
+ *
+ * Check whether the process creating the console was launched via
+ * a shell-link. ConsoleInfo->ConsoleTitle may be updated with the
+ * name of the shortcut, and ConsoleStartInfo->Icon[Path|Index] too.
+ */
+ // if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) // FIXME!! (for icon loading)
+ {
+ if (!LoadShellLinkConsoleInfo(&ConsoleInfo, ConsoleInitInfo))
+ {
+ ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
+ }
+ }
+
/*
* 4. Load the remaining console settings via the registry.
*/
- if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
+ if ((ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
{
/*
* Either we weren't created by an app launched via a shell-link,
* (and which was transmitted via the ConsoleStartInfo structure).
* We therefore overwrite the values read in the registry.
*/
- if (ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE)
+ if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USEFILLATTRIBUTE)
{
- ConsoleInfo.ScreenAttrib = (USHORT)ConsoleStartInfo->wFillAttribute;
+ ConsoleInfo.ScreenAttrib = (USHORT)ConsoleInitInfo->ConsoleStartInfo->wFillAttribute;
}
- if (ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS)
+ if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USECOUNTCHARS)
{
- ConsoleInfo.ScreenBufferSize = ConsoleStartInfo->dwScreenBufferSize;
+ ConsoleInfo.ScreenBufferSize = ConsoleInitInfo->ConsoleStartInfo->dwScreenBufferSize;
}
- if (ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
+ if (ConsoleInitInfo->ConsoleStartInfo->dwStartupFlags & STARTF_USESIZE)
{
- ConsoleInfo.ConsoleSize = ConsoleStartInfo->dwWindowSize;
+ ConsoleInfo.ConsoleSize = ConsoleInitInfo->ConsoleStartInfo->dwWindowSize;
}
}
/*** Register ConSrv features ***/
+ /* Initialize the console title */
+#if 0
+ WCHAR DefaultTitle[128];
+#endif
+ ConsoleCreateUnicodeString(&Console->OriginalTitle, ConsoleInfo.ConsoleTitle);
+#if 0
+ if (ConsoleInfo.ConsoleTitle[0] == L'\0')
+ {
+ if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, DefaultTitle, sizeof(DefaultTitle) / sizeof(DefaultTitle[0])))
+ {
+ ConsoleCreateUnicodeString(&Console->Title, DefaultTitle);
+ }
+ else
+ {
+ ConsoleCreateUnicodeString(&Console->Title, L"ReactOS Console");
+ }
+ }
+ else
+ {
+#endif
+ ConsoleCreateUnicodeString(&Console->Title, ConsoleInfo.ConsoleTitle);
+#if 0
+ }
+#endif
+
/* Initialize process support */
InitializeListHead(&Console->ProcessList);
Console->NotifiedLastCloseProcess = NULL;
IntDeleteAllAliases(Console);
HistoryDeleteBuffers(Console);
+ /* Free the console title */
+ ConsoleFreeUnicodeString(&Console->OriginalTitle);
+ ConsoleFreeUnicodeString(&Console->Title);
+
/* Now, call the driver. ConDrvDeregisterTerminal is called on-demand. */
ConDrvDeleteConsole((PCONSOLE)Console);
DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
- if (ProcessData->CtrlDispatcher)
+ if (ProcessData->CtrlRoutine)
{
_SEH2_TRY
{
_SEH2_TRY
{
Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
- ProcessData->CtrlDispatcher,
+ ProcessData->CtrlRoutine,
UlongToPtr(CtrlEvent), 0, NULL);
if (NULL == Thread)
{
}
else
{
- DPRINT("ProcessData->CtrlDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
+ DPRINT("ProcessData->CtrlRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n",
+ ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
WaitForSingleObject(Thread, Timeout);
}
}
}
-
-
-
/* PUBLIC SERVER APIS *********************************************************/
CSR_API(SrvAllocConsole)
PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
PCSR_PROCESS CsrProcess = CsrGetClientThread()->Process;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
+ CONSOLE_INIT_INFO ConsoleInitInfo;
if (ProcessData->ConsoleHandle != NULL)
{
return STATUS_ACCESS_DENIED;
}
- if (!CsrValidateMessageBuffer(ApiMessage,
- (PVOID*)&AllocConsoleRequest->ConsoleStartInfo,
- 1,
- sizeof(CONSOLE_START_INFO)))
+ if ( !CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&AllocConsoleRequest->ConsoleStartInfo,
+ 1,
+ sizeof(CONSOLE_START_INFO)) ||
+ !CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&AllocConsoleRequest->ConsoleTitle,
+ AllocConsoleRequest->TitleLength,
+ sizeof(BYTE)) ||
+ !CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&AllocConsoleRequest->Desktop,
+ AllocConsoleRequest->DesktopLength,
+ sizeof(BYTE)) ||
+ !CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&AllocConsoleRequest->CurDir,
+ AllocConsoleRequest->CurDirLength,
+ sizeof(BYTE)) ||
+ !CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&AllocConsoleRequest->AppName,
+ AllocConsoleRequest->AppNameLength,
+ sizeof(BYTE)) )
{
return STATUS_INVALID_PARAMETER;
}
+ /* Initialize the console initialization info structure */
+ ConsoleInitInfo.ConsoleStartInfo = AllocConsoleRequest->ConsoleStartInfo;
+ ConsoleInitInfo.TitleLength = AllocConsoleRequest->TitleLength;
+ ConsoleInitInfo.ConsoleTitle = AllocConsoleRequest->ConsoleTitle;
+ ConsoleInitInfo.DesktopLength = AllocConsoleRequest->DesktopLength;
+ ConsoleInitInfo.Desktop = AllocConsoleRequest->Desktop;
+ ConsoleInitInfo.AppNameLength = AllocConsoleRequest->AppNameLength;
+ ConsoleInitInfo.AppName = AllocConsoleRequest->AppName;
+ ConsoleInitInfo.CurDirLength = AllocConsoleRequest->CurDirLength;
+ ConsoleInitInfo.CurDir = AllocConsoleRequest->CurDir;
+
/* Initialize a new Console owned by the Console Leader Process */
Status = ConSrvAllocateConsole(ProcessData,
- &AllocConsoleRequest->InputHandle,
- &AllocConsoleRequest->OutputHandle,
- &AllocConsoleRequest->ErrorHandle,
- AllocConsoleRequest->ConsoleStartInfo);
+ &AllocConsoleRequest->ConsoleStartInfo->InputHandle,
+ &AllocConsoleRequest->ConsoleStartInfo->OutputHandle,
+ &AllocConsoleRequest->ConsoleStartInfo->ErrorHandle,
+ &ConsoleInitInfo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console allocation failed\n");
return Status;
}
+ /* Mark the process as having a console */
+ ProcessData->ConsoleApp = TRUE;
+ CsrProcess->Flags |= CsrProcessIsConsoleApp;
+
/* Return the console handle and the input wait handle to the caller */
- AllocConsoleRequest->ConsoleHandle = ProcessData->ConsoleHandle;
- AllocConsoleRequest->InputWaitHandle = ProcessData->InputWaitHandle;
+ AllocConsoleRequest->ConsoleStartInfo->ConsoleHandle = ProcessData->ConsoleHandle;
+ AllocConsoleRequest->ConsoleStartInfo->InputWaitHandle = ProcessData->InputWaitHandle;
/* Set the Property-Dialog and Control-Dispatcher handlers */
- ProcessData->PropDispatcher = AllocConsoleRequest->PropDispatcher;
- ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
+ ProcessData->PropRoutine = AllocConsoleRequest->PropRoutine;
+ ProcessData->CtrlRoutine = AllocConsoleRequest->CtrlRoutine;
return STATUS_SUCCESS;
}
return STATUS_ACCESS_DENIED;
}
+ if (!CsrValidateMessageBuffer(ApiMessage,
+ (PVOID*)&AttachConsoleRequest->ConsoleStartInfo,
+ 1,
+ sizeof(CONSOLE_START_INFO)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
/* Check whether we try to attach to the parent's console */
if (ProcessId == ULongToHandle(ATTACH_PARENT_PROCESS))
{
Status = ConSrvInheritConsole(TargetProcessData,
SourceProcessData->ConsoleHandle,
TRUE,
- &AttachConsoleRequest->InputHandle,
- &AttachConsoleRequest->OutputHandle,
- &AttachConsoleRequest->ErrorHandle);
+ &AttachConsoleRequest->ConsoleStartInfo->InputHandle,
+ &AttachConsoleRequest->ConsoleStartInfo->OutputHandle,
+ &AttachConsoleRequest->ConsoleStartInfo->ErrorHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console inheritance failed\n");
goto Quit;
}
+ /* Mark the process as having a console */
+ TargetProcessData->ConsoleApp = TRUE;
+ TargetProcess->Flags |= CsrProcessIsConsoleApp;
+
/* Return the console handle and the input wait handle to the caller */
- AttachConsoleRequest->ConsoleHandle = TargetProcessData->ConsoleHandle;
- AttachConsoleRequest->InputWaitHandle = TargetProcessData->InputWaitHandle;
+ AttachConsoleRequest->ConsoleStartInfo->ConsoleHandle = TargetProcessData->ConsoleHandle;
+ AttachConsoleRequest->ConsoleStartInfo->InputWaitHandle = TargetProcessData->InputWaitHandle;
/* Set the Property-Dialog and Control-Dispatcher handlers */
- TargetProcessData->PropDispatcher = AttachConsoleRequest->PropDispatcher;
- TargetProcessData->CtrlDispatcher = AttachConsoleRequest->CtrlDispatcher;
+ TargetProcessData->PropRoutine = AttachConsoleRequest->PropRoutine;
+ TargetProcessData->CtrlRoutine = AttachConsoleRequest->CtrlRoutine;
Status = STATUS_SUCCESS;
CSR_API(SrvFreeConsole)
{
+ PCSR_PROCESS CsrProcess = CsrGetClientThread()->Process;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
+
ConSrvRemoveConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process));
+
+ /* Mark the process as not having a console anymore */
+ ProcessData->ConsoleApp = FALSE;
+ CsrProcess->Flags &= ~CsrProcessIsConsoleApp;
+
return STATUS_SUCCESS;
}
return Status;
}
-NTSTATUS NTAPI
-ConDrvGetConsoleTitle(IN PCONSOLE Console,
- IN BOOLEAN Unicode,
- IN OUT PVOID TitleBuffer,
- IN OUT PULONG BufLength);
CSR_API(SrvGetConsoleTitle)
{
NTSTATUS Status;
PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
PCONSRV_CONSOLE Console;
+ ULONG Length;
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID)&TitleRequest->Title,
return Status;
}
- Status = ConDrvGetConsoleTitle(Console,
- TitleRequest->Unicode,
- TitleRequest->Title,
- &TitleRequest->Length);
+ /* Copy title of the console to the user title buffer */
+ if (TitleRequest->Unicode)
+ {
+ if (TitleRequest->Length >= sizeof(WCHAR))
+ {
+ Length = min(TitleRequest->Length - sizeof(WCHAR), Console->Title.Length);
+ RtlCopyMemory(TitleRequest->Title, Console->Title.Buffer, Length);
+ ((PWCHAR)TitleRequest->Title)[Length / sizeof(WCHAR)] = L'\0';
+ TitleRequest->Length = Length;
+ }
+ else
+ {
+ TitleRequest->Length = Console->Title.Length;
+ }
+ }
+ else
+ {
+ if (TitleRequest->Length >= sizeof(CHAR))
+ {
+ Length = min(TitleRequest->Length - sizeof(CHAR), Console->Title.Length / sizeof(WCHAR));
+ Length = WideCharToMultiByte(Console->InputCodePage, 0,
+ Console->Title.Buffer, Length,
+ TitleRequest->Title, Length,
+ NULL, NULL);
+ ((PCHAR)TitleRequest->Title)[Length] = '\0';
+ TitleRequest->Length = Length;
+ }
+ else
+ {
+ TitleRequest->Length = Console->Title.Length / sizeof(WCHAR);
+ }
+ }
ConSrvReleaseConsole(Console, TRUE);
return Status;
}
-NTSTATUS NTAPI
-ConDrvSetConsoleTitle(IN PCONSOLE Console,
- IN BOOLEAN Unicode,
- IN PVOID TitleBuffer,
- IN ULONG BufLength);
CSR_API(SrvSetConsoleTitle)
{
NTSTATUS Status;
PCONSOLE_GETSETCONSOLETITLE TitleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.TitleRequest;
PCONSRV_CONSOLE Console;
+ PWCHAR Buffer;
+ ULONG Length;
+
if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID)&TitleRequest->Title,
TitleRequest->Length,
return Status;
}
- Status = ConDrvSetConsoleTitle(Console,
- TitleRequest->Unicode,
- TitleRequest->Title,
- TitleRequest->Length);
- // FIXME: Keep this call here, or put it in ConDrvSetConsoleTitle ??
- if (NT_SUCCESS(Status)) TermChangeTitle(Console);
+ if (TitleRequest->Unicode)
+ {
+ /* Length is in bytes */
+ Length = TitleRequest->Length;
+ }
+ else
+ {
+ /* Use the console input CP for the conversion */
+ Length = MultiByteToWideChar(Console->InputCodePage, 0,
+ TitleRequest->Title, TitleRequest->Length,
+ NULL, 0);
+ /* The returned Length was in number of wchars, convert it in bytes */
+ Length *= sizeof(WCHAR);
+ }
+
+ /* Allocate a new buffer to hold the new title (NULL-terminated) */
+ Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, Length + sizeof(WCHAR));
+ if (!Buffer)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Quit;
+ }
+
+ /* Free the old title */
+ ConsoleFreeUnicodeString(&Console->Title);
+
+ /* Copy title to console */
+ Console->Title.Buffer = Buffer;
+ Console->Title.Length = Length;
+ Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR);
+
+ if (TitleRequest->Unicode)
+ {
+ RtlCopyMemory(Console->Title.Buffer, TitleRequest->Title, Console->Title.Length);
+ }
+ else
+ {
+ MultiByteToWideChar(Console->InputCodePage, 0,
+ TitleRequest->Title, TitleRequest->Length,
+ Console->Title.Buffer,
+ Console->Title.Length / sizeof(WCHAR));
+ }
+
+ /* NULL-terminate */
+ Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
+
+ TermChangeTitle(Console);
+ Status = STATUS_SUCCESS;
+Quit:
ConSrvReleaseConsole(Console, TRUE);
return Status;
}
#pragma once
+typedef struct _CONSOLE_INIT_INFO
+{
+ PCONSOLE_START_INFO ConsoleStartInfo;
+
+ ULONG TitleLength;
+ PWCHAR ConsoleTitle;
+ ULONG DesktopLength;
+ PWCHAR Desktop;
+ ULONG AppNameLength;
+ PWCHAR AppName;
+ ULONG CurDirLength;
+ PWCHAR CurDir;
+} CONSOLE_INIT_INFO, *PCONSOLE_INIT_INFO;
+
VOID NTAPI
ConSrvInitConsoleSupport(VOID);
NTSTATUS NTAPI
ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
OUT struct _CONSRV_CONSOLE** /* PCONSRV_CONSOLE* */ NewConsole,
- IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
+ IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo,
IN ULONG ConsoleLeaderProcessId);
VOID NTAPI ConSrvDeleteConsole(struct _CONSRV_CONSOLE* /* PCONSRV_CONSOLE */ Console);
{
LIST_ENTRY ConsoleLink;
PCSR_PROCESS Process; // Process owning this structure.
- HANDLE InputWaitHandle;
HANDLE ConsoleHandle;
- HANDLE ParentConsoleHandle;
+ HANDLE InputWaitHandle;
BOOLEAN ConsoleApp; // TRUE if it is a CUI app, FALSE otherwise.
ULONG HandleTableSize;
struct _CONSOLE_IO_HANDLE* /* PCONSOLE_IO_HANDLE */ HandleTable; // Length-varying table
- LPTHREAD_START_ROUTINE CtrlDispatcher;
- LPTHREAD_START_ROUTINE PropDispatcher; // We hold the property dialog handler there, till all the GUI thingie moves out from CSRSS.
+ LPTHREAD_START_ROUTINE CtrlRoutine;
+ LPTHREAD_START_ROUTINE PropRoutine; // We hold the property dialog handler there, till all the GUI thingie moves out from CSRSS.
+ // LPTHREAD_START_ROUTINE ImeRoutine;
} CONSOLE_PROCESS_DATA, *PCONSOLE_PROCESS_DATA;
}
/* Start the properties dialog */
- if (ProcessData->PropDispatcher)
+ if (ProcessData->PropRoutine)
{
_SEH2_TRY
{
_SEH2_TRY
{
Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
- ProcessData->PropDispatcher,
+ ProcessData->PropRoutine,
(PVOID)hClientSection, 0, NULL);
if (NULL == Thread)
{
}
else
{
- DPRINT("ProcessData->PropDispatcher remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
+ DPRINT("ProcessData->PropRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n",
+ ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
/// WaitForSingleObject(Thread, INFINITE);
}
}
#include <consrv.h>
-#define COBJMACROS
-#include <shlobj.h>
-
#define NDEBUG
#include <debug.h>
PGUI_CONSOLE_DATA GuiData;
GUI_CONSOLE_INFO TermInfo;
- SIZE_T Length = 0;
- LPWSTR IconPath = NULL;
- INT IconIndex = 0;
+ SIZE_T Length = 0;
if (This == NULL || Console == NULL || This->OldData == NULL)
return STATUS_INVALID_PARAMETER;
ConsoleInfo = GuiInitInfo->ConsoleInfo;
ConsoleStartInfo = GuiInitInfo->ConsoleStartInfo;
- IconPath = ConsoleStartInfo->IconPath;
- IconIndex = ConsoleStartInfo->IconIndex;
-
-
/* Terminal data allocation */
GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA));
if (!GuiData)
/* 1. Load the default settings */
GuiConsoleGetDefaultSettings(&TermInfo, GuiInitInfo->ProcessId);
- /* 3. Load the remaining console settings via the registry. */
+ /* 3. Load the remaining console settings via the registry */
if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
{
- /* Load the terminal infos from the registry. */
+ /* Load the terminal infos from the registry */
GuiConsoleReadUserSettings(&TermInfo,
ConsoleInfo->ConsoleTitle,
GuiInitInfo->ProcessId);
GuiData->GuiInfo.AutoPosition = TermInfo.AutoPosition;
GuiData->GuiInfo.WindowOrigin = TermInfo.WindowOrigin;
- /* Initialize the icon handles to their default values */
- GuiData->hIcon = ghDefaultIcon;
- GuiData->hIconSm = ghDefaultIconSm;
+ /* Initialize the icon handles */
+ if (ConsoleStartInfo->hIcon != NULL)
+ GuiData->hIcon = ConsoleStartInfo->hIcon;
+ else
+ GuiData->hIcon = ghDefaultIcon;
+
+ if (ConsoleStartInfo->hIconSm != NULL)
+ GuiData->hIconSm = ConsoleStartInfo->hIconSm;
+ else
+ GuiData->hIconSm = ghDefaultIconSm;
- /* Get the associated icon, if any */
- if (IconPath == NULL || IconPath[0] == L'\0')
- {
- IconPath = ConsoleStartInfo->AppPath;
- IconIndex = 0;
- }
- DPRINT("IconPath = %S ; IconIndex = %lu\n", (IconPath ? IconPath : L"n/a"), IconIndex);
- if (IconPath && IconPath[0] != L'\0')
- {
- HICON hIcon = NULL, hIconSm = NULL;
- PrivateExtractIconExW(IconPath,
- IconIndex,
- &hIcon,
- &hIconSm,
- 1);
- DPRINT("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm);
- if (hIcon != NULL) GuiData->hIcon = hIcon;
- if (hIconSm != NULL) GuiData->hIconSm = hIconSm;
- }
ASSERT(GuiData->hIcon && GuiData->hIconSm);
/* Mouse is shown by default with its default cursor shape */
};
-static BOOL
-LoadShellLinkConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
- IN OUT PCONSOLE_INFO ConsoleInfo)
-{
-#define PATH_SEPARATOR L'\\'
-
- BOOL RetVal = FALSE;
- HRESULT hRes = S_OK;
- LPWSTR LinkName = NULL;
- SIZE_T Length = 0;
-
- if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0)
- return FALSE;
-
- ConsoleStartInfo->IconPath[0] = L'\0';
- ConsoleStartInfo->IconIndex = 0;
-
- /* 1- Find the last path separator if any */
- LinkName = wcsrchr(ConsoleStartInfo->ConsoleTitle, PATH_SEPARATOR);
- if (LinkName == NULL)
- {
- LinkName = ConsoleStartInfo->ConsoleTitle;
- }
- else
- {
- /* Skip the path separator */
- ++LinkName;
- }
-
- /* 2- Check for the link extension. The name ".lnk" is considered invalid. */
- Length = wcslen(LinkName);
- if ( (Length <= 4) || (wcsicmp(LinkName + (Length - 4), L".lnk") != 0) )
- return FALSE;
-
- /* 3- It may be a link. Try to retrieve some properties */
- hRes = CoInitialize(NULL);
- if (SUCCEEDED(hRes))
- {
- /* Get a pointer to the IShellLink interface */
- IShellLinkW* pshl = NULL;
- hRes = CoCreateInstance(&CLSID_ShellLink,
- NULL,
- CLSCTX_INPROC_SERVER,
- &IID_IShellLinkW,
- (LPVOID*)&pshl);
- if (SUCCEEDED(hRes))
- {
- /* Get a pointer to the IPersistFile interface */
- IPersistFile* ppf = NULL;
- hRes = IPersistFile_QueryInterface(pshl, &IID_IPersistFile, (LPVOID*)&ppf);
- if (SUCCEEDED(hRes))
- {
- /* Load the shortcut */
- hRes = IPersistFile_Load(ppf, ConsoleStartInfo->ConsoleTitle, STGM_READ);
- if (SUCCEEDED(hRes))
- {
- /*
- * Finally we can get the properties !
- * Update the old ones if needed.
- */
- INT ShowCmd = 0;
- // WORD HotKey = 0;
-
- /* Reset the name of the console with the name of the shortcut */
- Length = min(/*Length*/ Length - 4, // 4 == len(".lnk")
- sizeof(ConsoleInfo->ConsoleTitle) / sizeof(ConsoleInfo->ConsoleTitle[0]) - 1);
- wcsncpy(ConsoleInfo->ConsoleTitle, LinkName, Length);
- ConsoleInfo->ConsoleTitle[Length] = L'\0';
-
- /* Get the window showing command */
- hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd);
- if (SUCCEEDED(hRes)) ConsoleStartInfo->wShowWindow = (WORD)ShowCmd;
-
- /* Get the hotkey */
- // hRes = pshl->GetHotkey(&ShowCmd);
- // if (SUCCEEDED(hRes)) ConsoleStartInfo->HotKey = HotKey;
-
- /* Get the icon location, if any */
- hRes = IShellLinkW_GetIconLocation(pshl,
- ConsoleStartInfo->IconPath,
- sizeof(ConsoleStartInfo->IconPath)/sizeof(ConsoleStartInfo->IconPath[0]) - 1, // == MAX_PATH
- &ConsoleStartInfo->IconIndex);
- if (!SUCCEEDED(hRes))
- {
- ConsoleStartInfo->IconPath[0] = L'\0';
- ConsoleStartInfo->IconIndex = 0;
- }
-
- // FIXME: Since we still don't load console properties from the shortcut,
- // return false. When this will be done, we will return true instead.
- RetVal = FALSE;
- }
- IPersistFile_Release(ppf);
- }
- IShellLinkW_Release(pshl);
- }
- }
- CoUninitialize();
-
- return RetVal;
-}
-
NTSTATUS NTAPI
GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
IN OUT PCONSOLE_INFO ConsoleInfo,
IN OUT PVOID ExtraConsoleInfo,
IN ULONG ProcessId)
{
- PCONSOLE_START_INFO ConsoleStartInfo = ExtraConsoleInfo;
+ PCONSOLE_INIT_INFO ConsoleInitInfo = ExtraConsoleInfo;
PGUI_INIT_INFO GuiInitInfo;
- if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleStartInfo == NULL)
+ if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL)
return STATUS_INVALID_PARAMETER;
/* Initialize GUI terminal emulator common functionalities */
if (!GuiInit()) return STATUS_UNSUCCESSFUL;
- /*
- * Load per-application terminal settings.
- *
- * Check whether the process creating the console was launched via
- * a shell-link. ConsoleInfo->ConsoleTitle may be updated with the
- * name of the shortcut, and ConsoleStartInfo->Icon[Path|Index] too.
- */
- if (ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME)
- {
- if (!LoadShellLinkConsoleInfo(ConsoleStartInfo, ConsoleInfo))
- {
- ConsoleStartInfo->dwStartupFlags &= ~STARTF_TITLEISLINKNAME;
- }
- }
-
/*
* Initialize a private initialization info structure for later use.
* It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd.
// HACK: We suppose that the pointers will be valid in GuiInitFrontEnd...
GuiInitInfo->ConsoleInfo = ConsoleInfo;
- GuiInitInfo->ConsoleStartInfo = ConsoleStartInfo;
+ GuiInitInfo->ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo;
GuiInitInfo->ProcessId = ProcessId;
+
/* Finally, initialize the frontend structure */
FrontEnd->Vtbl = &GuiVtbl;
FrontEnd->Data = NULL;
#include "guisettings.h"
#include "conwnd.h"
-NTSTATUS GuiInitConsole(PCONSOLE Console,
- /*IN*/ PCONSOLE_START_INFO ConsoleStartInfo,
- PCONSOLE_INFO ConsoleInfo,
- DWORD ProcessId,
- LPCWSTR IconPath,
- INT IconIndex);
-
VOID
GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData);
Console->FrontEndIFace = *FrontEnd;
Status = FrontEnd->Vtbl->InitFrontEnd(FrontEnd, FrontEnd->Console);
+ if (!NT_SUCCESS(Status))
+ DPRINT1("InitFrontEnd failed, Status = 0x%08lx\n", Status);
/** HACK HACK!! Be sure FrontEndIFace is correctly updated in the console!! **/
DPRINT1("Using FrontEndIFace HACK(2), should be removed after proper implementation!\n");
FrontEnd->Vtbl->ReleaseScreenBuffer(FrontEnd, ScreenBuffer);
}
-static VOID NTAPI
-ConSrvTermChangeTitle(IN OUT PTERMINAL This)
-{
- PFRONTEND FrontEnd = This->Data;
- FrontEnd->Vtbl->ChangeTitle(FrontEnd);
-}
-
static VOID NTAPI
ConSrvTermGetLargestConsoleWindowSize(IN OUT PTERMINAL This,
PCOORD pSize)
ConSrvTermResizeTerminal,
ConSrvTermSetActiveScreenBuffer,
ConSrvTermReleaseScreenBuffer,
- ConSrvTermChangeTitle,
ConSrvTermGetLargestConsoleWindowSize,
ConSrvTermSetPalette,
ConSrvTermShowMouseCursor,
-
-
-
NTSTATUS
ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
PHANDLE pInputHandle,
PHANDLE pOutputHandle,
PHANDLE pErrorHandle,
- PCONSOLE_START_INFO ConsoleStartInfo)
+ PCONSOLE_INIT_INFO ConsoleInitInfo)
{
NTSTATUS Status = STATUS_SUCCESS;
HANDLE ConsoleHandle;
/* Initialize a new Console owned by this process */
Status = ConSrvInitConsole(&ConsoleHandle,
&Console,
- ConsoleStartInfo,
+ ConsoleInitInfo,
HandleToUlong(ProcessData->Process->ClientId.UniqueProcess));
if (!NT_SUCCESS(Status))
{
/*
* External interface (functions corresponding to the Console API)
*/
- VOID (NTAPI *ChangeTitle)(IN OUT PTERMINAL This);
VOID (NTAPI *GetLargestConsoleWindowSize)(IN OUT PTERMINAL This,
PCOORD pSize);
BOOL (NTAPI *SetPalette)(IN OUT PTERMINAL This,
UINT OutputCodePage;
/****************************** Other properties ******************************/
- UNICODE_STRING OriginalTitle; /* Original title of console, the one defined when the console leader is launched; it never changes. Always NULL-terminated */
- UNICODE_STRING Title; /* Title of console. Always NULL-terminated */
-
COORD ConsoleSize; /* The current size of the console, for text-mode only */
BOOLEAN FixedSize; /* TRUE if the console is of fixed size */
HANDLE ErrorHardwareEvent;
/****************************** Other properties ******************************/
- LIST_ENTRY PopupWindows; /*List of popup windows */
+ LIST_ENTRY PopupWindows; /* List of popup windows */
+ UNICODE_STRING OriginalTitle; /* Original title of console, the one defined when the console leader is launched; it never changes. Always NULL-terminated */
+ UNICODE_STRING Title; /* Title of console. Always NULL-terminated */
COLORREF Colors[16]; /* Colour palette */
} WINSRV_CONSOLE; // , *PWINSRV_CONSOLE;
(Console)->TermIFace.Vtbl->SetActiveScreenBuffer(&(Console)->TermIFace)
#define TermReleaseScreenBuffer(Console, ScreenBuffer) \
(Console)->TermIFace.Vtbl->ReleaseScreenBuffer(&(Console)->TermIFace, (ScreenBuffer))
-#define TermChangeTitle(Console) \
- (Console)->TermIFace.Vtbl->ChangeTitle(&(Console)->TermIFace)
#define TermGetLargestConsoleWindowSize(Console, pSize) \
(Console)->TermIFace.Vtbl->GetLargestConsoleWindowSize(&(Console)->TermIFace, (pSize))
#define TermSetPalette(Console, PaletteHandle, PaletteUsage) \
#define TermRefreshInternalInfo(Console) \
(Console)->FrontEndIFace.Vtbl->RefreshInternalInfo(&(Console)->FrontEndIFace)
+#define TermChangeTitle(Console) \
+ (Console)->FrontEndIFace.Vtbl->ChangeTitle(&(Console)->FrontEndIFace)
#define TermChangeIcon(Console, IconHandle) \
(Console)->FrontEndIFace.Vtbl->ChangeIcon(&(Console)->FrontEndIFace, (IconHandle))
#define TermGetConsoleWindowHandle(Console) \
RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
TargetProcessData->Process = TargetProcess;
TargetProcessData->InputWaitHandle = NULL;
- TargetProcessData->ConsoleHandle = TargetProcessData->ParentConsoleHandle = NULL;
- TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
+ TargetProcessData->ConsoleHandle = NULL;
+ TargetProcessData->ConsoleApp = FALSE;
/*
* The handles table gets initialized either when inheriting from
* handles table: this can happen if it is a GUI application having called
* AllocConsole), then try to inherit handles from the parent process.
*/
- if (TargetProcessData->ConsoleApp /* && SourceProcessData->ConsoleApp */)
+ if (TargetProcess->Flags & CsrProcessIsConsoleApp /* && SourceProcessData->ConsoleHandle != NULL */)
{
PCONSOLE_PROCESS_DATA SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
PCONSRV_CONSOLE SourceConsole;
{
/* Inherit the parent's handles table */
Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
- if (NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
- /* Temporary save the parent's console too */
- TargetProcessData->ParentConsoleHandle = SourceProcessData->ConsoleHandle;
+ DPRINT1("Inheriting handles table failed\n");
}
/* Unlock the parent's console */
NTSTATUS Status = STATUS_SUCCESS;
PCONSRV_API_CONNECTINFO ConnectInfo = (PCONSRV_API_CONNECTINFO)ConnectionInfo;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
+ CONSOLE_INIT_INFO ConsoleInitInfo;
if ( ConnectionInfo == NULL ||
ConnectionInfoLength == NULL ||
- *ConnectionInfoLength != sizeof(CONSRV_API_CONNECTINFO) )
+ *ConnectionInfoLength != sizeof(*ConnectInfo) )
{
DPRINT1("CONSRV: Connection failed - ConnectionInfo = 0x%p ; ConnectionInfoLength = 0x%p (%lu), wanted %lu\n",
ConnectionInfo,
ConnectionInfoLength,
ConnectionInfoLength ? *ConnectionInfoLength : (ULONG)-1,
- sizeof(CONSRV_API_CONNECTINFO));
+ sizeof(*ConnectInfo));
return STATUS_UNSUCCESSFUL;
}
/* If we don't need a console, then get out of here */
- if (!ConnectInfo->ConsoleStartInfo.ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
- {
- return STATUS_SUCCESS;
- }
-
- /* If we don't have a console, then create a new one... */
- if (!ConnectInfo->ConsoleHandle ||
- ConnectInfo->ConsoleHandle != ProcessData->ParentConsoleHandle)
+ DPRINT("ConnectInfo->IsConsoleApp = %s\n", ConnectInfo->IsConsoleApp ? "True" : "False");
+ if (!ConnectInfo->IsConsoleApp) return STATUS_SUCCESS;
+
+ /* Initialize the console initialization info structure */
+ ConsoleInitInfo.ConsoleStartInfo = &ConnectInfo->ConsoleStartInfo;
+ ConsoleInitInfo.TitleLength = ConnectInfo->TitleLength;
+ ConsoleInitInfo.ConsoleTitle = ConnectInfo->ConsoleTitle;
+ ConsoleInitInfo.DesktopLength = ConnectInfo->DesktopLength;
+ ConsoleInitInfo.Desktop = ConnectInfo->Desktop;
+ ConsoleInitInfo.AppNameLength = ConnectInfo->AppNameLength;
+ ConsoleInitInfo.AppName = ConnectInfo->AppName;
+ ConsoleInitInfo.CurDirLength = ConnectInfo->CurDirLength;
+ ConsoleInitInfo.CurDir = ConnectInfo->CurDir;
+
+ /* If we don't inherit from an existing console, then create a new one... */
+ if (ConnectInfo->ConsoleStartInfo.ConsoleHandle == NULL)
{
DPRINT("ConSrvConnect - Allocate a new console\n");
/* Initialize a new Console owned by the Console Leader Process */
Status = ConSrvAllocateConsole(ProcessData,
- &ConnectInfo->InputHandle,
- &ConnectInfo->OutputHandle,
- &ConnectInfo->ErrorHandle,
- &ConnectInfo->ConsoleStartInfo);
+ &ConnectInfo->ConsoleStartInfo.InputHandle,
+ &ConnectInfo->ConsoleStartInfo.OutputHandle,
+ &ConnectInfo->ConsoleStartInfo.ErrorHandle,
+ &ConsoleInitInfo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console allocation failed\n");
/* Reuse our current console */
Status = ConSrvInheritConsole(ProcessData,
- ConnectInfo->ConsoleHandle,
+ ConnectInfo->ConsoleStartInfo.ConsoleHandle,
FALSE,
- NULL, // &ConnectInfo->InputHandle,
- NULL, // &ConnectInfo->OutputHandle,
- NULL); // &ConnectInfo->ErrorHandle);
+ NULL, // &ConnectInfo->ConsoleStartInfo.InputHandle,
+ NULL, // &ConnectInfo->ConsoleStartInfo.OutputHandle,
+ NULL); // &ConnectInfo->ConsoleStartInfo.ErrorHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console inheritance failed\n");
}
}
+ /* Mark the process as having a console */
+ ProcessData->ConsoleApp = TRUE;
+ // ProcessData->Flags |= CsrProcessIsConsoleApp;
+
/* Return the console handle and the input wait handle to the caller */
- ConnectInfo->ConsoleHandle = ProcessData->ConsoleHandle;
- ConnectInfo->InputWaitHandle = ProcessData->InputWaitHandle;
+ ConnectInfo->ConsoleStartInfo.ConsoleHandle = ProcessData->ConsoleHandle;
+ ConnectInfo->ConsoleStartInfo.InputWaitHandle = ProcessData->InputWaitHandle;
/* Set the Property-Dialog and Control-Dispatcher handlers */
- ProcessData->PropDispatcher = ConnectInfo->ConsoleStartInfo.PropDispatcher;
- ProcessData->CtrlDispatcher = ConnectInfo->ConsoleStartInfo.CtrlDispatcher;
+ ProcessData->PropRoutine = ConnectInfo->PropRoutine;
+ ProcessData->CtrlRoutine = ConnectInfo->CtrlRoutine;
return STATUS_SUCCESS;
}
{
DPRINT("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
ConSrvRemoveConsole(ProcessData);
+
+ /* Mark the process as not having a console anymore */
+ ProcessData->ConsoleApp = FALSE;
+ Process->Flags &= ~CsrProcessIsConsoleApp;
}
RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
PHANDLE pInputHandle,
PHANDLE pOutputHandle,
PHANDLE pErrorHandle,
- PCONSOLE_START_INFO ConsoleStartInfo);
+ PCONSOLE_INIT_INFO ConsoleInitInfo);
NTSTATUS ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
HANDLE ConsoleHandle,
BOOLEAN CreateNewHandlesTable,