/*++ 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 #include } 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 ); } }