1 /* 2 * PROJECT: ReactOS Spooler API 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Functions related to Printer Configuration Data 5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org) 6 */ 7 8 #include "precomp.h" 9 10 LONG WINAPI 11 AdvancedSetupDialog(HWND hWnd, INT Unknown, PDEVMODEA pDevModeInput, PDEVMODEA pDevModeOutput) 12 { 13 HANDLE hPrinter; 14 LONG Ret = -1; 15 16 TRACE("AdvancedSetupDialog(%p, %d, %p, %p)\n", hWnd, Unknown, pDevModeOutput, pDevModeInput); 17 18 if ( OpenPrinterA( (LPSTR)pDevModeInput->dmDeviceName, &hPrinter, NULL ) ) 19 { 20 Ret = AdvancedDocumentPropertiesA( hWnd, hPrinter, (PSTR)pDevModeInput->dmDeviceName, pDevModeOutput, pDevModeInput ); 21 ClosePrinter(hPrinter); 22 } 23 return Ret; 24 } 25 26 LONG WINAPI 27 AdvancedDocumentPropertiesA(HWND hWnd, HANDLE hPrinter, PSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput) 28 { 29 TRACE("AdvancedDocumentPropertiesA(%p, %p, %s, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput); 30 UNIMPLEMENTED; 31 return 0; 32 } 33 34 LONG WINAPI 35 AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput) 36 { 37 TRACE("AdvancedDocumentPropertiesW(%p, %p, %S, %p, %p)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput); 38 UNIMPLEMENTED; 39 return 0; 40 } 41 42 DWORD WINAPI 43 DeletePrinterDataA(HANDLE hPrinter, PSTR pValueName) 44 { 45 LPWSTR valuenameW = NULL; 46 INT len; 47 DWORD res; 48 49 TRACE("DeletePrinterDataA(%p, %s)\n", hPrinter, pValueName); 50 51 if (pValueName) 52 { 53 len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0); 54 valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 55 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len); 56 } 57 58 res = DeletePrinterDataW( hPrinter, valuenameW ); 59 60 if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW); 61 62 return res; 63 64 } 65 66 DWORD WINAPI 67 DeletePrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PCSTR pValueName) 68 { 69 LPWSTR keynameW = NULL; 70 LPWSTR valuenameW = NULL; 71 INT len; 72 DWORD res; 73 74 TRACE("DeletePrinterDataExA(%p, %s, %s)\n", hPrinter, pKeyName, pValueName); 75 76 if (pKeyName) 77 { 78 len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0); 79 keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 80 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len); 81 } 82 83 if (pValueName) 84 { 85 len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0); 86 valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 87 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len); 88 } 89 90 res = DeletePrinterDataExW( hPrinter, keynameW, valuenameW ); 91 92 if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW); 93 if (valuenameW) HeapFree(GetProcessHeap(), 0, valuenameW); 94 95 return res; 96 } 97 98 DWORD WINAPI 99 DeletePrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName) 100 { 101 TRACE("DeletePrinterDataExW(%p, %S, %S)\n", hPrinter, pKeyName, pValueName); 102 UNIMPLEMENTED; 103 return ERROR_NOT_SUPPORTED; 104 } 105 106 DWORD WINAPI 107 DeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName) 108 { 109 TRACE("DeletePrinterDataW(%p, %S)\n", hPrinter, pValueName); 110 UNIMPLEMENTED; 111 return ERROR_NOT_SUPPORTED; 112 } 113 114 DWORD WINAPI 115 DeletePrinterKeyA(HANDLE hPrinter, PCSTR pKeyName) 116 { 117 LPWSTR keynameW = NULL; 118 INT len; 119 DWORD res; 120 121 TRACE("DeletePrinterKeyA(%p, %s)\n", hPrinter, pKeyName); 122 123 if (pKeyName) 124 { 125 len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0); 126 keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 127 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len); 128 } 129 130 res = DeletePrinterKeyW( hPrinter, keynameW ); 131 132 if (keynameW) HeapFree(GetProcessHeap(), 0, keynameW); 133 134 return res; 135 } 136 137 DWORD WINAPI 138 DeletePrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName) 139 { 140 TRACE("DeletePrinterKeyW(%p, %S)\n", hPrinter, pKeyName); 141 UNIMPLEMENTED; 142 return ERROR_NOT_SUPPORTED; 143 } 144 145 DWORD WINAPI 146 EnumPrinterDataA(HANDLE hPrinter, DWORD dwIndex, PSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData) 147 { 148 TRACE("EnumPrinterDataA(%p, %lu, %s, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData); 149 UNIMPLEMENTED; 150 return ERROR_NOT_SUPPORTED; 151 } 152 153 DWORD WINAPI 154 EnumPrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues) 155 { 156 INT len; 157 LPWSTR pKeyNameW; 158 DWORD ret, dwIndex, dwBufSize; 159 HANDLE hHeap; 160 LPSTR pBuffer; 161 162 TRACE("EnumPrinterDataExA(%p, %s, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues); 163 164 if (pKeyName == NULL || *pKeyName == 0) 165 return ERROR_INVALID_PARAMETER; 166 167 len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0); 168 if (len == 0) 169 { 170 ret = GetLastError (); 171 ERR ("MultiByteToWideChar failed with code %i\n", ret); 172 return ret; 173 } 174 175 hHeap = GetProcessHeap (); 176 if (hHeap == NULL) 177 { 178 ERR ("GetProcessHeap failed\n"); 179 return ERROR_OUTOFMEMORY; 180 } 181 182 pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR)); 183 if (pKeyNameW == NULL) 184 { 185 ERR ("Failed to allocate %i bytes from process heap\n", 186 (LONG)(len * sizeof (WCHAR))); 187 return ERROR_OUTOFMEMORY; 188 } 189 190 if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0) 191 { 192 ret = GetLastError (); 193 ERR ("MultiByteToWideChar failed with code %i\n", ret); 194 if (HeapFree (hHeap, 0, pKeyNameW) == 0) 195 WARN ("HeapFree failed with code %i\n", GetLastError ()); 196 return ret; 197 } 198 199 ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues); 200 201 if (ret != ERROR_SUCCESS) 202 { 203 if (HeapFree (hHeap, 0, pKeyNameW) == 0) 204 WARN ("HeapFree failed with code %i\n", GetLastError ()); 205 TRACE ("EnumPrinterDataExW returned %i\n", ret); 206 return ret; 207 } 208 209 if (HeapFree (hHeap, 0, pKeyNameW) == 0) 210 { 211 ret = GetLastError (); 212 ERR ("HeapFree failed with code %i\n", ret); 213 return ret; 214 } 215 216 if (*pnEnumValues == 0) /* empty key */ 217 return ERROR_SUCCESS; 218 219 dwBufSize = 0; 220 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) 221 { 222 PPRINTER_ENUM_VALUESW ppev = &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; 223 224 if (dwBufSize < ppev->cbValueName) 225 dwBufSize = ppev->cbValueName; 226 227 if ( dwBufSize < ppev->cbData && 228 (ppev->dwType == REG_SZ || ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ)) 229 dwBufSize = ppev->cbData; 230 } 231 232 FIXME ("Largest Unicode name or value is %i bytes\n", dwBufSize); 233 234 pBuffer = HeapAlloc (hHeap, 0, dwBufSize); 235 if (pBuffer == NULL) 236 { 237 ERR ("Failed to allocate %i bytes from process heap\n", dwBufSize); 238 return ERROR_OUTOFMEMORY; 239 } 240 241 for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) 242 { 243 PPRINTER_ENUM_VALUESW ppev = 244 &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; 245 246 len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName, 247 ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL, 248 NULL); 249 if (len == 0) 250 { 251 ret = GetLastError (); 252 ERR ("WideCharToMultiByte failed with code %i\n", ret); 253 if (HeapFree (hHeap, 0, pBuffer) == 0) 254 WARN ("HeapFree failed with code %i\n", GetLastError ()); 255 return ret; 256 } 257 258 memcpy (ppev->pValueName, pBuffer, len); 259 260 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); 261 262 if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ && 263 ppev->dwType != REG_MULTI_SZ) 264 continue; 265 266 len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData, 267 ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL); 268 if (len == 0) 269 { 270 ret = GetLastError (); 271 ERR ("WideCharToMultiByte failed with code %i\n", ret); 272 if (HeapFree (hHeap, 0, pBuffer) == 0) 273 WARN ("HeapFree failed with code %i\n", GetLastError ()); 274 return ret; 275 } 276 277 memcpy (ppev->pData, pBuffer, len); 278 279 TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); 280 TRACE (" (only first string of REG_MULTI_SZ printed)\n"); 281 } 282 283 if (HeapFree (hHeap, 0, pBuffer) == 0) 284 { 285 ret = GetLastError (); 286 ERR ("HeapFree failed with code %i\n", ret); 287 return ret; 288 } 289 290 return ERROR_SUCCESS; 291 } 292 293 DWORD WINAPI 294 EnumPrinterDataExW(HANDLE hPrinter, PCWSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues) 295 { 296 TRACE("EnumPrinterDataExW(%p, %S, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues); 297 UNIMPLEMENTED; 298 return ERROR_NOT_SUPPORTED; 299 } 300 301 DWORD WINAPI 302 EnumPrinterDataW(HANDLE hPrinter, DWORD dwIndex, PWSTR pValueName, DWORD cbValueName, PDWORD pcbValueName, PDWORD pType, PBYTE pData, DWORD cbData, PDWORD pcbData) 303 { 304 TRACE("EnumPrinterDataW(%p, %lu, %S, %lu, %p, %p, %p, %lu, %p)\n", hPrinter, dwIndex, pValueName, cbValueName, pcbValueName, pType, pData, cbData, pcbData); 305 UNIMPLEMENTED; 306 return ERROR_NOT_SUPPORTED; 307 } 308 309 DWORD WINAPI 310 EnumPrinterKeyA(HANDLE hPrinter, PCSTR pKeyName, PSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey) 311 { 312 TRACE("EnumPrinterKeyA(%p, %s, %s, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey); 313 UNIMPLEMENTED; 314 return ERROR_NOT_SUPPORTED; 315 } 316 317 DWORD WINAPI 318 EnumPrinterKeyW(HANDLE hPrinter, PCWSTR pKeyName, PWSTR pSubkey, DWORD cbSubkey, PDWORD pcbSubkey) 319 { 320 TRACE("EnumPrinterKeyW(%p, %S, %S, %lu, %p)\n", hPrinter, pKeyName, pSubkey, cbSubkey, pcbSubkey); 321 UNIMPLEMENTED; 322 return ERROR_NOT_SUPPORTED; 323 } 324 325 DWORD WINAPI 326 GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) 327 { 328 TRACE("GetPrinterDataA(%p, %s, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded); 329 return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded); 330 } 331 332 DWORD WINAPI 333 GetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) 334 { 335 DWORD cbUnicodeData; 336 DWORD cch; 337 DWORD dwReturnValue; 338 DWORD dwType; 339 POSVERSIONINFOEXA pInfoA; 340 POSVERSIONINFOEXW pInfoW; 341 PVOID pUnicodeData = NULL; 342 PWSTR pwszKeyName = NULL; 343 PWSTR pwszValueName = NULL; 344 345 TRACE("GetPrinterDataExA(%p, %s, %s, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded); 346 347 if (pKeyName) 348 { 349 // Convert pKeyName to a Unicode string pwszKeyName 350 cch = strlen(pKeyName); 351 352 pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); 353 if (!pwszKeyName) 354 { 355 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 356 ERR("HeapAlloc failed!\n"); 357 goto Cleanup; 358 } 359 360 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1); 361 } 362 363 if (pValueName) 364 { 365 // Convert pValueName to a Unicode string pwszValueName 366 cch = strlen(pValueName); 367 368 pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); 369 if (!pwszValueName) 370 { 371 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 372 ERR("HeapAlloc failed!\n"); 373 goto Cleanup; 374 } 375 376 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1); 377 } 378 379 // We need the data type information, even if no pData was passed. 380 if (!pType) 381 pType = &dwType; 382 383 // Call GetPrinterDataExW for the first time. 384 // 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. 385 dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, pType, pData, nSize, pcbNeeded); 386 387 // If a critical error occurred, just return it. We cannot do anything else in this case. 388 if (dwReturnValue != ERROR_SUCCESS && dwReturnValue != ERROR_MORE_DATA) 389 goto Cleanup; 390 391 // Save the needed buffer size for the Unicode data. We may alter *pcbNeeded for an ANSI buffer size. 392 cbUnicodeData = *pcbNeeded; 393 394 if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ) 395 { 396 // This is a string that needs to be converted from Unicode to ANSI. 397 // Output the required buffer size for the ANSI string. 398 *pcbNeeded /= sizeof(WCHAR); 399 } 400 else if (*pType == REG_NONE) 401 { 402 if (cbUnicodeData == sizeof(OSVERSIONINFOW) && _wcsicmp(pwszValueName, SPLREG_OS_VERSION) == 0) 403 { 404 // This is a Unicode OSVERSIONINFOW structure that needs to be converted to an ANSI OSVERSIONINFOA. 405 *pcbNeeded = sizeof(OSVERSIONINFOA); 406 } 407 else if (cbUnicodeData == sizeof(OSVERSIONINFOEXW) && _wcsicmp(pwszValueName, SPLREG_OS_VERSIONEX) == 0) 408 { 409 // This is a Unicode OSVERSIONINFOEXW structure that needs to be converted to an ANSI OSVERSIONINFOEXA. 410 *pcbNeeded = sizeof(OSVERSIONINFOEXA); 411 } 412 else 413 { 414 // Other REG_NONE value, nothing to do. 415 goto Cleanup; 416 } 417 } 418 419 // Check if the supplied buffer is large enough for the ANSI data. 420 if (nSize < *pcbNeeded) 421 { 422 dwReturnValue = ERROR_MORE_DATA; 423 goto Cleanup; 424 } 425 426 // Allocate a temporary buffer for the Unicode data. 427 pUnicodeData = HeapAlloc(hProcessHeap, 0, cbUnicodeData); 428 if (!pUnicodeData) 429 { 430 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 431 ERR("HeapAlloc failed!\n"); 432 goto Cleanup; 433 } 434 435 if (dwReturnValue == ERROR_SUCCESS) 436 { 437 // ERROR_SUCCESS: The buffer is large enough for the ANSI and the Unicode string, 438 // so the Unicode string has been copied into pData. Copy it to pUnicodeData. 439 CopyMemory(pUnicodeData, pData, cbUnicodeData); 440 } 441 else 442 { 443 // ERROR_MORE_DATA: The buffer is large enough for the ANSI string, but not for the Unicode string. 444 // We have to call GetPrinterDataExW again with the temporary buffer. 445 dwReturnValue = GetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, NULL, (PBYTE)pUnicodeData, cbUnicodeData, &cbUnicodeData); 446 if (dwReturnValue != ERROR_SUCCESS) 447 goto Cleanup; 448 } 449 450 if (*pType == REG_SZ || *pType == REG_MULTI_SZ || *pType == REG_EXPAND_SZ) 451 { 452 // Convert the Unicode string to ANSI. 453 WideCharToMultiByte(CP_ACP, 0, (PWSTR)pUnicodeData, -1, (PSTR)pData, *pcbNeeded, NULL, NULL); 454 } 455 else 456 { 457 // This is a REG_NONE with either OSVERSIONINFOW or OSVERSIONINFOEXW. 458 // Copy the fields and convert the Unicode CSD Version string to ANSI. 459 pInfoW = (POSVERSIONINFOEXW)pUnicodeData; 460 pInfoA = (POSVERSIONINFOEXA)pData; 461 pInfoA->dwMajorVersion = pInfoW->dwMajorVersion; 462 pInfoA->dwMinorVersion = pInfoW->dwMinorVersion; 463 pInfoA->dwBuildNumber = pInfoW->dwBuildNumber; 464 pInfoA->dwPlatformId = pInfoW->dwPlatformId; 465 WideCharToMultiByte(CP_ACP, 0, pInfoW->szCSDVersion, -1, pInfoA->szCSDVersion, sizeof(pInfoA->szCSDVersion), NULL, NULL); 466 467 if (cbUnicodeData == sizeof(OSVERSIONINFOW)) 468 { 469 pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); 470 } 471 else 472 { 473 pInfoA->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); 474 pInfoA->wServicePackMajor = pInfoW->wServicePackMajor; 475 pInfoA->wServicePackMinor = pInfoW->wServicePackMinor; 476 pInfoA->wSuiteMask = pInfoW->wSuiteMask; 477 pInfoA->wProductType = pInfoW->wProductType; 478 pInfoA->wReserved = pInfoW->wReserved; 479 } 480 } 481 482 Cleanup: 483 if (pwszKeyName) 484 HeapFree(hProcessHeap, 0, pwszKeyName); 485 486 if (pwszValueName) 487 HeapFree(hProcessHeap, 0, pwszValueName); 488 489 if (pUnicodeData) 490 HeapFree(hProcessHeap, 0, pUnicodeData); 491 492 return dwReturnValue; 493 } 494 495 DWORD WINAPI 496 GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) 497 { 498 const WCHAR wszEmptyString[] = L""; 499 500 BYTE DummyData; 501 DWORD dwErrorCode; 502 DWORD dwType = REG_NONE; 503 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; 504 505 TRACE("GetPrinterDataExW(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded); 506 507 // Sanity checks 508 if (!pHandle) 509 return ERROR_INVALID_HANDLE; 510 511 // Yes, instead of declaring these pointers unique in the IDL file (and perfectly accepting NULL pointers this way), 512 // Windows does it differently for GetPrinterDataExW and points them to empty variables. 513 if (!pKeyName) 514 pKeyName = wszEmptyString; 515 516 if (!pType) 517 pType = &dwType; 518 519 if (!pData && !nSize) 520 pData = &DummyData; 521 522 // Do the RPC call 523 RpcTryExcept 524 { 525 dwErrorCode = _RpcGetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded); 526 } 527 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 528 { 529 dwErrorCode = RpcExceptionCode(); 530 } 531 RpcEndExcept; 532 533 return dwErrorCode; 534 } 535 536 DWORD WINAPI 537 GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) 538 { 539 TRACE("GetPrinterDataW(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded); 540 return GetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded); 541 } 542 543 DWORD WINAPI 544 SetPrinterDataA(HANDLE hPrinter, PSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData) 545 { 546 TRACE("SetPrinterDataA(%p, %s, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData); 547 return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type, pData, cbData); 548 } 549 550 DWORD WINAPI 551 SetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, LPCSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData) 552 { 553 DWORD cch; 554 DWORD dwReturnValue; 555 PWSTR pwszKeyName = NULL; 556 PWSTR pwszValueName = NULL; 557 PWSTR pUnicodeData = NULL; 558 559 TRACE("SetPrinterDataExA(%p, %s, %s, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData); 560 561 if (pKeyName) 562 { 563 // Convert pKeyName to a Unicode string pwszKeyName 564 cch = strlen(pKeyName); 565 566 pwszKeyName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); 567 if (!pwszKeyName) 568 { 569 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 570 ERR("HeapAlloc failed!\n"); 571 goto Cleanup; 572 } 573 574 MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, pwszKeyName, cch + 1); 575 } 576 577 if (pValueName) 578 { 579 // Convert pValueName to a Unicode string pwszValueName 580 cch = strlen(pValueName); 581 582 pwszValueName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); 583 if (!pwszValueName) 584 { 585 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 586 ERR("HeapAlloc failed!\n"); 587 goto Cleanup; 588 } 589 590 MultiByteToWideChar(CP_ACP, 0, pValueName, -1, pwszValueName, cch + 1); 591 } 592 593 if (Type == REG_SZ || Type == REG_MULTI_SZ || Type == REG_EXPAND_SZ) 594 { 595 // Convert pData to a Unicode string pUnicodeData. 596 pUnicodeData = HeapAlloc(hProcessHeap, 0, cbData * sizeof(WCHAR)); 597 if (!pUnicodeData) 598 { 599 dwReturnValue = ERROR_NOT_ENOUGH_MEMORY; 600 ERR("HeapAlloc failed!\n"); 601 goto Cleanup; 602 } 603 604 MultiByteToWideChar(CP_ACP, 0, (PCSTR)pData, -1, pUnicodeData, cbData); 605 606 pData = (PBYTE)pUnicodeData; 607 cbData *= sizeof(WCHAR); 608 } 609 610 dwReturnValue = SetPrinterDataExW(hPrinter, pwszKeyName, pwszValueName, Type, pData, cbData); 611 612 Cleanup: 613 if (pwszKeyName) 614 HeapFree(hProcessHeap, 0, pwszKeyName); 615 616 if (pwszValueName) 617 HeapFree(hProcessHeap, 0, pwszValueName); 618 619 if (pUnicodeData) 620 HeapFree(hProcessHeap, 0, pUnicodeData); 621 622 return dwReturnValue; 623 } 624 625 DWORD WINAPI 626 SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData) 627 { 628 const WCHAR wszEmptyString[] = L""; 629 630 DWORD dwErrorCode; 631 PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; 632 633 TRACE("SetPrinterDataExW(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData); 634 635 // Sanity checks 636 if (!pHandle) 637 return ERROR_INVALID_HANDLE; 638 639 if (!pKeyName) 640 pKeyName = wszEmptyString; 641 642 // Do the RPC call 643 RpcTryExcept 644 { 645 dwErrorCode = _RpcSetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, Type, pData, cbData); 646 } 647 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 648 { 649 dwErrorCode = RpcExceptionCode(); 650 } 651 RpcEndExcept; 652 653 return dwErrorCode; 654 } 655 656 DWORD WINAPI 657 SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData) 658 { 659 TRACE("SetPrinterDataW(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData); 660 return SetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, Type, pData, cbData); 661 } 662