471 lines
8.2 KiB
C++
471 lines
8.2 KiB
C++
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
Con
|
||
|
||
Abstract:
|
||
|
||
Takes care of request involving the console ( CON: )
|
||
|
||
Author:
|
||
|
||
Ramon Juan San Andres (ramonsa) 26-Jun-1991
|
||
|
||
Notes:
|
||
|
||
This module issues direct calls to USER, because having ULIB doing
|
||
so causes programs to crash.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "mode.hxx"
|
||
#include "cons.hxx"
|
||
#include "keyboard.hxx"
|
||
#include "path.hxx"
|
||
#include "screen.hxx"
|
||
#include "stream.hxx"
|
||
#include "system.hxx"
|
||
|
||
//
|
||
// Local prototypes
|
||
//
|
||
BOOLEAN
|
||
ConStatus(
|
||
IN PREQUEST_HEADER Request,
|
||
IN BOOLEAN JustCodePage
|
||
);
|
||
|
||
BOOLEAN
|
||
ConCodePage(
|
||
IN PREQUEST_HEADER Request
|
||
);
|
||
|
||
BOOLEAN
|
||
ConSetRowCol(
|
||
IN PREQUEST_HEADER Request
|
||
);
|
||
|
||
BOOLEAN
|
||
ConSetTypematic(
|
||
IN PREQUEST_HEADER Request
|
||
);
|
||
|
||
|
||
|
||
|
||
BOOLEAN
|
||
ConHandler(
|
||
IN PREQUEST_HEADER Request
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Handles console requests
|
||
|
||
Arguments:
|
||
|
||
Request - Supplies pointer to request
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
BOOLEAN Served = TRUE; // TRUE if request served OK.
|
||
|
||
DebugPtrAssert( Request );
|
||
DebugAssert( Request->DeviceType == DEVICE_TYPE_CON );
|
||
|
||
//
|
||
// So the device is valid. Now serve the request
|
||
//
|
||
switch( Request->RequestType ) {
|
||
|
||
case REQUEST_TYPE_STATUS:
|
||
|
||
//
|
||
// Display state of CON device
|
||
//
|
||
Served = ConStatus( Request, FALSE );
|
||
break;
|
||
|
||
case REQUEST_TYPE_CODEPAGE_PREPARE:
|
||
case REQUEST_TYPE_CODEPAGE_SELECT:
|
||
case REQUEST_TYPE_CODEPAGE_REFRESH:
|
||
|
||
//
|
||
// Handle Codepage requests
|
||
//
|
||
Served = ConCodePage( Request );
|
||
break;
|
||
|
||
case REQUEST_TYPE_CODEPAGE_STATUS:
|
||
|
||
//
|
||
// Display codepage status
|
||
//
|
||
Served = ConStatus( Request, TRUE );
|
||
break;
|
||
|
||
case REQUEST_TYPE_CON_SET_ROWCOL:
|
||
|
||
//
|
||
// Set rows & columns
|
||
//
|
||
Served = ConSetRowCol( Request );
|
||
break;
|
||
|
||
case REQUEST_TYPE_CON_SET_TYPEMATIC:
|
||
|
||
//
|
||
// Set typematic rate
|
||
//
|
||
Served = ConSetTypematic( Request );
|
||
break;
|
||
|
||
default:
|
||
|
||
DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
|
||
NULL,
|
||
(ULONG)EXIT_ERROR );
|
||
|
||
}
|
||
|
||
return Served;
|
||
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
ConStatus(
|
||
IN PREQUEST_HEADER Request,
|
||
IN BOOLEAN JustCodePage
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Displays status of a console
|
||
|
||
Arguments:
|
||
|
||
Request - Supplies pointer to request
|
||
JustCodePage- Supplies a flag which if TRUE means that only
|
||
the codepage status should be displayed.
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - TRUE if status displayed successfully,
|
||
FALSE otherwise
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
SCREEN Screen;
|
||
|
||
PATH ConPath;
|
||
|
||
USHORT Rows;
|
||
USHORT Cols;
|
||
|
||
ULONG Delay = 0;
|
||
ULONG Speed = 0;
|
||
|
||
DSTRING CodepageName;
|
||
|
||
ULONG Language;
|
||
ULONG Country;
|
||
ULONG Codepage;
|
||
|
||
DSTRING CodepageString;
|
||
PSTR S1, S2;
|
||
|
||
|
||
if ( !ConPath.Initialize( (LPWSTR)L"CON" ) ) {
|
||
DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR );
|
||
}
|
||
|
||
//
|
||
// Write the Header
|
||
//
|
||
WriteStatusHeader( &ConPath );
|
||
|
||
if ( !Screen.Initialize() ) {
|
||
DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR );
|
||
}
|
||
|
||
if ( !JustCodePage ) {
|
||
|
||
//
|
||
// Display non-codepage information
|
||
//
|
||
|
||
Screen.QueryScreenSize( &Rows, &Cols );
|
||
|
||
Message->Set( MODE_MESSAGE_STATUS_LINES );
|
||
Message->Display( "%d", Rows );
|
||
|
||
Message->Set( MODE_MESSAGE_STATUS_COLS );
|
||
Message->Display( "%d", Cols );
|
||
|
||
if (!SystemParametersInfo( SPI_GETKEYBOARDSPEED, 0, (PVOID)&Speed, 0 )) {
|
||
ExitWithError( GetLastError() );
|
||
}
|
||
Message->Set( MODE_MESSAGE_STATUS_RATE );
|
||
Message->Display( "%d", Speed );
|
||
|
||
if (!SystemParametersInfo( SPI_GETKEYBOARDDELAY, 0, (PVOID)&Delay, 0 )) {
|
||
ExitWithError( GetLastError() );
|
||
}
|
||
|
||
Message->Set( MODE_MESSAGE_STATUS_DELAY );
|
||
Message->Display( "%d", Delay );
|
||
|
||
|
||
}
|
||
|
||
Message->Set( MODE_MESSAGE_STATUS_CODEPAGE );
|
||
Message->Display( "%d", Screen.QueryCodePage( ) );
|
||
|
||
Get_Standard_Output_Stream()->WriteChar( '\r' );
|
||
Get_Standard_Output_Stream()->WriteChar( '\n' );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN
|
||
ConCodePage(
|
||
IN PREQUEST_HEADER Request
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Handles Codepage requests for the console
|
||
|
||
Arguments:
|
||
|
||
Request - Supplies pointer to request
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - TRUE if request handled successfully,
|
||
FALSE otherwise
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
|
||
{
|
||
SCREEN Screen;
|
||
PREQUEST_DATA_CON_CODEPAGE_SELECT Data;
|
||
|
||
|
||
//
|
||
// We only process Codepage Select requests, all other requests
|
||
// are No-Ops. Note that the Codepage Status request is not
|
||
// processed here.
|
||
//
|
||
if ( Request->RequestType == REQUEST_TYPE_CODEPAGE_SELECT ) {
|
||
|
||
Data = (PREQUEST_DATA_CON_CODEPAGE_SELECT)&(((PCON_REQUEST)Request)->
|
||
Data.CpSelect);
|
||
|
||
if ( !Screen.Initialize() ) {
|
||
DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR );
|
||
}
|
||
|
||
if ( !Screen.SetCodePage( Data->Codepage ) ||
|
||
!Screen.SetOutputCodePage( Data->Codepage) ) {
|
||
DisplayMessageAndExit( MODE_ERROR_INVALID_CODEPAGE, NULL, (ULONG)EXIT_ERROR );
|
||
}
|
||
|
||
#ifdef FE_SB
|
||
LANGID LangId;
|
||
|
||
switch (GetConsoleOutputCP()) {
|
||
case 932:
|
||
LangId = MAKELANGID( LANG_JAPANESE, SUBLANG_DEFAULT );
|
||
break;
|
||
case 949:
|
||
LangId = MAKELANGID( LANG_KOREAN, SUBLANG_KOREAN );
|
||
break;
|
||
case 936:
|
||
LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED );
|
||
break;
|
||
case 950:
|
||
LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL );
|
||
break;
|
||
default:
|
||
LangId = PRIMARYLANGID(LANGIDFROMLCID( GetUserDefaultLCID() ));
|
||
if (LangId == LANG_JAPANESE ||
|
||
LangId == LANG_KOREAN ||
|
||
LangId == LANG_CHINESE ) {
|
||
LangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
|
||
}
|
||
else {
|
||
LangId = MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT );
|
||
}
|
||
break;
|
||
}
|
||
|
||
SetThreadLocale( MAKELCID(LangId, SORT_DEFAULT) );
|
||
#endif
|
||
|
||
ConStatus( Request, FALSE );
|
||
|
||
} else {
|
||
|
||
DisplayMessageAndExit( MODE_MESSAGE_NOT_NEEDED, NULL, EXIT_SUCCESS );
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN
|
||
ConSetRowCol(
|
||
IN PREQUEST_HEADER Request
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets number of rows and columns in the console window.
|
||
|
||
|
||
Arguments:
|
||
|
||
Request - Supplies pointer to request
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - TRUE if Number of Rows & Columns set successfully,
|
||
FALSE otherwise
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PREQUEST_DATA_CON_ROWCOL Data;
|
||
|
||
SCREEN Screen;
|
||
|
||
USHORT Rows;
|
||
USHORT Cols;
|
||
BOOLEAN IsFullScreen;
|
||
|
||
|
||
DebugPtrAssert( Request);
|
||
|
||
Data = (PREQUEST_DATA_CON_ROWCOL)&(((PCON_REQUEST)Request)->Data.RowCol);
|
||
|
||
if ( !Screen.Initialize() ) {
|
||
DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR );
|
||
}
|
||
|
||
if ( !Data->SetCol || !Data->SetLines ) {
|
||
|
||
//
|
||
// Since we don't have both values, take the current ones.
|
||
//
|
||
Screen.QueryScreenSize( &Rows, &Cols );
|
||
}
|
||
|
||
//
|
||
// Set the number of rows and columns
|
||
//
|
||
if ( Data->SetCol ) {
|
||
|
||
Cols = (USHORT)Data->Col;
|
||
|
||
}
|
||
|
||
if ( Data->SetLines ) {
|
||
|
||
Rows = (USHORT)Data->Lines;
|
||
|
||
}
|
||
|
||
if ( !Screen.ChangeScreenSize( Rows, Cols, &IsFullScreen ) ) {
|
||
|
||
//
|
||
// Cannot change the screen size
|
||
//
|
||
if ( IsFullScreen ) {
|
||
DisplayMessageAndExit( MODE_ERROR_FULL_SCREEN, NULL, (ULONG)EXIT_ERROR );
|
||
} else {
|
||
DisplayMessageAndExit( MODE_ERROR_INVALID_SCREEN_SIZE, NULL, (ULONG)EXIT_ERROR );
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN
|
||
ConSetTypematic(
|
||
IN PREQUEST_HEADER Request
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets thje typematic rate
|
||
|
||
Arguments:
|
||
|
||
DevicePath - Supplies pointer to path of device
|
||
Request - Supplies pointer to request
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - TRUE if typematic rate set successfully,
|
||
FALSE otherwise
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
|
||
{
|
||
PREQUEST_DATA_CON_TYPEMATIC Data;
|
||
|
||
DebugPtrAssert( Request);
|
||
|
||
|
||
Data = (PREQUEST_DATA_CON_TYPEMATIC)&(((PCON_REQUEST)Request)->Data.Typematic);
|
||
|
||
if ( Data->SetRate ) {
|
||
if (!SystemParametersInfo( SPI_SETKEYBOARDSPEED, (UINT)Data->Rate, NULL, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE )) {
|
||
DisplayMessageAndExit( MODE_ERROR_INVALID_RATE, NULL, (ULONG)EXIT_ERROR);
|
||
}
|
||
}
|
||
if ( Data->SetDelay ) {
|
||
if (!SystemParametersInfo( SPI_SETKEYBOARDDELAY, (UINT)Data->Delay, NULL, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE )) {
|
||
DisplayMessageAndExit( MODE_ERROR_INVALID_DELAY, NULL, (ULONG)EXIT_ERROR);
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|