Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662/* * 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 WINAPIAdvancedSetupDialog(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 WINAPIAdvancedDocumentPropertiesA(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 WINAPIAdvancedDocumentPropertiesW(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 WINAPIDeletePrinterDataA(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 );
if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW);
return res;
}
DWORD WINAPIDeletePrinterDataExA(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 );
if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW); if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW);
return res;}
DWORD WINAPIDeletePrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName){ TRACE("DeletePrinterDataExW(%p, %S, %S)\n", hPrinter, pKeyName, pValueName); UNIMPLEMENTED; return ERROR_NOT_SUPPORTED;}
DWORD WINAPIDeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName){ TRACE("DeletePrinterDataW(%p, %S)\n", hPrinter, pValueName); UNIMPLEMENTED; return ERROR_NOT_SUPPORTED;}
DWORD WINAPIDeletePrinterKeyA(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 );
if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW);
return res;}
DWORD WINAPIDeletePrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName){ TRACE("DeletePrinterKeyW(%p, %S)\n", hPrinter, pKeyName); UNIMPLEMENTED; return ERROR_NOT_SUPPORTED;}
DWORD WINAPIEnumPrinterDataA(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 WINAPIEnumPrinterDataExA(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; }
FIXME ("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 WINAPIEnumPrinterDataExW(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 WINAPIEnumPrinterDataW(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 WINAPIEnumPrinterKeyA(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 WINAPIEnumPrinterKeyW(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 WINAPIGetPrinterDataA(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 WINAPIGetPrinterDataExA(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 WINAPIGetPrinterDataExW(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 WINAPIGetPrinterDataW(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 WINAPISetPrinterDataA(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 WINAPISetPrinterDataExA(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 WINAPISetPrinterDataExW(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 WINAPISetPrinterDataW(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);}