[KERNEL32][CONSRV]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 7 Sep 2014 22:53:49 +0000 (22:53 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 7 Sep 2014 22:53:49 +0000 (22:53 +0000)
- 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

22 files changed:
dll/win32/kernel32/client/console/console.c
dll/win32/kernel32/client/console/init.c
dll/win32/kernel32/client/console/readwrite.c
dll/win32/kernel32/client/dllmain.c
dll/win32/kernel32/client/proc.c
dll/win32/kernel32/include/console.h
include/reactos/subsys/win/conmsg.h
win32ss/user/winsrv/consrv/condrv/console.c
win32ss/user/winsrv/consrv/condrv/dummyterm.c
win32ss/user/winsrv/consrv/console.c
win32ss/user/winsrv/consrv/console.h
win32ss/user/winsrv/consrv/consrv.h
win32ss/user/winsrv/consrv/frontends/gui/guisettings.c
win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
win32ss/user/winsrv/consrv/frontends/gui/guiterm.h
win32ss/user/winsrv/consrv/frontends/terminal.c
win32ss/user/winsrv/consrv/handle.c
win32ss/user/winsrv/consrv/include/conio.h
win32ss/user/winsrv/consrv/include/conio_winsrv.h
win32ss/user/winsrv/consrv/include/term.h
win32ss/user/winsrv/consrv/init.c
win32ss/user/winsrv/consrv/procinit.h

index 0a4059a..fc79d88 100644 (file)
 /* 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)
 {
@@ -193,8 +201,7 @@ ConsoleControlDispatcher(IN LPVOID lpThreadParameter)
 }
 
 VOID
-WINAPI
-InitConsoleCtrlHandling(VOID)
+InitializeCtrlHandling(VOID)
 {
     /* Initialize Console Ctrl Handler */
     NrAllocatedHandlers = NrCtrlHandlers = 1;
@@ -203,6 +210,135 @@ InitConsoleCtrlHandling(VOID)
 }
 
 
+/* 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
@@ -999,77 +1135,197 @@ SetStdHandle(DWORD  nStdHandle,
 }
 
 
-/*--------------------------------------------------------------
- *    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
@@ -1114,9 +1370,7 @@ FreeConsole(VOID)
 }
 
 
-/*--------------------------------------------------------------
- *    GetConsoleScreenBufferInfo
- *
+/*
  * @implemented
  */
 BOOL
@@ -1159,9 +1413,7 @@ GetConsoleScreenBufferInfo(HANDLE hConsoleOutput,
 }
 
 
-/*--------------------------------------------------------------
- *    SetConsoleCursorPosition
- *
+/*
  * @implemented
  */
 BOOL
@@ -1190,9 +1442,7 @@ SetConsoleCursorPosition(HANDLE hConsoleOutput,
 }
 
 
-/*--------------------------------------------------------------
- *     GetConsoleMode
- *
+/*
  * @implemented
  */
 BOOL
@@ -1228,9 +1478,7 @@ GetConsoleMode(HANDLE hConsoleHandle,
 }
 
 
-/*--------------------------------------------------------------
- *     SetConsoleMode
- *
+/*
  * @implemented
  */
 BOOL
@@ -1259,9 +1507,7 @@ SetConsoleMode(HANDLE hConsoleHandle,
 }
 
 
-/*--------------------------------------------------------------
- *     GetNumberOfConsoleInputEvents
- *
+/*
  * @implemented
  */
 BOOL
@@ -1298,9 +1544,7 @@ GetNumberOfConsoleInputEvents(HANDLE hConsoleInput,
 }
 
 
-/*--------------------------------------------------------------
- *     GetLargestConsoleWindowSize
- *
+/*
  * @implemented
  */
 COORD
@@ -1329,9 +1573,7 @@ GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
 }
 
 
-/*--------------------------------------------------------------
- *    GetConsoleCursorInfo
- *
+/*
  * @implemented
  */
 BOOL
@@ -1371,9 +1613,7 @@ GetConsoleCursorInfo(HANDLE hConsoleOutput,
 }
 
 
-/*--------------------------------------------------------------
- *     SetConsoleCursorInfo
- *
+/*
  * @implemented
  */
 BOOL
@@ -1402,9 +1642,7 @@ SetConsoleCursorInfo(HANDLE hConsoleOutput,
 }
 
 
-/*--------------------------------------------------------------
- *     GetNumberOfConsoleMouseButtons
- *
+/*
  * @implemented
  */
 BOOL
@@ -1431,9 +1669,7 @@ GetNumberOfConsoleMouseButtons(LPDWORD lpNumberOfMouseButtons)
 }
 
 
