2 * PROJECT: ReactOS Local Spooler
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Implementation of the Thread that actually performs the printing process
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
11 PrintingThreadProc(PLOCAL_JOB pJob
)
13 const DWORD cchMaxJobIdDigits
= 5; // Job ID is limited to 5 decimal digits, see IS_VALID_JOB_ID
14 const WCHAR wszJobAppendix
[] = L
", Job ";
15 const DWORD cchJobAppendix
= _countof(wszJobAppendix
) - 1;
16 const WCHAR wszPortAppendix
[] = L
", Port";
21 HANDLE hPrintProcessor
= NULL
;
22 PLOCAL_PRINT_PROCESSOR pPrintProcessor
= pJob
->pPrintProcessor
;
23 PRINTPROCESSOROPENDATA OpenData
;
24 PWSTR pwszPrinterAndJob
= NULL
;
25 PWSTR pwszPrinterPort
= NULL
;
26 PWSTR pwszSPLFile
= NULL
;
28 TRACE("PrintingThreadProc(%p)\n", pJob
);
30 // Prepare the pPrinterName parameter.
31 // This is the string for LocalOpenPrinter to open a port (e.g. "LPT1:, Port").
32 cchPortName
= wcslen(pJob
->pPrinter
->pPort
->pwszName
);
33 pwszPrinterPort
= DllAllocSplMem(cchPortName
* sizeof(WCHAR
) + sizeof(wszPortAppendix
));
36 dwErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
37 ERR("DllAllocSplMem failed!\n");
41 CopyMemory(pwszPrinterPort
, pJob
->pPrinter
->pPort
->pwszName
, cchPortName
* sizeof(WCHAR
));
42 CopyMemory(&pwszPrinterPort
[cchPortName
], wszPortAppendix
, sizeof(wszPortAppendix
));
44 // Prepare the pPrintProcessorOpenData parameter.
45 OpenData
.JobId
= pJob
->dwJobID
;
46 OpenData
.pDatatype
= pJob
->pwszDatatype
;
47 OpenData
.pDevMode
= pJob
->pDevMode
;
48 OpenData
.pDocumentName
= pJob
->pwszDocumentName
;
49 OpenData
.pOutputFile
= NULL
;
50 OpenData
.pParameters
= pJob
->pwszPrintProcessorParameters
;
51 OpenData
.pPrinterName
= pJob
->pPrinter
->pwszPrinterName
;
53 // Associate our job to the port. The next port handle created through LocalOpenPrinter will pick this up.
54 // LocalStartDocPrinter needs this information to call StartDocPort of the Print Monitor, but as the parameters
55 // for LocalOpenPrinter and LocalStartDocPrinter are fixed, we can only pass over the information this way.
56 pJob
->pPrinter
->pPort
->pNextJobToProcess
= pJob
;
58 // Open a handle to the Print Processor.
59 hPrintProcessor
= pPrintProcessor
->pfnOpenPrintProcessor(pwszPrinterPort
, &OpenData
);
62 dwErrorCode
= GetLastError();
63 ERR("OpenPrintProcessor failed with error %lu!\n", dwErrorCode
);
67 // Let other functions use the Print Processor as well while it's opened.
68 pJob
->hPrintProcessor
= hPrintProcessor
;
70 // Prepare the pDocumentName parameter.
71 cchPrinterName
= wcslen(OpenData
.pPrinterName
);
72 pwszPrinterAndJob
= DllAllocSplMem((cchPrinterName
+ cchJobAppendix
+ cchMaxJobIdDigits
+ 1) * sizeof(WCHAR
));
73 if (!pwszPrinterAndJob
)
75 dwErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
76 ERR("DllAllocSplMem failed!\n");
80 CopyMemory(pwszPrinterAndJob
, OpenData
.pPrinterName
, cchPrinterName
* sizeof(WCHAR
));
81 CopyMemory(&pwszPrinterAndJob
[cchPrinterName
], wszJobAppendix
, cchJobAppendix
* sizeof(WCHAR
));
82 _ultow(OpenData
.JobId
, &pwszPrinterAndJob
[cchPrinterName
+ cchJobAppendix
], 10);
84 // Printing starts here.
85 pJob
->dwStatus
|= JOB_STATUS_PRINTING
;
87 // Print the document.
88 // Note that pJob is freed after this function, so we may not access it anymore.
89 if (!pPrintProcessor
->pfnPrintDocumentOnPrintProcessor(hPrintProcessor
, pwszPrinterAndJob
))
91 dwErrorCode
= GetLastError();
92 ERR("PrintDocumentOnPrintProcessor failed with error %lu!\n", dwErrorCode
);
96 // Close the Print Processor.
97 pPrintProcessor
->pfnClosePrintProcessor(hPrintProcessor
);
98 hPrintProcessor
= NULL
;
100 // Delete the spool file.
101 pwszSPLFile
= DllAllocSplMem(GetJobFilePath(L
"SPL", 0, NULL
));
104 dwErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
105 ERR("DllAllocSplMem failed!\n");
109 GetJobFilePath(L
"SPL", OpenData
.JobId
, pwszSPLFile
);
110 DeleteFileW(pwszSPLFile
);
112 // We were successful!
113 dwErrorCode
= ERROR_SUCCESS
;
117 pPrintProcessor
->pfnClosePrintProcessor(hPrintProcessor
);
120 DllFreeSplMem(pwszPrinterPort
);
122 if (pwszPrinterAndJob
)
123 DllFreeSplMem(pwszPrinterAndJob
);
126 DllFreeSplMem(pwszSPLFile
);