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,