mirror of
https://github.com/reactos/reactos.git
synced 2024-11-02 04:37:32 +00:00
7bffb70353
WinSpool : Implement missing API. Sync/Port from wine. Setting it to fast track for needed testing of the later GDI code. Leaving Fix-me debug prints on. Local tree has WinSpool_winetest turned on. So no debug noise during normal ReactOS operation. SpoolSS : Reordered header types. Have more Spl function to be added while SpoolSV is being coded to forward to LocalSpl. Based on wine and old research from the GDI code.
663 lines
20 KiB
C
663 lines
20 KiB
C
/*
|
|
* PROJECT: ReactOS Spooler API
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: Functions related to Printer Configuration Data
|
|
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
LONG WINAPI
|
|
AdvancedSetupDialog(HWND hWnd, INT Unknown, PDEVMODEA pDevModeInput, PDEVMODEA pDevModeOutput)
|
|
{
|
|
HANDLE hPrinter;
|
|
LONG Ret = -1;
|
|
|
|
TRACE("AdvancedSetupDialog(%p, %d, %p, %p)\n", hWnd, Unknown, pDevModeOutput, pDevModeInput);
|
|
|
|
if ( OpenPrinterA( (LPSTR)pDevModeInput->dmDeviceName, &hPrinter, NULL ) )
|
|
{
|
|
Ret = AdvancedDocumentPropertiesA( hWnd, hPrinter, (PSTR)pDevModeInput->dmDeviceName, pDevModeOutput, pDevModeInput );
|
|
ClosePrinter(hPrinter);
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
LONG WINAPI
|
|
AdvancedDocumentPropertiesA(HWND hWnd, HANDLE hPrinter, PSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput)
|
|
{
|
|
TRACE("AdvancedDocumentPropertiesA(%p, %p, %s, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput);
|
|
UNIMPLEMENTED;
|
|
return 0;
|
|
}
|
|
|
|
LONG WINAPI
|
|
AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput)
|
|
{
|
|
TRACE("AdvancedDocumentPropertiesW(%p, %p, %S, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput);
|
|
UNIMPLEMENTED;
|
|
return 0;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
DeletePrinterDataA(HANDLE hPrinter, PSTR pValueName)
|
|
{
|
|
LPWSTR valuenameW = NULL;
|
|
INT len;
|
|
DWORD res;
|
|
|
|
TRACE("DeletePrinterDataA(%p, %s)\n", hPrinter, pValueName);
|
|
|
|
if (pValueName)
|
|
{
|
|
len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0);
|
|
valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len);
|
|
}
|
|
|
|
res = DeletePrinterDataW( hPrinter, valuenameW );
|
|
|
|
HeapFree(GetProcessHeap(), 0, valuenameW);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
DWORD WINAPI
|
|
DeletePrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PCSTR pValueName)
|
|
{
|
|
LPWSTR keynameW = NULL;
|
|
LPWSTR valuenameW = NULL;
|
|
INT len;
|
|
DWORD res;
|
|
|
|
TRACE("DeletePrinterDataExA(%p, %s, %s)\n", hPrinter, pKeyName, pValueName);
|
|
|
|
if (pKeyName)
|
|
{
|
|
len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0);
|
|
keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len);
|
|
}
|
|
|
|
if (pValueName)
|
|
{
|
|
len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0);
|
|
valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len);
|
|
}
|
|
|
|
res = DeletePrinterDataExW( hPrinter, keynameW, valuenameW );
|
|
|
|
HeapFree(GetProcessHeap(), 0, keynameW);
|
|
HeapFree(GetProcessHeap(), 0, valuenameW);
|
|
|
|
return res;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
DeletePrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName)
|
|
{
|
|
TRACE("DeletePrinterDataExW(%p, %S, %S)\n", hPrinter, pKeyName, pValueName);
|
|
UNIMPLEMENTED;
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
DeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName)
|
|
{
|
|
TRACE("DeletePrinterDataW(%p, %S)\n", hPrinter, pValueName);
|
|
UNIMPLEMENTED;
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
DeletePrinterKeyA(HANDLE hPrinter, PCSTR pKeyName)
|
|
{
|
|
LPWSTR keynameW = NULL;
|
|
INT len;
|
|
DWORD res;
|
|
|
|
TRACE("DeletePrinterKeyA(%p, %s)\n", hPrinter, pKeyName);
|
|
|
|
if (pKeyName)
|
|
{
|
|
len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0);
|
|
keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len);
|
|
}
|
|
|
|
res = DeletePrinterKeyW( hPrinter, keynameW );
|
|
|
|
HeapFree(GetProcessHeap(), 0, keynameW);
|
|
|
|
return res;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
DeletePrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName)
|
|
{
|
|
TRACE("DeletePrinterKeyW(%p, %S)\n", hPrinter, pKeyName);
|
|
UNIMPLEMENTED;
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
EnumPrinterDataA(HANDLE hPrinter, DWORD dwIndex, PSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
|
|
{
|
|
TRACE("EnumPrinterDataA(%p, %lu, %s, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
|
|
UNIMPLEMENTED;
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
EnumPrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
|
|
{
|
|
INT len;
|
|
LPWSTR pKeyNameW;
|
|
DWORD ret, dwIndex, dwBufSize;
|
|
HANDLE hHeap;
|
|
LPSTR pBuffer;
|
|
|
|
TRACE("EnumPrinterDataExA(%p, %s, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
|
|
|
|
if (pKeyName == NULL || *pKeyName == 0)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0);
|
|
if (len == 0)
|
|
{
|
|
ret = GetLastError ();
|
|
ERR ("MultiByteToWideChar failed with code %i\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
hHeap = GetProcessHeap ();
|
|
if (hHeap == NULL)
|
|
{
|
|
ERR ("GetProcessHeap failed\n");
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR));
|
|
if (pKeyNameW == NULL)
|
|
{
|
|
ERR ("Failed to allocate %i bytes from process heap\n",
|
|
(LONG)(len * sizeof (WCHAR)));
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0)
|
|
{
|
|
ret = GetLastError ();
|
|
ERR ("MultiByteToWideChar failed with code %i\n", ret);
|
|
if (HeapFree (hHeap, 0, pKeyNameW) == 0)
|
|
WARN ("HeapFree failed with code %i\n", GetLastError ());
|
|
return ret;
|
|
}
|
|
|
|
ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
|
|
|
|
if (ret != ERROR_SUCCESS)
|
|
{
|
|
if (HeapFree (hHeap, 0, pKeyNameW) == 0)
|
|
WARN ("HeapFree failed with code %i\n", GetLastError ());
|
|
TRACE ("EnumPrinterDataExW returned %i\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
if (HeapFree (hHeap, 0, pKeyNameW) == 0)
|
|
{
|
|
ret = GetLastError ();
|
|
ERR ("HeapFree failed with code %i\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
if (*pnEnumValues == 0) /* empty key */
|
|
return ERROR_SUCCESS;
|
|
|
|
dwBufSize = 0;
|
|
for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
|
|
{
|
|
PPRINTER_ENUM_VALUESW ppev =
|
|
&((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
|
|
|
|
if (dwBufSize < ppev->cbValueName)
|
|
dwBufSize = ppev->cbValueName;
|
|
|
|
if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ ||
|
|
ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ))
|
|
dwBufSize = ppev->cbData;
|
|
}
|
|
|
|
TRACE ("Largest Unicode name or value is %i bytes\n", dwBufSize);
|
|
|
|
pBuffer = HeapAlloc (hHeap, 0, dwBufSize);
|
|
if (pBuffer == NULL)
|
|
{
|
|
ERR ("Failed to allocate %i bytes from process heap\n", dwBufSize);
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex)
|
|
{
|
|
PPRINTER_ENUM_VALUESW ppev =
|
|
&((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex];
|
|
|
|
len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName,
|
|
ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL,
|
|
NULL);
|
|
if (len == 0)
|
|
{
|
|
ret = GetLastError ();
|
|
ERR ("WideCharToMultiByte failed with code %i\n", ret);
|
|
if (HeapFree (hHeap, 0, pBuffer) == 0)
|
|
WARN ("HeapFree failed with code %i\n", GetLastError ());
|
|
return ret;
|
|
}
|
|
|
|
memcpy (ppev->pValueName, pBuffer, len);
|
|
|
|
TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
|
|
|
|
if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ &&
|
|
ppev->dwType != REG_MULTI_SZ)
|
|
continue;
|
|
|
|
len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData,
|
|
ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL);
|
|
if (len == 0)
|
|
{
|
|
ret = GetLastError ();
|
|
ERR ("WideCharToMultiByte failed with code %i\n", ret);
|
|
if (HeapFree (hHeap, 0, pBuffer) == 0)
|
|
WARN ("HeapFree failed with code %i\n", GetLastError ());
|
|
return ret;
|
|
}
|
|
|
|
memcpy (ppev->pData, pBuffer, len);
|
|
|
|
TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer);
|
|
TRACE (" (only first string of REG_MULTI_SZ printed)\n");
|
|
}
|
|
|
|
if (HeapFree (hHeap, 0, pBuffer) == 0)
|
|
{
|
|
ret = GetLastError ();
|
|
ERR ("HeapFree failed with code %i\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
EnumPrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues)
|
|
{
|
|
TRACE("EnumPrinterDataExW(%p, %S, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues);
|
|
UNIMPLEMENTED;
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
EnumPrinterDataW(HANDLE hPrinter, DWORD dwIndex, PWSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData)
|
|
{
|
|
TRACE("EnumPrinterDataW(%p, %lu, %S, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData);
|
|
UNIMPLEMENTED;
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
EnumPrinterKeyA(HANDLE hPrinter, PCSTR pKeyName, PSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
|
|
{
|
|
TRACE("EnumPrinterKeyA(%p, %s, %s, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
|
|
UNIMPLEMENTED;
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
EnumPrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName, PWSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey)
|
|
{
|
|
TRACE("EnumPrinterKeyW(%p, %S, %S, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey);
|
|
UNIMPLEMENTED;
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
|
|
{
|
|
TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
|
|
return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
|
|
}
|
|
|
|
DWORD WINAPI
|
|
GetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
|
|
{
|
|
DWORD cbUnicodeData;
|
|
DWORD cch;
|
|
DWORD dwReturnValue;
|
|
DWORD dwType;
|
|
POSVERSIONINFOEXA pInfoA;
|
|
POSVERSIONINFOEXW pInfoW;
|
|
PVOID pUnicodeData = NULL;
|
|
PWSTR pwszKeyName = NULL;
|
|
PWSTR pwszValueName = NULL;
|
|
|
|
TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
|
|
|
|
if (pKeyName)
|
|
{
|
|
// Convert pKeyName to a Unicode string pwszKeyName
|
|
cch = strlen(pKeyName);
|
|
|
|
pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
|
if (!pwszKeyName)
|
|
{
|
|
dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
|
|
ERR("HeapAlloc failed!\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
|
|
}
|
|
|
|
if (pValueName)
|
|
{
|
|
// Convert pValueName to a Unicode string pwszValueName
|
|
cch = strlen(pValueName);
|
|
|
|
pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
|
if (!pwszValueName)
|
|
{
|
|
dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
|
|
ERR("HeapAlloc failed!\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
|
|
}
|
|
|
|
// We need the data type information, even if no pData was passed.
|
|
if (!pType)
|
|
pType = &dwType;
|
|
|
|
// Call GetPrinterDataExW for the first time.
|
|
// If we're lucky, the supplied buffer is already large enough and we don't need to do the expensive RPC call a second time.
|
|
dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, pType, pData, nSize, pcbNeeded);
|
|
|
|
// If a critical error occurred, just return it. We cannot do anything else in this case.
|
|
if (dwReturnValue != ERROR_SUCCESS && dwReturnValue != ERROR_MORE_DATA)
|
|
goto Cleanup;
|
|
|
|
// Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size.
|
|
cbUnicodeData = *pcbNeeded;
|
|
|
|
if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
|
|
{
|
|
// This is a string that needs to be converted from Unicode to ANSI.
|
|
// Output the required buffer size for the ANSI string.
|
|
*pcbNeeded /= sizeof(WCHAR);
|
|
}
|
|
else if (*pType == REG_NONE)
|
|
{
|
|
if (cbUnicodeData == sizeof(OSVERSIONINFOW) && wcsicmp(pwszValueName, SPLREG_OS_VERSION) == 0)
|
|
{
|
|
// This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA.
|
|
*pcbNeeded = sizeof(OSVERSIONINFOA);
|
|
}
|
|
else if (cbUnicodeData == sizeof(OSVERSIONINFOEXW) && wcsicmp(pwszValueName, SPLREG_OS_VERSIONEX) == 0)
|
|
{
|
|
// This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA.
|
|
*pcbNeeded = sizeof(OSVERSIONINFOEXA);
|
|
}
|
|
else
|
|
{
|
|
// Other REG_NONE value, nothing to do.
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Check if the supplied buffer is large enough for the ANSI data.
|
|
if (nSize < *pcbNeeded)
|
|
{
|
|
dwReturnValue = ERROR_MORE_DATA;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Allocate a temporary buffer for the Unicode data.
|
|
pUnicodeData = HeapAlloc(hProcessHeap, 0, cbUnicodeData);
|
|
if (!pUnicodeData)
|
|
{
|
|
dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
|
|
ERR("HeapAlloc failed!\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (dwReturnValue == ERROR_SUCCESS)
|
|
{
|
|
// ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string,
|
|
// so the Unicode string has been copied into pData. Copy it to pUnicodeData.
|
|
CopyMemory(pUnicodeData, pData, cbUnicodeData);
|
|
}
|
|
else
|
|
{
|
|
// ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string.
|
|
// We have to call GetPrinterDataExW again with the temporary buffer.
|
|
dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, NULL, (PBYTE)pUnicodeData, cbUnicodeData, &cbUnicodeData);
|
|
if (dwReturnValue != ERROR_SUCCESS)
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ)
|
|
{
|
|
// Convert the Unicode string to ANSI.
|
|
WideCharToMultiByte(CP_ACP, 0, (PWSTR)pUnicodeData, -1, (PSTR)pData, *pcbNeeded, NULL, NULL);
|
|
}
|
|
else
|
|
{
|
|
// This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW.
|
|
// Copy the fields and convert the Unicode CSD Version string to ANSI.
|
|
pInfoW = (POSVERSIONINFOEXW)pUnicodeData;
|
|
pInfoA = (POSVERSIONINFOEXA)pData;
|
|
pInfoA->dwMajorVersion = pInfoW->dwMajorVersion;
|
|
pInfoA->dwMinorVersion = pInfoW->dwMinorVersion;
|
|
pInfoA->dwBuildNumber = pInfoW->dwBuildNumber;
|
|
pInfoA->dwPlatformId = pInfoW->dwPlatformId;
|
|
WideCharToMultiByte(CP_ACP, 0, pInfoW->szCSDVersion, -1, pInfoA->szCSDVersion, sizeof(pInfoA->szCSDVersion), NULL, NULL);
|
|
|
|
if (cbUnicodeData == sizeof(OSVERSIONINFOW))
|
|
{
|
|
pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
|
}
|
|
else
|
|
{
|
|
pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
|
|
pInfoA->wServicePackMajor = pInfoW->wServicePackMajor;
|
|
pInfoA->wServicePackMinor = pInfoW->wServicePackMinor;
|
|
pInfoA->wSuiteMask = pInfoW->wSuiteMask;
|
|
pInfoA->wProductType = pInfoW->wProductType;
|
|
pInfoA->wReserved = pInfoW->wReserved;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
if (pwszKeyName)
|
|
HeapFree(hProcessHeap, 0, pwszKeyName);
|
|
|
|
if (pwszValueName)
|
|
HeapFree(hProcessHeap, 0, pwszValueName);
|
|
|
|
if (pUnicodeData)
|
|
HeapFree(hProcessHeap, 0, pUnicodeData);
|
|
|
|
return dwReturnValue;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
|
|
{
|
|
const WCHAR wszEmptyString[] = L"";
|
|
|
|
BYTE DummyData;
|
|
DWORD dwErrorCode;
|
|
DWORD dwType = REG_NONE;
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
|
|
|
|
// Sanity checks
|
|
if (!pHandle)
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
// Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way),
|
|
// Windows does it differently for GetPrinterDataExW and points them to empty variables.
|
|
if (!pKeyName)
|
|
pKeyName = wszEmptyString;
|
|
|
|
if (!pType)
|
|
pType = &dwType;
|
|
|
|
if (!pData && !nSize)
|
|
pData = &DummyData;
|
|
|
|
// Do the RPC call
|
|
RpcTryExcept
|
|
{
|
|
dwErrorCode = _RpcGetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
|
|
}
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
dwErrorCode = RpcExceptionCode();
|
|
}
|
|
RpcEndExcept;
|
|
|
|
return dwErrorCode;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
|
|
{
|
|
TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
|
|
return GetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
|
|
}
|
|
|
|
DWORD WINAPI
|
|
SetPrinterDataA(HANDLE hPrinter, PSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
|
|
{
|
|
TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
|
|
return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type, pData, cbData);
|
|
}
|
|
|
|
DWORD WINAPI
|
|
SetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
|
|
{
|
|
DWORD cch;
|
|
DWORD dwReturnValue;
|
|
PWSTR pwszKeyName = NULL;
|
|
PWSTR pwszValueName = NULL;
|
|
PWSTR pUnicodeData = NULL;
|
|
|
|
TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
|
|
|
|
if (pKeyName)
|
|
{
|
|
// Convert pKeyName to a Unicode string pwszKeyName
|
|
cch = strlen(pKeyName);
|
|
|
|
pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
|
if (!pwszKeyName)
|
|
{
|
|
dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
|
|
ERR("HeapAlloc failed!\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1);
|
|
}
|
|
|
|
if (pValueName)
|
|
{
|
|
// Convert pValueName to a Unicode string pwszValueName
|
|
cch = strlen(pValueName);
|
|
|
|
pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
|
if (!pwszValueName)
|
|
{
|
|
dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
|
|
ERR("HeapAlloc failed!\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1);
|
|
}
|
|
|
|
if (Type == REG_SZ || Type == REG_MULTI_SZ || Type == REG_EXPAND_SZ)
|
|
{
|
|
// Convert pData to a Unicode string pUnicodeData.
|
|
pUnicodeData = HeapAlloc(hProcessHeap, 0, cbData * sizeof(WCHAR));
|
|
if (!pUnicodeData)
|
|
{
|
|
dwReturnValue = ERROR_NOT_ENOUGH_MEMORY;
|
|
ERR("HeapAlloc failed!\n");
|
|
goto Cleanup;
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, (PCSTR)pData, -1, pUnicodeData, cbData);
|
|
|
|
pData = (PBYTE)pUnicodeData;
|
|
cbData *= sizeof(WCHAR);
|
|
}
|
|
|
|
dwReturnValue = SetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, Type, pData, cbData);
|
|
|
|
Cleanup:
|
|
if (pwszKeyName)
|
|
HeapFree(hProcessHeap, 0, pwszKeyName);
|
|
|
|
if (pwszValueName)
|
|
HeapFree(hProcessHeap, 0, pwszValueName);
|
|
|
|
if (pUnicodeData)
|
|
HeapFree(hProcessHeap, 0, pUnicodeData);
|
|
|
|
return dwReturnValue;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
|
|
{
|
|
const WCHAR wszEmptyString[] = L"";
|
|
|
|
DWORD dwErrorCode;
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
|
|
|
|
// Sanity checks
|
|
if (!pHandle)
|
|
return ERROR_INVALID_HANDLE;
|
|
|
|
if (!pKeyName)
|
|
pKeyName = wszEmptyString;
|
|
|
|
// Do the RPC call
|
|
RpcTryExcept
|
|
{
|
|
dwErrorCode = _RpcSetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, Type, pData, cbData);
|
|
}
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
dwErrorCode = RpcExceptionCode();
|
|
}
|
|
RpcEndExcept;
|
|
|
|
return dwErrorCode;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
|
|
{
|
|
TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
|
|
return SetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, Type, pData, cbData);
|
|
}
|