reactos/win32ss/printing/providers/localspl/printingthread.c

130 lines
4.6 KiB
C

/*
* PROJECT: ReactOS Local Spooler
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Implementation of the Thread that actually performs the printing process
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
DWORD WINAPI
PrintingThreadProc(PLOCAL_JOB pJob)
{
const DWORD cchMaxJobIdDigits = 5; // Job ID is limited to 5 decimal digits, see IS_VALID_JOB_ID
const WCHAR wszJobAppendix[] = L", Job ";
const DWORD cchJobAppendix = _countof(wszJobAppendix) - 1;
const WCHAR wszPortAppendix[] = L", Port";
DWORD cchPortName;
DWORD cchPrinterName;
DWORD dwErrorCode;
HANDLE hPrintProcessor = NULL;
PLOCAL_PRINT_PROCESSOR pPrintProcessor = pJob->pPrintProcessor;
PRINTPROCESSOROPENDATA OpenData;
PWSTR pwszPrinterAndJob = NULL;
PWSTR pwszPrinterPort = NULL;
PWSTR pwszSPLFile = NULL;
TRACE("PrintingThreadProc(%p)\n", pJob);
// Prepare the pPrinterName parameter.
// This is the string for LocalOpenPrinter to open a port (e.g. "LPT1:, Port").
cchPortName = wcslen(pJob->pPrinter->pPort->pwszName);
pwszPrinterPort = DllAllocSplMem(cchPortName * sizeof(WCHAR) + sizeof(wszPortAppendix));
if (!pwszPrinterPort)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
CopyMemory(pwszPrinterPort, pJob->pPrinter->pPort->pwszName, cchPortName * sizeof(WCHAR));
CopyMemory(&pwszPrinterPort[cchPortName], wszPortAppendix, sizeof(wszPortAppendix));
// Prepare the pPrintProcessorOpenData parameter.
OpenData.JobId = pJob->dwJobID;
OpenData.pDatatype = pJob->pwszDatatype;
OpenData.pDevMode = pJob->pDevMode;
OpenData.pDocumentName = pJob->pwszDocumentName;
OpenData.pOutputFile = NULL;
OpenData.pParameters = pJob->pwszPrintProcessorParameters;
OpenData.pPrinterName = pJob->pPrinter->pwszPrinterName;
// Associate our job to the port. The next port handle created through LocalOpenPrinter will pick this up.
// LocalStartDocPrinter needs this information to call StartDocPort of the Print Monitor, but as the parameters
// for LocalOpenPrinter and LocalStartDocPrinter are fixed, we can only pass over the information this way.
pJob->pPrinter->pPort->pNextJobToProcess = pJob;
// Open a handle to the Print Processor.
hPrintProcessor = pPrintProcessor->pfnOpenPrintProcessor(pwszPrinterPort, &OpenData);
if (!hPrintProcessor)
{
dwErrorCode = GetLastError();
ERR("OpenPrintProcessor failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
// Let other functions use the Print Processor as well while it's opened.
pJob->hPrintProcessor = hPrintProcessor;
// Prepare the pDocumentName parameter.
cchPrinterName = wcslen(OpenData.pPrinterName);
pwszPrinterAndJob = DllAllocSplMem((cchPrinterName + cchJobAppendix + cchMaxJobIdDigits + 1) * sizeof(WCHAR));
if (!pwszPrinterAndJob)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
CopyMemory(pwszPrinterAndJob, OpenData.pPrinterName, cchPrinterName * sizeof(WCHAR));
CopyMemory(&pwszPrinterAndJob[cchPrinterName], wszJobAppendix, cchJobAppendix * sizeof(WCHAR));
_ultow(OpenData.JobId, &pwszPrinterAndJob[cchPrinterName + cchJobAppendix], 10);
// Printing starts here.
pJob->dwStatus |= JOB_STATUS_PRINTING;
// Print the document.
// Note that pJob is freed after this function, so we may not access it anymore.
if (!pPrintProcessor->pfnPrintDocumentOnPrintProcessor(hPrintProcessor, pwszPrinterAndJob))
{
dwErrorCode = GetLastError();
ERR("PrintDocumentOnPrintProcessor failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
// Close the Print Processor.
pPrintProcessor->pfnClosePrintProcessor(hPrintProcessor);
hPrintProcessor = NULL;
// Delete the spool file.
pwszSPLFile = DllAllocSplMem(GetJobFilePath(L"SPL", 0, NULL));
if (!pwszSPLFile)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
GetJobFilePath(L"SPL", OpenData.JobId, pwszSPLFile);
DeleteFileW(pwszSPLFile);
// We were successful!
dwErrorCode = ERROR_SUCCESS;
Cleanup:
if (hPrintProcessor)
pPrintProcessor->pfnClosePrintProcessor(hPrintProcessor);
if (pwszPrinterPort)
DllFreeSplMem(pwszPrinterPort);
if (pwszPrinterAndJob)
DllFreeSplMem(pwszPrinterAndJob);
if (pwszSPLFile)
DllFreeSplMem(pwszSPLFile);
return dwErrorCode;
}