mirror of
https://github.com/reactos/reactos.git
synced 2025-04-05 21:21:33 +00:00
[LOCALSPL]
- Partly implement LocalScheduleJob. - Set the default status to JOB_STATUS_SPOOLING in LocalAddJob. - Fix file sharing flags in ReadJobShadowFile and WriteJobShadowFile. [SPOOLSS, SPOOLSV, WINSPOOL] - Forward the newly implemented ScheduleJob call all the way down to localspl.dll. - Stub ReadPrinter. [WINPRINT] Implement a very simple RAW Print Processor that just takes the input and forwards it to the Print Monitor. This one doesn't even do pausing or multiple copies yet. The implementation includes: - Implemented ClosePrintProcessor, OpenPrintProcessor and PrintDocumentOnPrintProcessor (apart from the previously implemented EnumPrintProcessorDatatypesW). - Stubbed ControlPrintProcessor and GetPrintProcessorCapabilities. svn path=/branches/colins-printing-for-freedom/; revision=68304
This commit is contained in:
parent
b0bc4bb807
commit
14711237a1
15 changed files with 418 additions and 22 deletions
|
@ -25,6 +25,12 @@ GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPD
|
|||
return LocalSplFuncs.fpGetJob(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
ScheduleJob(HANDLE hPrinter, DWORD dwJobID)
|
||||
{
|
||||
return LocalSplFuncs.fpScheduleJob(hPrinter, dwJobID);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
|
||||
{
|
||||
|
|
|
@ -50,6 +50,12 @@ OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefau
|
|||
return LocalSplFuncs.fpOpenPrinter(pPrinterName, phPrinter, pDefault);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD WINAPI
|
||||
StartDocPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||
{
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
@ stub ProvidorFindClosePrinterChangeNotification
|
||||
@ stub ProvidorFindFirstPrinterChangeNotification
|
||||
@ stub pszDbgAllocMsgA
|
||||
@ stub ReadPrinter
|
||||
@ stdcall ReadPrinter(long ptr long ptr)
|
||||
@ stdcall ReallocSplMem(ptr long long)
|
||||
@ stdcall ReallocSplStr(ptr ptr)
|
||||
@ stub RemoteFindFirstPrinterChangeNotification
|
||||
|
@ -132,7 +132,7 @@
|
|||
@ stub RouterFreePrinterNotifyInfo
|
||||
@ stub RouterRefreshPrinterChangeNotification
|
||||
@ stub RouterReplyPrinter
|
||||
@ stub ScheduleJob
|
||||
@ stdcall ScheduleJob(long long)
|
||||
@ stub SeekPrinter
|
||||
@ stub SendRecvBidiData
|
||||
@ stub SetAllocFailCount
|
||||
|
|
|
@ -139,8 +139,20 @@ _RpcGetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, DWORD Level, BYTE* pJo
|
|||
DWORD
|
||||
_RpcScheduleJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return ERROR_INVALID_FUNCTION;
|
||||
DWORD dwErrorCode;
|
||||
|
||||
dwErrorCode = RpcImpersonateClient(NULL);
|
||||
if (dwErrorCode != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
|
||||
return dwErrorCode;
|
||||
}
|
||||
|
||||
ScheduleJob(hPrinter, JobId);
|
||||
dwErrorCode = GetLastError();
|
||||
|
||||
RpcRevertToSelf();
|
||||
return dwErrorCode;
|
||||
}
|
||||
|
||||
DWORD
|
||||
|
|
|
@ -163,6 +163,27 @@ GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWO
|
|||
return (dwErrorCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
ScheduleJob(HANDLE hPrinter, DWORD dwJobID)
|
||||
{
|
||||
DWORD dwErrorCode;
|
||||
|
||||
// Do the RPC call
|
||||
RpcTryExcept
|
||||
{
|
||||
dwErrorCode = _RpcScheduleJob(hPrinter, dwJobID);
|
||||
}
|
||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
dwErrorCode = RpcExceptionCode();
|
||||
ERR("_RpcSetJob failed with exception code %lu!\n", dwErrorCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
|
||||
SetLastError(dwErrorCode);
|
||||
return (dwErrorCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
|
||||
{
|
||||
|
|
|
@ -212,6 +212,12 @@ OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefau
|
|||
return bReturnValue;
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD WINAPI
|
||||
StartDocPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||
{
|
||||
|
|
|
@ -168,10 +168,10 @@
|
|||
267 stub QueryColorProfile
|
||||
268 stub QueryRemoteFonts
|
||||
269 stub QuerySpoolMode
|
||||
270 stub ReadPrinter
|
||||
270 stdcall ReadPrinter(long ptr long ptr)
|
||||
271 stub ResetPrinterA
|
||||
272 stub ResetPrinterW
|
||||
273 stub ScheduleJob
|
||||
273 stdcall ScheduleJob(long long)
|
||||
274 stub SeekPrinter
|
||||
275 stub SetAllocFailCount
|
||||
276 stub SetFormA
|
||||
|
|
|
@ -3,12 +3,12 @@ spec2def(winprint.dll winprint.spec ADD_IMPORTLIB)
|
|||
|
||||
list(APPEND SOURCE
|
||||
main.c
|
||||
raw.c
|
||||
precomp.h)
|
||||
|
||||
add_library(winprint SHARED
|
||||
${SOURCE}
|
||||
winprint.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/winprint_stubs.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/winprint.def)
|
||||
|
||||
set_module_type(winprint win32dll UNICODE)
|
||||
|
|
|
@ -7,11 +7,69 @@
|
|||
|
||||
#include "precomp.h"
|
||||
|
||||
PCWSTR pwszDatatypes[] = {
|
||||
// Local Constants
|
||||
static PCWSTR _pwszDatatypes[] = {
|
||||
L"RAW",
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @name ClosePrintProcessor
|
||||
*
|
||||
* Closes a Print Processor Handle that has previously been opened through OpenPrintProcessor.
|
||||
*
|
||||
* @param hPrintProcessor
|
||||
* The return value of a previous successful OpenPrintProcessor call.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the Print Processor Handle was successfully closed, FALSE otherwise.
|
||||
* A more specific error code can be obtained through GetLastError.
|
||||
*/
|
||||
BOOL WINAPI
|
||||
ClosePrintProcessor(HANDLE hPrintProcessor)
|
||||
{
|
||||
DWORD dwErrorCode;
|
||||
PWINPRINT_HANDLE pHandle;
|
||||
|
||||
// Sanity checks
|
||||
if (!hPrintProcessor)
|
||||
{
|
||||
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
pHandle = (PWINPRINT_HANDLE)hPrintProcessor;
|
||||
|
||||
// Free all structure fields for which memory has been allocated.
|
||||
if (pHandle->pwszDatatype)
|
||||
DllFreeSplStr(pHandle->pwszDatatype);
|
||||
|
||||
if (pHandle->pwszDocumentName)
|
||||
DllFreeSplStr(pHandle->pwszDocumentName);
|
||||
|
||||
if (pHandle->pwszOutputFile)
|
||||
DllFreeSplStr(pHandle->pwszOutputFile);
|
||||
|
||||
if (pHandle->pwszPrinterPort)
|
||||
DllFreeSplStr(pHandle->pwszPrinterPort);
|
||||
|
||||
// Finally free the WINSPOOL_HANDLE structure itself.
|
||||
DllFreeSplMem(pHandle);
|
||||
dwErrorCode = ERROR_SUCCESS;
|
||||
|
||||
Cleanup:
|
||||
SetLastError(dwErrorCode);
|
||||
return (dwErrorCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
ControlPrintProcessor(HANDLE hPrintProcessor, DWORD Command)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name EnumPrintProcessorDatatypesW
|
||||
*
|
||||
|
@ -50,7 +108,7 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
|
|||
{
|
||||
DWORD cbDatatype;
|
||||
DWORD dwErrorCode;
|
||||
DWORD dwOffsets[_countof(pwszDatatypes)];
|
||||
DWORD dwOffsets[_countof(_pwszDatatypes)];
|
||||
PCWSTR* pCurrentDatatype;
|
||||
PDWORD pCurrentOffset = dwOffsets;
|
||||
|
||||
|
@ -65,7 +123,7 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
|
|||
*pcbNeeded = 0;
|
||||
*pcReturned = 0;
|
||||
|
||||
for (pCurrentDatatype = pwszDatatypes; *pCurrentDatatype; pCurrentDatatype++)
|
||||
for (pCurrentDatatype = _pwszDatatypes; *pCurrentDatatype; pCurrentDatatype++)
|
||||
{
|
||||
cbDatatype = (wcslen(*pCurrentDatatype) + 1) * sizeof(WCHAR);
|
||||
*pcbNeeded += sizeof(DATATYPES_INFO_1W) + cbDatatype;
|
||||
|
@ -93,7 +151,7 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
|
|||
|
||||
// Copy over all datatypes.
|
||||
*pCurrentOffset = MAXDWORD;
|
||||
PackStrings(pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]);
|
||||
PackStrings(_pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]);
|
||||
|
||||
dwErrorCode = ERROR_SUCCESS;
|
||||
|
||||
|
@ -101,3 +159,114 @@ Cleanup:
|
|||
SetLastError(dwErrorCode);
|
||||
return (dwErrorCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI
|
||||
GetPrintProcessorCapabilities(PWSTR pValueName, DWORD dwAttributes, PBYTE pData, DWORD nSize, PDWORD pcbNeeded)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name OpenPrintProcessor
|
||||
*
|
||||
* Prepares this Print Processor for processing a document.
|
||||
*
|
||||
* @param pPrinterName
|
||||
* String in the format "\\COMPUTERNAME\Port:, Port" that is passed to OpenPrinterW for writing to the Print Monitor on the specified port.
|
||||
*
|
||||
* @param pPrintProcessorOpenData
|
||||
* Pointer to a PRINTPROCESSOROPENDATA structure containing details about the print job to be processed.
|
||||
*
|
||||
* @return
|
||||
* A Print Processor handle on success or NULL in case of a failure. This handle has to be passed to PrintDocumentOnPrintProcessor to do the actual processing.
|
||||
* A more specific error code can be obtained through GetLastError.
|
||||
*/
|
||||
HANDLE WINAPI
|
||||
OpenPrintProcessor(PWSTR pPrinterName, PPRINTPROCESSOROPENDATA pPrintProcessorOpenData)
|
||||
{
|
||||
DWORD dwErrorCode;
|
||||
HANDLE hReturnValue = NULL;
|
||||
PWINPRINT_HANDLE pHandle = NULL;
|
||||
|
||||
// Sanity checks
|
||||
// This time a datatype needs to be given. We can't fall back to a default here.
|
||||
if (!pPrintProcessorOpenData || !pPrintProcessorOpenData->pDatatype || !*pPrintProcessorOpenData->pDatatype)
|
||||
{
|
||||
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Create a new WINPRINT_HANDLE structure. and fill the relevant fields.
|
||||
pHandle = DllAllocSplMem(sizeof(WINPRINT_HANDLE));
|
||||
|
||||
// Check what datatype was given.
|
||||
if (wcsicmp(pPrintProcessorOpenData->pDatatype, L"RAW") == 0)
|
||||
{
|
||||
pHandle->Datatype = RAW;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwErrorCode = ERROR_INVALID_DATATYPE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Fill the relevant fields.
|
||||
pHandle->dwJobID = pPrintProcessorOpenData->JobId;
|
||||
pHandle->pwszDatatype = AllocSplStr(pPrintProcessorOpenData->pDatatype);
|
||||
pHandle->pwszDocumentName = AllocSplStr(pPrintProcessorOpenData->pDocumentName);
|
||||
pHandle->pwszOutputFile = AllocSplStr(pPrintProcessorOpenData->pOutputFile);
|
||||
pHandle->pwszPrinterPort = AllocSplStr(pPrintProcessorOpenData->pPrinterName);
|
||||
|
||||
// We were successful! Return the handle and don't let the cleanup routine free it.
|
||||
dwErrorCode = ERROR_SUCCESS;
|
||||
hReturnValue = pHandle;
|
||||
pHandle = NULL;
|
||||
|
||||
Cleanup:
|
||||
if (pHandle)
|
||||
DllFreeSplMem(pHandle);
|
||||
|
||||
SetLastError(dwErrorCode);
|
||||
return hReturnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name PrintDocumentOnPrintProcessor
|
||||
*
|
||||
* Prints a document on this Print Processor after a handle for the document has been opened through OpenPrintProcessor.
|
||||
*
|
||||
* @param hPrintProcessor
|
||||
* The return value of a previous successful OpenPrintProcessor call.
|
||||
*
|
||||
* @param pDocumentName
|
||||
* String in the format "Printer, Job N" describing the spooled job that is to be processed.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the document was successfully processed by this Print Processor, FALSE otherwise.
|
||||
* A more specific error code can be obtained through GetLastError.
|
||||
*/
|
||||
BOOL WINAPI
|
||||
PrintDocumentOnPrintProcessor(HANDLE hPrintProcessor, PWSTR pDocumentName)
|
||||
{
|
||||
DWORD dwErrorCode;
|
||||
PWINPRINT_HANDLE pHandle;
|
||||
|
||||
// Sanity checks
|
||||
if (!hPrintProcessor)
|
||||
{
|
||||
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
pHandle = (PWINPRINT_HANDLE)hPrintProcessor;
|
||||
|
||||
// Call the corresponding Print function for the datatype.
|
||||
if (pHandle->Datatype == RAW)
|
||||
dwErrorCode = PrintRawJob(pHandle, pDocumentName);
|
||||
|
||||
Cleanup:
|
||||
SetLastError(dwErrorCode);
|
||||
return (dwErrorCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -22,4 +22,19 @@
|
|||
#include <wine/debug.h>
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(winprint);
|
||||
|
||||
// Structures
|
||||
typedef struct _WINPRINT_HANDLE
|
||||
{
|
||||
enum { RAW } Datatype;
|
||||
DWORD dwJobID;
|
||||
PWSTR pwszDatatype;
|
||||
PWSTR pwszDocumentName;
|
||||
PWSTR pwszOutputFile;
|
||||
PWSTR pwszPrinterPort;
|
||||
}
|
||||
WINPRINT_HANDLE, *PWINPRINT_HANDLE;
|
||||
|
||||
// raw.c
|
||||
DWORD PrintRawJob(PWINPRINT_HANDLE pHandle, PWSTR pwszPrinterAndJob);
|
||||
|
||||
#endif
|
||||
|
|
100
reactos/win32ss/printing/processors/winprint/raw.c
Normal file
100
reactos/win32ss/printing/processors/winprint/raw.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Standard Print Processor
|
||||
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
|
||||
* PURPOSE: Printing a job with RAW datatype
|
||||
* COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
/**
|
||||
* @name PrintRawJob
|
||||
*
|
||||
* @param pHandle
|
||||
* Pointer to a WINPRINT_HANDLE structure containing information about this job.
|
||||
*
|
||||
* @param pwszPrinterAndJob
|
||||
* String in the format "Printer, Job N" that is passed to OpenPrinterW to read from the spooled print job.
|
||||
*
|
||||
* @return
|
||||
* An error code indicating success or failure.
|
||||
*/
|
||||
DWORD
|
||||
PrintRawJob(PWINPRINT_HANDLE pHandle, PWSTR pwszPrinterAndJob)
|
||||
{
|
||||
// Use a read buffer of 256 KB size like Windows does.
|
||||
const DWORD cbReadBuffer = 262144;
|
||||
|
||||
BOOL bStartedDoc = FALSE;
|
||||
DOC_INFO_1W DocInfo1;
|
||||
DWORD cbRead;
|
||||
DWORD cbWritten;
|
||||
DWORD dwErrorCode;
|
||||
HANDLE hPrintJob;
|
||||
HANDLE hPrintMonitor;
|
||||
PBYTE pBuffer = NULL;
|
||||
|
||||
// Open the spooled job to read from it.
|
||||
if (!OpenPrinterW(pwszPrinterAndJob, &hPrintJob, NULL))
|
||||
{
|
||||
dwErrorCode = GetLastError();
|
||||
ERR("OpenPrinterW failed for \"%S\" with error %lu!\n", pwszPrinterAndJob, GetLastError());
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Open a Print Monitor handle to write to it.
|
||||
if (!OpenPrinterW(pHandle->pwszPrinterPort, &hPrintMonitor, NULL))
|
||||
{
|
||||
dwErrorCode = GetLastError();
|
||||
ERR("OpenPrinterW failed for \"%S\" with error %lu!\n", pHandle->pwszPrinterPort, GetLastError());
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Fill the Document Information.
|
||||
DocInfo1.pDatatype = pHandle->pwszDatatype;
|
||||
DocInfo1.pDocName = pHandle->pwszDocumentName;
|
||||
DocInfo1.pOutputFile = pHandle->pwszOutputFile;
|
||||
|
||||
// Tell the Print Monitor that we're starting a new document.
|
||||
if (!StartDocPrinterW(hPrintMonitor, 1, (PBYTE)&DocInfo1))
|
||||
{
|
||||
dwErrorCode = GetLastError();
|
||||
ERR("StartDocPrinterW failed with error %lu!\n", GetLastError());
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
bStartedDoc = TRUE;
|
||||
|
||||
// Allocate a read buffer on the heap. This would easily exceed the stack size.
|
||||
pBuffer = DllAllocSplMem(cbReadBuffer);
|
||||
if (!pBuffer)
|
||||
{
|
||||
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Loop as long as data is available.
|
||||
while (ReadPrinter(hPrintJob, pBuffer, cbReadBuffer, &cbRead) && cbRead)
|
||||
{
|
||||
// Write it to the Print Monitor.
|
||||
WritePrinter(hPrintMonitor, pBuffer, cbRead, &cbWritten);
|
||||
}
|
||||
|
||||
dwErrorCode = ERROR_SUCCESS;
|
||||
|
||||
Cleanup:
|
||||
if (pBuffer)
|
||||
DllFreeSplMem(pBuffer);
|
||||
|
||||
if (bStartedDoc)
|
||||
EndDocPrinter(hPrintMonitor);
|
||||
|
||||
if (hPrintMonitor)
|
||||
ClosePrinter(hPrintMonitor);
|
||||
|
||||
if (hPrintJob)
|
||||
ClosePrinter(hPrintJob);
|
||||
|
||||
return dwErrorCode;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
@ stub ClosePrintProcessor
|
||||
@ stub ControlPrintProcessor
|
||||
@ stdcall ClosePrintProcessor(long)
|
||||
@ stdcall ControlPrintProcessor(long long)
|
||||
@ stdcall EnumPrintProcessorDatatypesW(ptr ptr long ptr long ptr ptr)
|
||||
@ stub GetPrintProcessorCapabilities
|
||||
@ stub OpenPrintProcessor
|
||||
@ stub PrintDocumentOnPrintProcessor
|
||||
@ stdcall GetPrintProcessorCapabilities(wstr long ptr long ptr)
|
||||
@ stdcall OpenPrintProcessor(wstr ptr)
|
||||
@ stdcall PrintDocumentOnPrintProcessor(long wstr)
|
||||
|
|
|
@ -267,6 +267,7 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
|
|||
pJob->pPrinter = pPrinterHandle->pPrinter;
|
||||
pJob->pPrintProcessor = pPrinterHandle->pPrinter->pPrintProcessor;
|
||||
pJob->dwPriority = DEF_PRIORITY;
|
||||
pJob->dwStatus = JOB_STATUS_SPOOLING;
|
||||
pJob->pwszDatatype = AllocSplStr(pPrinterHandle->pwszDatatype);
|
||||
pJob->pwszDocumentName = AllocSplStr(wszDefaultDocumentName);
|
||||
CopyMemory(&pJob->DevMode, &pPrinterHandle->DevMode, sizeof(DEVMODEW));
|
||||
|
@ -986,6 +987,65 @@ Cleanup:
|
|||
return (dwErrorCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
LocalScheduleJob(HANDLE hPrinter, DWORD dwJobID)
|
||||
{
|
||||
const WCHAR wszFolder[] = L"\\PRINTERS\\";
|
||||
const DWORD cchFolder = _countof(wszFolder) - 1;
|
||||
|
||||
DWORD dwAttributes;
|
||||
DWORD dwErrorCode;
|
||||
PLOCAL_HANDLE pHandle;
|
||||
PLOCAL_JOB pJob;
|
||||
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
||||
WCHAR wszFullPath[MAX_PATH];
|
||||
|
||||
// Check if this is a printer handle.
|
||||
pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||
if (pHandle->HandleType != Printer)
|
||||
{
|
||||
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
|
||||
|
||||
// Check if the Job ID is valid.
|
||||
pJob = LookupElementSkiplist(&GlobalJobList, &dwJobID, NULL);
|
||||
if (!pJob || pJob->pPrinter != pPrinterHandle->pPrinter)
|
||||
{
|
||||
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Construct the full path to the spool file.
|
||||
CopyMemory(wszFullPath, wszSpoolDirectory, cchSpoolDirectory * sizeof(WCHAR));
|
||||
CopyMemory(&wszFullPath[cchSpoolDirectory], wszFolder, cchFolder * sizeof(WCHAR));
|
||||
swprintf(&wszFullPath[cchSpoolDirectory + cchFolder], L"%05lu.SPL", dwJobID);
|
||||
|
||||
// Check if it exists.
|
||||
dwAttributes = GetFileAttributesW(wszFullPath);
|
||||
if (dwAttributes == INVALID_FILE_ATTRIBUTES || dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
dwErrorCode = ERROR_SPOOL_FILE_NOT_FOUND;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Switch from spooling to printing.
|
||||
pJob->dwStatus &= ~JOB_STATUS_SPOOLING;
|
||||
pJob->dwStatus |= JOB_STATUS_PRINTING;
|
||||
|
||||
// Write the job data into the shadow file.
|
||||
wcscpy(wcsrchr(wszFullPath, L'.'), L".SHD");
|
||||
WriteJobShadowFile(wszFullPath, pJob);
|
||||
|
||||
dwErrorCode = ERROR_SUCCESS;
|
||||
|
||||
Cleanup:
|
||||
SetLastError(dwErrorCode);
|
||||
return (dwErrorCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
PLOCAL_JOB
|
||||
ReadJobShadowFile(PCWSTR pwszFilePath)
|
||||
{
|
||||
|
@ -1001,7 +1061,7 @@ ReadJobShadowFile(PCWSTR pwszFilePath)
|
|||
PWSTR pwszPrintProcessor;
|
||||
|
||||
// Try to open the file.
|
||||
hFile = CreateFileW(pwszFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
hFile = CreateFileW(pwszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ERR("CreateFileW failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath);
|
||||
|
@ -1013,7 +1073,7 @@ ReadJobShadowFile(PCWSTR pwszFilePath)
|
|||
pShadowFile = DllAllocSplMem(cbFileSize);
|
||||
if (!pShadowFile)
|
||||
{
|
||||
ERR("DllAllocSplMem failed with error %lufor file \"%S\"!\n", GetLastError(), pwszFilePath);
|
||||
ERR("DllAllocSplMem failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
|
@ -1110,7 +1170,7 @@ WriteJobShadowFile(PWSTR pwszFilePath, const PLOCAL_JOB pJob)
|
|||
PSHD_HEADER pShadowFile = NULL;
|
||||
|
||||
// Try to open the SHD file.
|
||||
hSHDFile = CreateFileW(pwszFilePath, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);
|
||||
hSHDFile = CreateFileW(pwszFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (hSHDFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ERR("CreateFileW failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath);
|
||||
|
|
|
@ -60,7 +60,7 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
|
|||
NULL, // fpReadPrinter
|
||||
LocalEndDocPrinter, // fpEndDocPrinter
|
||||
LocalAddJob, // fpAddJob
|
||||
NULL, // fpScheduleJob
|
||||
LocalScheduleJob, // fpScheduleJob
|
||||
NULL, // fpGetPrinterData
|
||||
NULL, // fpSetPrinterData
|
||||
NULL, // fpWaitForPrinterChange
|
||||
|
|
|
@ -48,8 +48,8 @@ typedef BOOL (WINAPI *PPrintDocumentOnPrintProcessor)(HANDLE, LPWSTR);
|
|||
|
||||
// Structures
|
||||
/**
|
||||
* Describes a Print Processor.
|
||||
*/
|
||||
* Describes a Print Processor.
|
||||
*/
|
||||
typedef struct _LOCAL_PRINT_PROCESSOR
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
|
@ -189,6 +189,7 @@ void InitializePrinterJobList(PLOCAL_PRINTER pPrinter);
|
|||
BOOL WINAPI LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded);
|
||||
BOOL WINAPI LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
|
||||
BOOL WINAPI LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded);
|
||||
BOOL WINAPI LocalScheduleJob(HANDLE hPrinter, DWORD dwJobID);
|
||||
BOOL WINAPI LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command);
|
||||
PLOCAL_JOB ReadJobShadowFile(PCWSTR pwszFilePath);
|
||||
BOOL WriteJobShadowFile(PWSTR pwszFilePath, const PLOCAL_JOB pJob);
|
||||
|
|
Loading…
Reference in a new issue