From f4d53fbd9142b7913634bb8e6eb2c76cd2a9a3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 10 Feb 2013 12:36:57 +0000 Subject: [PATCH] [KERNEL32-CONSRV] - Introduce a CONSOLE_PROPS structure to hold console properties such as its title or startup attributes it should have. Initialized at console application launch time. I have to see how could it be possible to merge this structure with some parts of the GUI_CONSOLE_DATA structure and of the ConsoleInfo structure from console.dll (in /dll/cpl). - Use a helper function to initialize the CONSOLE_PROPS structure in kernel32, at console app start or when calling AllocConsole. - In BasepInitConsole, do initialization of CONSOLE_PROPS and related only if we are about to launch a console app. [CONSRV] - Adapt CONSOLE_CONNECTION_INFO and CONSOLE_ALLOCCONSOLE structures to take into account CONSOLE_PROPS. - Fix the way we are setting console titles. - Add experimental support for loading console properties and title and icon from shell links, thanks to the helper LoadShellLinkInfo. However I'm using there Shell COM facility to extract link properties (I could do it "the RAW way", however I would then know the format of link files, that I don't know and that I don't want to mix up with the console code). Therefore I must add dependencies to uuid and ole32 libraries. Note that icons are used in GUI consoles only (use the PrivateExtractIconExW function to retrieve both handles to the big and small icons at the same time). Part 1/2 [CONSRV] - Remove an unuseful xxxInitScreenBuffer function in the virtual functions console table. - In GUI_CONSOLE_DATA structure and related functions, temporarily explicitely mark which members may be used for both GUI and TUI consoles (for a future simplification). - Add temporary debug prints when we are setting console icon, to see the flow of calls (will be removed just before merging back to trunk). - Add temporary debug prints in ConSrvInitConsoleScreenBuffer and ConioDeleteScreenBuffer, to figure out how SBs are initialized. svn path=/branches/ros-csrss/; revision=58305 --- dll/win32/kernel32/client/console/alias.c | 6 +- dll/win32/kernel32/client/console/console.c | 138 ++++++--- dll/win32/kernel32/client/dllmain.c | 37 +-- dll/win32/kernel32/include/kernel32.h | 3 + include/reactos/subsys/win/conmsg.h | 22 +- win32ss/user/consrv/CMakeLists.txt | 4 +- win32ss/user/consrv/conio.h | 22 +- win32ss/user/consrv/conoutput.c | 9 +- win32ss/user/consrv/console.c | 283 ++++++++++++++---- win32ss/user/consrv/consrv.h | 4 +- win32ss/user/consrv/guiconsole.c | 304 +++++++++++++------- win32ss/user/consrv/guiconsole.h | 6 +- win32ss/user/consrv/handle.c | 15 +- win32ss/user/consrv/init.c | 8 +- win32ss/user/consrv/tuiconsole.c | 14 +- 15 files changed, 603 insertions(+), 272 deletions(-) diff --git a/dll/win32/kernel32/client/console/alias.c b/dll/win32/kernel32/client/console/alias.c index 385c26f2185..4b27e2e5ac2 100644 --- a/dll/win32/kernel32/client/console/alias.c +++ b/dll/win32/kernel32/client/console/alias.c @@ -211,7 +211,7 @@ GetConsoleAliasW(LPWSTR lpSource, ConsoleAliasRequest->Target, ConsoleAliasRequest->TargetLength); - /* Release the capture buffer and exits */ + /* Release the capture buffer and exit */ CsrFreeCaptureBuffer(CaptureBuffer); return ConsoleAliasRequest->TargetLength; @@ -347,7 +347,7 @@ GetConsoleAliasesW(LPWSTR AliasBuffer, GetAllAliasesRequest->AliasesBuffer, GetAllAliasesRequest->AliasesBufferLength); - /* Release the capture buffer and exits */ + /* Release the capture buffer and exit */ CsrFreeCaptureBuffer(CaptureBuffer); return GetAllAliasesRequest->AliasesBufferLength; // / sizeof(WCHAR); (original code) @@ -514,7 +514,7 @@ GetConsoleAliasExesW(LPWSTR lpExeNameBuffer, GetAliasesExesRequest->ExeNames, GetAliasesExesRequest->Length); - /* Release the capture buffer and exits */ + /* Release the capture buffer and exit */ CsrFreeCaptureBuffer(CaptureBuffer); return GetAliasesExesRequest->Length; diff --git a/dll/win32/kernel32/client/console/console.c b/dll/win32/kernel32/client/console/console.c index 84c8d9a88f0..ee885e96017 100644 --- a/dll/win32/kernel32/client/console/console.c +++ b/dll/win32/kernel32/client/console/console.c @@ -5,10 +5,6 @@ * PURPOSE: Win32 server console functions * PROGRAMMER: James Tabor * - * UPDATE HISTORY: - * 199901?? ?? Created - * 19990204 EA SetConsoleTitleA - * 19990306 EA Stubs */ /* INCLUDES *******************************************************************/ @@ -194,6 +190,49 @@ InitConsoleCtrlHandling(VOID) /* FUNCTIONS ******************************************************************/ +VOID +InitConsoleProps(IN OUT PCONSOLE_PROPS ConsoleProps) +{ + STARTUPINFOW si; + + GetStartupInfoW(&si); + + ConsoleProps->dwStartupFlags = si.dwFlags; + if (si.dwFlags & STARTF_USEFILLATTRIBUTE) + { + ConsoleProps->FillAttribute = si.dwFillAttribute; + } + if (si.dwFlags & STARTF_USECOUNTCHARS) + { + ConsoleProps->ScreenBufferSize.X = (SHORT)(si.dwXCountChars); + ConsoleProps->ScreenBufferSize.Y = (SHORT)(si.dwYCountChars); + } + if (si.dwFlags & STARTF_USESHOWWINDOW) + { + ConsoleProps->ShowWindow = si.wShowWindow; + } + if (si.dwFlags & STARTF_USEPOSITION) + { + ConsoleProps->ConsoleWindowOrigin.x = (LONG)(si.dwX); + ConsoleProps->ConsoleWindowOrigin.y = (LONG)(si.dwY); + } + if (si.dwFlags & STARTF_USESIZE) + { + ConsoleProps->ConsoleWindowSize.cx = (LONG)(si.dwXSize); + ConsoleProps->ConsoleWindowSize.cy = (LONG)(si.dwYSize); + } + + if (si.lpTitle) + { + wcsncpy(ConsoleProps->ConsoleTitle, si.lpTitle, MAX_PATH + 1); + } + else + { + ConsoleProps->ConsoleTitle[0] = L'\0'; + } +} + + LPCWSTR IntCheckForConsoleFileName(IN LPCWSTR pszName, IN DWORD dwDesiredAccess) @@ -764,9 +803,8 @@ GetStdHandle(DWORD nStdHandle) * of the specified device. Otherwise the value is INVALID_HANDLE_VALUE. */ { - PRTL_USER_PROCESS_PARAMETERS Ppb; + PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters; - Ppb = NtCurrentPeb()->ProcessParameters; switch (nStdHandle) { case STD_INPUT_HANDLE: @@ -802,12 +840,10 @@ SetStdHandle(DWORD nStdHandle, * RETURNS: TRUE if the function succeeds, FALSE otherwise. */ { - PRTL_USER_PROCESS_PARAMETERS Ppb; + PRTL_USER_PROCESS_PARAMETERS Ppb = NtCurrentPeb()->ProcessParameters; /* no need to check if hHandle == INVALID_HANDLE_VALUE */ - Ppb = NtCurrentPeb()->ProcessParameters; - switch (nStdHandle) { case STD_INPUT_HANDLE: @@ -823,7 +859,7 @@ SetStdHandle(DWORD nStdHandle, return TRUE; } - /* windows for whatever reason sets the last error to ERROR_INVALID_HANDLE here */ + /* Windows for whatever reason sets the last error to ERROR_INVALID_HANDLE here */ SetLastError(ERROR_INVALID_HANDLE); return FALSE; } @@ -839,36 +875,63 @@ WINAPI AllocConsole(VOID) { NTSTATUS Status; + PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest; - STARTUPINFO si; + PCSR_CAPTURE_BUFFER CaptureBuffer; + SIZE_T Length = 0; - DPRINT1("AllocConsole called !!!!\n"); + DPRINT1("AllocConsole\n"); - if (NtCurrentPeb()->ProcessParameters->ConsoleHandle) + if (Parameters->ConsoleHandle) { - DPRINT1("AllocConsole: Allocate duplicate console to the same Process\n"); + DPRINT1("AllocConsole: Allocating a console to a process already having one\n"); SetLastError(ERROR_ACCESS_DENIED); return FALSE; } - GetStartupInfo(&si); + CaptureBuffer = CsrAllocateCaptureBuffer(2, sizeof(CONSOLE_PROPS) + + (MAX_PATH + 1) * sizeof(WCHAR)); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed!\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + CsrAllocateMessagePointer(CaptureBuffer, + sizeof(CONSOLE_PROPS), + (PVOID*)&AllocConsoleRequest->ConsoleProps); + + CsrAllocateMessagePointer(CaptureBuffer, + (MAX_PATH + 1) * sizeof(WCHAR), + (PVOID*)&AllocConsoleRequest->AppPath); + +/** Copied from BasepInitConsole **********************************************/ + InitConsoleProps(AllocConsoleRequest->ConsoleProps); + + Length = min(MAX_PATH + 1, Parameters->ImagePathName.Length / sizeof(WCHAR)); + wcsncpy(AllocConsoleRequest->AppPath, Parameters->ImagePathName.Buffer, Length); + AllocConsoleRequest->AppPath[Length] = L'\0'; +/******************************************************************************/ - AllocConsoleRequest->ShowCmd = si.wShowWindow; AllocConsoleRequest->Console = NULL; AllocConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher; Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - NULL, + CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc), sizeof(CONSOLE_ALLOCCONSOLE)); + + CsrFreeCaptureBuffer(CaptureBuffer); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status)) { BaseSetLastNTError(Status); return FALSE; } - NtCurrentPeb()->ProcessParameters->ConsoleHandle = AllocConsoleRequest->Console; + Parameters->ConsoleHandle = AllocConsoleRequest->Console; SetStdHandle(STD_INPUT_HANDLE , AllocConsoleRequest->InputHandle ); SetStdHandle(STD_OUTPUT_HANDLE, AllocConsoleRequest->OutputHandle); SetStdHandle(STD_ERROR_HANDLE , AllocConsoleRequest->ErrorHandle ); @@ -1685,16 +1748,20 @@ BOOL WINAPI SetConsoleTitleA(LPCSTR lpConsoleTitle) { - ULONG Length = strlen(lpConsoleTitle) + 1; + BOOL Ret; + ULONG Length = strlen(lpConsoleTitle) + 1; LPWSTR WideTitle = HeapAlloc(GetProcessHeap(), 0, Length * sizeof(WCHAR)); - BOOL Ret; + if (!WideTitle) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } + MultiByteToWideChar(CP_ACP, 0, lpConsoleTitle, -1, WideTitle, Length); + Ret = SetConsoleTitleW(WideTitle); + HeapFree(GetProcessHeap(), 0, WideTitle); return Ret; } @@ -1963,12 +2030,13 @@ WINAPI AttachConsole(DWORD dwProcessId) { NTSTATUS Status; + PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = &ApiMessage.Data.AttachConsoleRequest; DPRINT1("AttachConsole(%lu)\n", dwProcessId); - if (NtCurrentPeb()->ProcessParameters->ConsoleHandle) + if (Parameters->ConsoleHandle) { DPRINT1("AttachConsole: Attaching a console to a process already having one\n"); SetLastError(ERROR_ACCESS_DENIED); @@ -1988,7 +2056,7 @@ AttachConsole(DWORD dwProcessId) return FALSE; } - NtCurrentPeb()->ProcessParameters->ConsoleHandle = AttachConsoleRequest->Console; + Parameters->ConsoleHandle = AttachConsoleRequest->Console; SetStdHandle(STD_INPUT_HANDLE , AttachConsoleRequest->InputHandle ); SetStdHandle(STD_OUTPUT_HANDLE, AttachConsoleRequest->OutputHandle); SetStdHandle(STD_ERROR_HANDLE , AttachConsoleRequest->ErrorHandle ); @@ -2070,9 +2138,9 @@ SetConsoleInputExeNameW(LPCWSTR lpInputExeName) { int lenName; - if (!lpInputExeName - || (lenName = lstrlenW(lpInputExeName)) == 0 - || lenName > INPUTEXENAME_BUFLEN - 1) + if ( !lpInputExeName || + (lenName = lstrlenW(lpInputExeName)) == 0 || + lenName > INPUTEXENAME_BUFLEN - 1 ) { /* Fail if string is empty or too long */ SetLastError(ERROR_INVALID_PARAMETER); @@ -2111,12 +2179,11 @@ SetConsoleInputExeNameA(LPCSTR lpInputExeName) ANSI_STRING InputExeNameA; UNICODE_STRING InputExeNameU; NTSTATUS Status; - BOOL Ret; RtlInitAnsiString(&InputExeNameA, lpInputExeName); - if(InputExeNameA.Length == 0 || - InputExeNameA.Length > INPUTEXENAME_BUFLEN - 1) + if ( InputExeNameA.Length == 0 || + InputExeNameA.Length > INPUTEXENAME_BUFLEN - 1 ) { /* Fail if string is empty or too long */ SetLastError(ERROR_INVALID_PARAMETER); @@ -2126,18 +2193,15 @@ SetConsoleInputExeNameA(LPCSTR lpInputExeName) InputExeNameU.Buffer = Buffer; InputExeNameU.MaximumLength = sizeof(Buffer); InputExeNameU.Length = 0; + Status = RtlAnsiStringToUnicodeString(&InputExeNameU, &InputExeNameA, FALSE); - if(NT_SUCCESS(Status)) - { - Ret = SetConsoleInputExeNameW(InputExeNameU.Buffer); - } - else + if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); - Ret = FALSE; + return FALSE; } - return Ret; + return SetConsoleInputExeNameW(InputExeNameU.Buffer); } @@ -2164,7 +2228,7 @@ GetConsoleInputExeNameW(DWORD nBufferLength, LPWSTR lpBuffer) return lenName + 1; } - if(lenName + 1 > nBufferLength) + if (lenName + 1 > nBufferLength) { /* Buffer is not large enough! */ SetLastError(ERROR_BUFFER_OVERFLOW); @@ -2219,7 +2283,7 @@ GetConsoleInputExeNameA(DWORD nBufferLength, LPSTR lpBuffer) RtlUnicodeStringToAnsiString(&BufferA, &BufferU, FALSE); /* Error handling */ - if(nBufferLength <= BufferU.Length / sizeof(WCHAR)) + if (nBufferLength <= BufferU.Length / sizeof(WCHAR)) { SetLastError(ERROR_BUFFER_OVERFLOW); return 2; diff --git a/dll/win32/kernel32/client/dllmain.c b/dll/win32/kernel32/client/dllmain.c index 256d618a52c..fc000fb96f4 100644 --- a/dll/win32/kernel32/client/dllmain.c +++ b/dll/win32/kernel32/client/dllmain.c @@ -5,8 +5,6 @@ * PURPOSE: Initialization * PROGRAMMERS: Ariadne (ariadne@xs4all.nl) * Aleksey Bragin (aleksey@reactos.org) - * UPDATE HISTORY: - * Created 01/11/98 */ /* INCLUDES ******************************************************************/ @@ -53,8 +51,6 @@ BasepInitConsole(VOID) { NTSTATUS Status; PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; - LPCWSTR ExeName; - STARTUPINFO si; WCHAR SessionDir[256]; ULONG SessionId = NtCurrentPeb()->SessionId; BOOLEAN InServer; @@ -62,9 +58,7 @@ BasepInitConsole(VOID) CONSOLE_CONNECTION_INFO ConnectInfo; ULONG ConnectInfoSize = sizeof(ConnectInfo); - WCHAR lpTest[MAX_PATH]; - GetModuleFileNameW(NULL, lpTest, MAX_PATH); - DPRINT("BasepInitConsole for : %S\n", lpTest); + DPRINT("BasepInitConsole for : %wZ\n", &Parameters->ImagePathName); DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n", Parameters->ConsoleHandle, Parameters->StandardInput, Parameters->StandardOutput, Parameters->StandardError); @@ -74,20 +68,35 @@ BasepInitConsole(VOID) if (!NT_SUCCESS(Status)) return FALSE; ConsoleInitialized = TRUE; - /* We have nothing to do if this isn't a console app... */ + /* 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.ConsoleNeeded = FALSE; // ConsoleNeeded is used for knowing whether or not this is a CUI app. + + ConnectInfo.ConsoleProps.ConsoleTitle[0] = L'\0'; + ConnectInfo.AppPath[0] = L'\0'; } else { + SIZE_T Length = 0; + LPCWSTR ExeName; + + InitConsoleProps(&ConnectInfo.ConsoleProps); + + Length = min(sizeof(ConnectInfo.AppPath) / sizeof(ConnectInfo.AppPath[0]), + Parameters->ImagePathName.Length / sizeof(WCHAR)); + wcsncpy(ConnectInfo.AppPath, Parameters->ImagePathName.Buffer, Length); + ConnectInfo.AppPath[Length] = L'\0'; + + /* Initialize Input EXE name */ + ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\'); + if (ExeName) SetConsoleInputExeNameW(ExeName + 1); + /* Assume one is needed */ - GetStartupInfo(&si); ConnectInfo.ConsoleNeeded = TRUE; - ConnectInfo.ShowCmd = si.wShowWindow; /* Handle the special flags given to us by BasePushProcessParameters */ if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS) @@ -108,7 +117,7 @@ BasepInitConsole(VOID) /* We'll get the real one soon */ DPRINT("Creating new invisible console\n"); Parameters->ConsoleHandle = NULL; - ConnectInfo.ShowCmd = SW_HIDE; + ConnectInfo.ConsoleProps.ShowWindow = SW_HIDE; } else { @@ -123,14 +132,10 @@ BasepInitConsole(VOID) /* Now use the proper console handle */ ConnectInfo.Console = Parameters->ConsoleHandle; - /* Initialize Console Ctrl Handler and input EXE name */ + /* Initialize Console Ctrl Handler */ InitConsoleCtrlHandling(); ConnectInfo.CtrlDispatcher = ConsoleControlDispatcher; - ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\'); - if (ExeName) - SetConsoleInputExeNameW(ExeName + 1); - /* Setup the right Object Directory path */ if (!SessionId) { diff --git a/dll/win32/kernel32/include/kernel32.h b/dll/win32/kernel32/include/kernel32.h index eb2a30f0b08..db3e7668330 100644 --- a/dll/win32/kernel32/include/kernel32.h +++ b/dll/win32/kernel32/include/kernel32.h @@ -196,6 +196,9 @@ BOOL WINAPI CloseConsoleHandle(HANDLE Handle); HANDLE WINAPI GetConsoleInputWaitHandle(VOID); +VOID +InitConsoleProps(IN OUT PCONSOLE_PROPS ConsoleProps); + LPCWSTR IntCheckForConsoleFileName(IN LPCWSTR pszName, IN DWORD dwDesiredAccess); diff --git a/include/reactos/subsys/win/conmsg.h b/include/reactos/subsys/win/conmsg.h index d652975b227..65ba39a93b6 100644 --- a/include/reactos/subsys/win/conmsg.h +++ b/include/reactos/subsys/win/conmsg.h @@ -112,12 +112,26 @@ typedef enum _CONSRV_API_NUMBER } CONSRV_API_NUMBER, *PCONSRV_API_NUMBER; +typedef struct _CONSOLE_PROPS +{ + DWORD dwStartupFlags; + DWORD FillAttribute; + COORD ScreenBufferSize; + WORD ShowWindow; + POINT ConsoleWindowOrigin; + SIZE ConsoleWindowSize; + // UNICODE_STRING ConsoleTitle; + WCHAR ConsoleTitle[MAX_PATH + 1]; +} CONSOLE_PROPS, *PCONSOLE_PROPS; + typedef struct _CONSOLE_CONNECTION_INFO { BOOL ConsoleNeeded; // Used for GUI apps only. - /* Copied from CONSOLE_ALLOCCONSOLE */ - INT ShowCmd; + /* Adapted from CONSOLE_ALLOCCONSOLE */ + CONSOLE_PROPS ConsoleProps; + WCHAR AppPath[MAX_PATH + 1]; + HANDLE Console; // ConsoleHandle // In fact, it is a PCSRSS_CONSOLE <-- correct that !! HANDLE InputHandle; HANDLE OutputHandle; @@ -168,7 +182,9 @@ typedef struct typedef struct { - INT ShowCmd; + PCONSOLE_PROPS ConsoleProps; + LPWSTR AppPath; + HANDLE Console; // ConsoleHandle // In fact, it is a PCSRSS_CONSOLE <-- correct that !! HANDLE InputHandle; HANDLE OutputHandle; diff --git a/win32ss/user/consrv/CMakeLists.txt b/win32ss/user/consrv/CMakeLists.txt index 7b85ac53689..5de0ebf2861 100644 --- a/win32ss/user/consrv/CMakeLists.txt +++ b/win32ss/user/consrv/CMakeLists.txt @@ -21,12 +21,12 @@ list(APPEND SOURCE add_library(consrv SHARED ${SOURCE}) -target_link_libraries(consrv win32ksys ${PSEH_LIB}) # win32ksys because of NtUser...() +target_link_libraries(consrv win32ksys ${PSEH_LIB} uuid) # win32ksys because of NtUser...() set_module_type(consrv win32dll UNICODE) add_importlibs(consrv psapi msvcrt kernel32 ntdll csrsrv) -add_delay_importlibs(consrv user32 gdi32 advapi32) +add_delay_importlibs(consrv user32 gdi32 advapi32 ole32) add_dependencies(consrv bugcodes) add_cd_file(TARGET consrv DESTINATION reactos/system32 FOR all) diff --git a/win32ss/user/consrv/conio.h b/win32ss/user/consrv/conio.h index 6d7feee1d39..282fc909da2 100644 --- a/win32ss/user/consrv/conio.h +++ b/win32ss/user/consrv/conio.h @@ -15,9 +15,10 @@ #ifndef WM_APP #define WM_APP 0x8000 #endif -#define PM_CREATE_CONSOLE (WM_APP + 1) -#define PM_DESTROY_CONSOLE (WM_APP + 2) -#define PM_CONSOLE_BEEP (WM_APP + 3) +#define PM_CREATE_CONSOLE (WM_APP + 1) +#define PM_DESTROY_CONSOLE (WM_APP + 2) +#define PM_CONSOLE_BEEP (WM_APP + 3) +#define PM_CONSOLE_SET_TITLE (WM_APP + 4) /************************************************************************ @@ -113,8 +114,10 @@ typedef struct _CONSOLE BOOLEAN HistoryNoDup; /* Remove old duplicate history entries */ /****************************** GUI-related data ******************************/ - UNICODE_STRING Title; /* Title of console */ - HWND hWindow; + UNICODE_STRING Title; /* Title of console. It is always NULL-terminated */ + HWND hWindow; /* Handle to the console's window */ + HICON hIcon; /* Handle to its icon (used when freeing) */ + HICON hIconSm; COORD Size; PVOID GuiData; @@ -135,7 +138,6 @@ do { \ typedef struct _CONSOLE_VTBL { - VOID (WINAPI *InitScreenBuffer)(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER ScreenBuffer); VOID (WINAPI *WriteStream)(PCONSOLE Console, SMALL_RECT* Block, LONG CursorStartX, LONG CursorStartY, UINT ScrolledLines, CHAR *Buffer, UINT Length); VOID (WINAPI *DrawRegion)(PCONSOLE Console, SMALL_RECT* Region); @@ -143,7 +145,7 @@ typedef struct _CONSOLE_VTBL BOOL (WINAPI *SetScreenInfo)(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER ScreenBuffer, UINT OldCursorX, UINT OldCursorY); BOOL (WINAPI *UpdateScreenInfo)(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER ScreenBuffer); - BOOL (WINAPI *ChangeTitle)(PCONSOLE Console); + VOID (WINAPI *ChangeTitle)(PCONSOLE Console); VOID (WINAPI *CleanupConsole)(PCONSOLE Console); BOOL (WINAPI *ChangeIcon)(PCONSOLE Console, HICON hWindowIcon); NTSTATUS (WINAPI *ResizeBuffer)(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER ScreenBuffer, COORD Size); @@ -163,7 +165,6 @@ typedef struct _CONSOLE_VTBL #define PAUSED_FROM_SCROLLBAR 0x2 #define PAUSED_FROM_SELECTION 0x4 -#define ConioInitScreenBuffer(Console, Buff) (Console)->Vtbl->InitScreenBuffer((Console), (Buff)) #define ConioDrawRegion(Console, Region) (Console)->Vtbl->DrawRegion((Console), (Region)) #define ConioWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \ (Console)->Vtbl->WriteStream((Console), (Block), (CurStartX), (CurStartY), \ @@ -181,7 +182,10 @@ typedef struct _CONSOLE_VTBL /* console.c */ VOID WINAPI ConSrvDeleteConsole(PCONSOLE Console); VOID WINAPI ConSrvInitConsoleSupport(VOID); -NTSTATUS WINAPI ConSrvInitConsole(PCONSOLE* NewConsole, int ShowCmd, PCSR_PROCESS ConsoleLeaderProcess); +NTSTATUS WINAPI ConSrvInitConsole(OUT PCONSOLE* NewConsole, + IN LPCWSTR AppPath, + IN OUT PCONSOLE_PROPS ConsoleProps, + IN PCSR_PROCESS ConsoleLeaderProcess); VOID FASTCALL ConioPause(PCONSOLE Console, UINT Flags); VOID FASTCALL ConioUnpause(PCONSOLE Console, UINT Flags); VOID FASTCALL ConSrvConsoleCtrlEvent(DWORD Event, PCONSOLE_PROCESS_DATA ProcessData); diff --git a/win32ss/user/consrv/conoutput.c b/win32ss/user/consrv/conoutput.c index 9949b1cd29d..0594808ffe4 100644 --- a/win32ss/user/consrv/conoutput.c +++ b/win32ss/user/consrv/conoutput.c @@ -63,7 +63,7 @@ NTSTATUS FASTCALL ConSrvInitConsoleScreenBuffer(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buffer) { - DPRINT("ConSrvInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer->MaxX, Buffer->MaxY); + DPRINT1("ConSrvInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer->MaxX, Buffer->MaxY); Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC; Buffer->Header.Console = Console; @@ -74,9 +74,10 @@ ConSrvInitConsoleScreenBuffer(PCONSOLE Console, Buffer->Buffer = RtlAllocateHeap(ConSrvHeap, HEAP_ZERO_MEMORY, Buffer->MaxX * Buffer->MaxY * 2); if (NULL == Buffer->Buffer) { + DPRINT1("ConSrvInitConsoleScreenBuffer - D'oh!\n"); return STATUS_INSUFFICIENT_RESOURCES; } - ConioInitScreenBuffer(Console, Buffer); + Buffer->DefaultAttrib = DEFAULT_ATTRIB; /* initialize buffer to be empty with default attributes */ for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++) { @@ -376,6 +377,7 @@ VOID WINAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) { PCONSOLE Console = Buffer->Header.Console; + DPRINT1("ConioDeleteScreenBuffer(Buffer = 0x%p, Buffer->Buffer = 0x%p) ; Console = 0x%p\n", Buffer, Buffer->Buffer, Console); RemoveEntryList(&Buffer->ListEntry); if (Buffer == Console->ActiveBuffer) @@ -384,6 +386,7 @@ ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer) Console->ActiveBuffer = NULL; if (!IsListEmpty(&Console->BufferList)) { + DPRINT1("ConioDeleteScreenBuffer - Bang !!!!!!!!\n"); Console->ActiveBuffer = CONTAINING_RECORD(Console->BufferList.Flink, CONSOLE_SCREEN_BUFFER, ListEntry); ConioDrawConsole(Console); } @@ -423,7 +426,7 @@ ConioComputeUpdateRect(PCONSOLE_SCREEN_BUFFER Buff, SMALL_RECT* UpdateRect, PCOO UpdateRect->Right = Start->X + Length - 1; } UpdateRect->Top = Start->Y; - UpdateRect->Bottom = Start->Y+ (Start->X + Length - 1) / Buff->MaxX; + UpdateRect->Bottom = Start->Y + (Start->X + Length - 1) / Buff->MaxX; if (Buff->MaxY <= UpdateRect->Bottom) { UpdateRect->Bottom = Buff->MaxY - 1; diff --git a/win32ss/user/consrv/console.c b/win32ss/user/consrv/console.c index 6bd546182bc..4b78c9ea001 100644 --- a/win32ss/user/consrv/console.c +++ b/win32ss/user/consrv/console.c @@ -8,10 +8,16 @@ /* INCLUDES ******************************************************************/ +#define COBJMACROS +#define NONAMELESSUNION + #include "consrv.h" #include "guiconsole.h" #include "tuiconsole.h" +#include +#include + //#define NDEBUG #include @@ -95,15 +101,117 @@ ConioUnpause(PCONSOLE Console, UINT Flags) } } +static BOOL +LoadShellLinkInfo(IN OUT PCONSOLE_PROPS ConsoleProps, + OUT LPWSTR IconPath, + IN SIZE_T IconPathLength, + OUT PINT piIcon) +{ +#define PATH_SEPARATOR L'\\' + + LPWSTR LinkName = NULL; + SIZE_T Length = 0; + + if ((ConsoleProps->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0) + return FALSE; + + if (IconPath == NULL || piIcon == NULL) + return FALSE; + + IconPath[0] = L'\0'; + *piIcon = 0; + + /* 1- Find the last path separator if any */ + LinkName = wcsrchr(ConsoleProps->ConsoleTitle, PATH_SEPARATOR); + if (LinkName == NULL) + { + LinkName = ConsoleProps->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 */ + HRESULT 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, ConsoleProps->ConsoleTitle, STGM_READ); + if (SUCCEEDED(hRes)) + { + /* + * Finally we can get the properties ! + * Update the old ones if needed. + */ + INT ShowCmd = 0; + // WORD HotKey = 0; + + // Get the name of the shortcut. + Length = min(Length - 4, + sizeof(ConsoleProps->ConsoleTitle) / sizeof(ConsoleProps->ConsoleTitle[0])); + wcsncpy(ConsoleProps->ConsoleTitle, LinkName, Length); + ConsoleProps->ConsoleTitle[Length] = L'\0'; + + // Get the window showing command. + hRes = IShellLinkW_GetShowCmd(pshl, &ShowCmd); + if (SUCCEEDED(hRes)) ConsoleProps->ShowWindow = (WORD)ShowCmd; + + // Get the hotkey. + // hRes = pshl->GetHotkey(&ShowCmd); + // if (SUCCEEDED(hRes)) ConsoleProps->HotKey = HotKey; + + // Get the icon location, if any. + hRes = IShellLinkW_GetIconLocation(pshl, IconPath, IconPathLength, piIcon); + if (!SUCCEEDED(hRes)) + { + IconPath[0] = L'\0'; + } + } + IPersistFile_Release(ppf); + } + IShellLinkW_Release(pshl); + } + } + CoUninitialize(); + + return TRUE; +} + NTSTATUS WINAPI -ConSrvInitConsole(PCONSOLE* NewConsole, int ShowCmd, PCSR_PROCESS ConsoleLeaderProcess) +ConSrvInitConsole(OUT PCONSOLE* NewConsole, + IN LPCWSTR AppPath, + IN OUT PCONSOLE_PROPS ConsoleProps, + IN PCSR_PROCESS ConsoleLeaderProcess) { NTSTATUS Status; SECURITY_ATTRIBUTES SecurityAttributes; PCONSOLE Console; PCONSOLE_SCREEN_BUFFER NewBuffer; BOOL GuiMode; - WCHAR Title[255]; + WCHAR Title[128]; + WCHAR IconPath[MAX_PATH + 1] = L""; + INT iIcon = 0; if (NewConsole == NULL) return STATUS_INVALID_PARAMETER; @@ -117,19 +225,21 @@ ConSrvInitConsole(PCONSOLE* NewConsole, int ShowCmd, PCSR_PROCESS ConsoleLeaderP return STATUS_NO_MEMORY; } + /* + * Check whether the process creating the console + * was launched via a shell-link. + */ + if (ConsoleProps->dwStartupFlags & STARTF_TITLEISLINKNAME) + { + LoadShellLinkInfo(ConsoleProps, + IconPath, + MAX_PATH, + &iIcon); + + ConsoleProps->dwStartupFlags &= ~STARTF_TITLEISLINKNAME; + } + /* Initialize the console */ - Console->Title.MaximumLength = Console->Title.Length = 0; - Console->Title.Buffer = NULL; - - if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, Title, sizeof(Title) / sizeof(Title[0]))) - { - RtlCreateUnicodeString(&Console->Title, Title); - } - else - { - RtlCreateUnicodeString(&Console->Title, L"ReactOS Console"); - } - InitializeCriticalSection(&Console->Lock); Console->ReferenceCount = 0; Console->LineBuffer = NULL; @@ -150,6 +260,7 @@ ConSrvInitConsole(PCONSOLE* NewConsole, int ShowCmd, PCSR_PROCESS ConsoleLeaderP Console->CodePage = GetOEMCP(); Console->OutputCodePage = GetOEMCP(); Console->GuiData = NULL; + Console->hIcon = Console->hIconSm = NULL; SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); SecurityAttributes.lpSecurityDescriptor = NULL; @@ -158,35 +269,65 @@ ConSrvInitConsole(PCONSOLE* NewConsole, int ShowCmd, PCSR_PROCESS ConsoleLeaderP Console->InputBuffer.ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL); if (NULL == Console->InputBuffer.ActiveEvent) { - RtlFreeUnicodeString(&Console->Title); DeleteCriticalSection(&Console->Lock); RtlFreeHeap(ConSrvHeap, 0, Console); return STATUS_UNSUCCESSFUL; } - GuiMode = DtbgIsDesktopVisible(); - - /* allocate console screen buffer */ + /* Allocate console screen buffer */ NewBuffer = RtlAllocateHeap(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CONSOLE_SCREEN_BUFFER)); if (NULL == NewBuffer) { - RtlFreeUnicodeString(&Console->Title); DeleteCriticalSection(&Console->Lock); CloseHandle(Console->InputBuffer.ActiveEvent); RtlFreeHeap(ConSrvHeap, 0, Console); return STATUS_INSUFFICIENT_RESOURCES; } - /* init screen buffer with defaults */ + /* Init screen buffer with defaults */ NewBuffer->CursorInfo.bVisible = TRUE; NewBuffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE; - /* make console active, and insert into console list */ - Console->ActiveBuffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer; + /* Make console active, and insert into console list */ + Console->ActiveBuffer = NewBuffer; + /** Finish to initialize the screen buffer ** + ** Fix problems with MaxX == 0 and MaxY == 0 + ** + Status = ConSrvInitConsoleScreenBuffer(Console, NewBuffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ConSrvInitConsoleScreenBuffer: failed\n"); + RtlFreeHeap(ConSrvHeap, 0, NewBuffer); + DeleteCriticalSection(&Console->Lock); + CloseHandle(Console->InputBuffer.ActiveEvent); + RtlFreeHeap(ConSrvHeap, 0, Console); + return Status; + } + **/ + + /* Initialize the console title */ + Console->Title.MaximumLength = Console->Title.Length = 0; + Console->Title.Buffer = NULL; + if (ConsoleProps->ConsoleTitle[0] == L'\0') + { + if (LoadStringW(ConSrvDllInstance, IDS_CONSOLE_TITLE, Title, sizeof(Title) / sizeof(Title[0]))) + { + RtlCreateUnicodeString(&Console->Title, Title); + } + else + { + RtlCreateUnicodeString(&Console->Title, L"ReactOS Console"); + } + } + else + { + RtlCreateUnicodeString(&Console->Title, ConsoleProps->ConsoleTitle); + } /* - * If we are not in GUI-mode, start the text-mode console. If we fail, - * try to start the GUI-mode console (win32k will automatically switch - * to graphical mode, therefore no additional code is needed). + * If we are not in GUI-mode, start the text-mode console. + * If we fail, try to start the GUI-mode console. */ + GuiMode = DtbgIsDesktopVisible(); + if (!GuiMode) { DPRINT1("CONSRV: Opening text-mode console\n"); @@ -204,33 +345,41 @@ ConSrvInitConsole(PCONSOLE* NewConsole, int ShowCmd, PCSR_PROCESS ConsoleLeaderP * failed and we start GUI-mode console. * - We are in text-mode, therefore GuiMode == FALSE, the previous test-case * succeeded BUT we failed at starting text-mode console. Then GuiMode - * was switched to TRUE in order to try to open the console in GUI-mode. + * was switched to TRUE in order to try to open the console in GUI-mode + * (win32k will automatically switch to graphical mode, therefore + * no additional code is needed). */ if (GuiMode) { DPRINT1("CONSRV: Opening GUI-mode console\n"); - Status = GuiInitConsole(Console, ShowCmd); + Status = GuiInitConsole(Console, + AppPath, + ConsoleProps->ShowWindow, + IconPath, + iIcon); if (!NT_SUCCESS(Status)) { - RtlFreeHeap(ConSrvHeap,0, NewBuffer); + DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status); RtlFreeUnicodeString(&Console->Title); DeleteCriticalSection(&Console->Lock); CloseHandle(Console->InputBuffer.ActiveEvent); - DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status); + RtlFreeHeap(ConSrvHeap, 0, NewBuffer); + /// ConioDeleteScreenBuffer(NewBuffer); RtlFreeHeap(ConSrvHeap, 0, Console); return Status; } } + // TODO: Move this call before initializing Tui/Gui console. But before fix freeing Buffer->Buffer !! Status = ConSrvInitConsoleScreenBuffer(Console, NewBuffer); if (!NT_SUCCESS(Status)) { + DPRINT1("ConSrvInitConsoleScreenBuffer: failed\n"); ConioCleanupConsole(Console); RtlFreeUnicodeString(&Console->Title); DeleteCriticalSection(&Console->Lock); CloseHandle(Console->InputBuffer.ActiveEvent); RtlFreeHeap(ConSrvHeap, 0, NewBuffer); - DPRINT1("ConSrvInitConsoleScreenBuffer: failed\n"); RtlFreeHeap(ConSrvHeap, 0, Console); return Status; } @@ -282,6 +431,7 @@ ConSrvDeleteConsole(PCONSOLE Console) CloseHandle(Console->InputBuffer.ActiveEvent); if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent); DeleteCriticalSection(&Console->Lock); + RtlFreeUnicodeString(&Console->Title); IntDeleteAllAliases(Console->Aliases); RtlFreeHeap(ConSrvHeap, 0, Console); @@ -353,8 +503,8 @@ CSR_API(SrvAllocConsole) { NTSTATUS Status = STATUS_SUCCESS; PCONSOLE_ALLOCCONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest; - PCSR_PROCESS ConsoleLeader = CsrGetClientThread()->Process; - PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(ConsoleLeader); + PCSR_PROCESS CsrProcess = CsrGetClientThread()->Process; + PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess); DPRINT("SrvAllocConsole\n"); @@ -364,6 +514,18 @@ CSR_API(SrvAllocConsole) return STATUS_ACCESS_DENIED; } + if ( !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&AllocConsoleRequest->ConsoleProps, + 1, + sizeof(CONSOLE_PROPS)) || + !CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&AllocConsoleRequest->AppPath, + MAX_PATH + 1, + sizeof(WCHAR)) ) + { + return STATUS_INVALID_PARAMETER; + } + /* * We are about to create a new console. However when ConSrvNewProcess * was called, we didn't know that we wanted to create a new console and @@ -379,11 +541,11 @@ CSR_API(SrvAllocConsole) /* Initialize a new Console owned by the Console Leader Process */ Status = ConSrvAllocateConsole(ProcessData, + AllocConsoleRequest->AppPath, &AllocConsoleRequest->InputHandle, &AllocConsoleRequest->OutputHandle, &AllocConsoleRequest->ErrorHandle, - AllocConsoleRequest->ShowCmd, - ConsoleLeader); + AllocConsoleRequest->ConsoleProps); if (!NT_SUCCESS(Status)) { DPRINT1("Console allocation failed\n"); @@ -602,34 +764,37 @@ CSR_API(SrvSetConsoleTitle) } Status = ConSrvGetConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process), &Console, TRUE); - if(NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { - Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest->Length); - if (Buffer) - { - /* Copy title to console */ - RtlFreeUnicodeString(&Console->Title); - Console->Title.Buffer = Buffer; - Console->Title.Length = Console->Title.MaximumLength = TitleRequest->Length; - memcpy(Console->Title.Buffer, TitleRequest->Title, Console->Title.Length); - - if (!ConioChangeTitle(Console)) - { - Status = STATUS_UNSUCCESSFUL; - } - else - { - Status = STATUS_SUCCESS; - } - } - else - { - Status = STATUS_NO_MEMORY; - } - - ConSrvReleaseConsole(Console, TRUE); + DPRINT1("Can't get console\n"); + return Status; } + /* Allocate a new buffer to hold the new title (NULL-terminated) */ + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, TitleRequest->Length + sizeof(WCHAR)); + if (Buffer) + { + /* Free the old title */ + RtlFreeUnicodeString(&Console->Title); + + /* Copy title to console */ + Console->Title.Buffer = Buffer; + Console->Title.Length = TitleRequest->Length; + Console->Title.MaximumLength = Console->Title.Length + sizeof(WCHAR); + RtlCopyMemory(Console->Title.Buffer, + TitleRequest->Title, + Console->Title.Length); + Console->Title.Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0'; + + ConioChangeTitle(Console); + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_NO_MEMORY; + } + + ConSrvReleaseConsole(Console, TRUE); return Status; } diff --git a/win32ss/user/consrv/consrv.h b/win32ss/user/consrv/consrv.h index b4e594285d6..b8cb53f61cb 100644 --- a/win32ss/user/consrv/consrv.h +++ b/win32ss/user/consrv/consrv.h @@ -178,11 +178,11 @@ NTSTATUS FASTCALL ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData, VOID FASTCALL ConSrvReleaseObject(Object_t *Object, BOOL IsConsoleLocked); NTSTATUS FASTCALL ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, + LPCWSTR AppPath, PHANDLE pInputHandle, PHANDLE pOutputHandle, PHANDLE pErrorHandle, - int ShowCmd, - PCSR_PROCESS CsrProcess); + PCONSOLE_PROPS ConsoleProps); NTSTATUS FASTCALL ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData, struct _CONSOLE* Console, BOOL CreateNewHandlesTable, diff --git a/win32ss/user/consrv/guiconsole.c b/win32ss/user/consrv/guiconsole.c index ea7d2b40485..3f894761723 100644 --- a/win32ss/user/consrv/guiconsole.c +++ b/win32ss/user/consrv/guiconsole.c @@ -39,34 +39,39 @@ PrivateCsrssManualGuiCheck(LONG Check) typedef struct _GUI_CONSOLE_DATA { - HFONT Font; - unsigned CharWidth; - unsigned CharHeight; - BOOL CursorBlinkOn; - BOOL ForceCursorOff; +/* GUI-specific */ HFONT Font; +/* GUI-specific */ WCHAR FontName[LF_FACESIZE]; +/* GUI-specific */ DWORD FontSize; +/* GUI-specific */ DWORD FontWeight; +/* GUI-specific */ UINT CharWidth; +/* GUI-specific */ UINT CharHeight; +/* non-specific */ BOOL CursorBlinkOn; +/* non-specific */ BOOL ForceCursorOff; + CRITICAL_SECTION Lock; HMODULE ConsoleLibrary; HANDLE hGuiInitEvent; - WCHAR FontName[LF_FACESIZE]; - DWORD FontSize; - DWORD FontWeight; - DWORD FullScreen; - DWORD QuickEdit; - DWORD InsertMode; - DWORD WindowPosition; - DWORD UseRasterFonts; - COLORREF ScreenText; - COLORREF ScreenBackground; - COLORREF PopupBackground; - COLORREF PopupText; - COLORREF Colors[16]; + +/* GUI-specific */ DWORD FullScreen; +/* non-specific */ DWORD QuickEdit; +/* non-specific */ DWORD InsertMode; +/* GUI-specific */ DWORD WindowPosition; +/* GUI-specific */ DWORD UseRasterFonts; +/* non-specific */ COLORREF ScreenText; +/* non-specific */ COLORREF ScreenBackground; +/* non-specific */ COLORREF PopupBackground; +/* non-specific */ COLORREF PopupText; +/* non-specific */ COLORREF Colors[16]; WCHAR szProcessName[MAX_PATH]; BOOL WindowSizeLock; POINT OldCursor; } GUI_CONSOLE_DATA, *PGUI_CONSOLE_DATA; -static BOOL ConsInitialized = FALSE; -static HWND NotifyWnd; +static BOOL ConsInitialized = FALSE; +static HICON ghDefaultIcon = NULL; +static HICON ghDefaultIconSm = NULL; +static HCURSOR ghDefaultCursor = NULL; +static HWND NotifyWnd = NULL; typedef struct _GUICONSOLE_MENUITEM { @@ -195,6 +200,12 @@ GuiGetWindowConsole(HWND hWnd) return (PCONSOLE)GetWindowLongPtrW(hWnd, GWLP_USERDATA); } + + +/******************************************************************************* + ** The following functions may be available for both GUI and CUI + ******************************************************************************/ + static BOOL GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId, PHANDLE hProcHandle, PHKEY hResult, REGSAM samDesired) { @@ -615,35 +626,40 @@ GuiConsoleUseDefaults(PCONSOLE Console, PGUI_CONSOLE_DATA GuiData, PCONSOLE_SCRE * init guidata with default properties */ - wcscpy(GuiData->FontName, L"DejaVu Sans Mono"); - GuiData->FontSize = 0x0008000C; // font is 8x12 - GuiData->FontWeight = FW_NORMAL; - GuiData->FullScreen = FALSE; - GuiData->QuickEdit = FALSE; - GuiData->InsertMode = TRUE; - GuiData->ScreenText = RGB(192, 192, 192); - GuiData->ScreenBackground = RGB(0, 0, 0); - GuiData->PopupText = RGB(128, 0, 128); - GuiData->PopupBackground = RGB(255, 255, 255); +/* GUI-specific */ wcscpy(GuiData->FontName, L"DejaVu Sans Mono"); +/* GUI-specific */ GuiData->FontSize = 0x0008000C; // font is 8x12 +/* GUI-specific */ GuiData->FontWeight = FW_NORMAL; +/* GUI-specific */ GuiData->FullScreen = FALSE; +/* non-specific */ GuiData->QuickEdit = FALSE; +/* non-specific */ GuiData->InsertMode = TRUE; +/* non-specific */ GuiData->ScreenText = RGB(192, 192, 192); +/* non-specific */ GuiData->ScreenBackground = RGB(0, 0, 0); +/* non-specific */ GuiData->PopupText = RGB(128, 0, 128); +/* non-specific */ GuiData->PopupBackground = RGB(255, 255, 255); GuiData->WindowPosition = UINT_MAX; - GuiData->UseRasterFonts = TRUE; - memcpy(GuiData->Colors, s_Colors, sizeof(s_Colors)); +/* GUI-specific */ GuiData->UseRasterFonts = TRUE; +/* non-specific */ memcpy(GuiData->Colors, s_Colors, sizeof(s_Colors)); - Console->HistoryBufferSize = 50; - Console->NumberOfHistoryBuffers = 5; - Console->HistoryNoDup = FALSE; - Console->Size.X = 80; - Console->Size.Y = 25; +/* non-specific */ Console->HistoryBufferSize = 50; +/* non-specific */ Console->NumberOfHistoryBuffers = 5; +/* non-specific */ Console->HistoryNoDup = FALSE; +/* XUI-specific */ Console->Size.X = 80; +/* XUI-specific */ Console->Size.Y = 25; if (Buffer) { - Buffer->MaxX = 80; - Buffer->MaxY = 300; - Buffer->CursorInfo.bVisible = TRUE; - Buffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE; +/* XUI-specific */ Buffer->MaxX = 80; +/* XUI-specific */ Buffer->MaxY = 300; +/* XUI-specific */ Buffer->CursorInfo.bVisible = TRUE; +/* XUI-specific */ Buffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE; } } +/******************************************************************************* + ******************************************************************************/ + + + VOID FASTCALL GuiConsoleInitScrollbar(PCONSOLE Console, HWND hwnd) @@ -2061,6 +2077,10 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) Beep(800, 200); break; + case PM_CONSOLE_SET_TITLE: + SetWindowText(hWnd, Console->Title.Buffer); + break; + default: Result = DefWindowProcW(hWnd, msg, wParam, lParam); break; @@ -2078,8 +2098,7 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) HWND NewWindow; LONG WindowCount; MSG Msg; - PWCHAR Buffer, Title; - PCONSOLE Console = (PCONSOLE) lParam; + PCONSOLE Console = (PCONSOLE)lParam; switch (msg) { @@ -2087,21 +2106,9 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) SetWindowLongW(hWnd, GWL_USERDATA, 0); return 0; case PM_CREATE_CONSOLE: - Buffer = RtlAllocateHeap(ConSrvHeap, 0, - Console->Title.Length + sizeof(WCHAR)); - if (NULL != Buffer) - { - memcpy(Buffer, Console->Title.Buffer, Console->Title.Length); - Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0'; - Title = Buffer; - } - else - { - Title = L""; - } NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE, GUI_CONSOLE_WINDOW_CLASS, - Title, + Console->Title.Buffer, WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, @@ -2109,16 +2116,29 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) CW_USEDEFAULT, NULL, NULL, - (HINSTANCE)GetModuleHandleW(NULL), + ConSrvDllInstance, (PVOID)Console); - if (NULL != Buffer) - { - RtlFreeHeap(ConSrvHeap, 0, Buffer); - } if (NULL != NewWindow) { + DPRINT1("CreateWindowExW succeeded\n"); SetConsoleWndConsoleLeaderCID(Console); SetWindowLongW(hWnd, GWL_USERDATA, GetWindowLongW(hWnd, GWL_USERDATA) + 1); + + DPRINT1("Set icons via PM_CREATE_CONSOLE\n"); + if (Console->hIcon == NULL) + { + DPRINT1("Not really...\n"); + Console->hIcon = ghDefaultIcon; + Console->hIconSm = ghDefaultIconSm; + } + else if (Console->hIcon != ghDefaultIcon) + { + DPRINT1("Yes !\n"); + SendMessageW(Console->hWindow, WM_SETICON, ICON_BIG, (LPARAM)Console->hIcon); + SendMessageW(Console->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)Console->hIconSm); + } + + DPRINT1("Show window\n"); ShowWindow(NewWindow, (int)wParam); } return (LRESULT)NewWindow; @@ -2164,7 +2184,7 @@ GuiConsoleGuiThread(PVOID Data) CW_USEDEFAULT, NULL, NULL, - (HINSTANCE) GetModuleHandleW(NULL), + ConSrvDllInstance, NULL); if (NULL == NotifyWnd) { @@ -2195,38 +2215,45 @@ GuiInit(VOID) PrivateCsrssManualGuiCheck(+1); } + /* Initialize the notification window class */ wc.cbSize = sizeof(WNDCLASSEXW); wc.lpszClassName = L"ConSrvCreateNotify"; wc.lpfnWndProc = GuiConsoleNotifyWndProc; wc.style = 0; - wc.hInstance = (HINSTANCE)GetModuleHandleW(NULL); + wc.hInstance = ConSrvDllInstance; wc.hIcon = NULL; + wc.hIconSm = NULL; wc.hCursor = NULL; wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hIconSm = NULL; if (RegisterClassExW(&wc) == 0) { DPRINT1("Failed to register GUI notify wndproc\n"); return FALSE; } + /* Initialize the console window class */ + ghDefaultIcon = LoadImageW(ConSrvDllInstance, MAKEINTRESOURCEW(IDI_CONSOLE), IMAGE_ICON, + GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), + LR_SHARED); + ghDefaultIconSm = LoadImageW(ConSrvDllInstance, MAKEINTRESOURCEW(IDI_CONSOLE), IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + LR_SHARED); + ghDefaultCursor = LoadCursorW(NULL, IDC_ARROW); wc.cbSize = sizeof(WNDCLASSEXW); wc.lpszClassName = GUI_CONSOLE_WINDOW_CLASS; wc.lpfnWndProc = GuiConsoleWndProc; wc.style = 0; - wc.hInstance = (HINSTANCE)GetModuleHandleW(NULL); - wc.hIcon = LoadIconW(ConSrvDllInstance, MAKEINTRESOURCEW(1)); - wc.hCursor = LoadCursorW(NULL, (LPCWSTR) IDC_ARROW); + wc.hInstance = ConSrvDllInstance; + wc.hIcon = ghDefaultIcon; + wc.hIconSm = ghDefaultIconSm; + wc.hCursor = ghDefaultCursor; wc.hbrBackground = CreateSolidBrush(RGB(0,0,0)); wc.lpszMenuName = NULL; wc.cbClsExtra = 0; wc.cbWndExtra = GWLP_CONSOLEWND_ALLOC; - wc.hIconSm = LoadImageW(ConSrvDllInstance, MAKEINTRESOURCEW(1), IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), - LR_SHARED); ConsoleClassAtom = RegisterClassExW(&wc); if (ConsoleClassAtom == 0) @@ -2243,44 +2270,50 @@ GuiInit(VOID) } static VOID WINAPI -GuiInitScreenBuffer(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buffer) -{ - Buffer->DefaultAttrib = DEFAULT_ATTRIB; -} - -static BOOL WINAPI GuiChangeTitle(PCONSOLE Console) { - PWCHAR Buffer, Title; - - Buffer = RtlAllocateHeap(ConSrvHeap, 0, - Console->Title.Length + sizeof(WCHAR)); - if (NULL != Buffer) - { - memcpy(Buffer, Console->Title.Buffer, Console->Title.Length); - Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0'; - Title = Buffer; - } - else - { - Title = L""; - } - - PostMessageW(Console->hWindow, WM_SETTEXT, 0, (LPARAM)Title); - - if (NULL != Buffer) - { - RtlFreeHeap(ConSrvHeap, 0, Buffer); - } - - return TRUE; + PostMessageW(Console->hWindow, PM_CONSOLE_SET_TITLE, 0, 0); } static BOOL WINAPI GuiChangeIcon(PCONSOLE Console, HICON hWindowIcon) { - PostMessageW(Console->hWindow, WM_SETICON, ICON_BIG, (LPARAM)hWindowIcon); - PostMessageW(Console->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)hWindowIcon); + HICON hIcon, hIconSm; + + if (hWindowIcon == NULL) + { + hIcon = ghDefaultIcon; + hIconSm = ghDefaultIconSm; + } + else + { + hIcon = CopyIcon(hWindowIcon); + hIconSm = CopyIcon(hWindowIcon); + } + + if (hIcon == NULL) + { + return FALSE; + } + + if (hIcon != Console->hIcon) + { + if (Console->hIcon != NULL && Console->hIcon != ghDefaultIcon) + { + DestroyIcon(Console->hIcon); + } + if (Console->hIconSm != NULL && Console->hIconSm != ghDefaultIconSm) + { + DestroyIcon(Console->hIconSm); + } + + Console->hIcon = hIcon; + Console->hIconSm = hIconSm; + + DPRINT1("Set icons in GuiChangeIcon\n"); + PostMessageW(Console->hWindow, WM_SETICON, ICON_BIG, (LPARAM)Console->hIcon); + PostMessageW(Console->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)Console->hIconSm); + } return TRUE; } @@ -2289,11 +2322,23 @@ static VOID WINAPI GuiCleanupConsole(PCONSOLE Console) { SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM)Console); + + DPRINT1("Destroying icons !! - Console->hIcon = 0x%p ; ghDefaultIcon = 0x%p ; Console->hIconSm = 0x%p ; ghDefaultIconSm = 0x%p\n", + Console->hIcon, ghDefaultIcon, Console->hIconSm, ghDefaultIconSm); + if (Console->hIcon != NULL && Console->hIcon != ghDefaultIcon) + { + DPRINT1("Destroy hIcon\n"); + DestroyIcon(Console->hIcon); + } + if (Console->hIconSm != NULL && Console->hIconSm != ghDefaultIconSm) + { + DPRINT1("Destroy hIconSm\n"); + DestroyIcon(Console->hIconSm); + } } static CONSOLE_VTBL GuiVtbl = { - GuiInitScreenBuffer, GuiWriteStream, GuiDrawRegion, GuiSetCursorInfo, @@ -2306,12 +2351,17 @@ static CONSOLE_VTBL GuiVtbl = }; NTSTATUS FASTCALL -GuiInitConsole(PCONSOLE Console, int ShowCmd) +GuiInitConsole(PCONSOLE Console, + LPCWSTR AppPath, + WORD ShowWindow, + LPCWSTR IconPath, + INT IconIndex) { HANDLE GraphicsStartupEvent; HANDLE ThreadHandle; PGUI_CONSOLE_DATA GuiData; + /* Initialize the GUI */ if (!ConsInitialized) { ConsInitialized = TRUE; @@ -2322,8 +2372,10 @@ GuiInitConsole(PCONSOLE Console, int ShowCmd) } } + /* Finish to initialize the console */ Console->Vtbl = &GuiVtbl; Console->hWindow = NULL; + if (NULL == NotifyWnd) { GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL); @@ -2356,6 +2408,7 @@ GuiInitConsole(PCONSOLE Console, int ShowCmd) return STATUS_UNSUCCESSFUL; } } + GuiData = RtlAllocateHeap(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(GUI_CONSOLE_DATA)); if (!GuiData) @@ -2363,22 +2416,51 @@ GuiInitConsole(PCONSOLE Console, int ShowCmd) DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n"); return STATUS_UNSUCCESSFUL; } - Console->GuiData = (PVOID)GuiData; + + /* Initialize the icon handles to their default values */ + Console->hIcon = ghDefaultIcon; + Console->hIconSm = ghDefaultIconSm; + + /* Get the associated icon, if any */ + if (IconPath == NULL || *IconPath == L'\0') + { + IconPath = AppPath; + IconIndex = 0; + } + DPRINT1("IconPath = %S ; IconIndex = %lu\n", (IconPath ? IconPath : L"n/a"), IconIndex); + if (IconPath) + { + HICON hIcon = NULL, hIconSm = NULL; + DPRINT1("Extracting icons\n"); + PrivateExtractIconExW(IconPath, + IconIndex, + &hIcon, + &hIconSm, + 1); + DPRINT1("hIcon = 0x%p ; hIconSm = 0x%p\n", hIcon, hIconSm); + if (hIcon != NULL) + { + DPRINT1("Effectively set the icons\n"); + Console->hIcon = hIcon; + Console->hIconSm = hIconSm; + } + } + /* - * we need to wait until the GUI has been fully initialized - * to retrieve custom settings i.e. WindowSize etc.. + * We need to wait until the GUI has been fully initialized + * to retrieve custom settings i.e. WindowSize etc... * Ideally we could use SendNotifyMessage for this but its not * yet implemented. - * */ GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - /* create console */ - PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, ShowCmd, (LPARAM)Console); - /* wait until initialization has finished */ + /* Create the GUI console */ + PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, ShowWindow, (LPARAM)Console); + + /* Wait until initialization has finished */ WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE); - DPRINT("received event Console %p GuiData %p X %d Y %d\n", Console, Console->GuiData, Console->Size.X, Console->Size.Y); + DPRINT("Received event Console %p GuiData %p X %d Y %d\n", Console, Console->GuiData, Console->Size.X, Console->Size.Y); CloseHandle(GuiData->hGuiInitEvent); GuiData->hGuiInitEvent = NULL; diff --git a/win32ss/user/consrv/guiconsole.h b/win32ss/user/consrv/guiconsole.h index 801e2967f93..5908c52a89d 100644 --- a/win32ss/user/consrv/guiconsole.h +++ b/win32ss/user/consrv/guiconsole.h @@ -13,7 +13,11 @@ #define CONGUI_UPDATE_TIME 0 #define CONGUI_UPDATE_TIMER 1 -NTSTATUS FASTCALL GuiInitConsole(PCONSOLE Console, BOOL Visible); +NTSTATUS FASTCALL GuiInitConsole(PCONSOLE Console, + LPCWSTR AppPath, + WORD ShowWindow, + LPCWSTR IconPath, + INT IconIndex); VOID FASTCALL GuiConsoleHandleScrollbarMenu(VOID); /*EOF*/ diff --git a/win32ss/user/consrv/handle.c b/win32ss/user/consrv/handle.c index 6ab3f9abf80..cdef4452a8f 100644 --- a/win32ss/user/consrv/handle.c +++ b/win32ss/user/consrv/handle.c @@ -73,7 +73,6 @@ ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry) WaitAll, NULL, (PVOID)Entry); - if (!IsListEmpty(&InputBuffer->ReadWaitQueue)) { CsrDereferenceWait(&InputBuffer->ReadWaitQueue); @@ -402,16 +401,16 @@ ConSrvReleaseObject(Object_t *Object, NTSTATUS FASTCALL ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, + LPCWSTR AppPath, PHANDLE pInputHandle, PHANDLE pOutputHandle, PHANDLE pErrorHandle, - int ShowCmd, - PCSR_PROCESS CsrProcess) + PCONSOLE_PROPS ConsoleProps) { NTSTATUS Status = STATUS_SUCCESS; - /* Initialize a new Console owned by the Console Leader Process */ - Status = ConSrvInitConsole(&ProcessData->Console, ShowCmd, CsrProcess); + /* Initialize a new Console owned by this process */ + Status = ConSrvInitConsole(&ProcessData->Console, AppPath, ConsoleProps, ProcessData->Process); if (!NT_SUCCESS(Status)) { DPRINT1("Console initialization failed\n"); @@ -601,7 +600,6 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess, DPRINT1("ConSrvNewProcess - OK\n"); TargetProcessData = ConsoleGetPerProcessData(TargetProcess); - DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData); /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData)); @@ -623,7 +621,6 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess, return STATUS_SUCCESS; SourceProcessData = ConsoleGetPerProcessData(SourceProcess); - DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData); /* * If both of the processes (parent and new child) are console applications, @@ -699,11 +696,11 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess, /* Initialize a new Console owned by the Console Leader Process */ Status = ConSrvAllocateConsole(ProcessData, + ConnectInfo->AppPath, &ConnectInfo->InputHandle, &ConnectInfo->OutputHandle, &ConnectInfo->ErrorHandle, - ConnectInfo->ShowCmd, - CsrProcess); + &ConnectInfo->ConsoleProps); if (!NT_SUCCESS(Status)) { DPRINT1("Console allocation failed\n"); diff --git a/win32ss/user/consrv/init.c b/win32ss/user/consrv/init.c index 2be911efda6..6a281c44e6a 100644 --- a/win32ss/user/consrv/init.c +++ b/win32ss/user/consrv/init.c @@ -465,6 +465,8 @@ CSR_SERVER_DLL_INIT(ConServerDllInitialization) LoadedServerDll->NewProcessCallback = ConSrvNewProcess; // LoadedServerDll->HardErrorCallback = ConSrvHardError; + ConSrvDllInstance = LoadedServerDll->ServerHandle; + /* All done */ return STATUS_SUCCESS; } @@ -477,12 +479,6 @@ DllMain(IN HINSTANCE hInstanceDll, { UNREFERENCED_PARAMETER(dwReason); UNREFERENCED_PARAMETER(lpReserved); - - if (DLL_PROCESS_ATTACH == dwReason) - { - ConSrvDllInstance = hInstanceDll; - } - return TRUE; } diff --git a/win32ss/user/consrv/tuiconsole.c b/win32ss/user/consrv/tuiconsole.c index bd275441249..08d98cce587 100644 --- a/win32ss/user/consrv/tuiconsole.c +++ b/win32ss/user/consrv/tuiconsole.c @@ -198,7 +198,7 @@ TuiInit(DWORD OemCP) wc.lpszClassName = TUI_CONSOLE_WINDOW_CLASS; wc.lpfnWndProc = TuiConsoleWndProc; wc.cbWndExtra = GWLP_CONSOLEWND_ALLOC; - wc.hInstance = (HINSTANCE)GetModuleHandleW(NULL); + wc.hInstance = ConSrvDllInstance; ConsoleClassAtom = RegisterClassExW(&wc); if (ConsoleClassAtom == 0) @@ -214,12 +214,6 @@ TuiInit(DWORD OemCP) return TRUE; } -static VOID WINAPI -TuiInitScreenBuffer(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buffer) -{ - Buffer->DefaultAttrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; -} - static void FASTCALL TuiCopyRect(char *Dest, PCONSOLE_SCREEN_BUFFER Buff, SMALL_RECT* Region) { @@ -358,10 +352,9 @@ TuiUpdateScreenInfo(PCONSOLE Console, PCONSOLE_SCREEN_BUFFER Buff) return TRUE; } -static BOOL WINAPI +static VOID WINAPI TuiChangeTitle(PCONSOLE Console) { - return TRUE; } static VOID WINAPI @@ -415,7 +408,7 @@ TuiConsoleThread(PVOID Data) 0, -32000, -32000, 0, 0, NULL, NULL, - (HINSTANCE)GetModuleHandleW(NULL), + ConSrvDllInstance, (PVOID)Console); if (NULL == NewWindow) { @@ -446,7 +439,6 @@ TuiConsoleThread(PVOID Data) static CONSOLE_VTBL TuiVtbl = { - TuiInitScreenBuffer, TuiWriteStream, TuiDrawRegion, TuiSetCursorInfo,