[PRINTING] Semi-implement GetPrinterDriverW

CORE-15522
This commit is contained in:
Mark Jansen 2018-12-29 23:51:32 +01:00
parent 2e4457f223
commit 796dd5f53c
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
7 changed files with 340 additions and 4 deletions

View file

@ -6,6 +6,7 @@
*/ */
#include "precomp.h" #include "precomp.h"
#include "marshalling/printerdrivers.h"
DWORD DWORD
_RpcAddPrinterDriver(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer) _RpcAddPrinterDriver(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer)
@ -45,8 +46,33 @@ _RpcEnumPrinterDrivers(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level,
DWORD DWORD
_RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWORD Level, BYTE* pDriver, DWORD cbBuf, DWORD* pcbNeeded) _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWORD Level, BYTE* pDriver, DWORD cbBuf, DWORD* pcbNeeded)
{ {
UNIMPLEMENTED; DWORD dwErrorCode;
return ERROR_INVALID_FUNCTION; PBYTE pDriverAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
return dwErrorCode;
}
pDriverAligned = AlignRpcPtr(pDriver, &cbBuf);
if (GetPrinterDriverW(hPrinter, pEnvironment, Level, pDriverAligned, cbBuf, pcbNeeded))
{
// Replace relative offset addresses in the output by absolute pointers.
ASSERT(Level >= 1 && Level <= 3);
MarshallDownStructure(pDriverAligned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pDriver, pDriverAligned, cbBuf, pcbNeeded);
return dwErrorCode;
} }
DWORD DWORD

View file

@ -7,6 +7,7 @@
#include "precomp.h" #include "precomp.h"
#include <marshalling/printers.h> #include <marshalling/printers.h>
#include <marshalling/printerdrivers.h>
// Local Constants // Local Constants
@ -513,8 +514,50 @@ GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriv
BOOL WINAPI BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded) GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
{ {
DWORD dwErrorCode;
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
TRACE("GetPrinterDriverW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); TRACE("GetPrinterDriverW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
return FALSE;
// Sanity checks.
if (!pHandle)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
// Dismiss invalid levels already at this point.
if (Level > 8 || Level < 1)
{
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
if (cbBuf && pDriverInfo)
ZeroMemory(pDriverInfo, cbBuf);
// Do the RPC call
RpcTryExcept
{
dwErrorCode = _RpcGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcGetPrinter failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
if (dwErrorCode == ERROR_SUCCESS)
{
// Replace relative offset addresses in the output by absolute pointers.
ASSERT(Level <= 3);
MarshallUpStructure(cbBuf, pDriverInfo, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
}
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
} }
BOOL WINAPI BOOL WINAPI

View file

@ -0,0 +1,51 @@
/*
* PROJECT: ReactOS Printing Stack Marshalling Functions
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Marshalling definitions for DRIVER_INFO_*
* COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
*/
static const MARSHALLING PrinterDriver1Marshalling = {
sizeof(DRIVER_INFO_1W),
{
{ FIELD_OFFSET(DRIVER_INFO_1W, pName), RTL_FIELD_SIZE(DRIVER_INFO_1W, pName), RTL_FIELD_SIZE(DRIVER_INFO_1W, pName), TRUE },
{ MAXDWORD, 0, 0, FALSE }
}
};
static const MARSHALLING PrinterDriver2Marshalling = {
sizeof(DRIVER_INFO_2W),
{
{ FIELD_OFFSET(DRIVER_INFO_2W, pName), RTL_FIELD_SIZE(DRIVER_INFO_2W, pName), RTL_FIELD_SIZE(DRIVER_INFO_2W, pName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_2W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_2W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_2W, pEnvironment), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_2W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_2W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_2W, pDriverPath), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_2W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_2W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_2W, pDataFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_2W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_2W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_2W, pConfigFile), TRUE },
{ MAXDWORD, 0, 0, FALSE }
}
};
static const MARSHALLING PrinterDriver3Marshalling = {
sizeof(DRIVER_INFO_3W),
{
{ FIELD_OFFSET(DRIVER_INFO_3W, pName), RTL_FIELD_SIZE(DRIVER_INFO_3W, pName), RTL_FIELD_SIZE(DRIVER_INFO_3W, pName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_3W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_3W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_3W, pEnvironment), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_3W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_3W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_3W, pDriverPath), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_3W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_3W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_3W, pDataFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_3W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_3W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_3W, pConfigFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_3W, pHelpFile), RTL_FIELD_SIZE(DRIVER_INFO_3W, pHelpFile), RTL_FIELD_SIZE(DRIVER_INFO_3W, pHelpFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_3W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_3W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_3W, pDependentFiles), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_3W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_3W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_3W, pMonitorName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_3W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_3W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_3W, pDefaultDataType), TRUE },
{ MAXDWORD, 0, 0, FALSE }
}
};
static const MARSHALLING* pPrinterDriverMarshalling[] = {
NULL,
&PrinterDriver1Marshalling,
&PrinterDriver2Marshalling,
&PrinterDriver3Marshalling,
};

