windows-nt/Source/XPSP1/NT/base/remoteboot/osdisp/osdisp.c

1147 lines
22 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// DISPLAY OSCHOOSE SCREENS
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntseapi.h>
#include <windows.h>
#include <winsock.h>
#undef ERROR
#include <stdio.h>
CHAR DomainName[64];
CHAR UserName[64];
CHAR Password[64];
VOID
BiosConsoleWrite(
IN ULONG FileId,
OUT PUCHAR Buffer,
IN ULONG Length,
OUT PULONG Count
);
ULONG __cdecl
BiosConsoleGetKey(
void
);
ULONG __cdecl
BiosConsoleGetCounter(
void
);
#include "..\boot\oschoice\oscheap.c"
#define _BUILDING_OSDISP_
#include "..\boot\oschoice\parse.c"
#if DBG
ULONG NetDebugFlag =
DEBUG_ERROR |
DEBUG_OSC;
#endif
//
// This is declared and expected by parse.c, so we defined the functions
// for the macros it uses (GET_KEY and GET_COUNTER) and NULL the rest out.
//
EXTERNAL_SERVICES_TABLE ServicesTable = {
NULL, // RebootProcessor
NULL, // DiskIOSystem
BiosConsoleGetKey,
BiosConsoleGetCounter,
NULL, // Reboot
NULL, // AbiosServices
NULL, // DetectHardware
NULL, // HardwareCursor
NULL, // GetDateTime
NULL, // ComPort
NULL, // IsMcaMachine
NULL, // GetStallCount
NULL, // InitializeDisplayForNt
NULL, // GetMemoryDescriptor
NULL, // GetEddsSector
NULL, // GetElToritoStatus
NULL // GetExtendedInt13Params
};
PEXTERNAL_SERVICES_TABLE ExternalServicesTable = &ServicesTable;
//
// This is used by the ArcWrite function -- it only cares about the firmware vector
// which is the 28th entry.
//
PVOID FirmwareVector[38] = {
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, (PVOID)BiosConsoleWrite, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL
};
SYSTEM_PARAMETER_BLOCK GlobalSystemBlock = {
0, // Signature
0, // Length
0, // Version
0, // Revision
NULL, // RestartBlock
NULL, // DebugBlock
NULL, // GenerateExceptionVector
NULL, // TlbMissExceptionVector
sizeof(FirmwareVector),
FirmwareVector,
0, // VendorVectorLength
NULL, // VendorVector
0, // AdapterCount
0, // Adapter0Type
0, // Adapter0Length
NULL // Adapter0Vector
};
//
// Current screen position.
//
USHORT TextColumn = 0;
USHORT TextRow = 0;
//
// Height and width of the console.
//
USHORT ScreenWidthCells;
USHORT ScreenHeightCells;
//
// Current text attribute
//
UCHAR TextCurrentAttribute = 0x07; // start with white on black.
//
// Standard input and output handles.
//
HANDLE StandardInput;
HANDLE StandardOutput;
UCHAR EightySpaces[] =
" ";
//
// defines for doing console I/O
//
#define CSI 0x95
#define SGR_INVERSE 7
#define SGR_NORMAL 0
//
// static data for console I/O
//
BOOLEAN ControlSequence=FALSE;
BOOLEAN EscapeSequence=FALSE;
BOOLEAN FontSelection=FALSE;
BOOLEAN HighIntensity=FALSE;
BOOLEAN Blink=FALSE;
ULONG PCount=0;
#define CONTROL_SEQUENCE_MAX_PARAMETER 10
ULONG Parameter[CONTROL_SEQUENCE_MAX_PARAMETER];
#define KEY_INPUT_BUFFER_SIZE 16
UCHAR KeyBuffer[KEY_INPUT_BUFFER_SIZE];
ULONG KeyBufferEnd=0;
ULONG KeyBufferStart=0;
//
// array for translating between ANSI colors and the VGA standard
//
UCHAR TranslateColor[] = {0,4,2,6,1,5,3,7};
#define ASCI_ESC 0x1b
//
// Need this to link.
//
ULONG BlConsoleOutDeviceId = 0;
CHAR
BlProcessScreen(
IN PCHAR InputString,
OUT PCHAR OutputString
);
CHAR g_OutputString[1024];
int __cdecl
main (argc, argv)
int argc;
char *argv[];
{
DWORD Error;
int i;
HANDLE hFile;
DWORD fileSize, bytesRead;
PCHAR fileBuffer;
CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
CONSOLE_CURSOR_INFO cursorInfo;
COORD coord;
PCHAR pszScreenName;
CHAR LastKey;
if (argc < 2) {
printf("USAGE: %s [screen-file-name]\n", argv[0]);
return -1;
}
//
// Set up the console correctly. We allocate our own and resize
// it to 80 x 25.
//
FreeConsole();
AllocConsole();
StandardInput = GetStdHandle(STD_INPUT_HANDLE);
StandardOutput = GetStdHandle(STD_OUTPUT_HANDLE);
ScreenWidthCells = 81;
ScreenHeightCells = 25;
coord.X = ScreenWidthCells;
coord.Y = ScreenHeightCells;
SetConsoleScreenBufferSize(StandardOutput, coord);
//
// This actually turns *off* most processing.
//
SetConsoleMode(StandardInput, ENABLE_PROCESSED_INPUT);
//
// Hide the cursor.
//
cursorInfo.dwSize = 1;
cursorInfo.bVisible = FALSE;
SetConsoleCursorInfo(StandardOutput, &cursorInfo);
//
// Open the first parameter as a file.
//
pszScreenName = argv[1];
NextScreen:
hFile = CreateFileA(pszScreenName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE ) {
printf("Could not open %s!\n", argv[1]);
return -1;
}
fileSize = GetFileSize(hFile, NULL);
printf("File %s is %d bytes\n", argv[1], fileSize);
fileBuffer = LocalAlloc(0, fileSize+1);
if (fileBuffer == NULL) {
printf("Allocate failed!\n");
return -1;
}
if (!ReadFile(hFile, fileBuffer, fileSize, &bytesRead, NULL)) {
printf("Read failed\n");
return -1;
}
if (bytesRead != fileSize) {
printf("Too few bytes read\n");
return -1;
}
CloseHandle(hFile);
fileBuffer[fileSize] = '\0';
LastKey = BlProcessScreen(fileBuffer, g_OutputString);
if (SpecialAction == ACTION_REFRESH)
goto NextScreen;
{
PCHAR psz = strchr( g_OutputString, '\n' );
if ( psz )
*psz = '\0';
pszScreenName = g_OutputString;
if ( strcmp( pszScreenName, "REBOOT" ) != 0
&& strcmp( pszScreenName, "LAUNCH" ) != 0 \
&& strcmp( pszScreenName, "" ) != 0 ) {
// add the extension and jump to the next screen
strcat( g_OutputString, ".osc" );
goto NextScreen;
}
}
//
// I can't figure out how to write to the old console -- so for
// now just display it and pause.
//
BlpClearScreen();
SetConsoleTextAttribute(StandardOutput, 0x7);
printf("String returned was <%s>\n", g_OutputString);
printf("Press any key to exit\n");
while (GET_KEY() == 0) {
;
}
}
VOID
TextGetCursorPosition(
OUT PULONG X,
OUT PULONG Y
)
/*++
Routine Description:
Gets the position of the soft cursor.
Arguments:
X - Receives column coordinate of where character would be written.
Y - Receives row coordinate of where next character would be written.
Returns:
Nothing.
--*/
{
*X = (ULONG)TextColumn;
*Y = (ULONG)TextRow;
}
VOID
TextSetCursorPosition(
IN ULONG X,
IN ULONG Y
)
/*++
Routine Description:
Moves the location of the software cursor to the specified X,Y position
on screen.
Arguments:
X - Supplies the X-position of the cursor
Y - Supplies the Y-position of the cursor
Return Value:
None.
--*/
{
COORD coord;
TextColumn = (USHORT)X;
TextRow = (USHORT)Y;
coord.X = (USHORT)X;
coord.Y = (USHORT)Y;
SetConsoleCursorPosition(StandardOutput, coord);
}
VOID
TextSetCurrentAttribute(
IN UCHAR Attribute
)
/*++
Routine Description:
Sets the character attribute to be used for subsequent text display.
Arguments:
Returns:
Nothing.
--*/
{
TextCurrentAttribute = Attribute;
SetConsoleTextAttribute(StandardOutput, Attribute);
}
UCHAR
TextGetCurrentAttribute(
VOID
)
{
return(TextCurrentAttribute);
}
PUCHAR
TextCharOut(
IN PUCHAR pc
)
{
DWORD numWritten;
WriteConsoleA(StandardOutput, pc, 1, &numWritten, NULL);
return(pc+1);
}
VOID
TextClearToEndOfLine(
VOID
)
/*++
Routine Description:
Clears from the current cursor position to the end of the line
by writing blanks with the current video attribute.
Arguments:
None
Returns:
Nothing
--*/
{
unsigned u;
ULONG OldX,OldY;
UCHAR temp;
//
// Fill with blanks up to char before cursor position.
//
temp = ' ';
TextGetCursorPosition(&OldX,&OldY);
for(u=TextColumn; u<ScreenWidthCells; u++) {
TextCharOut(&temp);
}
TextSetCursorPosition(OldX,OldY);
}
VOID
TextClearFromStartOfLine(
VOID
)
/*++
Routine Description:
Clears from the start of the line to the current cursor position
by writing blanks with the current video attribute.
The cursor position is not changed.
Arguments:
None
Returns:
Nothing
--*/
{
unsigned u;
ULONG OldX,OldY;
UCHAR temp = ' ';
//
// Fill with blanks up to char before cursor position.
//
TextGetCursorPosition(&OldX,&OldY);
TextSetCursorPosition(0,OldY);
for(u=0; u<TextColumn; u++) {
TextCharOut(&temp);
}
TextSetCursorPosition(OldX,OldY);
}
VOID
TextClearToEndOfDisplay(
VOID
)
/*++
Routine Description:
Clears from the current cursor position to the end of the video
display by writing blanks with the current video attribute.
The cursor position is not changed.
Arguments:
None
Returns:
Nothing
--*/
{
USHORT x,y;
ULONG OldX,OldY;
DWORD numWritten;
TextGetCursorPosition(&OldX,&OldY);
//
// Clear current line
//
TextClearToEndOfLine();
//
// Clear the remaining lines
//
for(y=TextRow+1; y<ScreenHeightCells; y++) {
TextSetCursorPosition(0, y);
WriteConsoleA(StandardOutput, EightySpaces, ScreenWidthCells, &numWritten, NULL);
}
TextSetCursorPosition(OldX,OldY);
}
VOID
TextClearDisplay(
VOID
)
/*++
Routine Description:
Clears the video display and positions the cursor
at the upper left corner of the screen (0,0).
Arguments:
None
Returns:
Nothing
--*/
{
USHORT y;
DWORD numWritten;
//
// Clear screen.
//
for(y=0; y<ScreenHeightCells; y++) {
TextSetCursorPosition(0, y);
WriteConsoleA(StandardOutput, EightySpaces, ScreenWidthCells, &numWritten, NULL);
}
TextSetCursorPosition(0,0);
}
//
// This function was stolen from ..\lib\i386\biosdrv.c (except the return
// type was changed to VOID).
//
VOID
BiosConsoleWrite(
IN ULONG FileId,
OUT PUCHAR Buffer,
IN ULONG Length,
OUT PULONG Count
)
/*++
Routine Description:
Outputs to the console. (In this case, the VGA display)
Arguments:
FileId - Supplies the FileId to be written (should always be 1 for this
function)
Buffer - Supplies characters to be output
Length - Supplies the length of the buffer (in bytes)
Count - Returns the actual number of bytes written
Return Value:
ESUCCESS - Console write completed succesfully.
--*/
{
ARC_STATUS Status;
PUCHAR String;
ULONG Index;
UCHAR a;
PUCHAR p;
//
// Process each character in turn.
//
Status = ESUCCESS;
String = (PUCHAR)Buffer;
for ( *Count = 0 ;
*Count < Length ;
(*Count)++, String++ ) {
//
// If we're in the middle of a control sequence, continue scanning,
// otherwise process character.
//
if (ControlSequence) {
//
// If the character is a digit, update parameter value.
//
if ((*String >= '0') && (*String <= '9')) {
Parameter[PCount] = Parameter[PCount] * 10 + *String - '0';
continue;
}
//
// If we are in the middle of a font selection sequence, this
// character must be a 'D', otherwise reset control sequence.
//
if (FontSelection) {
//if (*String == 'D') {
//
// //
// // Other fonts not implemented yet.
// //
//
//} else {
//}
ControlSequence = FALSE;
FontSelection = FALSE;
continue;
}
switch (*String) {
//
// If a semicolon, move to the next parameter.
//
case ';':
PCount++;
if (PCount > CONTROL_SEQUENCE_MAX_PARAMETER) {
PCount = CONTROL_SEQUENCE_MAX_PARAMETER;
}
Parameter[PCount] = 0;
break;
//
// If a 'J', erase part or all of the screen.
//
case 'J':
switch (Parameter[0]) {
case 0:
//
// Erase to end of the screen
//
TextClearToEndOfDisplay();
break;
case 1:
//
// Erase from the beginning of the screen
//
break;
default:
//
// Erase entire screen
//
TextClearDisplay();
break;
}
ControlSequence = FALSE;
break;
//
// If a 'K', erase part or all of the line.
//
case 'K':
switch (Parameter[0]) {
//
// Erase to end of the line.
//
case 0:
TextClearToEndOfLine();
break;
//
// Erase from the beginning of the line.
//
case 1:
TextClearFromStartOfLine();
break;
//
// Erase entire line.
//
default :
TextClearFromStartOfLine();
TextClearToEndOfLine();
break;
}
ControlSequence = FALSE;
break;
//
// If a 'H', move cursor to position.
//
case 'H':
TextSetCursorPosition(Parameter[1]-1, Parameter[0]-1);
ControlSequence = FALSE;
break;
//
// If a ' ', could be a FNT selection command.
//
case ' ':
FontSelection = TRUE;
break;
case 'm':
//
// Select action based on each parameter.
//
// Blink and HighIntensity are by default disabled
// each time a new SGR is specified, unless they are
// explicitly specified again, in which case these
// will be set to TRUE at that time.
//
HighIntensity = FALSE;
Blink = FALSE;
for ( Index = 0 ; Index <= PCount ; Index++ ) {
switch (Parameter[Index]) {
//
// Attributes off.
//
case 0:
TextSetCurrentAttribute(7);
HighIntensity = FALSE;
Blink = FALSE;
break;
//
// High Intensity.
//
case 1:
TextSetCurrentAttribute(0xf);
HighIntensity = TRUE;
break;
//
// Underscored.
//
case 4:
break;
//
// Blink.
//
case 5:
TextSetCurrentAttribute(0x87);
Blink = TRUE;
break;
//
// Reverse Video.
//
case 7:
TextSetCurrentAttribute(0x70);
HighIntensity = FALSE;
Blink = FALSE;
break;
//
// Font selection, not implemented yet.
//
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
break;
//
// Foreground Color
//
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
a = TextGetCurrentAttribute();
a &= 0x70;
a |= TranslateColor[Parameter[Index]-30];
if (HighIntensity) {
a |= 0x08;
}
if (Blink) {
a |= 0x80;
}
TextSetCurrentAttribute(a);
break;
//
// Background Color
//
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
a = TextGetCurrentAttribute();
a &= 0x8f;
a |= TranslateColor[Parameter[Index]-40] << 4;
TextSetCurrentAttribute(a);
break;
default:
break;
}
}
default:
ControlSequence = FALSE;
break;
}
//
// This is not a control sequence, check for escape sequence.
//
} else {
//
// If escape sequence, check for control sequence, otherwise
// process single character.
//
if (EscapeSequence) {
//
// Check for '[', means control sequence, any other following
// character is ignored.
//
if (*String == '[') {
ControlSequence = TRUE;
//
// Initialize first parameter.
//
PCount = 0;
Parameter[0] = 0;
}
EscapeSequence = FALSE;
//
// This is not a control or escape sequence, process single character.
//
} else {
switch (*String) {
//
// Check for escape sequence.
//
case ASCI_ESC:
EscapeSequence = TRUE;
break;
default:
p = TextCharOut(String);
//
// Each pass through the loop increments String by 1.
// If we output a dbcs char we need to increment by
// one more.
//
(*Count) += (p - String) - 1;
String += (p - String) - 1;
break;
}
}
}
}
return;
}
ULONG __cdecl
BiosConsoleGetKey(
VOID
)
{
INPUT_RECORD inputRecord;
DWORD numRead;
//
// Loop until we see a key event or nothing.
//
while (TRUE) {
PeekConsoleInput(
StandardInput,
&inputRecord,
1,
&numRead);
if (numRead == 0) {
//
// We read nothing -- sleep for a bit (since callers tend to loop
// calling this) and return.
//
Sleep(100);
return 0;
}
ReadConsoleInput(
StandardInput,
&inputRecord,
1,
&numRead);
if (inputRecord.EventType != KEY_EVENT) {
continue;
}
//
// We had a key event -- process the key down ones.
//
if (inputRecord.Event.KeyEvent.bKeyDown) {
//
// Construct the correct scancode/ASCII value combination.
//
//
// HACK: shift-tab needs to be special-cased for some reason.
//
if ((inputRecord.Event.KeyEvent.uChar.AsciiChar == 0x09) &&
((inputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) != 0)) {
return 0x0f00;
} else {
return
(((inputRecord.Event.KeyEvent.wVirtualScanCode) & 0xff) << 8) +
inputRecord.Event.KeyEvent.uChar.AsciiChar;
}
}
}
}
ULONG __cdecl
BiosConsoleGetCounter(
VOID
)
{
//
// GetTickCount is in milliseconds, we want an 18.2/sec counter
//
return (GetTickCount() * 182) / 10000;
}
//
// These two functions were taken from ..\lib\regboot.c.
//
VOID
BlpPositionCursor(
IN ULONG Column,
IN ULONG Row
)
/*++
Routine Description:
Sets the position of the cursor on the screen.
Arguments:
Column - supplies new Column for the cursor position.
Row - supplies new Row for the cursor position.
Return Value:
None.
--*/
{
CHAR Buffer[16];
ULONG Count;
sprintf(Buffer, ASCI_CSI_OUT "%d;%dH", Row, Column);
PRINTL(Buffer);
}
VOID
BlpClearScreen(
VOID
)
/*++
Routine Description:
Clears the screen.
Arguments:
None
Return Value:
None.
--*/
{
CHAR Buffer[16];
ULONG Count;
sprintf(Buffer, ASCI_CSI_OUT "2J");
PRINTL(Buffer);
}