-/*--------------------------------------------------------------
- *     SetConsoleActiveScreenBuffer
- *
+/*
  * @implemented
  */
 BOOL
@@ -1460,9 +1696,7 @@ SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)
 }
 
 
-/*--------------------------------------------------------------
- *     FlushConsoleInputBuffer
- *
+/*
  * @implemented
  */
 BOOL
@@ -1489,9 +1723,7 @@ FlushConsoleInputBuffer(HANDLE hConsoleInput)
 }
 
 
-/*--------------------------------------------------------------
- *     SetConsoleScreenBufferSize
- *
+/*
  * @implemented
  */
 BOOL
@@ -1564,9 +1796,7 @@ IntScrollConsoleScreenBuffer(HANDLE hConsoleOutput,
 }
 
 
-/*--------------------------------------------------------------
- *    ScrollConsoleScreenBufferA
- *
+/*
  * @implemented
  */
 BOOL
@@ -1586,9 +1816,7 @@ ScrollConsoleScreenBufferA(HANDLE hConsoleOutput,
 }
 
 
-/*--------------------------------------------------------------
- *     ScrollConsoleScreenBufferW
- *
+/*
  * @implemented
  */
 BOOL
@@ -1608,9 +1836,7 @@ ScrollConsoleScreenBufferW(HANDLE hConsoleOutput,
 }
 
 
-/*--------------------------------------------------------------
- *     SetConsoleWindowInfo
- *
+/*
  * @implemented
  */
 BOOL
@@ -1647,9 +1873,7 @@ SetConsoleWindowInfo(HANDLE hConsoleOutput,
 }
 
 
-/*--------------------------------------------------------------
- *      SetConsoleTextAttribute
- *
+/*
  * @implemented
  */
 BOOL
@@ -1774,9 +1998,7 @@ SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,
 }
 
 
-/*--------------------------------------------------------------
- *     GenerateConsoleCtrlEvent
- *
+/*
  * @implemented
  */
 BOOL
@@ -1854,9 +2076,9 @@ IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode)
         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);
@@ -1865,9 +2087,7 @@ IntGetConsoleTitle(LPVOID lpConsoleTitle, DWORD dwNumChars, BOOLEAN bUnicode)
 }
 
 
-/*--------------------------------------------------------------
- *    GetConsoleTitleW
- *
+/*
  * @implemented
  */
 DWORD
@@ -1879,9 +2099,7 @@ GetConsoleTitleW(LPWSTR lpConsoleTitle,
 }
 
 
-/*--------------------------------------------------------------
- *     GetConsoleTitleA
- *
+/*
  * @implemented
  */
 DWORD
@@ -1935,9 +2153,7 @@ IntSetConsoleTitle(CONST VOID *lpConsoleTitle, BOOLEAN bUnicode)
     return TRUE;
 }
 
-/*--------------------------------------------------------------
- *    SetConsoleTitleW
- *
+/*
  * @implemented
  */
 BOOL
@@ -1948,9 +2164,7 @@ SetConsoleTitleW(LPCWSTR lpConsoleTitle)
 }
 
 
-/*--------------------------------------------------------------
- *    SetConsoleTitleA
- *
+/*
  * @implemented
  */
 BOOL
@@ -1961,9 +2175,7 @@ SetConsoleTitleA(LPCSTR lpConsoleTitle)
 }
 
 
-/*--------------------------------------------------------------
- *    CreateConsoleScreenBuffer
- *
+/*
  * @implemented
  */
 HANDLE
@@ -2040,9 +2252,7 @@ CreateConsoleScreenBuffer(DWORD dwDesiredAccess,
 }
 
 
-/*--------------------------------------------------------------
- *    GetConsoleCP
- *
+/*
  * @implemented
  */
 UINT
@@ -2070,9 +2280,7 @@ GetConsoleCP(VOID)
 }
 
 
-/*--------------------------------------------------------------
- *    SetConsoleCP
- *
+/*
  * @implemented
  */
 BOOL
@@ -2102,9 +2310,7 @@ SetConsoleCP(UINT wCodePageID)
 }
 
 
-/*--------------------------------------------------------------
- *    GetConsoleOutputCP
- *
+/*
  * @implemented
  */
 UINT
@@ -2132,9 +2338,7 @@ GetConsoleOutputCP(VOID)
 }
 
 
-/*--------------------------------------------------------------
- *    SetConsoleOutputCP
- *
+/*
  * @implemented
  */
 BOOL
@@ -2164,9 +2368,7 @@ SetConsoleOutputCP(UINT wCodePageID)
 }
 
 
