[KERNEL32][CONSRV]

- 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
This commit is contained in:
Hermès Bélusca-Maïto 2014-09-07 22:53:49 +00:00
parent 4c18b81f0f
commit a9feb19181
22 changed files with 1544 additions and 965 deletions

File diff suppressed because it is too large Load diff

View file

@ -22,15 +22,14 @@
/* 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,203 +79,223 @@ 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;
}
static INT
ParseShellInfo(LPCWSTR lpszShellInfo,
LPCWSTR lpszKeyword)
{
DPRINT1("ParseShellInfo is UNIMPLEMENTED\n");
return 0;
}
/*
* NOTE:
* The "LPDWORD Length" parameters point on input to the maximum size of
* the buffers that can hold data (if != 0), and on output they hold the
* real size of the data. If "Length" are == 0 on input, then on output
* they receive the full size of the data.
* The "LPWSTR* lpTitle" parameter has a double meaning:
* - when "CaptureTitle" is TRUE, data is copied to the buffer pointed
* by the pointer (*lpTitle).
* - when "CaptureTitle" is FALSE, "*lpTitle" is set to the address of
* the source data.
*/
VOID
SetUpConsoleInfo(IN BOOLEAN CaptureTitle,
IN OUT LPDWORD pTitleLength,
IN OUT LPWSTR* lpTitle OPTIONAL,
IN OUT LPDWORD pDesktopLength,
IN OUT LPWSTR* lpDesktop OPTIONAL,
IN OUT PCONSOLE_START_INFO ConsoleStartInfo)
{
PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
DWORD Length;
/* Initialize the fields */
ConsoleStartInfo->IconIndex = 0;
ConsoleStartInfo->hIcon = NULL;
ConsoleStartInfo->hIconSm = NULL;
ConsoleStartInfo->dwStartupFlags = Parameters->WindowFlags;
ConsoleStartInfo->nFont = 0;
ConsoleStartInfo->nInputBufferSize = 0;
ConsoleStartInfo->uCodePage = GetOEMCP();
if (lpTitle)
{
LPWSTR Title;
/* If we don't have any title, use the default one */
if (Parameters->WindowTitle.Buffer == NULL)
{
Title = DefaultConsoleTitle;
Length = lstrlenW(DefaultConsoleTitle) * sizeof(WCHAR); // sizeof(DefaultConsoleTitle);
}
else
{
Title = Parameters->WindowTitle.Buffer;
Length = Parameters->WindowTitle.Length;
}
/* Retrieve the needed buffer size */
Length += sizeof(WCHAR);
if (*pTitleLength > 0) Length = min(Length, *pTitleLength);
*pTitleLength = Length;
/* Capture the data if needed, or, return a pointer to it */
if (CaptureTitle)
{
/*
* Length is always >= sizeof(WCHAR). Copy everything but the
* possible trailing NULL character, and then NULL-terminate.
*/
Length -= sizeof(WCHAR);
RtlCopyMemory(*lpTitle, Title, Length);
(*lpTitle)[Length / sizeof(WCHAR)] = UNICODE_NULL;
}
else
{
*lpTitle = Title;
}
}
else
{
*pTitleLength = 0;
}
if (lpDesktop && Parameters->DesktopInfo.Buffer && *Parameters->DesktopInfo.Buffer)
{
/* Retrieve the needed buffer size */
Length = Parameters->DesktopInfo.Length + sizeof(WCHAR);
if (*pDesktopLength > 0) Length = min(Length, *pDesktopLength);
*pDesktopLength = Length;
/* Return a pointer to the data */
*lpDesktop = Parameters->DesktopInfo.Buffer;
}
else
{
*pDesktopLength = 0;
if (lpDesktop) *lpDesktop = NULL;
}
if (Parameters->WindowFlags & STARTF_USEFILLATTRIBUTE)
{
ConsoleStartInfo->wFillAttribute = (WORD)Parameters->FillAttribute;
}
if (Parameters->WindowFlags & STARTF_USECOUNTCHARS)
{
ConsoleStartInfo->dwScreenBufferSize.X = (SHORT)Parameters->CountCharsX;
ConsoleStartInfo->dwScreenBufferSize.Y = (SHORT)Parameters->CountCharsY;
}
if (Parameters->WindowFlags & STARTF_USESHOWWINDOW)
{
ConsoleStartInfo->wShowWindow = (WORD)Parameters->ShowWindowFlags;
}
if (Parameters->WindowFlags & STARTF_USEPOSITION)
{
ConsoleStartInfo->dwWindowOrigin.X = (SHORT)Parameters->StartingX;
ConsoleStartInfo->dwWindowOrigin.Y = (SHORT)Parameters->StartingY;
}
if (Parameters->WindowFlags & STARTF_USESIZE)
{
ConsoleStartInfo->dwWindowSize.X = (SHORT)Parameters->CountX;
ConsoleStartInfo->dwWindowSize.Y = (SHORT)Parameters->CountY;
}
/* Get shell information (ShellInfo.Buffer is NULL-terminated) */
if (Parameters->ShellInfo.Buffer != NULL)
{
ConsoleStartInfo->IconIndex = ParseShellInfo(Parameters->ShellInfo.Buffer, L"dde.");
if ((Parameters->WindowFlags & STARTF_USEHOTKEY) == 0)
ConsoleStartInfo->dwHotKey = ParseShellInfo(Parameters->ShellInfo.Buffer, L"hotkey.");
else
ConsoleStartInfo->dwHotKey = HandleToUlong(Parameters->StandardInput);
}
}
VOID
InitConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
IN PUNICODE_STRING ImagePathName)
SetUpHandles(IN PCONSOLE_START_INFO ConsoleStartInfo)
{
STARTUPINFOW si;
SIZE_T Length;
PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
/* Get the startup information */
GetStartupInfoW(&si);
/* Initialize the fields */
ConsoleStartInfo->dwStartupFlags = si.dwFlags;
if (si.dwFlags & STARTF_USEFILLATTRIBUTE)
if (ConsoleStartInfo->dwStartupFlags & STARTF_USEHOTKEY)
{
ConsoleStartInfo->wFillAttribute = (WORD)si.dwFillAttribute;
Parameters->WindowFlags &= ~STARTF_USEHOTKEY;
}
if (si.dwFlags & STARTF_USECOUNTCHARS)
if (ConsoleStartInfo->dwStartupFlags & STARTF_SHELLPRIVATE)
{
ConsoleStartInfo->dwScreenBufferSize.X = (SHORT)(si.dwXCountChars);
ConsoleStartInfo->dwScreenBufferSize.Y = (SHORT)(si.dwYCountChars);
}
if (si.dwFlags & STARTF_USESHOWWINDOW)
{
ConsoleStartInfo->wShowWindow = si.wShowWindow;
}
if (si.dwFlags & STARTF_USEPOSITION)
{
ConsoleStartInfo->dwWindowOrigin.X = (SHORT)(si.dwX);
ConsoleStartInfo->dwWindowOrigin.Y = (SHORT)(si.dwY);
}
if (si.dwFlags & STARTF_USESIZE)
{
ConsoleStartInfo->dwWindowSize.X = (SHORT)(si.dwXSize);
ConsoleStartInfo->dwWindowSize.Y = (SHORT)(si.dwYSize);
Parameters->WindowFlags &= ~STARTF_SHELLPRIVATE;
}
/* Set up the title for the console */
if (si.lpTitle)
{
wcsncpy(ConsoleStartInfo->ConsoleTitle, si.lpTitle, MAX_PATH + 1);
}
else
{
ConsoleStartInfo->ConsoleTitle[0] = L'\0';
}
/* We got the handles, let's set them */
Parameters->ConsoleHandle = ConsoleStartInfo->ConsoleHandle;
/* 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;
if (!(ConsoleStartInfo->dwStartupFlags & STARTF_USESTDHANDLES))
{
Parameters->StandardInput = ConsoleStartInfo->InputHandle;
Parameters->StandardOutput = ConsoleStartInfo->OutputHandle;
Parameters->StandardError = ConsoleStartInfo->ErrorHandle;
}
}
BOOL
WINAPI
BasepInitConsole(VOID)
static BOOLEAN
IsConsoleApp(VOID)
{
PIMAGE_NT_HEADERS ImageNtHeader = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
return (ImageNtHeader && (ImageNtHeader->OptionalHeader.Subsystem ==
IMAGE_SUBSYSTEM_WINDOWS_CUI));
}
static BOOLEAN
ConnectConsole(IN PWSTR SessionDir,
IN PCONSRV_API_CONNECTINFO ConnectInfo,
OUT PBOOLEAN IsServerProcess)
{
NTSTATUS Status;
PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
WCHAR SessionDir[256];
ULONG SessionId = NtCurrentPeb()->SessionId;
BOOLEAN InServer;
ULONG ConnectInfoSize = sizeof(*ConnectInfo);
CONSRV_API_CONNECTINFO ConnectInfo;
ULONG ConnectInfoSize = sizeof(ConnectInfo);
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);
/* 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)
{
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';
}
else
{
LPCWSTR ExeName;
InitConsoleInfo(&ConnectInfo.ConsoleStartInfo,
&Parameters->ImagePathName);
/* Initialize Input EXE name */
ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\');
if (ExeName) SetConsoleInputExeNameW(ExeName + 1);
/* Assume one is needed */
ConnectInfo.ConsoleStartInfo.ConsoleNeeded = TRUE;
/* 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);
}
}
/* Now use the proper console handle */
ConnectInfo.ConsoleHandle = Parameters->ConsoleHandle;
/* Initialize the Console Ctrl Handler */
InitConsoleCtrlHandling();
ConnectInfo.ConsoleStartInfo.CtrlDispatcher = ConsoleControlDispatcher;
/* Initialize the Property Dialog Handler */
ConnectInfo.ConsoleStartInfo.PropDispatcher = PropDialogHandler;
/* Setup the right Object Directory path */
if (!SessionId)
{
/* Use the raw path */
wcscpy(SessionDir, WIN_OBJ_DIR);
}
else
{
/* Use the session path */
swprintf(SessionDir,
L"%ws\\%ld%ws",
SESSION_DIR,
SessionId,
WIN_OBJ_DIR);
}
ASSERT(SessionDir);
/* Connect to the Console Server */
DPRINT("Connecting to the Console Server in BasepInitConsole...\n");
DPRINT("Connecting to the Console Server...\n");
Status = CsrClientConnectToServer(SessionDir,
CONSRV_SERVERDLL_INDEX,
&ConnectInfo,
ConnectInfo,
&ConnectInfoSize,
&InServer);
IsServerProcess);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status);
@ -284,36 +303,222 @@ BasepInitConsole(VOID)
}
/* Nothing to do for server-to-server */
if (InServer) return TRUE;
if (*IsServerProcess) return TRUE;
/* Nothing to do if not a console app */
if (!ConnectInfo.ConsoleStartInfo.ConsoleNeeded) return TRUE;
/* Nothing to do if this is not a console app */
if (!ConnectInfo->IsConsoleApp) return TRUE;
/* We got the handles, let's set them */
if ((Parameters->ConsoleHandle = ConnectInfo.ConsoleHandle))
#ifdef USE_CONSOLE_INIT_HANDLES
/* Wait for the connection to finish */
Status = NtWaitForMultipleObjects(2, ConnectInfo->ConsoleStartInfo.Events,
WaitAny, FALSE, NULL);
if (!NT_SUCCESS(Status))
{
/* 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;
}
BaseSetLastNTError(Status);
return FALSE;
}
InputWaitHandle = ConnectInfo.InputWaitHandle;
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
ConDllInitialize(IN ULONG Reason,
IN PWSTR SessionDir)
{
NTSTATUS Status;
PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
BOOLEAN IsServerProcess;
CONSRV_API_CONNECTINFO ConnectInfo;
LCID lcid;
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;
/* Show by default the console window when applicable */
ConnectInfo.IsWindowVisible = TRUE;
/* If this is a console app, a console will be created/opened */
ConnectInfo.IsConsoleApp = IsConsoleApp();
/* Do nothing if this is not a console app... */
if (!ConnectInfo.IsConsoleApp)
{
DPRINT("Image is not a console application\n");
}
/*
* Handle the special flags given to us by BasePushProcessParameters.
*/
if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS)
{
/* No console to create */
DPRINT("No console to create\n");
/*
* The new process does not inherit its parent's console and cannot
* attach to the console of its parent. The new process can call the
* AllocConsole function at a later time to create a console.
*/
Parameters->ConsoleHandle = NULL; // Do not inherit the parent's console.
ConnectInfo.IsConsoleApp = FALSE; // Do not create any console.
}
else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
{
/* We'll get the real one soon */
DPRINT("Creating a new separate console\n");
/*
* The new process has a new console, instead of inheriting
* its parent's console.
*/
Parameters->ConsoleHandle = NULL; // Do not inherit the parent's console.
}
else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW)
{
/* We'll get the real one soon */
DPRINT("Creating a new invisible console\n");
/*
* The process is a console application that is being run
* without a console window. Therefore, the console handle
* for the application is not set.
*/
Parameters->ConsoleHandle = NULL; // Do not inherit the parent's console.
ConnectInfo.IsWindowVisible = FALSE; // A console is created but is not shown to the user.
}
else
{
DPRINT("Using existing console: 0x%p\n", Parameters->ConsoleHandle);
}
/* Do nothing if this is not a console app... */
if (!ConnectInfo.IsConsoleApp)
{
/* Do not inherit the parent's console if we are not a console app */
Parameters->ConsoleHandle = NULL;
}
/* Now use the proper console handle */
ConnectInfo.ConsoleStartInfo.ConsoleHandle = Parameters->ConsoleHandle;
/* Initialize the console dispatchers */
ConnectInfo.CtrlRoutine = ConsoleControlDispatcher;
ConnectInfo.PropRoutine = PropDialogHandler;
// ConnectInfo.ImeRoutine = ImeRoutine;
/* Set up the console properties */
if (ConnectInfo.IsConsoleApp && Parameters->ConsoleHandle == NULL)
{
/*
* We can set up the console properties only if we create a new one
* (we do not inherit it from our parent).
*/
LPWSTR ConsoleTitle = ConnectInfo.ConsoleTitle;
ConnectInfo.TitleLength = sizeof(ConnectInfo.ConsoleTitle);
ConnectInfo.DesktopLength = 0; // SetUpConsoleInfo will give us the real length.
SetUpConsoleInfo(TRUE,
&ConnectInfo.TitleLength,
&ConsoleTitle,
&ConnectInfo.DesktopLength,
&ConnectInfo.Desktop,
&ConnectInfo.ConsoleStartInfo);
DPRINT("ConsoleTitle = '%S' - Desktop = '%S'\n",
ConsoleTitle, ConnectInfo.Desktop);
}
else
{
ConnectInfo.TitleLength = 0;
ConnectInfo.DesktopLength = 0;
}
/* Initialize the Input EXE name */
if (ConnectInfo.IsConsoleApp)
{
LPWSTR CurDir = ConnectInfo.CurDir;
LPWSTR AppName = ConnectInfo.AppName;
InitExeName();
ConnectInfo.CurDirLength = sizeof(ConnectInfo.CurDir);
ConnectInfo.AppNameLength = sizeof(ConnectInfo.AppName);
SetUpAppName(TRUE,
&ConnectInfo.CurDirLength,
&CurDir,
&ConnectInfo.AppNameLength,
&AppName);
DPRINT("CurDir = '%S' - AppName = '%S'\n",
CurDir, AppName);
}
else
{
ConnectInfo.CurDirLength = 0;
ConnectInfo.AppNameLength = 0;
}
/*
* Initialize Console Ctrl Handling, that needs to be supported by
* all applications, especially because it is used at shutdown.
*/
InitializeCtrlHandling();
/* Connect to the Console Server */
if (!ConnectConsole(SessionDir,
&ConnectInfo,
&IsServerProcess))
{
// DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status);
return FALSE;
}
/* If we are not doing server-to-server init and if this is a console app... */
if (!IsServerProcess && ConnectInfo.IsConsoleApp)
{
/* ... set the handles that we got */
if (Parameters->ConsoleHandle == NULL)
SetUpHandles(&ConnectInfo.ConsoleStartInfo);
InputWaitHandle = ConnectInfo.ConsoleStartInfo.InputWaitHandle;
Exit:
SetTEBLangID(lcid);
}
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;
}

View file

@ -31,10 +31,6 @@
* 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 ***/
{

View 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;

View 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;

View file

@ -10,26 +10,35 @@
/* 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
InitConsoleInfo(IN OUT PCONSOLE_START_INFO ConsoleStartInfo,
IN PUNICODE_STRING ImagePathName);
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
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 */

View 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

View 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,

View 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,

View file

@ -14,6 +14,11 @@
#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;
}

View 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);

View 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;

View 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);
}
}

View 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;

View file

@ -14,13 +14,6 @@
#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);

View 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,

View 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))
{

View 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 */

View 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;

View 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) \

View 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;
}
DPRINT("ConnectInfo->IsConsoleApp = %s\n", ConnectInfo->IsConsoleApp ? "True" : "False");
if (!ConnectInfo->IsConsoleApp) return STATUS_SUCCESS;
/* If we don't have a console, then create a new one... */
if (!ConnectInfo->ConsoleHandle ||
ConnectInfo->ConsoleHandle != ProcessData->ParentConsoleHandle)
/* 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);

View 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,