[0.4.13][PRINTING] Fix regression CORE-16622 in comdlg32:printdlg ANSI

A very nice set of patches done by Doug Lyons!, Jim Tabor, Colin Finck
to fix:
- a crash on the testbots for comdlg32:printdlg
- erroneous behavior of PrintDlg in _A()-application "Kompozer", namely
  - prevents exceptions from being thrown when opening the print dlg
  - prevents heap allocations of 0 byte size when opening the print dlg
  - prevents a help-button that should be invisible from overlapping other controls
  - allows Kompozer to extend the print-dialog with additional controls
  - allows combobox to show the printers name, instead of memory garbage

[PRINTING] Improve Stubs for GetPrinterA and GetPrinterDeviceA (#2274)
cherry picked from commit 0.4.14-dev-849-g
acec69a1d7

[WINSPOOL] Add Implementation of EnumPrintersA (#2273)
cherry picked from commit 0.4.14-dev-878-g
e8b177825b

[FORMATTING] Fix indentation of winspool/printers.c
No code changes
cherry picked from commit 0.4.14-dev-879-g
45f39ffc25

[PRINTING] Part of GDI Support
Fix ups and added support to prevent GDI from crashing. These functions
will be required for GDI.
Part 1 of print support.
cherry picked from commit 0.4.14-dev-880-g
adffa8ea75

[WINSPOOL] printers.c: Demote 3 ERR() to TRACE(), Fix 1 copypasta (#2311)
cherry picked from commit 0.4.14-dev-889-g
06f8f80181

[WINSPOOL] Implement GetPrinterDriverA and a helper function UnicodeToAnsiInPlace (#2317)
cherry picked from commit 0.4.14-dev-957-g
d90beaeed2

[WINSPOOL] Fix build
cherry picked from commit 0.4.14-dev-958-g
8da7fbc704

[GDI32] GdiConvertToDevmodeW:
Import WINE commit 32393796bb534e9cf11dd988dce88722c67f7906
("gdi32: GdiConvertToDevmodeW should not refer to unintialized name bytes.")
This makes our GdiConvertToDevmodeW equivalent to the WINE counterpart again.
cherry picked from commit 0.4.14-dev-1031-g
5d8c39753e

[WINSPOOL] Implement DocumentPropertiesA including DEVMODE conversions (#2339)
Co-authored-by: Doug Lyons <douglyons@douglyons.com>
Co-authored-by: Colin Finck <colin@reactos.org>
cherry picked from commit 0.4.14-dev-1035-g
3077c0e43e
This commit is contained in:
Joachim Henze 2020-02-26 23:21:00 +01:00
parent 138d9acd79
commit 818e5bc752
10 changed files with 1523 additions and 19 deletions

View file

@ -962,6 +962,7 @@ bMakePathNameW(LPWSTR lpBuffer,LPCWSTR lpFileName,LPWSTR *lpFilePart,DWORD unkno
/*
* @implemented
* Synchronized with WINE dlls/gdi32/driver.c
*/
DEVMODEW *
WINAPI
@ -986,15 +987,19 @@ GdiConvertToDevmodeW(const DEVMODEA *dmA)
dmW = HeapAlloc(GetProcessHeap(), 0, dmW_size + dmA->dmDriverExtra);
if (!dmW) return NULL;
MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmDeviceName, CCHDEVICENAME,
dmW->dmDeviceName, CCHDEVICENAME);
MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmDeviceName, -1,
dmW->dmDeviceName, CCHDEVICENAME);
/* copy slightly more, to avoid long computations */
memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion, dmA_size - CCHDEVICENAME);
if (dmA_size >= FIELD_OFFSET(DEVMODEA, dmFormName) + CCHFORMNAME)
{
MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmFormName, CCHFORMNAME,
dmW->dmFormName, CCHFORMNAME);
if (dmA->dmFields & DM_FORMNAME)
MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmFormName, -1,
dmW->dmFormName, CCHFORMNAME);
else
dmW->dmFormName[0] = 0;
if (dmA_size > FIELD_OFFSET(DEVMODEA, dmLogPixels))
memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA_size - FIELD_OFFSET(DEVMODEA, dmLogPixels));
}

View file