-/*--------------------------------------------------------------
- *     GetConsoleProcessList
- *
+/*
  * @implemented
  */
 DWORD
@@ -2222,9 +2424,7 @@ GetConsoleProcessList(LPDWORD lpdwProcessList,
 }
 
 
-/*--------------------------------------------------------------
- *     GetConsoleSelectionInfo
- *
+/*
  * @implemented
  */
 BOOL
@@ -2258,60 +2458,136 @@ GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)
 }
 
 
-/*--------------------------------------------------------------
- *     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
@@ -2337,9 +2613,7 @@ GetConsoleWindow(VOID)
 }
 
 
-/*--------------------------------------------------------------
- *     SetConsoleIcon
- *
+/*
  * @implemented
  */
 BOOL
@@ -2369,35 +2643,35 @@ SetConsoleIcon(HICON hIcon)
 /******************************************************************************
  * \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;
 
@@ -2408,42 +2682,72 @@ SetConsoleInputExeNameW(LPCWSTR lpInputExeName)
 /******************************************************************************
  * \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
 }
 
 
@@ -2460,37 +2764,30 @@ SetConsoleInputExeNameA(LPCSTR lpInputExeName)
  */
 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;
 }
 
 
@@ -2505,33 +2802,40 @@ GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer)
  */
 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
index 1313b77..1d550b9 100644 (file)
 /* 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 ******************************************************************/