View file

@ -10,6 +10,7 @@ list(APPEND SOURCE
ports.c ports.c
precomp.h precomp.h
printerdata.c printerdata.c
printerdrivers.c
printers.c printers.c
printingthread.c printingthread.c
printprocessors.c printprocessors.c

View file

@ -43,7 +43,7 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
LocalEnumPrinters, // fpEnumPrinters LocalEnumPrinters, // fpEnumPrinters
NULL, // fpAddPrinterDriver NULL, // fpAddPrinterDriver
NULL, // fpEnumPrinterDrivers NULL, // fpEnumPrinterDrivers
NULL, // fpGetPrinterDriver LocalGetPrinterDriver, // fpGetPrinterDriver
NULL, // fpGetPrinterDriverDirectory NULL, // fpGetPrinterDriverDirectory
NULL, // fpDeletePrinterDriver NULL, // fpDeletePrinterDriver
NULL, // fpAddPrintProcessor NULL, // fpAddPrintProcessor

View file

@ -287,6 +287,10 @@ DWORD WINAPI LocalGetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pVal
DWORD WINAPI LocalSetPrinterData(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData); DWORD WINAPI LocalSetPrinterData(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData);
DWORD WINAPI LocalSetPrinterDataEx(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData); DWORD WINAPI LocalSetPrinterDataEx(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData);
// printerdriver.c
BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded);
// printers.c // printers.c
extern SKIPLIST PrinterList; extern SKIPLIST PrinterList;
BOOL InitializePrinterList(void); BOOL InitializePrinterList(void);

View file

