Files
harbour-core/harbour/contrib/win32/tprinter.c
Przemyslaw Czerpak 2bc540f378 2007-10-23 10:12 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/contrib/win32/tprinter.c
    * casting
2007-10-23 08:12:57 +00:00

669 lines
24 KiB
C

/*
* $Id$
*/
/*
* Harbour Project source code:
* Tprinter.cpp
* Harbour THarbourPrinter C++ Class for Harbour print support
* Copyright 2002 Luiz Rafael Culik<culikr@uol.com.br>
* www - http://www.harbour-project.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#include "hbsetup.h"
#if defined(HB_OS_WIN_32) && \
!( defined(__RSXNT__) || defined(__CYGWIN__) || defined(HB_WINCE) )
# include <windows.h>
# if defined(__LCC__)
# include <winspool.h>
# endif
# define HB_OS_WIN_32_USED
# include "hbapi.h"
# include "hbapiitm.h"
BOOL hb_GetDefaultPrinter( char * pPrinterName, LPDWORD pdwBufferSize );
BOOL hb_GetPrinterNameByPort( char * pPrinterName, LPDWORD pdwBufferSize, char * pPortName,
BOOL bSubStr );
# define MAXBUFFERSIZE 255
BOOL hb_isLegacyDevice( LPSTR pPrinterName )
{
BOOL bLegacyDev = FALSE;
int n = 0;
LPSTR pszPrnDev[] =
{ "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "com1", "com2", "com3", "com4", NULL };
while( pszPrnDev[n] && !bLegacyDev )
{
bLegacyDev = ( hb_strnicmp( pPrinterName, pszPrnDev[n], strlen( pszPrnDev[n] ) ) == 0 );
n++;
}
return ( bLegacyDev );
}
BOOL hb_PrinterExists( LPSTR pPrinterName )
{
BOOL Result = FALSE;
DWORD Flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;
PRINTER_INFO_4 *buffer4, *pPrinterEnum4;
HANDLE hPrinter;
ULONG needed = 0, returned = 0, a;
HB_TRACE( HB_TR_DEBUG, ( "hb_PrinterExists(%s)", pPrinterName ) );
if( !strchr( pPrinterName, OS_PATH_LIST_SEPARATOR ) && !hb_isLegacyDevice( pPrinterName ) )
{ // Don't bother with test if '\' in string
if( hb_iswinnt() )
{ // Use EnumPrinter() here because much faster than OpenPrinter()
EnumPrinters( Flags, NULL, 4, ( LPBYTE ) NULL, 0, &needed, &returned );
if( needed > 0 )
{
pPrinterEnum4 = buffer4 = ( PRINTER_INFO_4 * ) hb_xgrab( needed );
if( pPrinterEnum4 )
{
if( EnumPrinters
( Flags, NULL, 4, ( LPBYTE ) pPrinterEnum4, needed, &needed, &returned ) )
{
for( a = 0; !Result && a < returned; a++, pPrinterEnum4++ )
{
Result = strcmp( ( const char * ) pPrinterName,
( const char * ) pPrinterEnum4->pPrinterName ) == 0;
}
}
hb_xfree( buffer4 );
}
}
}
else
{
LPTSTR lpPrinterName = HB_TCHAR_CONVTO( pPrinterName );
if( OpenPrinter( lpPrinterName, &hPrinter, NULL ) )
{
ClosePrinter( hPrinter );
Result = TRUE;
}
HB_TCHAR_FREE( lpPrinterName );
}
}
return Result;
}
HB_FUNC( PRINTEREXISTS )
{
BOOL Result = FALSE;
if( ISCHAR( 1 ) )
{
Result = hb_PrinterExists( hb_parc( 1 ) );
}
hb_retl( Result );
}
BOOL hb_GetDefaultPrinter( char * pPrinterName, LPDWORD pdwBufferSize )
{
BOOL Result = FALSE;
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
GetVersionEx( &osvi );
if( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5 ) /* Windows 2000 or later */
{
typedef BOOL( WINAPI * DEFPRINTER ) ( LPSTR, LPDWORD ); // stops warnings
DEFPRINTER fnGetDefaultPrinter;
HMODULE hWinSpool = LoadLibrary( TEXT( "winspool.drv" ) );
if( hWinSpool )
{
fnGetDefaultPrinter = ( DEFPRINTER ) GetProcAddress( hWinSpool, "GetDefaultPrinterA" );
if( fnGetDefaultPrinter )
{
Result = ( *fnGetDefaultPrinter ) ( pPrinterName, pdwBufferSize );
}
FreeLibrary( hWinSpool );
}
}
if( !Result ) /* Win9X and Windows NT 4.0 or earlier & 2000+ if necessary for some reason i.e. dll could not load!!!! */
{
DWORD dwSize = GetProfileStringA( "windows", "device", "", pPrinterName, *pdwBufferSize );
if( dwSize && dwSize < *pdwBufferSize )
{
dwSize = 0;
while( pPrinterName[dwSize] != '\0' && pPrinterName[dwSize] != ',' )
{
dwSize++;
}
pPrinterName[dwSize] = '\0';
*pdwBufferSize = dwSize + 1;
Result = TRUE;
}
else
{
*pdwBufferSize = dwSize + 1;
}
}
if( !Result && osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
{
/*
This option should never be required but is included because of this article
http://support.microsoft.com/kb/246772/en-us
This option will not enumerate any network printers.
From the SDK technical reference for EnumPrinters();
If Level is 2 or 5, Name is a pointer to a null-terminated string that specifies
the name of a server whose printers are to be enumerated.
If this string is NULL, then the function enumerates the printers installed on the local machine.
*/
DWORD dwNeeded, dwReturned;
PRINTER_INFO_2 *ppi2;
if( EnumPrinters( PRINTER_ENUM_DEFAULT, NULL, 2, NULL, 0, &dwNeeded, &dwReturned ) )
{
if( dwNeeded > 0 )
{
ppi2 = ( PRINTER_INFO_2 * ) hb_xgrab( dwNeeded );
if( ppi2 )
{
if( EnumPrinters
( PRINTER_ENUM_DEFAULT, NULL, 2, ( LPBYTE ) ppi2, dwNeeded, &dwNeeded,
&dwReturned ) && dwReturned > 0 )
{
DWORD dwSize = ( DWORD ) lstrlen( ppi2->pPrinterName );
if( dwSize && dwSize < *pdwBufferSize )
{
HB_TCHAR_GETFROM( pPrinterName, ppi2->pPrinterName,
lstrlen( ppi2->pPrinterName ) );
*pdwBufferSize = dwSize + 1;
Result = TRUE;
}
}
hb_xfree( ppi2 );
}
}
}
}
return ( Result );
}
HB_FUNC( GETDEFAULTPRINTER )
{
char szDefaultPrinter[MAXBUFFERSIZE];
DWORD pdwBufferSize = MAXBUFFERSIZE;
if( hb_GetDefaultPrinter( szDefaultPrinter, &pdwBufferSize ) )
{
hb_retclen( szDefaultPrinter, pdwBufferSize - 1 );
}
else
{
hb_retc( NULL );
}
}
BOOL hb_GetPrinterNameByPort( char * pPrinterName, LPDWORD pdwBufferSize,
char * pPortName, BOOL bSubStr )
{
BOOL Result = FALSE, bFound = FALSE;
ULONG needed, returned, a;
PRINTER_INFO_5 *pPrinterEnum, *buffer;
HB_TRACE( HB_TR_DEBUG, ( "hb_GetPrinterNameByPort(%p,%p)", pPrinterName, pPortName ) );
EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 5, ( LPBYTE ) NULL, 0,
&needed, &returned );
if( needed > 0 )
{
pPrinterEnum = buffer = ( PRINTER_INFO_5 * ) hb_xgrab( needed );
if( EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 5,
( LPBYTE ) buffer, needed, &needed, &returned ) )
{
for( a = 0; a < returned && !bFound; a++, pPrinterEnum++ )
{
char * szPortName = HB_TCHAR_CONVFROM( pPrinterEnum->pPortName );
if( bSubStr )
{
bFound = hb_strnicmp( szPortName, pPortName, strlen( pPortName ) ) == 0;
}
else
{
bFound = ( hb_stricmp( szPortName, pPortName ) == 0 );
}
HB_TCHAR_FREE( szPortName );
if( bFound )
{
char * szPrinterName = HB_TCHAR_CONVFROM( pPrinterEnum->pPrinterName );
if( *pdwBufferSize >= strlen( szPrinterName ) + 1 )
{
strcpy( pPrinterName, szPrinterName );
Result = TRUE;
}
/* Store name length + \0 char for return */
*pdwBufferSize = ( DWORD ) strlen( szPrinterName ) + 1;
HB_TCHAR_FREE( szPrinterName );
}
}
}
hb_xfree( buffer );
}
return Result;
}
HB_FUNC( PRINTERPORTTONAME )
{
char szDefaultPrinter[MAXBUFFERSIZE];
DWORD pdwBufferSize = MAXBUFFERSIZE;
if( ISCHAR( 1 ) && hb_parclen( 1 ) > 0 &&
hb_GetPrinterNameByPort( szDefaultPrinter, &pdwBufferSize, hb_parcx( 1 ),
ISLOG( 2 ) ? hb_parl( 2 ) : FALSE ) )
{
hb_retc( szDefaultPrinter );
}
else
{
hb_retc( NULL );
}
}
# define BIG_PRINT_BUFFER (1024*32)
LONG hb_PrintFileRaw( UCHAR * cPrinterName, UCHAR * cFileName, UCHAR * cDocName )
{
UCHAR printBuffer[BIG_PRINT_BUFFER];
HANDLE hPrinter, hFile;
DOC_INFO_1 DocInfo;
DWORD nRead, nWritten, Result;
LPTSTR lpPrinterName = HB_TCHAR_CONVTO( ( char * ) cPrinterName );
if( OpenPrinter( lpPrinterName, &hPrinter, NULL ) != 0 )
{
LPTSTR lpDocName = HB_TCHAR_CONVTO( ( char * ) cDocName );
DocInfo.pDocName = lpDocName;
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = TEXT( "RAW" );
if( StartDocPrinter( hPrinter, 1, ( UCHAR * ) & DocInfo ) != 0 )
{
if( StartPagePrinter( hPrinter ) != 0 )
{
hFile =
CreateFileA( ( char * ) cFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
while( ReadFile( hFile, printBuffer, BIG_PRINT_BUFFER, &nRead, NULL )
&& ( nRead > 0 ) )
{
if( printBuffer[nRead - 1] == 26 )
{
nRead--; // Skip the EOF() character
}
WritePrinter( hPrinter, printBuffer, nRead, &nWritten );
}
Result = 1;
CloseHandle( hFile );
}
else
{
Result = -6;
}
EndPagePrinter( hPrinter );
}
else
{
Result = -4;
}
EndDocPrinter( hPrinter );
}
else
{
Result = -3;
}
HB_TCHAR_FREE( lpDocName );
ClosePrinter( hPrinter );
}
else
{
Result = -2;
}
HB_TCHAR_FREE( lpPrinterName );
return Result;
}
HB_FUNC( PRINTFILERAW )
{
UCHAR *cPrinterName, *cFileName, *cDocName;
DWORD Result = -1;
if( ISCHAR( 1 ) && ISCHAR( 2 ) )
{
cPrinterName = ( UCHAR * ) hb_parcx( 1 );
cFileName = ( UCHAR * ) hb_parcx( 2 );
cDocName = ( ISCHAR( 3 ) ? ( UCHAR * ) hb_parcx( 3 ) : cFileName );
Result = hb_PrintFileRaw( cPrinterName, cFileName, cDocName );
}
hb_retnl( Result );
}
HB_FUNC( GETPRINTERS )
{
HANDLE hPrinter;
DWORD Flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;
BOOL bPrinterNamesOnly = TRUE;
BOOL bLocalPrintersOnly;
PRINTER_INFO_4 *buffer4, *pPrinterEnum4;
PRINTER_INFO_5 *buffer, *pPrinterEnum;
PRINTER_INFO_2 *pPrinterInfo2;
ULONG needed = 0, returned = 0, a;
PHB_ITEM SubItems, File, Port, Net, Driver, ArrayPrinter;
char *pszData;
ArrayPrinter = hb_itemNew( NULL );
SubItems = hb_itemNew( NULL );
File = hb_itemNew( NULL );
Port = hb_itemNew( NULL );
Net = hb_itemNew( NULL );
Driver = hb_itemNew( NULL );
hb_arrayNew( ArrayPrinter, 0 );
buffer = NULL;
HB_TRACE( HB_TR_DEBUG, ( "GETPRINTERS()" ) );
if( ISLOG( 1 ) )
{
bPrinterNamesOnly = !hb_parl( 1 );
}
bLocalPrintersOnly = ISLOG( 2 ) ? hb_parl( 2 ) : FALSE;
if( hb_iswinnt() )
{
EnumPrinters( Flags, NULL, 4, ( LPBYTE ) NULL, 0, &needed, &returned );
if( needed > 0 )
{
pPrinterEnum4 = buffer4 = ( PRINTER_INFO_4 * ) hb_xgrab( needed );
if( pPrinterEnum4 )
{
if( EnumPrinters
( Flags, NULL, 4, ( LPBYTE ) pPrinterEnum4, needed, &needed, &returned ) )
{
if( bPrinterNamesOnly )
{
for( a = 0; a < returned; a++, pPrinterEnum4++ )
{
if( !bLocalPrintersOnly
|| pPrinterEnum4->Attributes & PRINTER_ATTRIBUTE_LOCAL )
{
pszData = HB_TCHAR_CONVFROM( pPrinterEnum4->pPrinterName );
hb_itemPutC( File, pszData );
HB_TCHAR_FREE( pszData );
hb_arrayAddForward( ArrayPrinter, File );
}
}
}
else
{
for( a = 0; a < returned; a++, pPrinterEnum4++ )
{
if( !bLocalPrintersOnly
|| pPrinterEnum4->Attributes & PRINTER_ATTRIBUTE_LOCAL )
{
if( OpenPrinter( pPrinterEnum4->pPrinterName, &hPrinter, NULL ) )
{
GetPrinter( hPrinter, 2, NULL, 0, &needed );
if( needed > 0 )
{
pPrinterInfo2 = ( PRINTER_INFO_2 * ) hb_xgrab( needed );
if( pPrinterInfo2 )
{
pszData = HB_TCHAR_CONVFROM( pPrinterEnum4->pPrinterName );
hb_itemPutC( File, pszData );
HB_TCHAR_FREE( pszData );
hb_arrayNew( SubItems, 0 );
if( GetPrinter
( hPrinter, 2, ( LPBYTE ) pPrinterInfo2, needed, &needed ) )
{
pszData = HB_TCHAR_CONVFROM( pPrinterInfo2->pPortName );
hb_itemPutC( Port, pszData );
HB_TCHAR_FREE( pszData );
pszData = HB_TCHAR_CONVFROM( pPrinterInfo2->pDriverName );
hb_itemPutC( Driver, pszData );
HB_TCHAR_FREE( pszData );
}
else
{
hb_itemPutC( Port, "Error" );
hb_itemPutC( Driver, "Error" );
}
if( pPrinterEnum4->Attributes & PRINTER_ATTRIBUTE_LOCAL )
{
hb_itemPutC( Net, "LOCAL" );
}
else
{
if( pPrinterEnum4->Attributes & PRINTER_ATTRIBUTE_NETWORK )
{
hb_itemPutC( Net, "NETWORK" );
}
else
{
hb_itemPutC( Net, "ERROR" );
}
}
hb_arrayAddForward( SubItems, File );
hb_arrayAddForward( SubItems, Port );
hb_arrayAddForward( SubItems, Net );
hb_arrayAddForward( SubItems, Driver );
hb_arrayAddForward( ArrayPrinter, SubItems );
hb_xfree( pPrinterInfo2 );
}
}
}
CloseHandle( hPrinter );
}
}
}
}
hb_xfree( buffer4 );
}
}
}
else
{
EnumPrinters( Flags, NULL, 5, ( LPBYTE ) buffer, 0, &needed, &returned );
if( needed > 0 )
{
pPrinterEnum = buffer = ( PRINTER_INFO_5 * ) hb_xgrab( needed );
if( pPrinterEnum )
{
if( EnumPrinters( Flags, NULL, 5, ( LPBYTE ) buffer, needed, &needed, &returned ) )
{
for( a = 0; a < returned; a++, pPrinterEnum++ )
{
if( !bLocalPrintersOnly || pPrinterEnum->Attributes & PRINTER_ATTRIBUTE_LOCAL )
{
if( bPrinterNamesOnly )
{
pszData = HB_TCHAR_CONVFROM( pPrinterEnum->pPrinterName );
hb_itemPutC( File, pszData );
HB_TCHAR_FREE( pszData );
hb_arrayAddForward( ArrayPrinter, File );
}
else
{
// Tony (ABC) 11/1/2005 1:40PM.
for( a = 0; a < returned; a++, pPrinterEnum++ )
{
if( !bLocalPrintersOnly
|| pPrinterEnum->Attributes & PRINTER_ATTRIBUTE_LOCAL )
{
if( OpenPrinter( pPrinterEnum->pPrinterName, &hPrinter, NULL ) )
{
GetPrinter( hPrinter, 2, NULL, 0, &needed );
if( needed > 0 )
{
pPrinterInfo2 = ( PRINTER_INFO_2 * ) hb_xgrab( needed );
if( pPrinterInfo2 )
{
hb_arrayNew( SubItems, 0 );
pszData = HB_TCHAR_CONVFROM( pPrinterEnum->pPrinterName );
hb_itemPutC( File, pszData );
HB_TCHAR_FREE( pszData );
if( GetPrinter
( hPrinter, 2, ( LPBYTE ) pPrinterInfo2, needed,
&needed ) )
{
pszData = HB_TCHAR_CONVFROM( pPrinterInfo2->pPortName );
hb_itemPutC( Port, pszData );
HB_TCHAR_FREE( pszData );
pszData = HB_TCHAR_CONVFROM( pPrinterInfo2->pDriverName );
hb_itemPutC( Driver, pszData );
HB_TCHAR_FREE( pszData );
}
else
{
hb_itemPutC( Port, "Error" );
hb_itemPutC( Driver, "Error" );
}
if( pPrinterEnum->Attributes & PRINTER_ATTRIBUTE_LOCAL )
{
hb_itemPutC( Net, "LOCAL" );
}
else
{
if( pPrinterEnum->Attributes & PRINTER_ATTRIBUTE_NETWORK )
{
hb_itemPutC( Net, "NETWORK" );
}
else
{
hb_itemPutC( Net, "ERROR" );
}
}
hb_arrayAddForward( SubItems, File );
hb_arrayAddForward( SubItems, Port );
hb_arrayAddForward( SubItems, Net );
hb_arrayAddForward( SubItems, Driver );
hb_arrayAddForward( ArrayPrinter, SubItems );
hb_xfree( pPrinterInfo2 );
}
}
}
CloseHandle( hPrinter );
}
}
// Tony (ABC) 11/1/2005 1:40PM. Old Code... Justo in case.
// hb_arrayNew( SubItems, 0 );
// hb_itemPutC( File, pPrinterEnum->pPrinterName );
// hb_itemPutC( Port, pPrinterEnum->pPortName );
// if ( pPrinterEnum->Attributes & PRINTER_ATTRIBUTE_LOCAL)
// {
// hb_itemPutC( Net,"LOCAL" );
// }
// else
// {
// if ( pPrinterEnum->Attributes & PRINTER_ATTRIBUTE_NETWORK)
// {
// hb_itemPutC( Net,"NETWORK" );
// }
// else
// {
// hb_itemPutC( Net, "ERROR" );
// }
// }
// hb_arrayAddForward( SubItems , File ) ;
// hb_arrayAddForward( SubItems , Port ) ;
// hb_arrayAddForward( SubItems, Net ) ;
// hb_arrayAddForward( ArrayPrinter , SubItems );
}
}
}
}
hb_xfree( buffer );
}
}
}
hb_itemReturnForward( ArrayPrinter );
hb_itemRelease( ArrayPrinter );
hb_itemRelease( SubItems );
hb_itemRelease( File );
hb_itemRelease( Port );
hb_itemRelease( Net );
hb_itemRelease( Driver );
}
#endif