@@ -41,6 +40,7 @@ PropDialogHandler(IN LPVOID lpThreadParameter)
 {
     // NOTE: lpThreadParameter corresponds to the client shared section handle.
 
+    NTSTATUS Status = STATUS_SUCCESS;
     APPLET_PROC CPLFunc;
 
     /*
@@ -67,12 +67,11 @@ PropDialogHandler(IN LPVOID lpThreadParameter)
         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;
         }
     }
 
@@ -80,240 +79,446 @@ PropDialogHandler(IN LPVOID lpThreadParameter)
     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;
 }
 
index f1818a0..39d0727 100644 (file)
  * Read functions *
  ******************/
 
-DWORD
-WINAPI
-GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer);
-
 static
 BOOL
 IntReadConsole(IN HANDLE hConsoleInput,
@@ -58,26 +54,12 @@ 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 ***/
     {
index 0442129..09aa3c0 100644 (file)
@@ -200,7 +200,7 @@ DllMain(HANDLE hDll,
             }
 
             /* Initialize Console Support */
-            if (!BasepInitConsole())
+            if (!ConDllInitialize(dwReason, SessionDir))
             {
                 DPRINT1("Failed to set up console\n");
                 return FALSE;
index 47bb140..e590f20 100644 (file)
@@ -726,7 +726,7 @@ BasePushProcessParameters(IN ULONG ParameterFlags,
         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;
index 1886608..d21fec0 100644 (file)
 
 /* 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
@@ -59,9 +68,32 @@ GetConsoleInputWaitHandle(VOID);
 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,
@@ -73,7 +105,4 @@ OpenConsoleW(LPCWSTR wsName,
              BOOL    bInheritHandle,
              DWORD   dwShareMode);
 
-BOOL WINAPI
-SetConsoleInputExeNameW(LPCWSTR lpInputExeName);
-
 /* EOF */
index 9bb3d7c..42d8398 100644 (file)
@@ -119,6 +119,13 @@ typedef enum _CONSRV_API_NUMBER
 //
 typedef struct _CONSOLE_PROPERTIES
 {
+    INT   IconIndex;
+    HICON hIcon;
+    HICON hIconSm;
+    DWORD dwHotKey;
+    DWORD dwStartupFlags;
+
+    // NT_CONSOLE_PROPS
     WORD wFillAttribute;
     WORD wPopupFillAttribute;
 
@@ -134,62 +141,60 @@ typedef struct _CONSOLE_PROPERTIES
     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)
@@ -259,25 +264,31 @@ typedef struct _CONSOLE_ALLOCCONSOLE
 {
     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
index 6e289a2..4075e76 100644 (file)
@@ -76,35 +76,6 @@ RemoveConsole(IN PCONSOLE Console)
 
 /* 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)
 {
@@ -194,9 +165,6 @@ ConDrvInitConsole(OUT PCONSOLE* NewConsole,
     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;
@@ -272,28 +240,6 @@ ConDrvInitConsole(OUT PCONSOLE* NewConsole,
     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 */
@@ -460,9 +406,6 @@ ConDrvDeleteConsole(IN PCONSOLE Console)
 
     if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
 
-    ConsoleFreeUnicodeString(&Console->OriginalTitle);
-    ConsoleFreeUnicodeString(&Console->Title);
-
     DPRINT("ConDrvDeleteConsole - Unlocking\n");
     LeaveCriticalSection(&Console->Lock);
     DPRINT("ConDrvDeleteConsole - Destroying lock\n");
@@ -566,111 +509,6 @@ ConDrvSetConsoleMode(IN PCONSOLE Console,
     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,
index 2b61232..2066cb5 100644 (file)
@@ -108,11 +108,6 @@ DummyReleaseScreenBuffer(IN OUT PTERMINAL This,
 {
 }
 
-static VOID NTAPI
-DummyChangeTitle(IN OUT PTERMINAL This)
-{
-}
-
 static VOID NTAPI
 DummyGetLargestConsoleWindowSize(IN OUT PTERMINAL This,
                                  PCOORD pSize)
@@ -148,7 +143,6 @@ static TERMINAL_VTBL DummyVtbl =
     DummyResizeTerminal,
     DummySetActiveScreenBuffer,
     DummyReleaseScreenBuffer,
-    DummyChangeTitle,
     DummyGetLargestConsoleWindowSize,
     DummySetPalette,
     DummyShowMouseCursor,
index dcade22..fc0c8cd 100644 (file)
 
 #include <ndk/psfuncs.h>
 
+/* This is for COM usage */
+#define COBJMACROS
+#include <shlobj.h>
+
+
 #include <alias.h>
 #include <history.h>
 #include "procinit.h"
@@ -209,6 +214,35 @@ ConSrvValidateConsole(OUT PCONSRV_CONSOLE* Console,
 
 /* 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)
 {
@@ -317,10 +351,157 @@ ConSrvInitTerminal(IN OUT PTERMINAL Terminal,
 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;
@@ -331,7 +512,7 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
 
     TERMINAL Terminal; /* The ConSrv terminal for this console */
 
-    if (NewConsole == NULL || ConsoleStartInfo == NULL)
+    if (NewConsole == NULL || ConsoleInitInfo == NULL)
         return STATUS_INVALID_PARAMETER;
 
     *NewConsole = NULL;
@@ -344,15 +525,15 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
     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))
     {
@@ -361,10 +542,25 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
     }
     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,
@@ -379,17 +575,17 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
          * (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;
         }
     }
 
@@ -410,6 +606,31 @@ ConSrvInitConsole(OUT PHANDLE NewConsoleHandle,
 
     /*** 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;
@@ -482,6 +703,10 @@ ConSrvDeleteConsole(PCONSRV_CONSOLE Console)
     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);
 
@@ -504,7 +729,7 @@ ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent,
 
     DPRINT("ConSrvConsoleCtrlEventTimeout Parent ProcessId = %x\n", ProcessData->Process->ClientId.UniqueProcess);
 
-    if (ProcessData->CtrlDispatcher)
+    if (ProcessData->CtrlRoutine)
     {
         _SEH2_TRY
         {
@@ -513,7 +738,7 @@ ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent,
             _SEH2_TRY
             {
                 Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
-                                            ProcessData->CtrlDispatcher,
+                                            ProcessData->CtrlRoutine,
                                             UlongToPtr(CtrlEvent), 0, NULL);
                 if (NULL == Thread)
                 {
@@ -522,7 +747,8 @@ ConSrvConsoleCtrlEventTimeout(IN ULONG CtrlEvent,
                 }
                 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);
                 }
             }
@@ -628,9 +854,6 @@ ConSrvConsoleProcessCtrlEvent(IN PCONSRV_CONSOLE Console,
 }
 
 
-
-
-
 /* PUBLIC SERVER APIS *********************************************************/
 
 CSR_API(SrvAllocConsole)
@@ -639,6 +862,7 @@ 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)
     {
@@ -646,33 +870,64 @@ CSR_API(SrvAllocConsole)
         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;
 }
@@ -694,6 +949,14 @@ CSR_API(SrvAttachConsole)
         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))
     {
@@ -734,22 +997,26 @@ CSR_API(SrvAttachConsole)
     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;
 
@@ -761,7 +1028,15 @@ Quit:
 
 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;
 }
 
@@ -865,16 +1140,12 @@ CSR_API(SrvSetConsoleMode)
     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,
@@ -891,26 +1162,52 @@ CSR_API(SrvGetConsoleTitle)
         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,
@@ -926,13 +1223,56 @@ CSR_API(SrvSetConsoleTitle)
         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;
 }
index c70341c..7118dff 100644 (file)
@@ -8,13 +8,27 @@
 
 #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);
 
index 18aabfb..09b87fc 100644 (file)
@@ -51,10 +51,9 @@ typedef struct _CONSOLE_PROCESS_DATA
 {
     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.
 
@@ -62,8 +61,9 @@ typedef struct _CONSOLE_PROCESS_DATA
     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;
 
 
index 0d83faf..f7d67ef 100644 (file)
@@ -372,7 +372,7 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
     }
 
     /* Start the properties dialog */
-    if (ProcessData->PropDispatcher)
+    if (ProcessData->PropRoutine)
     {
         _SEH2_TRY
         {
@@ -381,7 +381,7 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
             _SEH2_TRY
             {
                 Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0,
-                                            ProcessData->PropDispatcher,
+                                            ProcessData->PropRoutine,
                                             (PVOID)hClientSection, 0, NULL);
                 if (NULL == Thread)
                 {
@@ -389,7 +389,8 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
                 }
                 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);
                 }
             }
index 52f441a..261692e 100644 (file)
@@ -13,9 +13,6 @@
 
 #include <consrv.h>
 
-#define COBJMACROS
-#include <shlobj.h>
-
 #define NDEBUG
 #include <debug.h>
 
@@ -405,9 +402,7 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
     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;
@@ -422,10 +417,6 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
     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)