@ -49,6 +49,8 @@ _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWOR
DWORD dwErrorCode;
PBYTE pDriverAligned;
ERR("_RpcGetPrinterDriver(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriver, cbBuf, pcbNeeded);
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
@ -61,7 +63,7 @@ _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWOR
if (GetPrinterDriverW(hPrinter, pEnvironment, Level, pDriverAligned, cbBuf, pcbNeeded))
{
// Replace relative offset addresses in the output by absolute pointers.
ASSERT(Level >= 1 && Level <= 3);
ASSERT(Level >= 1 && Level <= 5);
MarshallDownStructure(pDriverAligned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
}
else

View file

@ -17,6 +17,7 @@ list(APPEND SOURCE
printers.c
printprocessors.c
printproviders.c
utils.c
${CMAKE_CURRENT_BINARY_DIR}/winspool_c.c)
add_library(winspool MODULE

View file

@ -233,3 +233,82 @@ Failure:
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW pDevModeOutput)
{
// FIXME: This function should become ConvertAnsiDevModeToUnicodeDevmode when its parameters are known!
// Check if a pDevModeInput and pDevModeOutput are both not NULL.
if (!pDevModeInput || !pDevModeOutput)
return;
pDevModeOutput = GdiConvertToDevmodeW(pDevModeInput);
}
// Internal counterpart to GdiConvertToDevmodeW from gdi32
static __inline DEVMODEA*
_ConvertToDevmodeA(const DEVMODEW *dmW)
{
DEVMODEA *dmA;
WORD dmA_size, dmW_size;
size_t BytesToCopy;
dmW_size = dmW->dmSize;
/* this is the minimal dmSize that XP accepts */
if (dmW_size < FIELD_OFFSET(DEVMODEW, dmFields))
return NULL;
// Guard against callers that set dmSize incorrectly.
if (dmW_size > sizeof(DEVMODEW))
dmW_size = sizeof(DEVMODEW);
// dmA_size must become dmW_size without the additional 1 byte per character for each Unicode string (dmDeviceName and dmFormName).
dmA_size = dmW_size - CCHDEVICENAME;
if (dmW_size >= FIELD_OFFSET(DEVMODEW, dmFormName) + CCHFORMNAME * sizeof(WCHAR))
dmA_size -= CCHFORMNAME;
// Allocate the required bytes, that is dmSize for the ANSI DEVMODEA structure plus any extra bytes requested through dmDriverExtra.
dmA = HeapAlloc(GetProcessHeap(), 0, dmA_size + dmW->dmDriverExtra);
if (!dmA) return NULL;
// Every valid DEVMODEW has a dmDeviceName, which we convert to ANSI here.
WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, (LPSTR)dmA->dmDeviceName, CCHDEVICENAME, NULL, NULL);
// Copy everything up to dmFormName or the remaining dmW_size, whatever is smaller.
BytesToCopy = min(FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion), dmW_size - CCHDEVICENAME * sizeof(WCHAR));
memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion, BytesToCopy);
// Handle dmFormName if the input DEVMODEW is large enough to contain one.
if (dmW_size >= FIELD_OFFSET(DEVMODEW, dmFormName) + CCHFORMNAME * sizeof(WCHAR))
{
if (dmW->dmFields & DM_FORMNAME)
WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, (LPSTR)dmA->dmFormName, CCHFORMNAME, NULL, NULL);
else
dmA->dmFormName[0] = 0;
// Copy the remaining fields.
if (dmW_size > FIELD_OFFSET(DEVMODEW, dmLogPixels))
memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW_size - FIELD_OFFSET(DEVMODEW, dmLogPixels));
}
// Append dmDriverExtra if required.
if (dmW->dmDriverExtra)
memcpy((char *)dmA + dmA_size, (const char *)dmW + dmW_size, dmW->dmDriverExtra);
// Set the corrected dmSize and we are done.
dmA->dmSize = dmA_size;
return dmA;
}
void RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput, PDEVMODEA pDevModeOutput)
{
// FIXME: This function should become ConvertUnicodeDevModeToAnsiDevmode when its parameters are known!
// Check if a pDevModeInput and pDevModeOutput are both not NULL.
if (!pDevModeInput || !pDevModeOutput)
return;
pDevModeOutput = _ConvertToDevmodeA(pDevModeInput);
}

View file

