873 lines
22 KiB
C
873 lines
22 KiB
C
/*++
|
|
|
|
Copyright (c) 1990-1994 Microsoft Corporation
|
|
All rights reserved
|
|
|
|
Module Name:
|
|
|
|
spooler.c
|
|
|
|
Abstract:
|
|
|
|
|
|
Author:
|
|
|
|
Environment:
|
|
|
|
User Mode -Win32
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "winsprlp.h"
|
|
//
|
|
// RPC Buffer size 64K
|
|
//
|
|
#define BUFFER_SIZE 0x10000
|
|
|
|
|
|
DWORD
|
|
StartDocPrinterW(
|
|
HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pDocInfo)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpStartDocPrinter)
|
|
(pPrintHandle->hPrinter,
|
|
Level, pDocInfo);
|
|
}
|
|
|
|
BOOL
|
|
StartPagePrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpStartPagePrinter)
|
|
(pPrintHandle->hPrinter);
|
|
}
|
|
|
|
BOOL
|
|
SplCommitSpoolData(
|
|
HANDLE hPrinter,
|
|
HANDLE hAppProcess,
|
|
DWORD cbCommit,
|
|
DWORD dwLevel,
|
|
LPBYTE pSpoolFileInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded
|
|
)
|
|
|
|
/*++
|
|
Function Description: Commits data written into the spool file. creates a new temp
|
|
file handle for remote printing.
|
|
|
|
Parameters: hPrinter - printer handle
|
|
hAppProcess - application process handle
|
|
cbCommit - number of bytes to commit (incremental)
|
|
dwLevel - spoolfileinfo level
|
|
pSpoolFileInfo - pointer to buffer
|
|
cbBuf - buffer size
|
|
pcbNeeded - pointer to return required buffer size
|
|
|
|
Return Values: TRUE if sucessful;
|
|
FALSE otherwise
|
|
--*/
|
|
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
DWORD cbTotalWritten, cbWritten, cbRead, cbToRead;
|
|
BYTE *Buffer = NULL;
|
|
HANDLE hFile, hSpoolerProcess = NULL, hFileApp = INVALID_HANDLE_VALUE;
|
|
|
|
PSPOOL_FILE_INFO_1 pSpoolFileInfo1;
|
|
LPPRINTHANDLE pPrintHandle = (LPPRINTHANDLE)hPrinter;
|
|
|
|
// Check Handle validity
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return bReturn;
|
|
}
|
|
|
|
// Check for valid level and sufficient buffer
|
|
switch (dwLevel) {
|
|
case 1:
|
|
if (cbBuf < sizeof(SPOOL_FILE_INFO_1)) {
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
*pcbNeeded = sizeof(SPOOL_FILE_INFO_1);
|
|
goto CleanUp;
|
|
}
|
|
|
|
pSpoolFileInfo1 = (PSPOOL_FILE_INFO_1)pSpoolFileInfo;
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
goto CleanUp;
|
|
}
|
|
|
|
// Initialize spoolfileinfo1 struct
|
|
pSpoolFileInfo1->dwVersion = 1;
|
|
pSpoolFileInfo1->hSpoolFile = INVALID_HANDLE_VALUE;
|
|
pSpoolFileInfo1->dwAttributes = SPOOL_FILE_PERSISTENT;
|
|
|
|
if (pPrintHandle->pProvidor == pLocalProvidor) {
|
|
|
|
bReturn = (pLocalProvidor->PrintProvidor.fpCommitSpoolData)(pPrintHandle->hPrinter,
|
|
cbCommit);
|
|
return bReturn;
|
|
}
|
|
|
|
// For remote printing send the temp file across the wire using WritePrinter
|
|
if (pPrintHandle->hFileSpooler == INVALID_HANDLE_VALUE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return bReturn;
|
|
}
|
|
|
|
hFile = pPrintHandle->hFileSpooler;
|
|
|
|
if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == 0xffffffff) {
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// Use a Buffer to send Data over RPC.
|
|
//
|
|
Buffer = AllocSplMem(BUFFER_SIZE);
|
|
|
|
if ( !Buffer ) {
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
goto CleanUp;
|
|
}
|
|
|
|
while ((cbToRead = min(cbCommit, BUFFER_SIZE)) &&
|
|
ReadFile(hFile, Buffer, cbToRead, &cbRead, NULL)) {
|
|
|
|
cbCommit -= cbRead;
|
|
|
|
for (cbTotalWritten = 0;
|
|
cbTotalWritten < cbRead;
|
|
cbTotalWritten += cbWritten) {
|
|
|
|
if (!(*pPrintHandle->pProvidor->PrintProvidor.fpWritePrinter)
|
|
(pPrintHandle->hPrinter,
|
|
(LPBYTE)Buffer + cbTotalWritten,
|
|
cbRead - cbTotalWritten,
|
|
&cbWritten)) {
|
|
goto CleanUp;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Buffer) {
|
|
FreeSplMem(Buffer);
|
|
Buffer = NULL;
|
|
}
|
|
|
|
if ((cbToRead != 0) ||
|
|
(SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == 0xffffffff)) {
|
|
|
|
goto CleanUp;
|
|
}
|
|
|
|
if ((hSpoolerProcess = GetCurrentProcess()) &&
|
|
DuplicateHandle(hSpoolerProcess,
|
|
pPrintHandle->hFileSpooler,
|
|
hAppProcess,
|
|
&hFileApp,
|
|
0,
|
|
TRUE,
|
|
DUPLICATE_SAME_ACCESS)) {
|
|
|
|
pSpoolFileInfo1->dwVersion = 1;
|
|
pSpoolFileInfo1->hSpoolFile = hFileApp;
|
|
pSpoolFileInfo1->dwAttributes = SPOOL_FILE_TEMPORARY;
|
|
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
CleanUp:
|
|
|
|
if (Buffer) {
|
|
FreeSplMem(Buffer);
|
|
}
|
|
if (hSpoolerProcess) {
|
|
CloseHandle(hSpoolerProcess);
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL
|
|
SplCloseSpoolFileHandle(
|
|
HANDLE hPrinter
|
|
)
|
|
|
|
/*++
|
|
Function Description: Closes the remote spool file handle for remote printing.
|
|
|
|
Parameters: hPrinter - printer handle
|
|
|
|
Return Values: TRUE if sucessful;
|
|
FALSE otherwise
|
|
--*/
|
|
|
|
{
|
|
LPPRINTHANDLE pPrintHandle = (LPPRINTHANDLE)hPrinter;
|
|
|
|
// Check Handle validity
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pPrintHandle->pProvidor == pLocalProvidor) {
|
|
|
|
return (pLocalProvidor->PrintProvidor.fpCloseSpoolFileHandle)(pPrintHandle->hPrinter);
|
|
|
|
} else if ((pPrintHandle->hFileSpooler != INVALID_HANDLE_VALUE)) {
|
|
|
|
// close temp files for remote printing
|
|
CloseHandle(pPrintHandle->hFileSpooler);
|
|
pPrintHandle->hFileSpooler = INVALID_HANDLE_VALUE;
|
|
|
|
if (pPrintHandle->szTempSpoolFile) {
|
|
|
|
HANDLE hToken = RevertToPrinterSelf();
|
|
|
|
if (!DeleteFile(pPrintHandle->szTempSpoolFile)) {
|
|
|
|
MoveFileEx(pPrintHandle->szTempSpoolFile, NULL,
|
|
MOVEFILE_DELAY_UNTIL_REBOOT);
|
|
}
|
|
|
|
if (hToken)
|
|
{
|
|
ImpersonatePrinterClient(hToken);
|
|
}
|
|
|
|
FreeSplMem(pPrintHandle->szTempSpoolFile);
|
|
pPrintHandle->szTempSpoolFile = NULL;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SplGetSpoolFileInfo(
|
|
HANDLE hPrinter,
|
|
HANDLE hAppProcess,
|
|
DWORD dwLevel,
|
|
LPBYTE pSpoolFileInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded
|
|
)
|
|
|
|
/*++
|
|
Function Description: Get spool file info for the job in hPrinter. For local jobs
|
|
localspl returns the hFile. For remote jobs a temp file is created
|
|
by the router. The file handle is dupped into the application.
|
|
|
|
Parameters: hPrinter - printer handle
|
|
hAppProcess - application process handle
|
|
dwLevel - spool file info level
|
|
pSpoolFileInfo - pointer to buffer
|
|
cbBuf - buffer size
|
|
pcbNeeded - pointer to return required buffer size
|
|
|
|
Return Values: TRUE if sucessful;
|
|
FALSE otherwise
|
|
--*/
|
|
|
|
{
|
|
HANDLE hFileSpooler = NULL, hFileApp = NULL;
|
|
HANDLE hSpoolerProcess = NULL;
|
|
BOOL bReturn = FALSE;
|
|
DWORD dwSpoolerProcessID;
|
|
LPWSTR pSpoolDir = NULL;
|
|
|
|
PSPOOL_FILE_INFO_1 pSpoolFileInfo1;
|
|
LPPRINTHANDLE pPrintHandle = (LPPRINTHANDLE)hPrinter;
|
|
|
|
// Check Handle validity
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
goto CleanUp;
|
|
}
|
|
|
|
// Check for valid level and sufficient buffer
|
|
switch (dwLevel) {
|
|
case 1:
|
|
if (cbBuf < sizeof(SPOOL_FILE_INFO_1)) {
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
*pcbNeeded = sizeof(SPOOL_FILE_INFO_1);
|
|
goto CleanUp;
|
|
}
|
|
|
|
pSpoolFileInfo1 = (PSPOOL_FILE_INFO_1)pSpoolFileInfo;
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
goto CleanUp;
|
|
}
|
|
|
|
if (!(hSpoolerProcess = GetCurrentProcess())) {
|
|
// Cant get a pseudo handle to the spooler
|
|
goto CleanUp;
|
|
}
|
|
|
|
if ((pPrintHandle->pProvidor != pLocalProvidor) &&
|
|
(pPrintHandle->hFileSpooler != INVALID_HANDLE_VALUE)) {
|
|
|
|
// Return cached temp file handle.
|
|
bReturn = DuplicateHandle(hSpoolerProcess,
|
|
pPrintHandle->hFileSpooler,
|
|
hAppProcess,
|
|
&hFileApp,
|
|
0,
|
|
TRUE,
|
|
DUPLICATE_SAME_ACCESS);
|
|
if (bReturn) {
|
|
pSpoolFileInfo1->dwVersion = 1;
|
|
pSpoolFileInfo1->hSpoolFile = hFileApp;
|
|
pSpoolFileInfo1->dwAttributes = SPOOL_FILE_TEMPORARY;
|
|
}
|
|
|
|
goto CleanUp;
|
|
}
|
|
|
|
if (pPrintHandle->pProvidor == pLocalProvidor) {
|
|
|
|
bReturn = (pLocalProvidor->PrintProvidor.fpGetSpoolFileInfo)(pPrintHandle->hPrinter,
|
|
NULL,
|
|
&hFileApp,
|
|
hSpoolerProcess,
|
|
hAppProcess);
|
|
|
|
if (bReturn) {
|
|
pSpoolFileInfo1->dwVersion = 1;
|
|
pSpoolFileInfo1->hSpoolFile = hFileApp;
|
|
pSpoolFileInfo1->dwAttributes = SPOOL_FILE_PERSISTENT;
|
|
}
|
|
|
|
goto CleanUp;
|
|
|
|
} else {
|
|
|
|
bReturn = (pLocalProvidor->PrintProvidor.fpGetSpoolFileInfo)(NULL, &pSpoolDir,
|
|
NULL, NULL, NULL);
|
|
}
|
|
|
|
// Remote Printing, create a temp file in the spool directory
|
|
if (bReturn) {
|
|
|
|
HANDLE hToken;
|
|
|
|
//
|
|
// Revert to system context to ensure that we can open the file.
|
|
//
|
|
hToken = RevertToPrinterSelf();
|
|
|
|
if ((pPrintHandle->szTempSpoolFile = AllocSplMem(MAX_PATH * sizeof(WCHAR))) &&
|
|
|
|
GetTempFileName(pSpoolDir, L"SPL", 0, pPrintHandle->szTempSpoolFile) &&
|
|
|
|
((pPrintHandle->hFileSpooler = CreateFile(pPrintHandle->szTempSpoolFile,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
0, NULL)) != INVALID_HANDLE_VALUE) &&
|
|
DuplicateHandle(hSpoolerProcess,
|
|
pPrintHandle->hFileSpooler,
|
|
hAppProcess,
|
|
&hFileApp,
|
|
0,
|
|
TRUE,
|
|
DUPLICATE_SAME_ACCESS)) {
|
|
|
|
pSpoolFileInfo1->dwVersion = 1;
|
|
pSpoolFileInfo1->hSpoolFile = hFileApp;
|
|
pSpoolFileInfo1->dwAttributes = SPOOL_FILE_TEMPORARY;
|
|
|
|
} else {
|
|
|
|
bReturn = FALSE;
|
|
}
|
|
|
|
if (hToken)
|
|
{
|
|
ImpersonatePrinterClient(hToken);
|
|
}
|
|
}
|
|
|
|
CleanUp:
|
|
|
|
if (hSpoolerProcess) {
|
|
CloseHandle(hSpoolerProcess);
|
|
}
|
|
if (pSpoolDir) {
|
|
FreeSplMem(pSpoolDir);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL
|
|
WritePrinter(
|
|
HANDLE hPrinter,
|
|
LPVOID pBuf,
|
|
DWORD cbBuf,
|
|
LPDWORD pcWritten
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (!pPrintHandle ||
|
|
(pPrintHandle->signature != PRINTHANDLE_SIGNATURE) ||
|
|
(pPrintHandle->hFileSpooler != INVALID_HANDLE_VALUE)) {
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpWritePrinter) (pPrintHandle->hPrinter,
|
|
pBuf, cbBuf, pcWritten);
|
|
}
|
|
|
|
BOOL
|
|
SeekPrinter(
|
|
HANDLE hPrinter,
|
|
LARGE_INTEGER liDistanceToMove,
|
|
PLARGE_INTEGER pliNewPointer,
|
|
DWORD dwMoveMethod,
|
|
BOOL bWritePrinter
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
LARGE_INTEGER liNewPointer;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Allow a NULL pliNewPointer to be passed in.
|
|
//
|
|
if( !pliNewPointer ){
|
|
pliNewPointer = &liNewPointer;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpSeekPrinter) (
|
|
pPrintHandle->hPrinter,
|
|
liDistanceToMove,
|
|
pliNewPointer,
|
|
dwMoveMethod,
|
|
bWritePrinter );
|
|
}
|
|
|
|
BOOL
|
|
FlushPrinter(
|
|
HANDLE hPrinter,
|
|
LPVOID pBuf,
|
|
DWORD cbBuf,
|
|
LPDWORD pcWritten,
|
|
DWORD cSleep
|
|
)
|
|
|
|
/*++
|
|
Function Description: FlushPrinter is typically used by the driver to send a burst of zeros
|
|
to the printer and introduce a delay in the i/o line to the printer.
|
|
The spooler does not schedule any job for cSleep milliseconds.
|
|
|
|
Parameters: hPrinter - printer handle
|
|
pBuf - buffer to be sent to the printer
|
|
cbBuf - size of the buffer
|
|
pcWritten - pointer to return the number of bytes written
|
|
cSleep - sleep time in milliseconds.
|
|
|
|
Return Values: TRUE if successful;
|
|
FALSE otherwise
|
|
--*/
|
|
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
//
|
|
// Check for valid printer handle
|
|
//
|
|
if (!pPrintHandle ||
|
|
(pPrintHandle->signature != PRINTHANDLE_SIGNATURE) ||
|
|
(pPrintHandle->hFileSpooler != INVALID_HANDLE_VALUE))
|
|
{
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpFlushPrinter) (pPrintHandle->hPrinter,
|
|
pBuf,
|
|
cbBuf,
|
|
pcWritten,
|
|
cSleep);
|
|
}
|
|
|
|
BOOL
|
|
EndPagePrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpEndPagePrinter) (pPrintHandle->hPrinter);
|
|
}
|
|
|
|
BOOL
|
|
AbortPrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpAbortPrinter) (pPrintHandle->hPrinter);
|
|
}
|
|
|
|
BOOL
|
|
ReadPrinter(
|
|
HANDLE hPrinter,
|
|
LPVOID pBuf,
|
|
DWORD cbBuf,
|
|
LPDWORD pRead
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpReadPrinter)
|
|
(pPrintHandle->hPrinter, pBuf, cbBuf, pRead);
|
|
}
|
|
|
|
BOOL
|
|
SplReadPrinter(
|
|
HANDLE hPrinter,
|
|
LPBYTE *pBuf,
|
|
DWORD cbBuf
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpSplReadPrinter)
|
|
(pPrintHandle->hPrinter, pBuf, cbBuf);
|
|
}
|
|
|
|
BOOL
|
|
EndDocPrinter(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpEndDocPrinter) (pPrintHandle->hPrinter);
|
|
}
|
|
|
|
HANDLE
|
|
CreatePrinterIC(
|
|
HANDLE hPrinter,
|
|
LPDEVMODEW pDevMode
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
HANDLE ReturnValue;
|
|
PGDIHANDLE pGdiHandle;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
pGdiHandle = AllocSplMem(sizeof(GDIHANDLE));
|
|
|
|
if (!pGdiHandle) {
|
|
|
|
DBGMSG(DBG_WARN, ("Failed to alloc GDI handle."));
|
|
return FALSE;
|
|
}
|
|
|
|
ReturnValue = (HANDLE)(*pPrintHandle->pProvidor->PrintProvidor.fpCreatePrinterIC)
|
|
(pPrintHandle->hPrinter,
|
|
pDevMode);
|
|
|
|
if (ReturnValue) {
|
|
|
|
pGdiHandle->signature = GDIHANDLE_SIGNATURE;
|
|
pGdiHandle->pProvidor = pPrintHandle->pProvidor;
|
|
pGdiHandle->hGdi = ReturnValue;
|
|
|
|
return pGdiHandle;
|
|
}
|
|
|
|
FreeSplMem(pGdiHandle);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
PlayGdiScriptOnPrinterIC(
|
|
HANDLE hPrinterIC,
|
|
LPBYTE pIn,
|
|
DWORD cIn,
|
|
LPBYTE pOut,
|
|
DWORD cOut,
|
|
DWORD ul
|
|
)
|
|
{
|
|
PGDIHANDLE pGdiHandle=(PGDIHANDLE)hPrinterIC;
|
|
|
|
if (!pGdiHandle || pGdiHandle->signature != GDIHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pGdiHandle->pProvidor->PrintProvidor.fpPlayGdiScriptOnPrinterIC)
|
|
(pGdiHandle->hGdi, pIn, cIn, pOut, cOut, ul);
|
|
}
|
|
|
|
BOOL
|
|
DeletePrinterIC(
|
|
HANDLE hPrinterIC
|
|
)
|
|
{
|
|
LPGDIHANDLE pGdiHandle=(LPGDIHANDLE)hPrinterIC;
|
|
|
|
if (!pGdiHandle || pGdiHandle->signature != GDIHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
if ((*pGdiHandle->pProvidor->PrintProvidor.fpDeletePrinterIC) (pGdiHandle->hGdi)) {
|
|
|
|
FreeSplMem(pGdiHandle);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD
|
|
PrinterMessageBox(
|
|
HANDLE hPrinter,
|
|
DWORD Error,
|
|
HWND hWnd,
|
|
LPWSTR pText,
|
|
LPWSTR pCaption,
|
|
DWORD dwType
|
|
)
|
|
{
|
|
LPPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (!pPrintHandle || pPrintHandle->signature != PRINTHANDLE_SIGNATURE) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pPrintHandle->pProvidor->PrintProvidor.fpPrinterMessageBox)
|
|
(hPrinter, Error, hWnd, pText, pCaption, dwType);
|
|
|
|
}
|
|
|
|
DWORD
|
|
SendRecvBidiData(
|
|
IN HANDLE hPrinter,
|
|
IN LPCTSTR pAction,
|
|
IN PBIDI_REQUEST_CONTAINER pReqData,
|
|
OUT PBIDI_RESPONSE_CONTAINER* ppResData
|
|
)
|
|
{
|
|
DWORD dwRet = ERROR_SUCCESS;
|
|
LPPRINTHANDLE pPrintHandle = (LPPRINTHANDLE)hPrinter;
|
|
//
|
|
// Check for valid printer handle
|
|
//
|
|
if (!pPrintHandle ||
|
|
(pPrintHandle->signature != PRINTHANDLE_SIGNATURE) ||
|
|
(pPrintHandle->hFileSpooler != INVALID_HANDLE_VALUE))
|
|
{
|
|
dwRet = ERROR_INVALID_HANDLE;
|
|
}
|
|
else
|
|
{
|
|
dwRet = (*pPrintHandle->pProvidor->PrintProvidor.fpSendRecvBidiData)(pPrintHandle->hPrinter,
|
|
pAction,
|
|
pReqData,
|
|
ppResData);
|
|
}
|
|
return (dwRet);
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
|
|
Routine Name:
|
|
|
|
SplPromptUIInUsersSession
|
|
|
|
Routine Description:
|
|
|
|
Pops message boxes in the user's session.
|
|
For Whistler this function shows only message boxes in Spoolsv.exe.
|
|
|
|
Arguments:
|
|
|
|
hPrinter -- printer handle
|
|
JobId -- job ID
|
|
pUIParams -- UI parameters
|
|
pResponse -- user's response
|
|
|
|
Return Value:
|
|
|
|
TRUE if succeeded
|
|
|
|
Last Error:
|
|
|
|
Win32 error
|
|
|
|
--*/
|
|
BOOL
|
|
SplPromptUIInUsersSession(
|
|
IN HANDLE hPrinter,
|
|
IN DWORD JobId,
|
|
IN PSHOWUIPARAMS pUIParams,
|
|
OUT DWORD *pResponse
|
|
)
|
|
{
|
|
typedef BOOL (*FPPROMPT_UI)(HANDLE, DWORD, PSHOWUIPARAMS, DWORD*);
|
|
|
|
FPPROMPT_UI fpPromptUIPerSessionUser;
|
|
BOOL bRetValue = FALSE;
|
|
PPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (pPrintHandle && pPrintHandle->signature == PRINTHANDLE_SIGNATURE)
|
|
{
|
|
if (pPrintHandle->pProvidor == pLocalProvidor &&
|
|
(fpPromptUIPerSessionUser = (FPPROMPT_UI)GetProcAddress(pLocalProvidor->hModule,
|
|
"LclPromptUIPerSessionUser")))
|
|
{
|
|
bRetValue = (*fpPromptUIPerSessionUser)(pPrintHandle->hPrinter, JobId, pUIParams, pResponse);
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
return bRetValue;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
|
|
Routine Name:
|
|
|
|
SplIsSessionZero
|
|
|
|
Routine Description:
|
|
|
|
Determine is user that submitted a certain job runs in Session 0.
|
|
It is used by Canon monitor to determine when to show
|
|
resource template base UI versus calling SplPromptUIInUsersSession.
|
|
|
|
Arguments:
|
|
|
|
hPrinter -- printer handle
|
|
JobId -- job ID
|
|
pIsSessionZero -- TRUE if user runs in Session 0
|
|
|
|
Return Value:
|
|
|
|
Win32 last error
|
|
|
|
Last Error:
|
|
|
|
--*/
|
|
DWORD
|
|
SplIsSessionZero(
|
|
IN HANDLE hPrinter,
|
|
IN DWORD JobId,
|
|
OUT BOOL *pIsSessionZero
|
|
)
|
|
{
|
|
typedef DWORD (*FPISSESSIONZERO)(HANDLE, DWORD, BOOL*);
|
|
|
|
FPISSESSIONZERO fpIsSessionZero;
|
|
DWORD dwRetValue = ERROR_SUCCESS;
|
|
PPRINTHANDLE pPrintHandle=(LPPRINTHANDLE)hPrinter;
|
|
|
|
if (pPrintHandle && pPrintHandle->signature == PRINTHANDLE_SIGNATURE)
|
|
{
|
|
if (pPrintHandle->pProvidor == pLocalProvidor &&
|
|
(fpIsSessionZero = (FPISSESSIONZERO)GetProcAddress(pLocalProvidor->hModule,
|
|
"LclIsSessionZero")))
|
|
{
|
|
dwRetValue = (*fpIsSessionZero)(pPrintHandle->hPrinter, JobId, pIsSessionZero);
|
|
}
|
|
else
|
|
{
|
|
dwRetValue = ERROR_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwRetValue = ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
return dwRetValue;
|
|
} |