Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

426 lines
13 KiB

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