@ -15,7 +15,9 @@
#include <winreg.h>
#include <winspool.h>
#include <winspool_c.h>
#include <winddiui.h>
#include <ndk/rtlfuncs.h>
#include <strsafe.h>
#include <spoolss.h>
#include <marshalling/marshalling.h>
@ -39,4 +41,12 @@ SPOOLER_HANDLE, *PSPOOLER_HANDLE;
// main.c
extern HANDLE hProcessHeap;
// utils.c
extern BOOL UnicodeToAnsiInPlace(PWSTR pwszField);
// devmode.c
extern void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW pDevModeOutput);
extern void RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput, PDEVMODEA pDevModeOutput);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,55 @@
/*
* PROJECT: ReactOS Spooler API
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Utility Functions related to Print Processors
* COPYRIGHT: Copyright 2020 Doug Lyons (douglyons@douglyons.com)
*/
#include "precomp.h"
BOOL UnicodeToAnsiInPlace(PWSTR pwszField)
{
/*
* This converts an incoming Unicode string to an ANSI string.
* It returns FALSE on failure, otherwise it returns TRUE.
* It is only useful for "in-place" conversions where the ANSI string goes
* back into the same place where the Unicode string came into this function.
* It seems that many of the functions involving printing can use this.
*/
PSTR pszTemp;
DWORD cch;
/*
* Map the incoming Unicode pwszField string to an ANSI one here so that we can do
* in-place conversion. We read the Unicode input and then we write back the ANSI
* conversion into the same buffer for use with our GetPrinterDriverA function
*/
PSTR pszField = (PSTR)pwszField;
if (!pwszField)
{
return TRUE;
}
cch = wcslen(pwszField);
if (cch == 0)
{
return TRUE;
}
pszTemp = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
if (!pszField)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
ERR("HeapAlloc failed!\n");
return FALSE; // indicates a failure to be handled by caller
}
WideCharToMultiByte(CP_ACP, 0, pwszField, -1, pszTemp, cch + 1, NULL, NULL);
StringCchCopyA(pszField, cch + 1, pszTemp);
HeapFree(hProcessHeap, 0, pszTemp);
return TRUE;
}

View file

@ -74,7 +74,7 @@
173 stdcall DeviceCapabilitiesW(wstr wstr long ptr ptr)
174 stub DeviceMode
175 stub DevicePropertySheets
176 stub DocumentEvent
176 stdcall DocumentEvent(ptr ptr long long ptr long ptr)
177 stdcall DocumentPropertiesA(ptr ptr ptr ptr ptr long)
178 stdcall DocumentPropertiesW(ptr ptr ptr ptr ptr long)
179 stub DocumentPropertySheets
@ -186,7 +186,7 @@
285 stdcall SetPrinterDataExW(ptr wstr wstr long ptr long)
286 stdcall SetPrinterDataW(ptr wstr long ptr long)
287 stdcall SetPrinterW(ptr long ptr long)
288 stub SplDriverUnloadComplete
288 stdcall SplDriverUnloadComplete(ptr)
289 stub SpoolerDevQueryPrintW
290 stdcall SpoolerInit()
291 stub SpoolerPrinterEvent

View file

