diff --git a/reactos/include/csrss/csrss.h b/reactos/include/csrss/csrss.h index bc68347fe52..4017c4d9355 100644 --- a/reactos/include/csrss/csrss.h +++ b/reactos/include/csrss/csrss.h @@ -196,13 +196,26 @@ typedef struct CLIENT_ID Cid; } CSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY, * PCSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY; +typedef struct +{ + HANDLE Console; + DWORD Length; + WCHAR Title[1]; +} CSRSS_SET_TITLE_REQUEST, *PCSRSS_SET_TITLE_REQUEST; + + #define CSRSS_MAX_WRITE_CONSOLE_REQUEST (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_REQUEST)) + +#define CSRSS_MAX_SET_TITLE_REQUEST (MAX_MESSAGE_DATA - sizeof( HANDLE ) - sizeof( DWORD ) - sizeof( ULONG ) - sizeof( LPC_MESSAGE_HEADER )) + #define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST )) #define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB ((MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST )) / 2) #define CSRSS_MAX_READ_CONSOLE_REQUEST (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_READ_CONSOLE_REQUEST )) +#define CSRSS_MAX_TITLE_LENGTH 50 + #define CSRSS_CREATE_PROCESS (0x0) #define CSRSS_TERMINATE_PROCESS (0x1) #define CSRSS_WRITE_CONSOLE (0x2) @@ -224,6 +237,7 @@ typedef struct #define CSRSS_SET_MODE (0x12) #define CSRSS_CREATE_SCREEN_BUFFER (0x13) #define CSRSS_SET_SCREEN_BUFFER (0x14) +#define CSRSS_SET_TITLE (0x15) typedef struct { @@ -249,6 +263,7 @@ typedef struct CSRSS_GET_CONSOLE_MODE_REQUEST GetConsoleModeRequest; CSRSS_CREATE_SCREEN_BUFFER_REQUEST CreateScreenBufferRequest; CSRSS_SET_ACTIVE_SCREEN_BUFFER_REQUEST SetActiveScreenBufferRequest; + CSRSS_SET_TITLE_REQUEST SetTitleRequest; } Data; } CSRSS_API_REQUEST, *PCSRSS_API_REQUEST; diff --git a/reactos/lib/kernel32/misc/console.c b/reactos/lib/kernel32/misc/console.c index 98e32833d93..ef5663f9031 100644 --- a/reactos/lib/kernel32/misc/console.c +++ b/reactos/lib/kernel32/misc/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.32 2001/04/04 22:21:30 dwelch Exp $ +/* $Id: console.c,v 1.33 2001/06/22 02:11:43 phreak Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -1814,8 +1814,43 @@ SetConsoleTitleW( LPCWSTR lpConsoleTitle ) { -/* --- TO DO --- */ - return FALSE; + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + unsigned int c; + + Request = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST); + if (Request == NULL) + { + return(FALSE); + } + + Request->Type = CSRSS_SET_TITLE; + Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE ); + + for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ ) + Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c]; + // add null + Request->Data.SetTitleRequest.Title[c] = 0; + Request->Data.SetTitleRequest.Length = c; + Status = CsrClientCallServer(Request, + &Reply, + sizeof(CSRSS_SET_TITLE_REQUEST) + + c + + sizeof( LPC_MESSAGE_HEADER ) + + sizeof( ULONG ), + sizeof(CSRSS_API_REPLY)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) ) + { + RtlFreeHeap( GetProcessHeap(), 0, Request ); + SetLastErrorByStatus (Status); + return(FALSE); + } + RtlFreeHeap( GetProcessHeap(), 0, Request ); + return TRUE; } @@ -1831,36 +1866,43 @@ SetConsoleTitleA( LPCSTR lpConsoleTitle ) { - wchar_t WideTitle [MAX_CONSOLE_TITLE_LENGTH]; - char AnsiTitle [MAX_CONSOLE_TITLE_LENGTH]; - INT nWideTitle; - - if (!lpConsoleTitle) return FALSE; - ZeroMemory( WideTitle, sizeof WideTitle ); - nWideTitle = lstrlenA(lpConsoleTitle); - if (!lstrcpynA( - AnsiTitle, - lpConsoleTitle, - nWideTitle - )) - { - return FALSE; - } - AnsiTitle[nWideTitle] = '\0'; -#if 0 - if ( MultiByteToWideChar( - CP_ACP, // ANSI code page - MB_PRECOMPOSED, // character-type options - AnsiTitle, // address of string to map - nWideTitle, // number of characters in string - (LPWSTR) WideTitle, // address of wide-character buffer - (-1) // size of buffer: -1=...\0 - )) - { - return SetConsoleTitleW( (LPWSTR) WideTitle ); - } -#endif - return FALSE; + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + unsigned int c; + + Request = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST); + if (Request == NULL) + { + return(FALSE); + } + + Request->Type = CSRSS_SET_TITLE; + Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE ); + + for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ ) + Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c]; + // add null + Request->Data.SetTitleRequest.Title[c] = 0; + Request->Data.SetTitleRequest.Length = c; + Status = CsrClientCallServer(Request, + &Reply, + sizeof(CSRSS_SET_TITLE_REQUEST) + + c + + sizeof( LPC_MESSAGE_HEADER ) + + sizeof( ULONG ), + sizeof(CSRSS_API_REPLY)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) ) + { + RtlFreeHeap( GetProcessHeap(), 0, Request ); + SetLastErrorByStatus (Status); + return(FALSE); + } + RtlFreeHeap( GetProcessHeap(), 0, Request ); + return TRUE; } diff --git a/reactos/subsys/csrss/api.h b/reactos/subsys/csrss/api.h index 258284a44e2..cd57e714717 100644 --- a/reactos/subsys/csrss/api.h +++ b/reactos/subsys/csrss/api.h @@ -62,6 +62,7 @@ typedef struct CSRSS_CONSOLE_t PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */ WORD Mode; /* Console mode flags */ WORD EchoCount; /* count of chars to echo, in line buffered mode */ + UNICODE_STRING Title; /* Title of console */ } CSRSS_CONSOLE, *PCSRSS_CONSOLE; typedef struct @@ -132,6 +133,8 @@ NTSTATUS CsrCreateScreenBuffer( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQU NTSTATUS CsrSetScreenBuffer( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply ); +NTSTATUS CsrSetTitle( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply ); + /* print.c */ VOID DisplayString(LPCWSTR lpwString); VOID PrintString (char* fmt, ...); diff --git a/reactos/subsys/csrss/api/conio.c b/reactos/subsys/csrss/api/conio.c index 277792f8cfd..720122f5240 100644 --- a/reactos/subsys/csrss/api/conio.c +++ b/reactos/subsys/csrss/api/conio.c @@ -1,4 +1,4 @@ -/* $Id: conio.c,v 1.18 2001/06/18 03:07:37 phreak Exp $ +/* $Id: conio.c,v 1.19 2001/06/22 02:11:44 phreak Exp $ * * reactos/subsys/csrss/api/conio.c * @@ -353,7 +353,7 @@ NTSTATUS CsrInitConsoleScreenBuffer( PCSRSS_SCREEN_BUFFER Console ) Console->Header.Type = CSRSS_SCREEN_BUFFER_MAGIC; Console->Header.ReferenceCount = 0; Console->MaxX = PhysicalConsoleSize.X; - Console->MaxY = PhysicalConsoleSize.Y; + Console->MaxY = PhysicalConsoleSize.Y * 2; Console->ShowX = 0; Console->ShowY = 0; Console->CurrentX = 0; @@ -389,6 +389,11 @@ VOID CsrDeleteScreenBuffer( PCSRSS_SCREEN_BUFFER Buffer ) NTSTATUS CsrInitConsole(PCSRSS_CONSOLE Console) { NTSTATUS Status; + + Console->Title.MaximumLength = Console->Title.Length = 0; + Console->Title.Buffer = 0; + + RtlCreateUnicodeString( &Console->Title, L"Command Prompt" ); Console->Header.ReferenceCount = 0; Console->WaitingChars = 0; @@ -506,6 +511,7 @@ VOID CsrDrawConsole( PCSRSS_SCREEN_BUFFER Buff ) VOID CsrDeleteConsole( PCSRSS_CONSOLE Console ) { ConsoleInput *Event; + DPRINT1( "CsrDeleteConsole\n" ); RtlEnterCriticalSection( &ActiveConsoleLock ); /* Drain input event queue */ while( Console->InputEvents.Flink != &Console->InputEvents ) @@ -532,6 +538,7 @@ VOID CsrDeleteConsole( PCSRSS_CONSOLE Console ) if( !--Console->ActiveBuffer->Header.ReferenceCount ) CsrDeleteScreenBuffer( Console->ActiveBuffer ); NtClose( Console->ActiveEvent ); + RtlFreeUnicodeString( &Console->Title ); RtlFreeHeap( CsrssApiHeap, 0, Console ); } @@ -602,6 +609,7 @@ VOID Console_Api( DWORD RefreshEvent ) HANDLE Events[2]; // 0 = keyboard, 1 = refresh int c; int updown; + PCSRSS_CONSOLE SwapConsole = 0; // console we are thinking about swapping with Events[0] = 0; Status = NtCreateEvent( &Events[0], STANDARD_RIGHTS_ALL, NULL, FALSE, FALSE ); @@ -649,23 +657,91 @@ VOID Console_Api( DWORD RefreshEvent ) else break; } } - if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&& KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == 'q' ) + if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&& KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_TAB ) if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE ) { + ANSI_STRING Title; + void * Buffer; + COORD *pos; + unsigned int src, dst; + /* alt-tab, swap consoles */ - RtlEnterCriticalSection( &ActiveConsoleLock ); - if( ActiveConsole->Next != ActiveConsole ) - ActiveConsole = ActiveConsole->Next; - CsrDrawConsole( ActiveConsole->ActiveBuffer ); - RtlLeaveCriticalSection( &ActiveConsoleLock ); - RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); - continue; + // move SwapConsole to next console, and print its title + RtlEnterCriticalSection( &ActiveConsoleLock ); + if( !SwapConsole ) + SwapConsole = ActiveConsole; + + if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED ) + SwapConsole = SwapConsole->Prev; + else SwapConsole = SwapConsole->Next; + Title.MaximumLength = RtlUnicodeStringToAnsiSize( &SwapConsole->Title ); + Title.Length = 0; + Buffer = RtlAllocateHeap( CsrssApiHeap, + 0, + sizeof( COORD ) + Title.MaximumLength ); + pos = (COORD *)Buffer; + Title.Buffer = Buffer + sizeof( COORD ); + + /* this does not seem to work + RtlUnicodeStringToAnsiString( &Title, &SwapConsole->Title, FALSE ); */ + // temp hack + for( src = 0, dst = 0; src < SwapConsole->Title.Length; src++, dst++ ) + Title.Buffer[dst] = (char)SwapConsole->Title.Buffer[dst]; + + pos->Y = PhysicalConsoleSize.Y / 2; + pos->X = ( PhysicalConsoleSize.X - Title.MaximumLength ) / 2; + // redraw the console to clear off old title + CsrDrawConsole( ActiveConsole->ActiveBuffer ); + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, + 0, + 0, + Buffer, + sizeof (COORD) + Title.MaximumLength ); + if( !NT_SUCCESS( Status ) ) + { + DPRINT1( "Error writing to console\n" ); + } + RtlFreeHeap( CsrssApiHeap, 0, Buffer ); + + RtlLeaveCriticalSection( &ActiveConsoleLock ); + RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); + continue; } else { RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); continue; } - else if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) && (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP || KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) ) + else if( SwapConsole && + KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_MENU && + KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == FALSE ) + { + // alt key released, swap consoles + PCSRSS_CONSOLE tmp; + + RtlEnterCriticalSection( &ActiveConsoleLock ); + if( SwapConsole != ActiveConsole ) + { + // first remove swapconsole from the list + SwapConsole->Prev->Next = SwapConsole->Next; + SwapConsole->Next->Prev = SwapConsole->Prev; + // now insert before activeconsole + SwapConsole->Next = ActiveConsole; + SwapConsole->Prev = ActiveConsole->Prev; + ActiveConsole->Prev->Next = SwapConsole; + ActiveConsole->Prev = SwapConsole; + } + ActiveConsole = SwapConsole; + SwapConsole = 0; + CsrDrawConsole( ActiveConsole->ActiveBuffer ); + + RtlLeaveCriticalSection( &ActiveConsoleLock ); + } + if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) && (KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP || KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) ) { if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE ) { @@ -787,6 +863,8 @@ VOID Console_Api( DWORD RefreshEvent ) } } ActiveConsole->WaitingChars++; + if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT) ) + NtSetEvent( ActiveConsole->ActiveEvent, 0 ); RtlLeaveCriticalSection( &ActiveConsoleLock ); } } @@ -1296,3 +1374,25 @@ NTSTATUS CsrSetScreenBuffer( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST RtlLeaveCriticalSection( &ActiveConsoleLock ); return Reply->Status; } + +NTSTATUS CsrSetTitle( PCSRSS_PROCESS_DATA ProcessData, PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply ) +{ + NTSTATUS Status; + PCSRSS_CONSOLE Console; + + Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY ); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + RtlEnterCriticalSection( &ActiveConsoleLock ); + Status = CsrGetObject( ProcessData, Request->Data.SetTitleRequest.Console, (Object_t **)&Console ); + if( !NT_SUCCESS( Status ) ) + Reply->Status = Status; + else { + // copy title to console + RtlFreeUnicodeString( &Console->Title ); + RtlCreateUnicodeString( &Console->Title, Request->Data.SetTitleRequest.Title ); + Reply->Status = STATUS_SUCCESS; + } + RtlLeaveCriticalSection( &ActiveConsoleLock ); + return Reply->Status; +} +