Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

913 lines
17 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
Keyb
Abstract:
Keyb is a DOS5-Compatible keyboard preparation utility
Author:
Ramon Juan San Andres (ramonsa) 01-May-1991
Revision History:
--*/
#include "ulib.hxx"
#include "error.hxx"
#include "stream.hxx"
#include "screen.hxx"
#include "smsg.hxx"
#include "rtmsg.h"
#include "keyb.hxx"
#include <winuser.h>
extern "C" {
#include <stdio.h>
}
ERRSTACK *perrstk;
VOID _CRTAPI1
main (
)
/*++
Routine Description:
Main function of the Keyb utility
Arguments:
None.
Return Value:
None.
Notes:
--*/
{
//
// Initialize stuff
//
DEFINE_CLASS_DESCRIPTOR( KEYB );
{
KEYB Keyb;
Keyb.Initialize();
Keyb.ConfigureKeyboard();
}
}
DEFINE_CONSTRUCTOR( KEYB, PROGRAM );
KEYB::~KEYB (
)
/*++
Routine Description:
Destructs a KEYB object
Arguments:
None.
Return Value:
None.
Notes:
--*/
{
}
BOOLEAN
KEYB::Initialize (
)
/*++
Routine Description:
Initializes a KEYB object
Arguments:
None.
Return Value:
TRUE.
Notes:
--*/
{
//
// Initialize program object
//
PROGRAM::Initialize( MSG_KEYB_USAGE );
return TRUE;
}
BOOLEAN
KEYB::ConfigureKeyboard (
)
/*++
Routine Description:
Configures the keyboard
Arguments:
None.
Return Value:
TRUE.
Notes:
--*/
{
DWORD KeyboardCode;
HKL Hkl;
DSTRING Code;
SCREEN Screen;
char CharBuffer[MAX_PATH];
WCHAR WCharBuffer[MAX_PATH];
if ( !Screen.Initialize() ) {
DisplayMessage( MSG_INSUFFICIENT_MEMORY, ERROR_MESSAGE );
return FALSE;
}
if ( ParseArguments() ) {
if ( !_SetKeyboardCode && !_SetCodePage && !_SetKeyboardId ) {
//
// Display current status
//
DisplayCurrentKeyboardCode( );
DisplayMessage( MSG_KEYB_CON_CODE_PAGE, NORMAL_MESSAGE, "%d", Screen.QueryCodePage( ) );
} else {
//
// Set keyboard and/or codepage
//
if ( _SetKeyboardCode ) {
//
// Get keyboard code
//
KeyboardCode = GetKeyboardCode();
//
// Set keyboard layer
//
//
// The keyboard code is a number, but the API takes a
// wide character string, so we have to do some funky
// stuff to do the conversion.
//
sprintf( CharBuffer, "%8.8X", KeyboardCode );
Code.Initialize( CharBuffer );
Code.QueryWSTR( 0, TO_END, WCharBuffer, MAX_PATH );
Hkl = LoadKeyboardLayout( WCharBuffer, KLF_ACTIVATE | KLF_UNLOADPREVIOUS);
if ( Hkl == 0 || Hkl == INVALID_HANDLE_VALUE ) {
DisplayMessage( MSG_KEYB_INVALID_CODE, ERROR_MESSAGE );
ExitProgram( EXIT_SYNTAXERROR );
}
}
if ( _SetCodePage ) {
if ( Screen.SetCodePage( _CodePage ) &&
Screen.SetOutputCodePage( _CodePage ) ) {
DisplayMessage( MSG_KEYB_CON_CODE_PAGE, NORMAL_MESSAGE, "%d", Screen.QueryCodePage( ) );
} else {
DisplayMessage( MSG_KEYB_INVALID_CODE_PAGE, ERROR_MESSAGE );
return FALSE;
}
}
}
ExitProgram( EXIT_NORMAL );
} else {
ExitProgram( EXIT_SYNTAXERROR );
}
return TRUE;
}
BOOLEAN
LookupKeyboardCode(
IN PWSTR LangIdString,
OUT PWSTRING KeyboardString
)
/*++
Routine Description:
This method looks up the keyboard code string for the specified
Language ID string.
Arguments:
LangIdString -- Supplies the language ID as a string representing
a hexadecimal number.
KeyboardString -- Receives the two-letter keyboard code string
which corresponds to the given language ID.
Return Value:
TRUE upon successful completion.
--*/
{
HKEY Key;
BYTE Data[32];
DWORD DataLength, DataType;
BOOLEAN Result;
DataLength = 32;
if( RegOpenKey( HKEY_LOCAL_MACHINE,
KEYBOARD_LAYOUT_KEY_NAME,
&Key ) != ERROR_SUCCESS ) {
return FALSE;
}
Result = RegQueryValueEx( Key,
LangIdString,
NULL,
&DataType,
Data,
&DataLength ) == ERROR_SUCCESS &&
DataType == REG_SZ &&
KeyboardString->Initialize( (PCWSTR)Data );
RegCloseKey( Key );
return Result;
}
DWORD
LookupLanguageId(
IN PCWSTR KeyboardString,
IN PCWSTR KbdId,
OUT PDWORD LanguageId
)
/*++
Routine Description:
This method looks up the Language ID for the specified keyboard
code string.
Arguments:
KeyboardString -- Supplies the two-letter keyboard string.
LangId -- Receives the language ID corresponding to
the specified keyboard code.
Return Value:
TRUE upon successful completion.
--*/
{
HKEY Key;
HKEY KeyIds;
WCHAR Value[REG_VALUE_LEN];
BYTE Data[REG_DATA_LEN];
PWCHAR p;
DWORD ValueLength, DataLength, DataType;
ULONG i;
DWORD ErrorMsg;
if( RegOpenKey( HKEY_LOCAL_MACHINE,
KEYBOARD_LAYOUT_KEY_NAME,
&Key ) != ERROR_SUCCESS ) {
return MSG_KEYB_BAD_REGISTRY;
}
if( ( KbdId != NULL ) &&
( RegOpenKey( HKEY_LOCAL_MACHINE,
KEYBOARD_LAYOUT_KEY_IDS,
&KeyIds ) != ERROR_SUCCESS ) ) {
RegCloseKey( Key );
return MSG_KEYB_BAD_REGISTRY;
}
ErrorMsg = MSG_KEYB_INVALID_CODE;
// Iterate through the values until one is found which has
// the keyboard string for its value.
//
for( i = 0, DataLength = REG_DATA_LEN, ValueLength = REG_VALUE_LEN;
RegEnumValue( Key, i, Value, &ValueLength, NULL, &DataType,
Data, &DataLength ) == ERROR_SUCCESS;
i++, DataLength = REG_DATA_LEN, ValueLength = REG_VALUE_LEN ) {
if( DataType == REG_SZ &&
_wcsicmp( KeyboardString, (PCWSTR)Data ) == 0 ) {
// It's a match. The value name is a string which
// represents the Language ID as a hexadecimal number.
// If there is a _KeyboardId, make sure it matches.
//
if( KbdId != NULL ) {
DataLength = REG_DATA_LEN;
if( ( RegQueryValueEx( KeyIds,
Value,
NULL, &DataType,
Data, &DataLength ) == ERROR_SUCCESS ) &&
(DataType == REG_SZ) ) {
// Value is found, does data match KbdId ?
//
if( wcscmp(KbdId, (PCWSTR)Data ) == 0 ) {
// If it doesn't match, continue enumerating to find
// another match with KeyboardString
goto Match;
}
}
ErrorMsg = MSG_KEYB_INVALID_ID;
continue;
}
Match:
// Its the match we want - convert it to a DWORD and return it.
ErrorMsg = 0;
p = Value;
*LanguageId = 0;
while ( *p ) {
*LanguageId *= 0x10;
if ( *p >= '0' && *p <= '9' ) {
*LanguageId += *p - '0';
} else {
*LanguageId += *p - 'A' + 0xA;
}
p++;
}
break;
}
}
if( KbdId != NULL ) {
RegCloseKey( KeyIds );
}
RegCloseKey( Key );
return ErrorMsg;
}
VOID
KEYB::DisplayCurrentKeyboardCode (
)
/*++
Routine Description:
Displays the current keyboard code
Arguments:
None.
Return Value:
None.
Notes:
--*/
{
DSTRING KeyboardString;
WCHAR Buffer[12];
PWCHAR p;
DWORD LangId;
BYTE Lang;
BYTE Sublang;
if ( !GetKeyboardLayoutName( Buffer ) ) {
DebugAssert( FALSE );
} else {
// The keyboard API returns a string representing a hexadecimal
// number. This string is a value-name on the keyboard-layout
// registry key; the content of that value is the two-letter
// keyboard ID string.
//
if( LookupKeyboardCode( Buffer, &KeyboardString ) ) {
DisplayMessage( MSG_KEYB_KEYBOARD_CODE, NORMAL_MESSAGE, "%W", &KeyboardString );
} else {
// This language code is not in the registry. Convert
// the string to a number, break it into language and
// sublanguage, and display that information.
//
p = Buffer;
LangId = 0;
while ( *p ) {
LangId *= 0x10;
if ( *p >= '0' && *p <= '9' ) {
LangId += *p - '0';
} else {
LangId += *p - 'A' + 0xA;
}
p++;
}
Lang = PRIMARYLANGID( LangId );
Sublang = SUBLANGID( LangId );
DisplayMessage( MSG_KEYB_KEYBOARD_LAYOUT, NORMAL_MESSAGE, "%d%d", Lang, Sublang );
}
}
}
BOOLEAN
KEYB::ParseArguments (
)
/*++
Routine Description:
Parses arguments
Arguments:
None.
Return Value:
TRUE if success, FALSE if syntax error.
Notes:
--*/
{
DSTRING Line;
DSTRING Blanks;
CHNUM Pos;
_SetKeyboardCode = FALSE;
_SetCodePage = FALSE;
_SetKeyboardId = FALSE;
if ( !Line.Initialize( GetCommandLine() ) ||
!Blanks.Initialize( " \t" )
) {
return FALSE;
}
Pos = Line.Strcspn( &Blanks );
//DisplayToken( "Program name", Line, Len );
SkipBlanks( &Line, &Pos );
return KeyboardCode( &Line, Pos );
}
BOOLEAN
KEYB::KeyboardCode(
IN PWSTRING Line,
IN CHNUM Pos
)
{
CHNUM Len;
DSTRING Delimiters;
if ( !Delimiters.Initialize( " ," ) ) {
return FALSE;
}
switch ( Line->QueryChAt( Pos ) ) {
case INVALID_CHAR:
return TRUE;
case '/':
return Switches( Line, Pos );
case ',':
Pos++;
SkipBlanks( Line, &Pos );
return CodePage( Line, Pos );
default:
Len = Line->Strcspn( &Delimiters, Pos );
if ( Len == INVALID_CHNUM ) {
Len = Line->QueryChCount();
}
Len-=Pos;
if ( !_KeyboardCode.Initialize( Line, Pos, Len ) ) {
return FALSE;
}
_KeyboardCode.Strupr();
_SetKeyboardCode = TRUE;
Pos += Len;
SkipBlanks( Line, &Pos );
switch( Line->QueryChAt( Pos ) ) {
case INVALID_CHAR:
return TRUE;
case ',':
Pos++;
return CodePage( Line, Pos );
case '/':
return Switches( Line, Pos );
default:
return ParseError( MSG_KEYB_INVALID_PARAMETER, Line, Pos );
}
}
}
BOOLEAN
KEYB::CodePage(
IN PWSTRING Line,
IN CHNUM Pos
)
{
CHNUM Len;
DSTRING Delimiters;
if ( !Delimiters.Initialize( " ," ) ) {
return FALSE;
}
switch( Line->QueryChAt( Pos ) ) {
case INVALID_CHAR:
return TRUE;
case '/':
return Switches( Line, Pos );
case ',':
Pos++;
SkipBlanks( Line, &Pos );
return FileName( Line, Pos );
default:
Len = Line->Strcspn( &Delimiters, Pos );
if ( Len == INVALID_CHNUM ) {
Len = Line->QueryChCount();
}
Len-=Pos;
if ( !Line->QueryNumber( &_CodePage, Pos, Len ) ) {
return ParseError( MSG_KEYB_INVALID_PARAMETER, Line, Pos );
}
_SetCodePage = TRUE;
Pos += Len;
SkipBlanks( Line, &Pos );
switch( Line->QueryChAt( Pos ) ) {
case INVALID_CHAR:
return TRUE;
case ',':
Pos++;
return FileName( Line, Pos );
case '/':
return Switches( Line, Pos );
default:
return ParseError( MSG_KEYB_INVALID_PARAMETER, Line, Pos );
}
}
}
BOOLEAN
KEYB::FileName(
IN PWSTRING Line,
IN CHNUM Pos
)
{
CHNUM Len;
DSTRING Delimiters;
if ( !Delimiters.Initialize( " /" ) ) {
return FALSE;
}
switch( Line->QueryChAt( Pos ) ) {
case INVALID_CHAR:
return TRUE;
case '/':
return Switches( Line, Pos );
default:
Len = Line->Strcspn( &Delimiters, Pos );
if ( Len == INVALID_CHNUM ) {
Len = Line->QueryChCount();
}
Len-=Pos;
//DisplayToken( "File Name", Line, Len );
Pos += Len;
SkipBlanks( Line, &Pos );
return Switches( Line, Pos );
}
}
BOOLEAN
KEYB::Switches(
IN PWSTRING Line,
IN CHNUM Pos
)
{
WCHAR Char;
Char = Line->QueryChAt( Pos );
if ( Char == INVALID_CHAR ) {
return TRUE;
} else if ( Char != '/' ) {
return ParseError( MSG_KEYB_INVALID_PARAMETER, Line, Pos );
}
Pos++;
switch( Line->QueryChAt( Pos ) ) {
case '?':
Usage();
case 'e':
case 'E':
return Enhanced( Line, Pos );
case 'i':
case 'I':
return KeyboardId( Line, Pos );
default:
return ParseError( MSG_KEYB_INVALID_SWITCH, Line, Pos-1 );
}
}
BOOLEAN
KEYB::Enhanced(
IN PWSTRING Line,
IN CHNUM Pos
)
{
DSTRING Delimiters;
CHNUM Len;
if ( !Delimiters.Initialize( " \t" ) ) {
return FALSE;
}
Len = Line->Strcspn( &Delimiters, Pos);
if ( Len != INVALID_CHNUM && Len != Pos+1 ) {
return ParseError( MSG_KEYB_INVALID_SWITCH, Line, Pos-1);
}
Pos++;
SkipBlanks( Line, &Pos );
switch ( Line->QueryChAt( Pos ) ) {
case INVALID_CHAR:
return FALSE;
case '/':
Pos++;
switch ( Line->QueryChAt( Pos ) ) {
case 'i':
case 'I':
return KeyboardId( Line, Pos );
default:
return ParseError( MSG_KEYB_INVALID_SWITCH, Line, Pos-1 );
}
default:
return ParseError( MSG_KEYB_INVALID_SWITCH, Line, Pos );
}
}
BOOLEAN
KEYB::KeyboardId(
IN PWSTRING Line,
IN CHNUM Pos
)
{
CHNUM Len;
DSTRING Delimiters;
if ( !Delimiters.Initialize( " \t" ) ) {
return FALSE;
}
Len = Line->Strcspn( &Delimiters, Pos );
if ( Len == INVALID_CHNUM ) {
Len = Line->QueryChCount();
}
if ( ( Line->QueryChAt( Pos+1)=='d' || Line->QueryChAt(Pos+1)=='D' ) &&
( Line->QueryChAt( Pos+2)==':' ) ) {
if ( !_KeyboardId.Initialize( Line, Pos+3, Len-3 ) ) {
return ParseError( MSG_KEYB_INVALID_SWITCH, Line, Pos );
}
_SetKeyboardId = TRUE;
Pos += Len;
SkipBlanks( Line, &Pos );
if ( Line->QueryChAt( Pos ) == INVALID_CHAR ) {
return TRUE;
}
return ParseError( MSG_KEYB_INVALID_SWITCH, Line, Pos );
} else {
return ParseError( MSG_KEYB_INVALID_SWITCH, Line, Pos );
}
}
BOOLEAN
KEYB::ParseError(
IN DWORD MessageId,
IN PWSTRING Line,
IN CHNUM Pos
)
{
DSTRING Error;
Error.Initialize( Line, Pos );
DisplayMessage( MessageId, ERROR_MESSAGE, "%W", &Error );
ExitProgram( EXIT_SYNTAXERROR );
return FALSE;
}
VOID
KEYB::SkipBlanks(
IN PWSTRING Line,
IN PCHNUM Pos
)
{
DSTRING Delimiters;
CHNUM Len;
CHNUM NewPos = *Pos;
if ( Line->QueryChAt( NewPos ) == INVALID_CHAR ) {
return;
}
if ( !Delimiters.Initialize( " \t" ) ) {
return;
}
Len = Line->Strspn( &Delimiters, NewPos );
if ( Len == INVALID_CHNUM ) {
NewPos = Line->QueryChCount();
} else {
NewPos = Len;
}
*Pos = NewPos;
}
DWORD
KEYB::GetKeyboardCode (
)
{
DWORD LanguageId;
DWORD ErrMsg = MSG_KEYB_INVALID_CODE;
if ( _KeyboardCode.QueryChCount() != 0 ) {
ErrMsg = LookupLanguageId( _KeyboardCode.GetWSTR(), _KeyboardId.GetWSTR(), &LanguageId );
if ( ErrMsg == 0 ) {
return LanguageId;
}
}
DisplayMessage( ErrMsg, ERROR_MESSAGE );
ExitProgram( EXIT_SYNTAXERROR );
return 0;
}