reactos/win32ss/printing/providers/localspl/printerdrivers.c
Katayama Hirofumi MZ f3b1185cdc
[LOCALSPL] Don't hardcode C:\ReactOS (#2343)
Use static top-level variables wszLocalSplFile and wszPrintUiFile instead of static hardcoded literal strings.
CORE-14747
2020-02-14 22:53:38 +09:00

348 lines
11 KiB
C

/*
* 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)
* Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/
#include "precomp.h"
#include <strsafe.h>
static WCHAR wszLocalSplFile[MAX_PATH] = L"";
static WCHAR wszPrintUiFile[MAX_PATH] = L"";
static BOOL
DoInitPrinterDriversInternal(void)
{
WCHAR szSysDir[MAX_PATH];
if (wszLocalSplFile[0] && wszPrintUiFile[0])
return TRUE;
if (!GetSystemDirectoryW(szSysDir, _countof(szSysDir)))
{
ERR("GetSystemDirectoryW failed\n");
return FALSE;
}
StringCbCopyW(wszLocalSplFile, sizeof(wszLocalSplFile), szSysDir);
StringCbCatW(wszLocalSplFile, sizeof(wszLocalSplFile), L"\\localspl.dll");
StringCbCopyW(wszPrintUiFile, sizeof(wszPrintUiFile), szSysDir);
StringCbCatW(wszPrintUiFile, sizeof(wszPrintUiFile), L"\\printui.dll");
return TRUE;
}
// 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 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)
{
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];
pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
pwszStrings[2] = wszLocalSplFile; // pDriverPath
pwszStrings[3] = wszLocalSplFile; // pDataFile
pwszStrings[4] = wszLocalSplFile; // 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];
pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
pwszStrings[2] = wszLocalSplFile; // pDriverPath
pwszStrings[3] = wszLocalSplFile; // pDataFile
pwszStrings[4] = wszPrintUiFile; // 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)++;
}
static void
_LocalGetPrinterDriverLevel4(PLOCAL_PRINTER_HANDLE pHandle, PDRIVER_INFO_4W* ppDriverInfo, PBYTE* ppDriverInfoEnd, PDWORD pcbNeeded)
{
DWORD n;
PCWSTR pwszStrings[10];
pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
pwszStrings[2] = wszLocalSplFile; // pDriverPath
pwszStrings[3] = wszLocalSplFile; // pDataFile
pwszStrings[4] = wszPrintUiFile; // 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];
pwszStrings[0] = pHandle->pPrinter->pwszPrinterDriver; // pName
pwszStrings[1] = wszCurrentEnvironment; // pEnvironment
pwszStrings[2] = wszLocalSplFile; // pDriverPath UniDrv.dll
pwszStrings[3] = wszLocalSplFile; // pDataFile.ppd
pwszStrings[4] = wszPrintUiFile; // 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)
{
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);
DoInitPrinterDriversInternal();
// 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 5 levels for now
if (Level > 5)
{
// 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);
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)
{
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);
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;
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}