https://git.reactos.org/?p=reactos.git;a=commitdiff;h=796dd5f53c50f8bdb85a2…
commit 796dd5f53c50f8bdb85a20d44cee83bb8603a594
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sat Dec 29 23:51:32 2018 +0100
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sun Jan 6 21:07:27 2019 +0100
[PRINTING] Semi-implement GetPrinterDriverW
CORE-15522
---
win32ss/printing/base/spoolsv/printerdrivers.c | 30 ++-
win32ss/printing/base/winspool/printers.c | 45 ++++-
.../printing/include/marshalling/printerdrivers.h | 51 +++++
win32ss/printing/providers/localspl/CMakeLists.txt | 1 +
win32ss/printing/providers/localspl/main.c | 2 +-
win32ss/printing/providers/localspl/precomp.h | 4 +
.../printing/providers/localspl/printerdrivers.c | 211 +++++++++++++++++++++
7 files changed, 340 insertions(+), 4 deletions(-)
diff --git a/win32ss/printing/base/spoolsv/printerdrivers.c
b/win32ss/printing/base/spoolsv/printerdrivers.c
index ac9ac5801b..a1f45865c1 100644
--- a/win32ss/printing/base/spoolsv/printerdrivers.c
+++ b/win32ss/printing/base/spoolsv/printerdrivers.c
@@ -6,6 +6,7 @@
*/
#include "precomp.h"
+#include "marshalling/printerdrivers.h"
DWORD
_RpcAddPrinterDriver(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer)
@@ -45,8 +46,33 @@ _RpcEnumPrinterDrivers(WINSPOOL_HANDLE pName, WCHAR* pEnvironment,
DWORD Level,
DWORD
_RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWORD Level,
BYTE* pDriver, DWORD cbBuf, DWORD* pcbNeeded)
{
- UNIMPLEMENTED;
- return ERROR_INVALID_FUNCTION;
+ DWORD dwErrorCode;
+ 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
diff --git a/win32ss/printing/base/winspool/printers.c
b/win32ss/printing/base/winspool/printers.c
index 9c2d12b31f..5f130a3d15 100644
--- a/win32ss/printing/base/winspool/printers.c
+++ b/win32ss/printing/base/winspool/printers.c
@@ -7,6 +7,7 @@
#include "precomp.h"
#include <marshalling/printers.h>
+#include <marshalling/printerdrivers.h>
// Local Constants
@@ -513,8 +514,50 @@ GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level,
LPBYTE pDriv
BOOL WINAPI
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);
- 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
diff --git a/win32ss/printing/include/marshalling/printerdrivers.h
b/win32ss/printing/include/marshalling/printerdrivers.h
new file mode 100644
index 0000000000..49951bdca2
--- /dev/null
+++ b/win32ss/printing/include/marshalling/printerdrivers.h
@@ -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(a)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,
+};
diff --git a/win32ss/printing/providers/localspl/CMakeLists.txt
b/win32ss/printing/providers/localspl/CMakeLists.txt
index fb6e988ab9..a5608db406 100644
--- a/win32ss/printing/providers/localspl/CMakeLists.txt
+++ b/win32ss/printing/providers/localspl/CMakeLists.txt
@@ -10,6 +10,7 @@ list(APPEND SOURCE
ports.c
precomp.h
printerdata.c
+ printerdrivers.c
printers.c
printingthread.c
printprocessors.c
diff --git a/win32ss/printing/providers/localspl/main.c
b/win32ss/printing/providers/localspl/main.c
index 7666050446..7c39ec2cf0 100644
--- a/win32ss/printing/providers/localspl/main.c
+++ b/win32ss/printing/providers/localspl/main.c
@@ -43,7 +43,7 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
LocalEnumPrinters, // fpEnumPrinters
NULL, // fpAddPrinterDriver
NULL, // fpEnumPrinterDrivers
- NULL, // fpGetPrinterDriver
+ LocalGetPrinterDriver, // fpGetPrinterDriver
NULL, // fpGetPrinterDriverDirectory
NULL, // fpDeletePrinterDriver
NULL, // fpAddPrintProcessor
diff --git a/win32ss/printing/providers/localspl/precomp.h
b/win32ss/printing/providers/localspl/precomp.h
index 83061a8a8b..1b9a2d5540 100644
--- a/win32ss/printing/providers/localspl/precomp.h
+++ b/win32ss/printing/providers/localspl/precomp.h
@@ -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 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
extern SKIPLIST PrinterList;
BOOL InitializePrinterList(void);
diff --git a/win32ss/printing/providers/localspl/printerdrivers.c
b/win32ss/printing/providers/localspl/printerdrivers.c
new file mode 100644
index 0000000000..5bb5b3db73
--- /dev/null
+++ b/win32ss/printing/providers/localspl/printerdrivers.c
@@ -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(a)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);
+}