@@ -451,10 +442,10 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
     /* 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);
@@ -500,29 +491,17 @@ GuiInitFrontEnd(IN OUT PFRONTEND This,
     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 */
@@ -1114,138 +1093,21 @@ static FRONTEND_VTBL GuiVtbl =
 };
 
 
-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.
@@ -1255,9 +1117,10 @@ GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd,
 
     // 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;
index 8755cdd..3b252af 100644 (file)
 #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);
 
index 30ad25c..668b4d6 100644 (file)
@@ -273,6 +273,8 @@ ConSrvTermInitTerminal(IN OUT PTERMINAL This,
     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");
@@ -697,13 +699,6 @@ ConSrvTermReleaseScreenBuffer(IN OUT PTERMINAL This,
     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)
@@ -743,7 +738,6 @@ static TERMINAL_VTBL ConSrvTermVtbl =
     ConSrvTermResizeTerminal,
     ConSrvTermSetActiveScreenBuffer,
     ConSrvTermReleaseScreenBuffer,
-    ConSrvTermChangeTitle,
     ConSrvTermGetLargestConsoleWindowSize,
     ConSrvTermSetPalette,
     ConSrvTermShowMouseCursor,
index f45bfff..f54a459 100644 (file)
@@ -470,15 +470,12 @@ ConSrvReleaseObject(IN PCONSOLE_IO_OBJECT Object,
 
 
 
-
-
-
 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;
@@ -499,7 +496,7 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
     /* Initialize a new Console owned by this process */
     Status = ConSrvInitConsole(&ConsoleHandle,
                                &Console,
-                               ConsoleStartInfo,
+                               ConsoleInitInfo,
                                HandleToUlong(ProcessData->Process->ClientId.UniqueProcess));
     if (!NT_SUCCESS(Status))
     {
index e326e78..a372864 100644 (file)
@@ -251,7 +251,6 @@ typedef struct _TERMINAL_VTBL
     /*
      * 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,
@@ -326,9 +325,6 @@ typedef struct _CONSOLE
     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 */
 
index 36f9446..135ccb5 100644 (file)
@@ -183,7 +183,9 @@ typedef struct _WINSRV_CONSOLE
     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;
index beb3cb8..ecea140 100644 (file)
@@ -31,8 +31,6 @@
     (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) \
@@ -45,6 +43,8 @@
 
 #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) \
index db82eb9..743166d 100644 (file)
@@ -354,8 +354,8 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess,
     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
@@ -377,7 +377,7 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess,
      * 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;
@@ -389,10 +389,9 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess,
         {
             /* 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 */
@@ -416,28 +415,37 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
     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");
 
@@ -454,10 +462,10 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
 
         /* 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");
@@ -470,11 +478,11 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
 
         /* 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");
@@ -482,13 +490,17 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
         }
     }
 
+    /* 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;
 }
@@ -508,6 +520,10 @@ ConSrvDisconnect(PCSR_PROCESS Process)
     {
         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);
index 5ceca6a..cbc0d6b 100644 (file)
@@ -12,7 +12,7 @@ NTSTATUS ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
                                PHANDLE pInputHandle,
                                PHANDLE pOutputHandle,
                                PHANDLE pErrorHandle,
-                               PCONSOLE_START_INFO ConsoleStartInfo);
+                               PCONSOLE_INIT_INFO ConsoleInitInfo);
 NTSTATUS ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
                               HANDLE ConsoleHandle,
                               BOOLEAN CreateNewHandlesTable,