windows-nt/Source/XPSP1/NT/base/fs/utils/mode/lpt.cxx
2020-09-26 16:20:57 +08:00

676 lines
13 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
Lpt
Abstract:
Takes care of request involving an LPT device
Author:
Ramon Juan San Andres (ramonsa) 26-Jun-1991
Revision History:
--*/
#define _NTAPI_ULIB_
#include "mode.hxx"
#include "lpt.hxx"
#include "file.hxx"
#include "path.hxx"
#include "stream.hxx"
#include "redir.hxx"
#include "registry.hxx"
#include "regvalue.hxx"
#include "array.hxx"
#include "arrayit.hxx"
//
// When an LPT port is set, mode only sends it an EPSON/IBM sequence.
// The following macros define the EPSON sequences used.
//
#define CODE_ESCAPE 0x27
#define CODE_COLS_80 0x18
#define CODE_COLS_132 0x15
#define CODE_LINES_6 '2'
#define CODE_LINES_8 '0'
#undef LAST_COM
#define LAST_COM 4
//
// Local prototypes
//
BOOLEAN
LptStatus(
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
);
BOOLEAN
LptCodePage(
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
);
BOOLEAN
LptSetup(
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
);
BOOLEAN
LptRedirect(
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
);
BOOLEAN
LptEndRedir(
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
);
PPATH
GetRedirection(
IN PCPATH DevicePath,
OUT PREDIR_STATUS RedirStatus
);
BOOLEAN
IsAValidLptDevice (
IN DEVICE_TTYPE DeviceType,
IN ULONG DeviceNumber,
OUT PPATH *DevicePathPointer
)
/*++
Routine Description:
Determines if a certain comm device exists and optionally
creates a path for it.
Arguments:
DeviceType - Supplies the type of device
DeviceNumber - Supplies the device number
DeviceName - Supplies a pointer to a pointer to the path for
the device.
Return Value:
BOOLEAN - TRUE if the device exists,
FALSE otherwise.
Notes:
--*/
{
DSTRING DeviceName;
DSTRING AlternateName;
DSTRING Number;
BOOLEAN Valid = FALSE;
REGISTRY Registry;
DSTRING ParentName;
DSTRING KeyName;
ARRAY ValueArray;
PARRAY_ITERATOR Iterator;
ULONG ErrorCode;
PCBYTE Data;
DSTRING PortName;
PREGISTRY_VALUE_ENTRY Value;
UNREFERENCED_PARAMETER( DeviceType );
if ( DeviceName.Initialize( (LPWSTR)L"LPT" )&&
Number.Initialize( DeviceNumber ) &&
DeviceName.Strcat( &Number ) &&
AlternateName.Initialize( (LPWSTR)L"\\DosDevices\\" ) &&
AlternateName.Strcat( &DeviceName ) &&
ParentName.Initialize( "" ) &&
KeyName.Initialize( LPT_KEY_NAME ) &&
ValueArray.Initialize() &&
Registry.Initialize()
) {
//
// Get the names of all the serial ports
//
if ( Registry.QueryValues(
PREDEFINED_KEY_LOCAL_MACHINE,
&ParentName,
&KeyName,
&ValueArray,
&ErrorCode
) ) {
//
// See if the given name matches any of the serial ports
//
if ( Iterator = (PARRAY_ITERATOR)ValueArray.QueryIterator() ) {
while ( Value = (PREGISTRY_VALUE_ENTRY)(Iterator->GetNext() ) ) {
if ( Value->GetData( &Data ) ) {
if ( PortName.Initialize( (PWSTR)Data ) ) {
if ( !DeviceName.Stricmp( &PortName ) ||
!AlternateName.Stricmp( &PortName ) ) {
Valid = TRUE;
break;
}
}
}
}
DELETE( Iterator );
}
}
if ( DevicePathPointer ) {
if (!(*DevicePathPointer = NEW PATH)) {
DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
NULL,
(ULONG)EXIT_ERROR );
return FALSE; // help lint
}
(*DevicePathPointer)->Initialize( &DeviceName );
}
}
return Valid;
}
BOOLEAN
LptHandler(
IN PREQUEST_HEADER Request
)
/*++
Routine Description:
Handles LPT requests
Arguments:
Request - Supplies pointer to request
Return Value:
None.
Notes:
--*/
{
PPATH DevicePath; // Name of Device
BOOLEAN Served = TRUE; // TRUE if request served OK.
REDIR_STATUS Status;
DebugPtrAssert( Request );
DebugAssert( Request->DeviceType == DEVICE_TYPE_LPT );
//
// Make sure that the device exists, and at the same time get its
// name ( For calling APIs ).
//
if ( Request->DeviceName ) {
if (!(DevicePath = NEW PATH)) {
DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
NULL,
(ULONG)EXIT_ERROR );
return FALSE; // help lint
}
DevicePath->Initialize( Request->DeviceName );
} else if ( (!IsAValidLptDevice( Request->DeviceType, Request->DeviceNumber, &DevicePath ) &&
Request->RequestType != REQUEST_TYPE_LPT_REDIRECT &&
!REDIR::IsRedirected( &Status, DevicePath )) ||
Request->DeviceNumber > LAST_LPT ) {
DisplayMessageAndExit( MODE_ERROR_INVALID_DEVICE_NAME,
DevicePath->GetPathString(),
(ULONG)EXIT_ERROR );
}
//
// So the device is valid. Now serve the request
//
switch( Request->RequestType ) {
case REQUEST_TYPE_STATUS:
//
// Display State of device
//
Served = LptStatus( DevicePath, Request );
break;
case REQUEST_TYPE_CODEPAGE_PREPARE:
case REQUEST_TYPE_CODEPAGE_SELECT:
case REQUEST_TYPE_CODEPAGE_REFRESH:
case REQUEST_TYPE_CODEPAGE_STATUS:
//
// Codepage request
//
Served = LptCodePage( DevicePath, Request );
break;
case REQUEST_TYPE_LPT_SETUP:
//
// Printer setup
//
Served = LptSetup( DevicePath, Request );
break;
case REQUEST_TYPE_LPT_REDIRECT:
//
// Redirect LPT to COM
//
Served = LptRedirect( DevicePath, Request );
break;
case REQUEST_TYPE_LPT_ENDREDIR:
//
// End redirection of LPT
//
Served = LptEndRedir( DevicePath, Request );
break;
default:
DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
NULL,
(ULONG)EXIT_ERROR );
}
DELETE( DevicePath );
return Served;
}
BOOLEAN
LptStatus(
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
)
/*++
Routine Description:
Displays status if an LPT device
Arguments:
DevicePath - Supplies pointer to path of device
Request - Supplies pointer to request
Return Value:
BOOLEAN - TRUE if status displayed successfully,
FALSE otherwise
Notes:
--*/
{
UNREFERENCED_PARAMETER( DevicePath );
UNREFERENCED_PARAMETER( Request );
PPATH RedirPath = NULL;
REDIR_STATUS RedirStatus;
RedirPath = GetRedirection( DevicePath, &RedirStatus );
if ( !RedirPath && (RedirStatus != REDIR_STATUS_NONEXISTENT) ) {
//
// We cannot find out the status of the redirection.
// This is almost certainly due to lack of privileges.
// We won't display the LPT status
//
return TRUE;
}
//
// Write the Header
//
WriteStatusHeader( DevicePath );
if ( !RedirPath ) {
DisplayMessage( MODE_MESSAGE_STATUS_NOT_REROUTED, NULL );
} else {
DisplayMessage( MODE_MESSAGE_STATUS_REROUTED, RedirPath->GetPathString() );
DELETE( RedirPath );
}
Get_Standard_Output_Stream()->WriteChar( '\r' );
Get_Standard_Output_Stream()->WriteChar( '\n' );
return TRUE;
}
BOOLEAN
LptCodePage(
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
)
/*++
Routine Description:
Handles Codepage requests for LPT device
Arguments:
DevicePath - Supplies pointer to path of device
Request - Supplies pointer to request
Return Value:
BOOLEAN - TRUE if request handled successfully,
FALSE otherwise
Notes:
--*/
{
UNREFERENCED_PARAMETER( DevicePath );
UNREFERENCED_PARAMETER( Request );
DisplayMessage( MODE_ERROR_CODEPAGE_OPERATION_NOT_SUPPORTED, NULL );
return TRUE;
}
BOOLEAN
LptSetup(
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
)
/*++
Routine Description:
Sets LPT state
Arguments:
DevicePath - Supplies pointer to path of device
Request - Supplies pointer to request
Return Value:
BOOLEAN - TRUE if state set successfully,
FALSE otherwise
Notes:
--*/
{
PREQUEST_DATA_LPT_SETUP Data;
PFSN_FILE Lpt;
PFILE_STREAM LptStream;
Data = (PREQUEST_DATA_LPT_SETUP)&(((PLPT_REQUEST)Request)->Data.Setup);
if ( ( Data->SetCol && (Data->Col != 132) && ( Data->Col != 80 ) ) ||
( Data->SetLines && (Data->Lines != 6) && (Data->Lines != 8) ) ) {
//
// Invalid number of lines or columns
//
DisplayMessageAndExit( MODE_ERROR_LPT_CANNOT_SET, NULL, (ULONG)EXIT_ERROR );
}
Lpt = SYSTEM::QueryFile( DevicePath );
DebugPtrAssert( Lpt );
if ( Lpt ) {
LptStream = Lpt->QueryStream( WRITE_ACCESS );
DebugPtrAssert( LptStream );
}
if ( !Lpt || !LptStream ) {
DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR );
}
if ( Data->SetCol ) {
//
// Set number of columns. The sequence consists of one byte.
//
LptStream->WriteByte( (Data->Col == 80) ? CODE_COLS_80 : CODE_COLS_132 );
}
if ( Data->SetLines ) {
//
// Set line spacing. The sequence consists of one escape byte
// followed by one CODE_LINES_6 or CODE_LINES 8 byte.
//
LptStream->WriteByte( CODE_ESCAPE );
LptStream->WriteByte( (Data->Lines == 6) ? CODE_LINES_6 : CODE_LINES_8 );
}
DELETE( LptStream );
DELETE( Lpt );
return TRUE;
}
BOOLEAN
LptRedirect(
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
)
/*++
Routine Description:
Redirects LPT to a COMM port.
Arguments:
DevicePath - Supplies pointer to path of device
Request - Supplies pointer to request
Return Value:
BOOLEAN - TRUE if LPT redirected,
FALSE otherwise
Notes:
--*/
{
PREQUEST_DATA_LPT_REDIRECT Data;
PPATH RedirPath;
Data = (PREQUEST_DATA_LPT_REDIRECT)&(((PLPT_REQUEST)Request)->Data.Redirect);
//
// Verify that the serial device specified is valid
//
if ( !IsAValidDevice( Data->DeviceType, Data->DeviceNumber, &RedirPath )) {
DisplayMessageAndExit( MODE_ERROR_INVALID_DEVICE_NAME,
RedirPath->GetPathString(),
(ULONG)EXIT_ERROR );
}
if ( !REDIR::Redirect( DevicePath, RedirPath ) ) {
DisplayMessageAndExit( MODE_ERROR_LPT_CANNOT_REROUTE, RedirPath->GetPathString(), (ULONG)EXIT_ERROR );
}
//
// Display the status as confirmation
//
LptStatus( DevicePath, Request );
DELETE( RedirPath );
return TRUE;
}
BOOLEAN
LptEndRedir (
IN PCPATH DevicePath,
IN PREQUEST_HEADER Request
)
/*++
Routine Description:
Ends the redirection of an LPT port
Arguments:
DevicePath - Supplies pointer to path of device
Request - Supplies pointer to request
Return Value:
BOOLEAN - TRUE
Notes:
--*/
{
REDIR_STATUS Status;
//
// If the LPT is being redirected, end the redirection
//
if ( REDIR::IsRedirected( &Status, DevicePath ) ) {
if ( !REDIR::EndRedirection( DevicePath )) {
DisplayMessageAndExit( MODE_ERROR_LPT_CANNOT_ENDREROUTE, NULL, (ULONG)EXIT_ERROR );
}
}
//
// Display status
//
LptStatus( DevicePath, Request );
return TRUE;
}
PPATH
GetRedirection(
IN PCPATH DevicePath,
OUT PREDIR_STATUS RedirStatus
)
/*++
Routine Description:
Determines to what device is the LPT redirected to
Arguments:
DevicePath - Supplies pointer to path of device
RedirStatus - Supplies pointer to redirection status
Return Value:
PPATH - Pointer to the redirected device
--*/
{
ULONG DeviceNumber = 1;
PPATH DestPath = NULL;
BOOLEAN ValidDevice = TRUE;
if ( REDIR::IsRedirected( RedirStatus, DevicePath ) ) {
for ( DeviceNumber = 1; DeviceNumber <= LAST_COM; DeviceNumber++ ) {
IsAValidDevice( DEVICE_TYPE_COM, DeviceNumber, &DestPath );
if ( REDIR::IsRedirected( RedirStatus, DevicePath, DestPath )) {
break;
}
DELETE( DestPath );
DestPath = NULL;
}
}
return DestPath;
}