windows-nt/Source/XPSP1/NT/ds/netapi/dosprint/dosspool.c
2020-09-26 16:20:57 +08:00

729 lines
18 KiB
C

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
dosspool.c
Abstract:
Contains the entry points for the functions that live in a
separate DLL. The entry points are made available here, but
will not load the WINSPOOL.DRV until it is needed.
Contains:
Author:
Congpa You (CongpaY) 22-Jan-1993
Environment:
Notes:
Revision History:
--*/
#include <windows.h>
#include <netdebug.h> // NetpAssert()
#include "dosspool.h"
#include "myspool.h"
/*
* global defines.
*/
#define WINSPOOL_DLL_NAME TEXT("WINSPOOL.DRV")
/*
* global data.
*
* here we store handles to the MPRUI dll and pointers to the function
* all of below is protect in multi threaded case with MprLoadLibSemaphore.
*/
HINSTANCE vhWinspoolDll = NULL ;
PF_ClosePrinter pfClosePrinter = NULL ;
PF_EnumJobsA pfEnumJobsA = NULL ;
PF_EnumPrintersA pfEnumPrintersA = NULL ;
PF_GetJobA pfGetJobA = NULL ;
PF_GetPrinterA pfGetPrinterA = NULL ;
PF_OpenPrinterA pfOpenPrinterA = NULL ;
PF_OpenPrinterW pfOpenPrinterW = NULL ;
PF_SetJobA pfSetJobA = NULL ;
PF_SetPrinterW pfSetPrinterW = NULL ;
PF_GetPrinterDriverA pfGetPrinterDriverA = NULL;
/*
* global functions
*/
BOOL MakeSureDllIsLoaded(void) ;
/*******************************************************************
NAME: GetFileNameA
SYNOPSIS: Gets the filename part from a fully qualified path
HISTORY:
MuhuntS 06-Feb-1996 Created
********************************************************************/
LPSTR
GetFileNameA(
LPSTR pPathName
)
{
LPSTR pSlash = pPathName, pTemp;
if ( pSlash ) {
while ( pTemp = strchr(pSlash, '\\') )
pSlash = pTemp+1;
if ( !*pSlash )
pSlash = NULL;
NetpAssert(pSlash != NULL);
}
return pSlash;
}
/*******************************************************************
NAME: GetDependentFileNameA
SYNOPSIS: Gets the dependent filename to send to Win95. Normally just
the file name part. But for ICM files this would be
Color\<filename>
HISTORY:
MuhuntS 23-Apr-1997 Created
********************************************************************/
LPSTR
GetDependentFileNameA(
LPSTR pPathName
)
{
LPSTR pRet = GetFileNameA(pPathName), p;
if (pRet)
{
DWORD dwLen = strlen(pRet);
p = pRet+dwLen-4;
if ( dwLen > 3 &&
( !_stricmp(p, ".ICM") ||
!_stricmp(p, ".ICC") ) &&
(p = pRet - 7) > pPathName &&
!_strnicmp(p, "\\Color\\", 7) ) {
pRet = p + 1;
}
}
return pRet;
}
/*******************************************************************
NAME: MyClosePrinter
SYNOPSIS: calls thru to the superset function
HISTORY:
CongpaY 22-Jan-1993 Created
********************************************************************/
BOOL MyClosePrinter (HANDLE hPrinter)
{
PF_ClosePrinter pfTemp;
// if function has not been used before, get its address.
if (pfClosePrinter == NULL)
{
// make sure DLL Is loaded
if (!MakeSureDllIsLoaded())
{
return(FALSE) ;
}
pfTemp = (PF_ClosePrinter)
GetProcAddress(vhWinspoolDll,
"ClosePrinter") ;
if (pfTemp == NULL)
{
return(FALSE);
}
else
{
pfClosePrinter = pfTemp;
}
}
return ((*pfClosePrinter)(hPrinter));
}
/*******************************************************************
NAME: MyEnumJobs
SYNOPSIS: calls thru to the superset function
NOTES: This is defined ANSI version. If change to UNICODE version
in the future, you should change the code to make it call
UNICODE version!!!
HISTORY:
CongpaY 22-Jan-1993 Created
********************************************************************/
BOOL MyEnumJobs (HANDLE hPrinter,
DWORD FirstJob,
DWORD NoJobs,
DWORD Level,
LPBYTE pJob,
DWORD cbBuf,
LPDWORD pcbNeeded,
LPDWORD pcReturned)
{
PF_EnumJobsA pfTemp;
// if function has not been used before, get its address.
if (pfEnumJobsA == NULL)
{
// make sure DLL Is loaded
if (!MakeSureDllIsLoaded())
{
return(FALSE) ;
}
pfTemp = (PF_EnumJobsA)
GetProcAddress(vhWinspoolDll,
"EnumJobsA") ;
if (pfTemp == NULL)
{
return(FALSE);
}
else
{
pfEnumJobsA = pfTemp;
}
}
return ((*pfEnumJobsA)(hPrinter,
FirstJob,
NoJobs,
Level,
pJob,
cbBuf,
pcbNeeded,
pcReturned));
}
/*******************************************************************
NAME: MyEnumPrinters
SYNOPSIS: calls thru to the superset function
HISTORY:
CongpaY 22-Jan-1993 Created
********************************************************************/
BOOL MyEnumPrinters(DWORD Flags,
LPSTR Name,
DWORD Level,
LPBYTE pPrinterEnum,
DWORD cbBuf,
LPDWORD pcbNeeded,
LPDWORD pcReturned)
{
PF_EnumPrintersA pfTemp;
// if function has not been used before, get its address.
if (pfEnumPrintersA == NULL)
{
// make sure DLL Is loaded
if (!MakeSureDllIsLoaded())
{
return(FALSE) ;
}
pfTemp = (PF_EnumPrintersA)
GetProcAddress(vhWinspoolDll,
"EnumPrintersA") ;
if (pfTemp == NULL)
{
return(TRUE);
}
else
pfEnumPrintersA = pfTemp;
}
return ((*pfEnumPrintersA)(Flags,
Name,
Level,
pPrinterEnum,
cbBuf,
pcbNeeded,
pcReturned));
}
/*******************************************************************
NAME: MyGetJobA
SYNOPSIS: calls thru to the superset function
HISTORY:
CongpaY 22-Jan-1993 Created
********************************************************************/
BOOL MyGetJobA(HANDLE hPrinter,
DWORD JobId,
DWORD Level,
LPBYTE pJob,
DWORD cbBuf,
LPDWORD pcbNeeded)
{
PF_GetJobA pfTemp;
// if function has not been used before, get its address.
if (pfGetJobA == NULL)
{
// make sure DLL Is loaded
if (!MakeSureDllIsLoaded())
{
return(FALSE) ;
}
pfTemp = (PF_GetJobA)
GetProcAddress(vhWinspoolDll,
"GetJobA") ;
if (pfTemp == NULL)
{
return(FALSE);
}
else
pfGetJobA = pfTemp;
}
return ((*pfGetJobA)(hPrinter,
JobId,
Level,
pJob,
cbBuf,
pcbNeeded));
}
/*******************************************************************
NAME: MyGetPrinter
SYNOPSIS: calls thru to the superset function
HISTORY:
CongpaY 22-Jan-1993 Created
********************************************************************/
BOOL MyGetPrinter (HANDLE hPrinter,
DWORD Level,
LPBYTE pPrinter,
DWORD cbBuf,
LPDWORD pcbNeeded)
{
PF_GetPrinterA pfTemp;
LPSTR pszDriverName = NULL;
DWORD cbDriverName = 0;
BOOL bRet;
// if function has not been used before, get its address.
if (pfGetPrinterA == NULL)
{
// make sure DLL Is loaded
if (!MakeSureDllIsLoaded())
{
return(FALSE) ;
}
pfTemp = (PF_GetPrinterA)
GetProcAddress(vhWinspoolDll,
"GetPrinterA") ;
if (pfTemp == NULL)
{
return(FALSE);
}
else
pfGetPrinterA = pfTemp;
}
//
// Win95 driver name could be different than NT. If it is different AND
// the win95 driver with the different name is installed we want to send
// that name to Win9x client
//
if ( Level == 2 ) {
DWORD dwNeeded = 0;
// Check the size of the name and make sure that we copy the printer driver name to the
// beginning of the buffer. The previous code would let the GetPrinterDriver call determine
// where to put it which could result in the strcpy copying data from one string on top of another
// if the call used the end of the buffer like we plan on using. We address this by doing an STRNCPY to
// make sure we don't start doing an infinite copy and also make sure our buffers don't overlap with
// an assert.
bRet = MyGetPrinterDriver(hPrinter,
WIN95_ENVIRONMENT,
1,
NULL,
0,
&dwNeeded);
if( dwNeeded <= cbBuf )
{
if( MyGetPrinterDriver( hPrinter,
WIN95_ENVIRONMENT,
1,
pPrinter,
dwNeeded,
pcbNeeded ))
{
pszDriverName = ((LPDRIVER_INFO_1A)pPrinter)->pName;
cbDriverName = (strlen(pszDriverName) + 1) * sizeof(CHAR);
NetpAssert( pszDriverName + cbDriverName < pPrinter + cbBuf - cbDriverName );
strncpy((LPSTR)(pPrinter + cbBuf - cbDriverName), pszDriverName, cbDriverName);
pszDriverName = (LPSTR)(pPrinter + cbBuf - cbDriverName);
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER )
{
//
// DRIVER_INFO_1 has pDriverName only. So if we fail with
// insufficient buffer GetPrinter is guaranteed to fail too.
// If we use a different level that may not be TRUE
//
cbDriverName = *pcbNeeded - sizeof(DRIVER_INFO_1A);
}
}
else
{
cbDriverName = dwNeeded - sizeof(DRIVER_INFO_1A);
}
}
if( cbBuf > cbDriverName )
{
bRet = pfGetPrinterA(hPrinter, Level, pPrinter, cbBuf-cbDriverName, pcbNeeded);
}
else
{
bRet = pfGetPrinterA(hPrinter, Level, pPrinter, 0, pcbNeeded);
}
if ( Level != 2 )
return bRet;
if ( bRet ) {
if ( pszDriverName ) {
((LPPRINTER_INFO_2A)pPrinter)->pDriverName = pszDriverName;
*pcbNeeded += cbDriverName;
}
} else if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
*pcbNeeded += cbDriverName;
}
return bRet;
}
/*******************************************************************
NAME: MyOpenPrinterA
SYNOPSIS: calls thru to the superset function
HISTORY:
CongpaY 22-Jan-1993 Created
********************************************************************/
BOOL MyOpenPrinterA(LPSTR pPrinterName,
LPHANDLE phPrinter,
LPPRINTER_DEFAULTSA pDefault)
{
PF_OpenPrinterA pfTemp;
// if function has not been used before, get its address.
if (pfOpenPrinterA == NULL)
{
// make sure DLL Is loaded
if (!MakeSureDllIsLoaded())
{
return(FALSE) ;
}
pfTemp = (PF_OpenPrinterA)
GetProcAddress(vhWinspoolDll,
"OpenPrinterA") ;
if (pfTemp == NULL)
{
return(FALSE);
}
else
pfOpenPrinterA = pfTemp;
}
return ((*pfOpenPrinterA)(pPrinterName,
phPrinter,
pDefault));
}
/*******************************************************************
NAME: MyOpenPrinterW
SYNOPSIS: calls thru to the superset function
HISTORY:
CongpaY 22-Jan-1993 Created
********************************************************************/
BOOL MyOpenPrinterW (LPWSTR pPrinterName,
LPHANDLE phPrinter,
LPPRINTER_DEFAULTSW pDefault)
{
PF_OpenPrinterW pfTemp;
// if function has not been used before, get its address.
if (pfOpenPrinterW == NULL)
{
// make sure DLL Is loaded
if (!MakeSureDllIsLoaded())
{
return(FALSE) ;
}
pfTemp = (PF_OpenPrinterW)
GetProcAddress(vhWinspoolDll,
"OpenPrinterW") ;
if (pfTemp == NULL)
{
return(FALSE);
}
else
pfOpenPrinterW = pfTemp;
}
return ((*pfOpenPrinterW)(pPrinterName,
phPrinter,
pDefault));
}
/*******************************************************************
NAME: MySetJobA
SYNOPSIS: calls thru to the superset function
HISTORY:
CongpaY 22-Jan-1993 Created
AlbertT 24-Mar-1995 AddedLevel and pJob
********************************************************************/
BOOL MySetJobA (HANDLE hPrinter,
DWORD JobId,
DWORD Level,
LPBYTE pJob,
DWORD Command)
{
PF_SetJobA pfTemp;
// if function has not been used before, get its address.
if (pfSetJobA == NULL)
{
// make sure DLL Is loaded
if (!MakeSureDllIsLoaded())
{
return(FALSE) ;
}
pfTemp = (PF_SetJobA)
GetProcAddress(vhWinspoolDll,
"SetJobA") ;
if (pfTemp == NULL)
{
return(FALSE);
}
else
pfSetJobA = pfTemp;
}
return ((*pfSetJobA)(hPrinter,
JobId,
Level,
pJob,
Command));
}
/*******************************************************************
NAME: MySetPrinterW
SYNOPSIS: calls thru to the superset function
HISTORY:
AlbertT 23-Mar-1995 Created
********************************************************************/
BOOL MySetPrinterW(HANDLE hPrinter,
DWORD Level,
LPBYTE pPrinter,
DWORD Command)
{
PF_SetPrinterW pfTemp;
// if function has not been used before, get its address.
if (pfSetPrinterW == NULL)
{
// make sure DLL Is loaded
if (!MakeSureDllIsLoaded())
{
return(FALSE) ;
}
pfTemp = (PF_SetPrinterW)
GetProcAddress(vhWinspoolDll,
"SetPrinterW") ;
if (pfTemp == NULL)
{
return(FALSE);
}
else
pfSetPrinterW = pfTemp;
}
return ((*pfSetPrinterW)(hPrinter,
Level,
pPrinter,
Command));
}
/*******************************************************************
NAME: MyGetPrinterDriver
SYNOPSIS: calls thru to the superset function
HISTORY:
MuhuntS 06-Feb-1996 Created
********************************************************************/
BOOL
MyGetPrinterDriver(
HANDLE hPrinter,
LPSTR pEnvironment,
DWORD Level,
LPBYTE pDriver,
DWORD cbBuf,
LPDWORD pcbNeeded
)
{
//
// if function has not been used before, get its address.
//
if ( !pfGetPrinterDriverA ) {
//
// If dll is not loaded yet load it
//
if ( !MakeSureDllIsLoaded() ) {
return FALSE;
}
(FARPROC) pfGetPrinterDriverA = GetProcAddress(vhWinspoolDll,
"GetPrinterDriverA");
if ( !pfGetPrinterDriverA )
return FALSE;
}
return ((*pfGetPrinterDriverA)(hPrinter,
pEnvironment,
Level,
pDriver,
cbBuf,
pcbNeeded));
}
/*******************************************************************
NAME: MakeSureDllIsLoaded
SYNOPSIS: loads the WINSPOOL dll if need.
EXIT: returns TRUE if dll already loaded, or loads
successfully. Returns false otherwise. Caller
should call GetLastError() to determine error.
NOTES: it is up to the caller to call EnterLoadLibCritSect
before he calls this.
HISTORY:
chuckc 29-Jul-1992 Created
congpay 22-Jan-1993 Modified.
********************************************************************/
BOOL MakeSureDllIsLoaded(void)
{
HINSTANCE handle ;
// if already load, just return TRUE
if (vhWinspoolDll != NULL)
return TRUE ;
// load the library. if it fails, it would have done a SetLastError.
handle = LoadLibrary(WINSPOOL_DLL_NAME);
if (handle == NULL)
return FALSE ;
// we are cool.
vhWinspoolDll = handle ;
return TRUE ;
}