@ -0,0 +1,211 @@
/*
* PROJECT: ReactOS Local Spooler
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions for printer driver information
* COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
*/
#include "precomp.h"
// Local Constants
static DWORD dwDriverInfo1Offsets[] = {
FIELD_OFFSET(DRIVER_INFO_1W, pName),
MAXDWORD
};
static DWORD dwDriverInfo2Offsets[] = {
FIELD_OFFSET(DRIVER_INFO_2W, pName),
FIELD_OFFSET(DRIVER_INFO_2W, pEnvironment),
FIELD_OFFSET(DRIVER_INFO_2W, pDriverPath),
FIELD_OFFSET(DRIVER_INFO_2W, pDataFile),
FIELD_OFFSET(DRIVER_INFO_2W, pConfigFile),
MAXDWORD
};
static DWORD dwDriverInfo3Offsets[] = {
FIELD_OFFSET(DRIVER_INFO_3W, pName),
FIELD_OFFSET(DRIVER_INFO_3W, pEnvironment),
FIELD_OFFSET(DRIVER_INFO_3W, pDriverPath),
FIELD_OFFSET(DRIVER_INFO_3W, pDataFile),
FIELD_OFFSET(DRIVER_INFO_3W, pConfigFile),
FIELD_OFFSET(DRIVER_INFO_3W, pHelpFile),
FIELD_OFFSET(DRIVER_INFO_3W, pDependentFiles),
FIELD_OFFSET(DRIVER_INFO_3W, pMonitorName),
FIELD_OFFSET(DRIVER_INFO_3W, pDefaultDataType),
MAXDWORD
};
static void
ToMultiSz(LPWSTR pString)
{
while (*pString)
{
if (*pString == '|')
*pString = '\0';
pString++;
}
}
static void
_LocalGetPrinterDriverLevel1(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_1W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[1];
/* This value is only here to send something, I have not verified if it is actually correct */
pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver;
// Calculate the string lengths.
if (!ppDriverInfo)
{
for (n = 0; n < _countof(pwszStrings); ++n)
{
*pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
}
*pcbNeeded += sizeof(DRIVER_INFO_1W);
return;
}
// Finally copy the structure and advance to the next one in the output buffer.
*ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo1Offsets, *ppDriverInfoEnd);
(*ppDriverInfo)++;
}
static void
_LocalGetPrinterDriverLevel2(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_2W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[5];
/* Clearly these things should not be hardcoded, so when it is needed, someone can add meaningfull values here */
pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
pwszStrings[2] = L"c:\\reactos\\system32\\localspl.dll"; // pDriverPath
pwszStrings[3] = L"c:\\reactos\\system32\\localspl.dll"; // pDataFile
pwszStrings[4] = L"c:\\reactos\\system32\\localspl.dll"; // pConfigFile
// Calculate the string lengths.
if (!ppDriverInfo)
{
for (n = 0; n < _countof(pwszStrings); ++n)
{
*pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
}
*pcbNeeded += sizeof(DRIVER_INFO_2W);
return;
}
(*ppDriverInfo)->cVersion = 3;
// Finally copy the structure and advance to the next one in the output buffer.
*ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo2Offsets, *ppDriverInfoEnd);
(*ppDriverInfo)++;
}
static void
_LocalGetPrinterDriverLevel3(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_3W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[9];
/* Clearly these things should not be hardcoded, so when it is needed, someone can add meaningfull values here */
pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
pwszStrings[2] = L"c:\\reactos\\system32\\localspl.dll"; // pDriverPath
pwszStrings[3] = L"c:\\reactos\\system32\\localspl.dll"; // pDataFile
pwszStrings[4] = L"c:\\reactos\\system32\\printui.dll"; // pConfigFile
pwszStrings[5] = L""; // pHelpFile
pwszStrings[6] = L"localspl.dll|printui.dll|"; // pDependentFiles, | is separator and terminator!
pwszStrings[7] = NULL; // pMonitorName
pwszStrings[8] = NULL; // pDefaultDataType
// Calculate the string lengths.
if (!ppDriverInfo)
{
for (n = 0; n < _countof(pwszStrings); ++n)
{
if (pwszStrings[n])
{
*pcbNeeded += (wcslen(pwszStrings[n]) + 1) * sizeof(WCHAR);
}
}
*pcbNeeded += sizeof(DRIVER_INFO_3W);
return;
}
(*ppDriverInfo)->cVersion = 3;
// Finally copy the structure and advance to the next one in the output buffer.
*ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo3Offsets, *ppDriverInfoEnd);
ToMultiSz((*ppDriverInfo)->pDependentFiles);
(*ppDriverInfo)++;
}
BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
{
DWORD dwErrorCode;
PBYTE pEnd = &pDriverInfo[cbBuf];
PLOCAL_HANDLE pHandle;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
// Only support 3 levels for now
if (Level > 3)
{
// The caller supplied an invalid level.
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
// Count the required buffer size.
*pcbNeeded = 0;
if (Level == 1)
_LocalGetPrinterDriverLevel1(pPrinterHandle, NULL, NULL, pcbNeeded);
else if (Level == 2)
_LocalGetPrinterDriverLevel2(pPrinterHandle, NULL, NULL, pcbNeeded);
else if (Level == 3)
_LocalGetPrinterDriverLevel3(pPrinterHandle, NULL, NULL, pcbNeeded);
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// Copy over the information.
pEnd = &pDriverInfo[*pcbNeeded];
if (Level == 1)
_LocalGetPrinterDriverLevel1(pPrinterHandle, (PDRIVER_INFO_1W*)&pDriverInfo, &pEnd, NULL);
else if (Level == 2)
_LocalGetPrinterDriverLevel2(pPrinterHandle, (PDRIVER_INFO_2W*)&pDriverInfo, &pEnd, NULL);
else if (Level == 3)
_LocalGetPrinterDriverLevel3(pPrinterHandle, (PDRIVER_INFO_3W*)&pDriverInfo, &pEnd, NULL);
dwErrorCode = ERROR_SUCCESS;
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}