@ -41,6 +41,34 @@ static const MARSHALLING PrinterDriver3Marshalling = {
}
};
static const MARSHALLING PrinterDriver4Marshalling = {
sizeof(DRIVER_INFO_4W),
{
{ FIELD_OFFSET(DRIVER_INFO_4W, pName), RTL_FIELD_SIZE(DRIVER_INFO_4W, pName), RTL_FIELD_SIZE(DRIVER_INFO_4W, pName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_4W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_4W, pEnvironment), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDriverPath), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDataFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_4W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_4W, pConfigFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pHelpFile), RTL_FIELD_SIZE(DRIVER_INFO_4W, pHelpFile), RTL_FIELD_SIZE(DRIVER_INFO_4W, pHelpFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDependentFiles), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_4W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_4W, pMonitorName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDefaultDataType), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_4W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDefaultDataType), TRUE },
{ MAXDWORD, 0, 0, FALSE }
}
};
static const MARSHALLING PrinterDriver5Marshalling = {
sizeof(DRIVER_INFO_5W),
{
{ FIELD_OFFSET(DRIVER_INFO_5W, pName), RTL_FIELD_SIZE(DRIVER_INFO_5W, pName), RTL_FIELD_SIZE(DRIVER_INFO_5W, pName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_5W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_5W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_5W, pEnvironment), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_5W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_5W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_5W, pDriverPath), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_5W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_5W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_5W, pDataFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_5W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_5W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_5W, pConfigFile), TRUE },
{ MAXDWORD, 0, 0, FALSE }
}
};
static const MARSHALLING* pPrinterDriverMarshalling[] = {
@ -48,4 +76,6 @@ static const MARSHALLING* pPrinterDriverMarshalling[] = {
&PrinterDriver1Marshalling,
&PrinterDriver2Marshalling,
&PrinterDriver3Marshalling,
&PrinterDriver4Marshalling,
&PrinterDriver5Marshalling,
};

View file

@ -7,7 +7,6 @@
#include "precomp.h"
// Local Constants
static DWORD dwDriverInfo1Offsets[] = {
FIELD_OFFSET(DRIVER_INFO_1W, pName),
@ -36,6 +35,29 @@ static DWORD dwDriverInfo3Offsets[] = {
MAXDWORD
};
static DWORD dwDriverInfo4Offsets[] = {
FIELD_OFFSET(DRIVER_INFO_4W, pName),
FIELD_OFFSET(DRIVER_INFO_4W, pEnvironment),
FIELD_OFFSET(DRIVER_INFO_4W, pDriverPath),
FIELD_OFFSET(DRIVER_INFO_4W, pDataFile),
FIELD_OFFSET(DRIVER_INFO_4W, pConfigFile),
FIELD_OFFSET(DRIVER_INFO_4W, pHelpFile),
FIELD_OFFSET(DRIVER_INFO_4W, pDependentFiles),
FIELD_OFFSET(DRIVER_INFO_4W, pMonitorName),
FIELD_OFFSET(DRIVER_INFO_4W, pDefaultDataType),
FIELD_OFFSET(DRIVER_INFO_4W, pszzPreviousNames),
MAXDWORD
};
static DWORD dwDriverInfo5Offsets[] = {
FIELD_OFFSET(DRIVER_INFO_5W, pName),
FIELD_OFFSET(DRIVER_INFO_5W, pEnvironment),
FIELD_OFFSET(DRIVER_INFO_5W, pDriverPath),
FIELD_OFFSET(DRIVER_INFO_5W, pDataFile),
FIELD_OFFSET(DRIVER_INFO_5W, pConfigFile),
MAXDWORD
};
static void
ToMultiSz(LPWSTR pString)
{
@ -118,7 +140,7 @@ _LocalGetPrinterDriverLevel3(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_3W* ppD
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[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
@ -148,6 +170,87 @@ _LocalGetPrinterDriverLevel3(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_3W* ppD
(*ppDriverInfo)++;
}
static void
_LocalGetPrinterDriverLevel4(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_4W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[10];
/* 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
pwszStrings[9] = NULL; // pszzPreviousNames
// 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_4W);
return;
}
(*ppDriverInfo)->cVersion = 3;
// Finally copy the structure and advance to the next one in the output buffer.
*ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo4Offsets, *ppDriverInfoEnd);
ToMultiSz((*ppDriverInfo)->pDependentFiles);
(*ppDriverInfo)++;
}
static void
_LocalGetPrinterDriverLevel5(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_5W* 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 UniDrv.dll
pwszStrings[3] = L"c:\\reactos\\system32\\localspl.dll"; // pDataFile.ppd
pwszStrings[4] = L"c:\\reactos\\system32\\printui.dll"; // pConfigFile UniDrvUI.dll
// 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_5W);
return;
}
(*ppDriverInfo)->cVersion = 3;
// Driver attributes, like UMPD/KMPD.
(*ppDriverInfo)->dwDriverAttributes = 0; // UMPD/KMPD, So where are they?
// Number of times the configuration file for this driver has been upgraded or downgraded since the last spooler restart.
(*ppDriverInfo)->dwConfigVersion = 1;
// Number of times the driver file for this driver has been upgraded or downgraded since the last spooler restart.
(*ppDriverInfo)->dwDriverVersion = 1;
// Finally copy the structure and advance to the next one in the output buffer.
*ppDriverInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppDriverInfo), dwDriverInfo5Offsets, *ppDriverInfoEnd);
(*ppDriverInfo)++;
}
BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
{
@ -168,8 +271,8 @@ BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Le
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
// Only support 3 levels for now
if (Level > 3)
// Only support 5 levels for now
if (Level > 5)
{
// The caller supplied an invalid level.
dwErrorCode = ERROR_INVALID_LEVEL;
@ -185,6 +288,10 @@ BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Le
_LocalGetPrinterDriverLevel2(pPrinterHandle, NULL, NULL, pcbNeeded);
else if (Level == 3)
_LocalGetPrinterDriverLevel3(pPrinterHandle, NULL, NULL, pcbNeeded);
else if (Level == 4)
_LocalGetPrinterDriverLevel4(pPrinterHandle, NULL, NULL, pcbNeeded);
else if (Level == 5)
_LocalGetPrinterDriverLevel5(pPrinterHandle, NULL, NULL, pcbNeeded);
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
@ -202,6 +309,10 @@ BOOL WINAPI LocalGetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Le
_LocalGetPrinterDriverLevel2(pPrinterHandle, (PDRIVER_INFO_2W*)&pDriverInfo, &pEnd, NULL);
else if (Level == 3)
_LocalGetPrinterDriverLevel3(pPrinterHandle, (PDRIVER_INFO_3W*)&pDriverInfo, &pEnd, NULL);
else if (Level == 4)
_LocalGetPrinterDriverLevel4(pPrinterHandle, (PDRIVER_INFO_4W*)&pDriverInfo, &pEnd, NULL);
else if (Level == 5)
_LocalGetPrinterDriverLevel5(pPrinterHandle, (PDRIVER_INFO_5W*)&pDriverInfo, &pEnd, NULL);
dwErrorCode = ERROR_SUCCESS;