1c2c66affSColin Finck /* 2c2c66affSColin Finck * PROJECT: ReactOS Spooler API 3c2c66affSColin Finck * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4c2c66affSColin Finck * PURPOSE: Functions related to Printer Configuration Data 5c2c66affSColin Finck * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org) 6c2c66affSColin Finck */ 7c2c66affSColin Finck 8c2c66affSColin Finck #include "precomp.h" 9c2c66affSColin Finck 10c2c66affSColin Finck LONG WINAPI 11*7bffb703SJames Tabor AdvancedSetupDialog(HWND hWnd, INT Unknown, PDEVMODEA pDevModeInput, PDEVMODEA pDevModeOutput) 12*7bffb703SJames Tabor { 13*7bffb703SJames Tabor HANDLE hPrinter; 14*7bffb703SJames Tabor LONG Ret = -1; 15*7bffb703SJames Tabor 16*7bffb703SJames Tabor TRACE("AdvancedSetupDialog(%p, %d, %p, %p)\n", hWnd, Unknown, pDevModeOutput, pDevModeInput); 17*7bffb703SJames Tabor 18*7bffb703SJames Tabor if ( OpenPrinterA( (LPSTR)pDevModeInput->dmDeviceName, &hPrinter, NULL ) ) 19*7bffb703SJames Tabor { 20*7bffb703SJames Tabor Ret = AdvancedDocumentPropertiesA( hWnd, hPrinter, (PSTR)pDevModeInput->dmDeviceName, pDevModeOutput, pDevModeInput ); 21*7bffb703SJames Tabor ClosePrinter(hPrinter); 22*7bffb703SJames Tabor } 23*7bffb703SJames Tabor return Ret; 24*7bffb703SJames Tabor } 25*7bffb703SJames Tabor 26*7bffb703SJames Tabor LONG WINAPI 2746b91659SColin Finck AdvancedDocumentPropertiesA(HWND hWnd, HANDLE hPrinter, PSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput) 2846b91659SColin Finck { 2946b91659SColin Finck TRACE("AdvancedDocumentPropertiesA(%p, %p, %s, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput); 3046b91659SColin Finck UNIMPLEMENTED; 3146b91659SColin Finck return 0; 3246b91659SColin Finck } 3346b91659SColin Finck 3446b91659SColin Finck LONG WINAPI 35c2c66affSColin Finck AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput) 36c2c66affSColin Finck { 371f6f08ecSColin Finck TRACE("AdvancedDocumentPropertiesW(%p, %p, %S, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput); 38c2c66affSColin Finck UNIMPLEMENTED; 3946b91659SColin Finck return 0; 4046b91659SColin Finck } 4146b91659SColin Finck 4246b91659SColin Finck DWORD WINAPI 4346b91659SColin Finck DeletePrinterDataA(HANDLE hPrinter, PSTR pValueName) 4446b91659SColin Finck { 45*7bffb703SJames Tabor LPWSTR valuenameW = NULL; 46*7bffb703SJames Tabor INT len; 47*7bffb703SJames Tabor DWORD res; 48*7bffb703SJames Tabor 4946b91659SColin Finck TRACE("DeletePrinterDataA(%p, %s)\n", hPrinter, pValueName); 50*7bffb703SJames Tabor 51*7bffb703SJames Tabor if (pValueName) 52*7bffb703SJames Tabor { 53*7bffb703SJames Tabor len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0); 54*7bffb703SJames Tabor valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 55*7bffb703SJames Tabor MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len); 56*7bffb703SJames Tabor } 57*7bffb703SJames Tabor 58*7bffb703SJames Tabor res = DeletePrinterDataW( hPrinter, valuenameW ); 59*7bffb703SJames Tabor 60*7bffb703SJames Tabor HeapFree(GetProcessHeap(), 0, valuenameW); 61*7bffb703SJames Tabor 62*7bffb703SJames Tabor return res; 63*7bffb703SJames Tabor 6446b91659SColin Finck } 6546b91659SColin Finck 6646b91659SColin Finck DWORD WINAPI 6746b91659SColin Finck DeletePrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PCSTR pValueName) 6846b91659SColin Finck { 69*7bffb703SJames Tabor LPWSTR keynameW = NULL; 70*7bffb703SJames Tabor LPWSTR valuenameW = NULL; 71*7bffb703SJames Tabor INT len; 72*7bffb703SJames Tabor DWORD res; 73*7bffb703SJames Tabor 7446b91659SColin Finck TRACE("DeletePrinterDataExA(%p, %s, %s)\n", hPrinter, pKeyName, pValueName); 75*7bffb703SJames Tabor 76*7bffb703SJames Tabor if (pKeyName) 77*7bffb703SJames Tabor { 78*7bffb703SJames Tabor len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0); 79*7bffb703SJames Tabor keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 80*7bffb703SJames Tabor MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len); 81*7bffb703SJames Tabor } 82*7bffb703SJames Tabor 83*7bffb703SJames Tabor if (pValueName) 84*7bffb703SJames Tabor { 85*7bffb703SJames Tabor len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0); 86*7bffb703SJames Tabor valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 87*7bffb703SJames Tabor MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len); 88*7bffb703SJames Tabor } 89*7bffb703SJames Tabor 90*7bffb703SJames Tabor res = DeletePrinterDataExW( hPrinter, keynameW, valuenameW ); 91*7bffb703SJames Tabor 92*7bffb703SJames Tabor HeapFree(GetProcessHeap(), 0, keynameW); 93*7bffb703SJames Tabor HeapFree(GetProcessHeap(), 0, valuenameW); 94*7bffb703SJames Tabor 95*7bffb703SJames Tabor return res; 9646b91659SColin Finck } 9746b91659SColin Finck 9846b91659SColin Finck DWORD WINAPI 9946b91659SColin Finck DeletePrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName) 10046b91659SColin Finck { 10146b91659SColin Finck TRACE("DeletePrinterDataExW(%p, %S, %S)\n", hPrinter, pKeyName, pValueName); 10246b91659SColin Finck UNIMPLEMENTED; 10346b91659SColin Finck return ERROR_NOT_SUPPORTED; 10446b91659SColin Finck } 10546b91659SColin Finck 10646b91659SColin Finck DWORD WINAPI 10746b91659SColin Finck DeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName) 10846b91659SColin Finck { 10946b91659SColin Finck TRACE("DeletePrinterDataW(%p, %S)\n", hPrinter, pValueName); 11046b91659SColin Finck UNIMPLEMENTED; 11146b91659SColin Finck return ERROR_NOT_SUPPORTED; 11246b91659SColin Finck } 11346b91659SColin Finck 11446b91659SColin Finck DWORD WINAPI 11546b91659SColin Finck DeletePrinterKeyA(HANDLE hPrinter, PCSTR pKeyName) 11646b91659SColin Finck { 117*7bffb703SJames Tabor LPWSTR keynameW = NULL; 118*7bffb703SJames Tabor INT len; 119*7bffb703SJames Tabor DWORD res; 120*7bffb703SJames Tabor 12146b91659SColin Finck TRACE("DeletePrinterKeyA(%p, %s)\n", hPrinter, pKeyName); 122*7bffb703SJames Tabor 123*7bffb703SJames Tabor if (pKeyName) 124*7bffb703SJames Tabor { 125*7bffb703SJames Tabor len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0); 126*7bffb703SJames Tabor keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 127*7bffb703SJames Tabor MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len); 128*7bffb703SJames Tabor } 129*7bffb703SJames Tabor 130*7bffb703SJames Tabor res = DeletePrinterKeyW( hPrinter, keynameW ); 131*7bffb703SJames Tabor 132*7bffb703SJames Tabor HeapFree(GetProcessHeap(), 0, keynameW); 133*7bffb703SJames Tabor 134*7bffb703SJames Tabor return res; 13546b91659SColin Finck } 13646b91659SColin Finck 13746b91659SColin Finck DWORD WINAPI 13846b91659SColin Finck DeletePrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName) 13946b91659SColin Finck { 14046b91659SColin Finck TRACE("DeletePrinterKeyW(%p, %S)\n", hPrinter, pKeyName); 14146b91659SColin Finck UNIMPLEMENTED; 14246b91659SColin Finck return ERROR_NOT_SUPPORTED; 14346b91659SColin Finck } 14446b91659SColin Finck 14546b91659SColin Finck DWORD WINAPI 14646b91659SColin Finck EnumPrinterDataA(HANDLE hPrinter, DWORD dwIndex, PSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData) 14746b91659SColin Finck { 14846b91659SColin Finck TRACE("EnumPrinterDataA(%p, %lu, %s, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData); 14946b91659SColin Finck UNIMPLEMENTED; 15046b91659SColin Finck return ERROR_NOT_SUPPORTED; 15146b91659SColin Finck } 15246b91659SColin Finck 15346b91659SColin Finck DWORD WINAPI 15446b91659SColin Finck EnumPrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues) 15546b91659SColin Finck { 156*7bffb703SJames Tabor INT len; 157*7bffb703SJames Tabor LPWSTR pKeyNameW; 158*7bffb703SJames Tabor DWORD ret, dwIndex, dwBufSize; 159*7bffb703SJames Tabor HANDLE hHeap; 160*7bffb703SJames Tabor LPSTR pBuffer; 161*7bffb703SJames Tabor 16246b91659SColin Finck TRACE("EnumPrinterDataExA(%p, %s, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues); 163*7bffb703SJames Tabor 164*7bffb703SJames Tabor if (pKeyName == NULL || *pKeyName == 0) 165*7bffb703SJames Tabor return ERROR_INVALID_PARAMETER; 166*7bffb703SJames Tabor 167*7bffb703SJames Tabor len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0); 168*7bffb703SJames Tabor if (len == 0) 169*7bffb703SJames Tabor { 170*7bffb703SJames Tabor ret = GetLastError (); 171*7bffb703SJames Tabor ERR ("MultiByteToWideChar failed with code %i\n", ret); 172*7bffb703SJames Tabor return ret; 173*7bffb703SJames Tabor } 174*7bffb703SJames Tabor 175*7bffb703SJames Tabor hHeap = GetProcessHeap (); 176*7bffb703SJames Tabor if (hHeap == NULL) 177*7bffb703SJames Tabor { 178*7bffb703SJames Tabor ERR ("GetProcessHeap failed\n"); 179*7bffb703SJames Tabor return ERROR_OUTOFMEMORY; 180*7bffb703SJames Tabor } 181*7bffb703SJames Tabor 182*7bffb703SJames Tabor pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR)); 183*7bffb703SJames Tabor if (pKeyNameW == NULL) 184*7bffb703SJames Tabor { 185*7bffb703SJames Tabor ERR ("Failed to allocate %i bytes from process heap\n", 186*7bffb703SJames Tabor (LONG)(len * sizeof (WCHAR))); 187*7bffb703SJames Tabor return ERROR_OUTOFMEMORY; 188*7bffb703SJames Tabor } 189*7bffb703SJames Tabor 190*7bffb703SJames Tabor if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0) 191*7bffb703SJames Tabor { 192*7bffb703SJames Tabor ret = GetLastError (); 193*7bffb703SJames Tabor ERR ("MultiByteToWideChar failed with code %i\n", ret); 194*7bffb703SJames Tabor if (HeapFree (hHeap, 0, pKeyNameW) == 0) 195*7bffb703SJames Tabor WARN ("HeapFree failed with code %i\n", GetLastError ()); 196*7bffb703SJames Tabor return ret; 197*7bffb703SJames Tabor } 198*7bffb703SJames Tabor 199*7bffb703SJames Tabor ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues); 200*7bffb703SJames Tabor 201*7bffb703SJames Tabor if (ret != ERROR_SUCCESS) 202*7bffb703SJames Tabor { 203*7bffb703SJames Tabor if (HeapFree (hHeap, 0, pKeyNameW) == 0) 204*7bffb703SJames Tabor WARN ("HeapFree failed with code %i\n", GetLastError ()); 205*7bffb703SJames Tabor TRACE ("EnumPrinterDataExW returned %i\n", ret); 206*7bffb703SJames Tabor return ret; 207*7bffb703SJames Tabor } 208*7bffb703SJames Tabor 209*7bffb703SJames Tabor if (HeapFree (hHeap, 0, pKeyNameW) == 0) 210*7bffb703SJames Tabor { 211*7bffb703SJames Tabor ret = GetLastError (); 212*7bffb703SJames Tabor ERR ("HeapFree failed with code %i\n", ret); 213*7bffb703SJames Tabor return ret; 214*7bffb703SJames Tabor } 215*7bffb703SJames Tabor 216*7bffb703SJames Tabor if (*pnEnumValues == 0) /* empty key */ 217*7bffb703SJames Tabor return ERROR_SUCCESS; 218*7bffb703SJames Tabor 219*7bffb703SJames Tabor dwBufSize = 0; 220*7bffb703SJames Tabor for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) 221*7bffb703SJames Tabor { 222*7bffb703SJames Tabor PPRINTER_ENUM_VALUESW ppev = 223*7bffb703SJames Tabor &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; 224*7bffb703SJames Tabor 225*7bffb703SJames Tabor if (dwBufSize < ppev->cbValueName) 226*7bffb703SJames Tabor dwBufSize = ppev->cbValueName; 227*7bffb703SJames Tabor 228*7bffb703SJames Tabor if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ || 229*7bffb703SJames Tabor ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ)) 230*7bffb703SJames Tabor dwBufSize = ppev->cbData; 231*7bffb703SJames Tabor } 232*7bffb703SJames Tabor 233*7bffb703SJames Tabor TRACE ("Largest Unicode name or value is %i bytes\n", dwBufSize); 234*7bffb703SJames Tabor 235*7bffb703SJames Tabor pBuffer = HeapAlloc (hHeap, 0, dwBufSize); 236*7bffb703SJames Tabor if (pBuffer == NULL) 237*7bffb703SJames Tabor { 238*7bffb703SJames Tabor ERR ("Failed to allocate %i bytes from process heap\n", dwBufSize); 239*7bffb703SJames Tabor return ERROR_OUTOFMEMORY; 240*7bffb703SJames Tabor } 241*7bffb703SJames Tabor 242*7bffb703SJames Tabor for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) 243*7bffb703SJames Tabor { 244*7bffb703SJames Tabor PPRINTER_ENUM_VALUESW ppev = 245*7bffb703SJames Tabor &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; 246*7bffb703SJames Tabor 247*7bffb703SJames Tabor len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName, 248*7bffb703SJames Tabor ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL, 249*7bffb703SJames Tabor NULL); 250*7bffb703SJames Tabor if (len == 0) 251*7bffb703SJames Tabor { 252*7bffb703SJames Tabor ret = GetLastError (); 253*7bffb703SJames Tabor ERR ("WideCharToMultiByte failed with code %i\n", ret); 254*7bffb703SJames Tabor if (HeapFree (hHeap, 0, pBuffer) == 0) 255*7bffb703SJames Tabor WARN ("HeapFree failed with code %i\n", GetLastError ()); 256*7bffb703SJames Tabor return ret; 257*7bffb703SJames Tabor } 258*7bffb703SJames Tabor 259*7bffb703SJames Tabor memcpy (ppev->pValueName, pBuffer, len); 260*7bffb703SJames Tabor 261*7bffb703SJames Tabor TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); 262*7bffb703SJames Tabor 263*7bffb703SJames Tabor if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ && 264*7bffb703SJames Tabor ppev->dwType != REG_MULTI_SZ) 265*7bffb703SJames Tabor continue; 266*7bffb703SJames Tabor 267*7bffb703SJames Tabor len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData, 268*7bffb703SJames Tabor ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL); 269*7bffb703SJames Tabor if (len == 0) 270*7bffb703SJames Tabor { 271*7bffb703SJames Tabor ret = GetLastError (); 272*7bffb703SJames Tabor ERR ("WideCharToMultiByte failed with code %i\n", ret); 273*7bffb703SJames Tabor if (HeapFree (hHeap, 0, pBuffer) == 0) 274*7bffb703SJames Tabor WARN ("HeapFree failed with code %i\n", GetLastError ()); 275*7bffb703SJames Tabor return ret; 276*7bffb703SJames Tabor } 277*7bffb703SJames Tabor 278*7bffb703SJames Tabor memcpy (ppev->pData, pBuffer, len); 279*7bffb703SJames Tabor 280*7bffb703SJames Tabor TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); 281*7bffb703SJames Tabor TRACE (" (only first string of REG_MULTI_SZ printed)\n"); 282*7bffb703SJames Tabor } 283*7bffb703SJames Tabor 284*7bffb703SJames Tabor if (HeapFree (hHeap, 0, pBuffer) == 0) 285*7bffb703SJames Tabor { 286*7bffb703SJames Tabor ret = GetLastError (); 287*7bffb703SJames Tabor ERR ("HeapFree failed with code %i\n", ret); 288*7bffb703SJames Tabor return ret; 289*7bffb703SJames Tabor } 290*7bffb703SJames Tabor 291*7bffb703SJames Tabor return ERROR_SUCCESS; 29246b91659SColin Finck } 29346b91659SColin Finck 29446b91659SColin Finck DWORD WINAPI 29546b91659SColin Finck EnumPrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues) 29646b91659SColin Finck { 29746b91659SColin Finck TRACE("EnumPrinterDataExW(%p, %S, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues); 29846b91659SColin Finck UNIMPLEMENTED; 29946b91659SColin Finck return ERROR_NOT_SUPPORTED; 30046b91659SColin Finck } 30146b91659SColin Finck 30246b91659SColin Finck DWORD WINAPI 30346b91659SColin Finck EnumPrinterDataW(HANDLE hPrinter, DWORD dwIndex, PWSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData) 30446b91659SColin Finck { 30546b91659SColin Finck TRACE("EnumPrinterDataW(%p, %lu, %S, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData); 30646b91659SColin Finck UNIMPLEMENTED; 30746b91659SColin Finck return ERROR_NOT_SUPPORTED; 30846b91659SColin Finck } 30946b91659SColin Finck 31046b91659SColin Finck DWORD WINAPI 31146b91659SColin Finck EnumPrinterKeyA(HANDLE hPrinter, PCSTR pKeyName, PSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey) 31246b91659SColin Finck { 31346b91659SColin Finck TRACE("EnumPrinterKeyA(%p, %s, %s, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey); 31446b91659SColin Finck UNIMPLEMENTED; 31546b91659SColin Finck return ERROR_NOT_SUPPORTED; 31646b91659SColin Finck } 31746b91659SColin Finck 31846b91659SColin Finck DWORD WINAPI 31946b91659SColin Finck EnumPrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName, PWSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey) 32046b91659SColin Finck { 32146b91659SColin Finck TRACE("EnumPrinterKeyW(%p, %S, %S, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey); 32246b91659SColin Finck UNIMPLEMENTED; 32346b91659SColin Finck return ERROR_NOT_SUPPORTED; 324c2c66affSColin Finck } 325c2c66affSColin Finck 326c2c66affSColin Finck DWORD WINAPI 327c2c66affSColin Finck GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) 328c2c66affSColin Finck { 3291f6f08ecSColin Finck TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded); 330c2c66affSColin Finck return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded); 331c2c66affSColin Finck } 332c2c66affSColin Finck 333c2c66affSColin Finck DWORD WINAPI 334c2c66affSColin Finck GetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) 335c2c66affSColin Finck { 336c2c66affSColin Finck DWORD cbUnicodeData; 337c2c66affSColin Finck DWORD cch; 338c2c66affSColin Finck DWORD dwReturnValue; 339c2c66affSColin Finck DWORD dwType; 340c2c66affSColin Finck POSVERSIONINFOEXA pInfoA; 341c2c66affSColin Finck POSVERSIONINFOEXW pInfoW; 342c2c66affSColin Finck PVOID pUnicodeData = NULL; 343c2c66affSColin Finck PWSTR pwszKeyName = NULL; 344c2c66affSColin Finck PWSTR pwszValueName = NULL; 345c2c66affSColin Finck 3461f6f08ecSColin Finck TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded); 3471f6f08ecSColin Finck 348c2c66affSColin Finck if (pKeyName) 349c2c66affSColin Finck { 350c2c66affSColin Finck // Convert pKeyName to a Unicode string pwszKeyName 351c2c66affSColin Finck cch = strlen(pKeyName); 352c2c66affSColin Finck 353c2c66affSColin Finck pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); 354c2c66affSColin Finck if (!pwszKeyName) 355c2c66affSColin Finck { 356c2c66affSColin Finck dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 357c2c66affSColin Finck ERR("HeapAlloc failed!\n"); 358c2c66affSColin Finck goto Cleanup; 359c2c66affSColin Finck } 360c2c66affSColin Finck 361c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1); 362c2c66affSColin Finck } 363c2c66affSColin Finck 364c2c66affSColin Finck if (pValueName) 365c2c66affSColin Finck { 366c2c66affSColin Finck // Convert pValueName to a Unicode string pwszValueName 367c2c66affSColin Finck cch = strlen(pValueName); 368c2c66affSColin Finck 369c2c66affSColin Finck pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); 370c2c66affSColin Finck if (!pwszValueName) 371c2c66affSColin Finck { 372c2c66affSColin Finck dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 373c2c66affSColin Finck ERR("HeapAlloc failed!\n"); 374c2c66affSColin Finck goto Cleanup; 375c2c66affSColin Finck } 376c2c66affSColin Finck 377c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1); 378c2c66affSColin Finck } 379c2c66affSColin Finck 380c2c66affSColin Finck // We need the data type information, even if no pData was passed. 381c2c66affSColin Finck if (!pType) 382c2c66affSColin Finck pType = &dwType; 383c2c66affSColin Finck 384c2c66affSColin Finck // Call GetPrinterDataExW for the first time. 385c2c66affSColin Finck // 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. 386c2c66affSColin Finck dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, pType, pData, nSize, pcbNeeded); 387c2c66affSColin Finck 388c2c66affSColin Finck // If a critical error occurred, just return it. We cannot do anything else in this case. 389c2c66affSColin Finck if (dwReturnValue != ERROR_SUCCESS && dwReturnValue != ERROR_MORE_DATA) 390c2c66affSColin Finck goto Cleanup; 391c2c66affSColin Finck 392c2c66affSColin Finck // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size. 393c2c66affSColin Finck cbUnicodeData = *pcbNeeded; 394c2c66affSColin Finck 395c2c66affSColin Finck if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ) 396c2c66affSColin Finck { 397c2c66affSColin Finck // This is a string that needs to be converted from Unicode to ANSI. 398c2c66affSColin Finck // Output the required buffer size for the ANSI string. 399c2c66affSColin Finck *pcbNeeded /= sizeof(WCHAR); 400c2c66affSColin Finck } 401c2c66affSColin Finck else if (*pType == REG_NONE) 402c2c66affSColin Finck { 403c2c66affSColin Finck if (cbUnicodeData == sizeof(OSVERSIONINFOW) && wcsicmp(pwszValueName, SPLREG_OS_VERSION) == 0) 404c2c66affSColin Finck { 405c2c66affSColin Finck // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA. 406c2c66affSColin Finck *pcbNeeded = sizeof(OSVERSIONINFOA); 407c2c66affSColin Finck } 408c2c66affSColin Finck else if (cbUnicodeData == sizeof(OSVERSIONINFOEXW) && wcsicmp(pwszValueName, SPLREG_OS_VERSIONEX) == 0) 409c2c66affSColin Finck { 410c2c66affSColin Finck // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA. 411c2c66affSColin Finck *pcbNeeded = sizeof(OSVERSIONINFOEXA); 412c2c66affSColin Finck } 413c2c66affSColin Finck else 414c2c66affSColin Finck { 415c2c66affSColin Finck // Other REG_NONE value, nothing to do. 416c2c66affSColin Finck goto Cleanup; 417c2c66affSColin Finck } 418c2c66affSColin Finck } 419c2c66affSColin Finck 420c2c66affSColin Finck // Check if the supplied buffer is large enough for the ANSI data. 421c2c66affSColin Finck if (nSize < *pcbNeeded) 422c2c66affSColin Finck { 423c2c66affSColin Finck dwReturnValue = ERROR_MORE_DATA; 424c2c66affSColin Finck goto Cleanup; 425c2c66affSColin Finck } 426c2c66affSColin Finck 427c2c66affSColin Finck // Allocate a temporary buffer for the Unicode data. 428c2c66affSColin Finck pUnicodeData = HeapAlloc(hProcessHeap, 0, cbUnicodeData); 429c2c66affSColin Finck if (!pUnicodeData) 430c2c66affSColin Finck { 431c2c66affSColin Finck dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 432c2c66affSColin Finck ERR("HeapAlloc failed!\n"); 433c2c66affSColin Finck goto Cleanup; 434c2c66affSColin Finck } 435c2c66affSColin Finck 436c2c66affSColin Finck if (dwReturnValue == ERROR_SUCCESS) 437c2c66affSColin Finck { 438c2c66affSColin Finck // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string, 439c2c66affSColin Finck // so the Unicode string has been copied into pData. Copy it to pUnicodeData. 440c2c66affSColin Finck CopyMemory(pUnicodeData, pData, cbUnicodeData); 441c2c66affSColin Finck } 442c2c66affSColin Finck else 443c2c66affSColin Finck { 444c2c66affSColin Finck // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string. 445c2c66affSColin Finck // We have to call GetPrinterDataExW again with the temporary buffer. 446c2c66affSColin Finck dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, NULL, (PBYTE)pUnicodeData, cbUnicodeData, &cbUnicodeData); 447c2c66affSColin Finck if (dwReturnValue != ERROR_SUCCESS) 448c2c66affSColin Finck goto Cleanup; 449c2c66affSColin Finck } 450c2c66affSColin Finck 451c2c66affSColin Finck if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ) 452c2c66affSColin Finck { 453c2c66affSColin Finck // Convert the Unicode string to ANSI. 454c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, (PWSTR)pUnicodeData, -1, (PSTR)pData, *pcbNeeded, NULL, NULL); 455c2c66affSColin Finck } 456c2c66affSColin Finck else 457c2c66affSColin Finck { 458c2c66affSColin Finck // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW. 459c2c66affSColin Finck // Copy the fields and convert the Unicode CSD Version string to ANSI. 460c2c66affSColin Finck pInfoW = (POSVERSIONINFOEXW)pUnicodeData; 461c2c66affSColin Finck pInfoA = (POSVERSIONINFOEXA)pData; 462c2c66affSColin Finck pInfoA->dwMajorVersion = pInfoW->dwMajorVersion; 463c2c66affSColin Finck pInfoA->dwMinorVersion = pInfoW->dwMinorVersion; 464c2c66affSColin Finck pInfoA->dwBuildNumber = pInfoW->dwBuildNumber; 465c2c66affSColin Finck pInfoA->dwPlatformId = pInfoW->dwPlatformId; 466c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, pInfoW->szCSDVersion, -1, pInfoA->szCSDVersion, sizeof(pInfoA->szCSDVersion), NULL, NULL); 467c2c66affSColin Finck 468c2c66affSColin Finck if (cbUnicodeData == sizeof(OSVERSIONINFOW)) 469c2c66affSColin Finck { 470c2c66affSColin Finck pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); 471c2c66affSColin Finck } 472c2c66affSColin Finck else 473c2c66affSColin Finck { 474c2c66affSColin Finck pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); 475c2c66affSColin Finck pInfoA->wServicePackMajor = pInfoW->wServicePackMajor; 476c2c66affSColin Finck pInfoA->wServicePackMinor = pInfoW->wServicePackMinor; 477c2c66affSColin Finck pInfoA->wSuiteMask = pInfoW->wSuiteMask; 478c2c66affSColin Finck pInfoA->wProductType = pInfoW->wProductType; 479c2c66affSColin Finck pInfoA->wReserved = pInfoW->wReserved; 480c2c66affSColin Finck } 481c2c66affSColin Finck } 482c2c66affSColin Finck 483c2c66affSColin Finck Cleanup: 484c2c66affSColin Finck if (pwszKeyName) 485c2c66affSColin Finck HeapFree(hProcessHeap, 0, pwszKeyName); 486c2c66affSColin Finck 487c2c66affSColin Finck if (pwszValueName) 488c2c66affSColin Finck HeapFree(hProcessHeap, 0, pwszValueName); 489c2c66affSColin Finck 490c2c66affSColin Finck if (pUnicodeData) 491c2c66affSColin Finck HeapFree(hProcessHeap, 0, pUnicodeData); 492c2c66affSColin Finck 493c2c66affSColin Finck return dwReturnValue; 494c2c66affSColin Finck } 495c2c66affSColin Finck 496c2c66affSColin Finck DWORD WINAPI 497c2c66affSColin Finck GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) 498c2c66affSColin Finck { 499c2c66affSColin Finck const WCHAR wszEmptyString[] = L""; 500c2c66affSColin Finck 501c2c66affSColin Finck BYTE DummyData; 502c2c66affSColin Finck DWORD dwErrorCode; 503c2c66affSColin Finck DWORD dwType = REG_NONE; 504c2c66affSColin Finck PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; 505c2c66affSColin Finck 5061f6f08ecSColin Finck TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded); 5071f6f08ecSColin Finck 508c2c66affSColin Finck // Sanity checks 509c2c66affSColin Finck if (!pHandle) 510c2c66affSColin Finck return ERROR_INVALID_HANDLE; 511c2c66affSColin Finck 512c2c66affSColin Finck // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way), 513c2c66affSColin Finck // Windows does it differently for GetPrinterDataExW and points them to empty variables. 514c2c66affSColin Finck if (!pKeyName) 515c2c66affSColin Finck pKeyName = wszEmptyString; 516c2c66affSColin Finck 517c2c66affSColin Finck if (!pType) 518c2c66affSColin Finck pType = &dwType; 519c2c66affSColin Finck 520c2c66affSColin Finck if (!pData && !nSize) 521c2c66affSColin Finck pData = &DummyData; 522c2c66affSColin Finck 523c2c66affSColin Finck // Do the RPC call 524c2c66affSColin Finck RpcTryExcept 525c2c66affSColin Finck { 526c2c66affSColin Finck dwErrorCode = _RpcGetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded); 527c2c66affSColin Finck } 528c2c66affSColin Finck RpcExcept(EXCEPTION_EXECUTE_HANDLER) 529c2c66affSColin Finck { 530c2c66affSColin Finck dwErrorCode = RpcExceptionCode(); 531c2c66affSColin Finck } 532c2c66affSColin Finck RpcEndExcept; 533c2c66affSColin Finck 534c2c66affSColin Finck return dwErrorCode; 535c2c66affSColin Finck } 536c2c66affSColin Finck 537c2c66affSColin Finck DWORD WINAPI 538c2c66affSColin Finck GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) 539c2c66affSColin Finck { 5401f6f08ecSColin Finck TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded); 541c2c66affSColin Finck return GetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded); 542c2c66affSColin Finck } 543c2c66affSColin Finck 544c2c66affSColin Finck DWORD WINAPI 545c2c66affSColin Finck SetPrinterDataA(HANDLE hPrinter, PSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData) 546c2c66affSColin Finck { 5471f6f08ecSColin Finck TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData); 548c2c66affSColin Finck return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type, pData, cbData); 549c2c66affSColin Finck } 550c2c66affSColin Finck 551c2c66affSColin Finck DWORD WINAPI 552c2c66affSColin Finck SetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData) 553c2c66affSColin Finck { 554c2c66affSColin Finck DWORD cch; 555c2c66affSColin Finck DWORD dwReturnValue; 556c2c66affSColin Finck PWSTR pwszKeyName = NULL; 557c2c66affSColin Finck PWSTR pwszValueName = NULL; 558c2c66affSColin Finck PWSTR pUnicodeData = NULL; 559c2c66affSColin Finck 5601f6f08ecSColin Finck TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData); 5611f6f08ecSColin Finck 562c2c66affSColin Finck if (pKeyName) 563c2c66affSColin Finck { 564c2c66affSColin Finck // Convert pKeyName to a Unicode string pwszKeyName 565c2c66affSColin Finck cch = strlen(pKeyName); 566c2c66affSColin Finck 567c2c66affSColin Finck pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); 568c2c66affSColin Finck if (!pwszKeyName) 569c2c66affSColin Finck { 570c2c66affSColin Finck dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 571c2c66affSColin Finck ERR("HeapAlloc failed!\n"); 572c2c66affSColin Finck goto Cleanup; 573c2c66affSColin Finck } 574c2c66affSColin Finck 575c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1); 576c2c66affSColin Finck } 577c2c66affSColin Finck 578c2c66affSColin Finck if (pValueName) 579c2c66affSColin Finck { 580c2c66affSColin Finck // Convert pValueName to a Unicode string pwszValueName 581c2c66affSColin Finck cch = strlen(pValueName); 582c2c66affSColin Finck 583c2c66affSColin Finck pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); 584c2c66affSColin Finck if (!pwszValueName) 585c2c66affSColin Finck { 586c2c66affSColin Finck dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 587c2c66affSColin Finck ERR("HeapAlloc failed!\n"); 588c2c66affSColin Finck goto Cleanup; 589c2c66affSColin Finck } 590c2c66affSColin Finck 591c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1); 592c2c66affSColin Finck } 593c2c66affSColin Finck 594c2c66affSColin Finck if (Type == REG_SZ || Type == REG_MULTI_SZ || Type == REG_EXPAND_SZ) 595c2c66affSColin Finck { 596c2c66affSColin Finck // Convert pData to a Unicode string pUnicodeData. 597c2c66affSColin Finck pUnicodeData = HeapAlloc(hProcessHeap, 0, cbData * sizeof(WCHAR)); 598c2c66affSColin Finck if (!pUnicodeData) 599c2c66affSColin Finck { 600c2c66affSColin Finck dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 601c2c66affSColin Finck ERR("HeapAlloc failed!\n"); 602c2c66affSColin Finck goto Cleanup; 603c2c66affSColin Finck } 604c2c66affSColin Finck 605c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, (PCSTR)pData, -1, pUnicodeData, cbData); 606c2c66affSColin Finck 607c2c66affSColin Finck pData = (PBYTE)pUnicodeData; 608c2c66affSColin Finck cbData *= sizeof(WCHAR); 609c2c66affSColin Finck } 610c2c66affSColin Finck 611c2c66affSColin Finck dwReturnValue = SetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, Type, pData, cbData); 612c2c66affSColin Finck 613c2c66affSColin Finck Cleanup: 614c2c66affSColin Finck if (pwszKeyName) 615c2c66affSColin Finck HeapFree(hProcessHeap, 0, pwszKeyName); 616c2c66affSColin Finck 617c2c66affSColin Finck if (pwszValueName) 618c2c66affSColin Finck HeapFree(hProcessHeap, 0, pwszValueName); 619c2c66affSColin Finck 620c2c66affSColin Finck if (pUnicodeData) 621c2c66affSColin Finck HeapFree(hProcessHeap, 0, pUnicodeData); 622c2c66affSColin Finck 623c2c66affSColin Finck return dwReturnValue; 624c2c66affSColin Finck } 625c2c66affSColin Finck 626c2c66affSColin Finck DWORD WINAPI 627c2c66affSColin Finck SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData) 628c2c66affSColin Finck { 629c2c66affSColin Finck const WCHAR wszEmptyString[] = L""; 630c2c66affSColin Finck 631c2c66affSColin Finck DWORD dwErrorCode; 632c2c66affSColin Finck PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; 633c2c66affSColin Finck 6341f6f08ecSColin Finck TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData); 6351f6f08ecSColin Finck 636c2c66affSColin Finck // Sanity checks 637c2c66affSColin Finck if (!pHandle) 638c2c66affSColin Finck return ERROR_INVALID_HANDLE; 639c2c66affSColin Finck 640c2c66affSColin Finck if (!pKeyName) 641c2c66affSColin Finck pKeyName = wszEmptyString; 642c2c66affSColin Finck 643c2c66affSColin Finck // Do the RPC call 644c2c66affSColin Finck RpcTryExcept 645c2c66affSColin Finck { 646c2c66affSColin Finck dwErrorCode = _RpcSetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, Type, pData, cbData); 647c2c66affSColin Finck } 648c2c66affSColin Finck RpcExcept(EXCEPTION_EXECUTE_HANDLER) 649c2c66affSColin Finck { 650c2c66affSColin Finck dwErrorCode = RpcExceptionCode(); 651c2c66affSColin Finck } 652c2c66affSColin Finck RpcEndExcept; 653c2c66affSColin Finck 654c2c66affSColin Finck return dwErrorCode; 655c2c66affSColin Finck } 656c2c66affSColin Finck 657c2c66affSColin Finck DWORD WINAPI 658c2c66affSColin Finck SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData) 659c2c66affSColin Finck { 6601f6f08ecSColin Finck TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData); 661c2c66affSColin Finck return SetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, Type, pData, cbData); 662c2c66affSColin Finck } 663