427 lines
13 KiB
C++
427 lines
13 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991-2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
print.cxx
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jaime F. Sasson - jaimes - 14-Jun-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
ULIB, User Mode
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "ulib.hxx"
|
|||
|
#include "arg.hxx"
|
|||
|
#include "path.hxx"
|
|||
|
#include "wstring.hxx"
|
|||
|
#include "system.hxx"
|
|||
|
#include "array.hxx"
|
|||
|
#include "arrayit.hxx"
|
|||
|
#include "smsg.hxx"
|
|||
|
#include "stream.hxx"
|
|||
|
#include "rtmsg.h"
|
|||
|
#include "prtstrm.hxx"
|
|||
|
#include "file.hxx"
|
|||
|
#include "print.hxx"
|
|||
|
|
|||
|
extern "C" {
|
|||
|
#include <stdio.h>
|
|||
|
#include <string.h>
|
|||
|
}
|
|||
|
|
|||
|
PSTREAM Get_Standard_Input_Stream();
|
|||
|
PSTREAM Get_Standard_Output_Stream();
|
|||
|
|
|||
|
DEFINE_CONSTRUCTOR( PRINT, PROGRAM );
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
PRINT::Initialize(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initializes a PRINT class.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - Indicates if the initialization succeeded.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
{
|
|||
|
ARGUMENT_LEXEMIZER ArgLex;
|
|||
|
ARRAY LexArray;
|
|||
|
|
|||
|
ARRAY ArgumentArray;
|
|||
|
FLAG_ARGUMENT FlagDisplayHelp;
|
|||
|
|
|||
|
STRING_ARGUMENT ProgramNameArgument;
|
|||
|
PWSTRING InvalidArgument;
|
|||
|
|
|||
|
PATH_ARGUMENT DeviceArgument;
|
|||
|
PPATH DevicePath;
|
|||
|
PCWSTRING DeviceString;
|
|||
|
PPATH FilePath;
|
|||
|
PCWSTRING FileString;
|
|||
|
PARRAY PathArray;
|
|||
|
PARRAY_ITERATOR PathArrayIterator;
|
|||
|
PFSN_FILE FsnFile;
|
|||
|
|
|||
|
|
|||
|
_StandardOutput = Get_Standard_Output_Stream();
|
|||
|
|
|||
|
if (_StandardOutput == NULL) {
|
|||
|
DebugPrint("PRINT: Out of memory\n");
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize MESSAGE class
|
|||
|
//
|
|||
|
_Message.Initialize( _StandardOutput, Get_Standard_Input_Stream() );
|
|||
|
|
|||
|
//
|
|||
|
// Parse command line
|
|||
|
//
|
|||
|
if ( !LexArray.Initialize() ) {
|
|||
|
DebugAbort( "LexArray.Initialize() failed \n" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if ( !ArgLex.Initialize( &LexArray ) ) {
|
|||
|
DebugAbort( "ArgLex.Initialize() failed \n" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
ArgLex.PutSwitches( "/" );
|
|||
|
ArgLex.SetCaseSensitive( FALSE );
|
|||
|
ArgLex.PutStartQuotes( "\"" );
|
|||
|
ArgLex.PutEndQuotes( "\"" );
|
|||
|
|
|||
|
if( !ArgLex.PrepareToParse() ) {
|
|||
|
DebugAbort( "ArgLex.PrepareToParse() failed \n" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if ( !ArgumentArray.Initialize() ) {
|
|||
|
DebugAbort( "ArgumentArray.Initialize() failed \n" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( !ProgramNameArgument.Initialize("*") ||
|
|||
|
!DeviceArgument.Initialize( "/D:*" ) ||
|
|||
|
!_BufferSize.Initialize( "/B:*" ) ||
|
|||
|
!_Ticks1.Initialize( "/U:*" ) ||
|
|||
|
!_Ticks2.Initialize( "/M:*" ) ||
|
|||
|
!_Ticks3.Initialize( "/S:*" ) ||
|
|||
|
!_NumberOfFiles.Initialize( "/Q:*" ) ||
|
|||
|
!_FlagRemoveFiles.Initialize( "/T" ) ||
|
|||
|
!_Files.Initialize( "*", FALSE, TRUE ) ||
|
|||
|
!_FlagCancelPrinting.Initialize( "/C" ) ||
|
|||
|
!_FlagAddFiles.Initialize( "/P" ) ||
|
|||
|
!FlagDisplayHelp.Initialize( "/?" ) ) {
|
|||
|
DebugAbort( "Unable to initialize flag or string arguments \n" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( !ArgumentArray.Put( &ProgramNameArgument ) ||
|
|||
|
!ArgumentArray.Put( &DeviceArgument ) ||
|
|||
|
!ArgumentArray.Put( &_BufferSize ) ||
|
|||
|
!ArgumentArray.Put( &_Ticks1 ) ||
|
|||
|
!ArgumentArray.Put( &_Ticks2 ) ||
|
|||
|
!ArgumentArray.Put( &_Ticks3 ) ||
|
|||
|
!ArgumentArray.Put( &_NumberOfFiles ) ||
|
|||
|
!ArgumentArray.Put( &_FlagRemoveFiles ) ||
|
|||
|
!ArgumentArray.Put( &_Files ) ||
|
|||
|
!ArgumentArray.Put( &_FlagCancelPrinting ) ||
|
|||
|
!ArgumentArray.Put( &_FlagAddFiles ) ||
|
|||
|
!ArgumentArray.Put( &FlagDisplayHelp ) ) {
|
|||
|
DebugAbort( "ArgumentArray.Put() failed \n" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( !ArgLex.DoParsing( &ArgumentArray ) ) {
|
|||
|
InvalidArgument = ArgLex.QueryInvalidArgument();
|
|||
|
DebugPtrAssert( InvalidArgument );
|
|||
|
_Message.Set( MSG_PRINT_INVALID_SWITCH );
|
|||
|
_Message.Display( "%W", InvalidArgument );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// /B: /U: /M: /S: /Q: /T: /C: and /P: are not implemented
|
|||
|
// if one of these arguments was found in the command line
|
|||
|
// then inform user, and don't print anything
|
|||
|
//
|
|||
|
if( _BufferSize.IsValueSet() ) {
|
|||
|
_Message.Set( MSG_PRINT_NOT_IMPLEMENTED );
|
|||
|
_Message.Display( "%s", "/B:" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( _Ticks1.IsValueSet() ) {
|
|||
|
_Message.Set( MSG_PRINT_NOT_IMPLEMENTED );
|
|||
|
_Message.Display( "%s", "/U:" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( _Ticks2.IsValueSet() ) {
|
|||
|
_Message.Set( MSG_PRINT_NOT_IMPLEMENTED );
|
|||
|
_Message.Display( "%s", "/M:" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( _Ticks3.IsValueSet() ) {
|
|||
|
_Message.Set( MSG_PRINT_NOT_IMPLEMENTED );
|
|||
|
_Message.Display( "%s", "/S:" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( _NumberOfFiles.IsValueSet() ) {
|
|||
|
_Message.Set( MSG_PRINT_NOT_IMPLEMENTED );
|
|||
|
_Message.Display( "%s", "/Q:" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( _FlagRemoveFiles.IsValueSet() ) {
|
|||
|
_Message.Set( MSG_PRINT_NOT_IMPLEMENTED );
|
|||
|
_Message.Display( "%s", "/T:" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( _FlagCancelPrinting.IsValueSet() ) {
|
|||
|
_Message.Set( MSG_PRINT_NOT_IMPLEMENTED );
|
|||
|
_Message.Display( "%s", "/C:" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
if( _FlagAddFiles.IsValueSet() ) {
|
|||
|
_Message.Set( MSG_PRINT_NOT_IMPLEMENTED );
|
|||
|
_Message.Display( "%s", "/P:" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Displays help message if /? was found in the command line
|
|||
|
//
|
|||
|
if( FlagDisplayHelp.QueryFlag() ) {
|
|||
|
_Message.Set( MSG_PRINT_HELP_MESSAGE );
|
|||
|
_Message.Display( " " );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If no filename was specified, display error message
|
|||
|
//
|
|||
|
if( _Files.QueryPathCount() == 0 ) {
|
|||
|
_Message.Set( MSG_PRINT_NO_FILE );
|
|||
|
_Message.Display( " " );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get device name if one exists. Otherwise use PRN as default
|
|||
|
//
|
|||
|
if( !DeviceArgument.IsValueSet() ) {
|
|||
|
DevicePath = NEW( PATH );
|
|||
|
DebugPtrAssert( DevicePath );
|
|||
|
if( !DevicePath->Initialize( (LPWSTR)L"PRN" ) ) {
|
|||
|
_Message.Set( MSG_PRINT_UNABLE_INIT_DEVICE );
|
|||
|
_Message.Display( "%s", "PRN" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
} else {
|
|||
|
DevicePath = DeviceArgument.GetPath();
|
|||
|
DebugPtrAssert( DevicePath );
|
|||
|
}
|
|||
|
if( !_Printer.Initialize( DevicePath ) ) {
|
|||
|
DeviceString = DevicePath->GetPathString();
|
|||
|
DebugPtrAssert( DeviceString );
|
|||
|
_Message.Set( MSG_PRINT_UNABLE_INIT_DEVICE );
|
|||
|
_Message.Display( "%W", DeviceString );
|
|||
|
if( !DeviceArgument.IsValueSet() ) {
|
|||
|
DELETE( DevicePath );
|
|||
|
}
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get FSNODE of each file and put them in an array
|
|||
|
//
|
|||
|
PathArray = _Files.GetPathArray();
|
|||
|
DebugPtrAssert( PathArray );
|
|||
|
PathArrayIterator = ( PARRAY_ITERATOR )PathArray->QueryIterator();
|
|||
|
DebugPtrAssert( PathArrayIterator );
|
|||
|
|
|||
|
if( !_FsnFileArray.Initialize() ) {
|
|||
|
DebugAbort( "_FsnFileArray.Initialize() failed \n" );
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
while( ( FilePath = ( PPATH )PathArrayIterator->GetNext() ) != NULL ) {
|
|||
|
FsnFile = SYSTEM::QueryFile( FilePath );
|
|||
|
if( FsnFile != NULL ) {
|
|||
|
_FsnFileArray.Put( ( POBJECT )FsnFile );
|
|||
|
} else {
|
|||
|
FileString = FilePath->GetPathString();
|
|||
|
_Message.Set( MSG_PRINT_FILE_NOT_FOUND );
|
|||
|
_Message.Display( "%W", FileString );
|
|||
|
}
|
|||
|
}
|
|||
|
DELETE( PathArrayIterator );
|
|||
|
return( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
PRINT::PrintFiles(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Prints the files specified by the user.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - TRUE if all files were printed.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFSN_FILE FsnFile;
|
|||
|
PSTREAM FileStream;
|
|||
|
PARRAY_ITERATOR ArrayIterator;
|
|||
|
PBYTE Buffer;
|
|||
|
ULONG Size;
|
|||
|
ULONG BytesRead;
|
|||
|
ULONG BytesWritten;
|
|||
|
PCPATH FilePath;
|
|||
|
PCWSTRING FileName;
|
|||
|
INT _BufferStreamType;
|
|||
|
INT BytesConverted;
|
|||
|
INT cbStuff;
|
|||
|
LPSTR lpStuffANSI;
|
|||
|
BOOL fUsedDefault;
|
|||
|
|
|||
|
|
|||
|
Size = 512;
|
|||
|
Buffer = ( PBYTE )MALLOC( ( size_t )Size );
|
|||
|
lpStuffANSI = ( LPSTR )MALLOC( ( size_t )Size );
|
|||
|
if (Buffer == NULL || lpStuffANSI == NULL) {
|
|||
|
DebugPrint("PRINT: Out of memory\n");
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
ArrayIterator = ( PARRAY_ITERATOR )_FsnFileArray.QueryIterator();
|
|||
|
if (ArrayIterator == NULL) {
|
|||
|
DebugPrint("PRINT: ArrayIterator equals NULL\n");
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
while( ( FsnFile = ( PFSN_FILE )ArrayIterator->GetNext() ) != NULL ) {
|
|||
|
FileStream = ( PSTREAM )FsnFile->QueryStream( READ_ACCESS );
|
|||
|
if (FileStream == NULL) {
|
|||
|
DebugPrint("PRINT: FileStream equals NULL\n");
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
FileName = FsnFile->GetPath()->GetPathString();
|
|||
|
if( FileName != NULL ) {
|
|||
|
_Message.Set( MSG_PRINT_PRINTING );
|
|||
|
_Message.Display( "%W", FileName );
|
|||
|
}
|
|||
|
|
|||
|
_BufferStreamType = -1;
|
|||
|
while( !FileStream->IsAtEnd() ) {
|
|||
|
FileStream->Read( Buffer, Size, &BytesRead );
|
|||
|
// is file unicode?
|
|||
|
if (_BufferStreamType < 0) {
|
|||
|
if (IsTextUnicode((LPTSTR)Buffer, (INT)BytesRead,
|
|||
|
NULL) ) {
|
|||
|
_BufferStreamType = 1;
|
|||
|
} else {
|
|||
|
_BufferStreamType = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
// does the buffer need to be converted?
|
|||
|
if (_BufferStreamType == 1) {
|
|||
|
|
|||
|
cbStuff = Size;
|
|||
|
BytesConverted = WideCharToMultiByte(CP_ACP,0,
|
|||
|
(LPTSTR)Buffer,BytesRead/sizeof(WCHAR),
|
|||
|
lpStuffANSI,cbStuff,NULL,&fUsedDefault) ;
|
|||
|
DebugAssert(cbStuff>0);
|
|||
|
DebugAssert(BytesConverted >= 0);
|
|||
|
_Printer.Write((PBYTE)lpStuffANSI,BytesConverted,&BytesWritten );
|
|||
|
} else {
|
|||
|
_Printer.Write( Buffer, BytesRead, &BytesWritten );
|
|||
|
}
|
|||
|
}
|
|||
|
_Printer.WriteByte( '\f' );
|
|||
|
DELETE( FileStream );
|
|||
|
}
|
|||
|
DELETE( ArrayIterator );
|
|||
|
return( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PRINT::Terminate(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Deletes objects created during initialization.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ULONG __cdecl
|
|||
|
main()
|
|||
|
|
|||
|
{
|
|||
|
DEFINE_CLASS_DESCRIPTOR( PRINT );
|
|||
|
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
PRINT Print;
|
|||
|
|
|||
|
|
|||
|
if( Print.Initialize() ) {
|
|||
|
Print.PrintFiles();
|
|||
|
}
|
|||
|
// Print.Terminate();
|
|||
|
return( 0 );
|
|||
|
}
|
|||
|
}
|