reactos/win32ss/printing/processors/winprint/main.c

279 lines
8.4 KiB
C

/*
* PROJECT: ReactOS Standard Print Processor
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Main functions
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
// 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;
TRACE("ClosePrintProcessor(%p)\n", hPrintProcessor);
// 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)
{
TRACE("ControlPrintProcessor(%p, %lu)\n", hPrintProcessor, Command);
UNIMPLEMENTED;
return FALSE;
}
/**
* @name EnumPrintProcessorDatatypesW
*
* Obtains an array of all datatypes supported by this Print Processor.
*
* @param pName
* Server Name. Ignored here, because every caller of EnumPrintProcessorDatatypesW is interested in this Print Processor's information.
*
* @param pPrintProcessorName
* Print Processor Name. Ignored here, because every caller of EnumPrintProcessorDatatypesW is interested in this Print Processor's information.
*
* @param Level
* The level of the structure supplied through pDatatypes. This must be 1.
*
* @param pDatatypes
* Pointer to the buffer that receives an array of DATATYPES_INFO_1W structures.
* Can be NULL if you just want to know the required size of the buffer.
*
* @param cbBuf
* Size of the buffer you supplied for pDatatypes, in bytes.
*
* @param pcbNeeded
* Pointer to a variable that receives the required size of the buffer for pDatatypes, in bytes.
* This parameter mustn't be NULL!
*
* @param pcReturned
* Pointer to a variable that receives the number of elements of the DATATYPES_INFO_1W array.
* This parameter mustn't be NULL!
*
* @return
* TRUE if we successfully copied the array into pDatatypes, FALSE otherwise.
* A more specific error code can be obtained through GetLastError.
*/
BOOL WINAPI
EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
DWORD cbDatatype;
DWORD dwDatatypeCount = 0;
DWORD dwOffsets[_countof(_pwszDatatypes)];
PCWSTR* pCurrentDatatype;
PDWORD pCurrentOffset = dwOffsets;
TRACE("EnumPrintProcessorDatatypesW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
// Sanity checks
if (Level != 1 || !pcbNeeded || !pcReturned)
return FALSE;
// Count the required buffer size and the number of datatypes.
*pcbNeeded = 0;
*pcReturned = 0;
for (pCurrentDatatype = _pwszDatatypes; *pCurrentDatatype; pCurrentDatatype++)
{
cbDatatype = (wcslen(*pCurrentDatatype) + 1) * sizeof(WCHAR);
*pcbNeeded += sizeof(DATATYPES_INFO_1W) + cbDatatype;
// Also calculate the offset in the output buffer of the pointer to this datatype string.
*pCurrentOffset = dwDatatypeCount * sizeof(DATATYPES_INFO_1W) + FIELD_OFFSET(DATATYPES_INFO_1W, pName);
dwDatatypeCount++;
pCurrentOffset++;
}
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
// Check if a buffer was supplied at all.
if (!pDatatypes)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
// Copy over all datatypes.
*pCurrentOffset = MAXDWORD;
PackStrings(_pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]);
*pcReturned = dwDatatypeCount;
return TRUE;
}
DWORD WINAPI
GetPrintProcessorCapabilities(PWSTR pValueName, DWORD dwAttributes, PBYTE pData, DWORD nSize, PDWORD pcbNeeded)
{
TRACE("GetPrintProcessorCapabilities(%S, %lu, %p, %lu, %p)\n", pValueName, dwAttributes, pData, nSize, 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;
TRACE("OpenPrintProcessor(%S, %p)\n", pPrinterName, pPrintProcessorOpenData);
// 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(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;
TRACE("PrintDocumentOnPrintProcessor(%p, %S)\n", hPrintProcessor, pDocumentName);
// 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);
}