#include "precomp.h"
#include <marshalling/printers.h>
#include <marshalling/printerdrivers.h>
+#include <strsafe.h>
// Local Constants
return 0;
}
+INT WINAPI
+DocumentEvent( HANDLE hPrinter, HDC hdc, int iEsc, ULONG cbIn, PVOID pvIn, ULONG cbOut, PVOID pvOut)
+{
+ TRACE("DocumentEvent(%p, %p, %lu, %lu, %p, %lu, %p)\n", hPrinter, hdc, iEsc, cbIn, pvIn, cbOut, pvOut);
+ UNIMPLEMENTED;
+ return DOCUMENTEVENT_UNSUPPORTED;
+}
+
LONG WINAPI
DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode)
{
+ PWSTR pwszDeviceName = NULL;
+ PDEVMODEW pdmwInput = NULL;
+ PDEVMODEW pdmwOutput = NULL;
+ BOOL bReturnValue = -1;
+ DWORD cch;
+
TRACE("DocumentPropertiesA(%p, %p, %s, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
- UNIMPLEMENTED;
- return -1;
+
+ if (pDeviceName)
+ {
+ // Convert pName to a Unicode string pwszDeviceName.
+ cch = strlen(pDeviceName);
+
+ pwszDeviceName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
+ if (!pwszDeviceName)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ MultiByteToWideChar(CP_ACP, 0, pDeviceName, -1, pwszDeviceName, cch + 1);
+ }
+
+ if (pDevModeInput)
+ {
+ // Create working buffer for input to DocumentPropertiesW.
+ pdmwInput = HeapAlloc(hProcessHeap, 0, sizeof(DEVMODEW));
+ if (!pdmwInput)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+ RosConvertAnsiDevModeToUnicodeDevmode(pDevModeInput, pdmwInput);
+ }
+
+ if (pDevModeOutput)
+ {
+ // Create working buffer for output from DocumentPropertiesW.
+ pdmwOutput = HeapAlloc(hProcessHeap, 0, sizeof(DEVMODEW));
+ if (!pdmwOutput)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+ }
+
+ bReturnValue = DocumentPropertiesW(hWnd, hPrinter, pwszDeviceName, pdmwOutput, pdmwInput, fMode);
+ TRACE("bReturnValue from DocumentPropertiesW is '%ld'.\n", bReturnValue);
+
+ if (pwszDeviceName)
+ {
+ HeapFree(hProcessHeap, 0, pwszDeviceName);
+ }
+
+ if (bReturnValue < 0)
+ {
+ TRACE("DocumentPropertiesW failed!\n");
+ goto Cleanup;
+ }
+
+ if (pdmwOutput)
+ {
+ RosConvertUnicodeDevModeToAnsiDevmode(pdmwOutput, pDevModeOutput);
+ }
+
+Cleanup:
+ if(pwszDeviceName)
+ HeapFree(hProcessHeap, 0, pwszDeviceName);
+
+ if (pdmwInput)
+ HeapFree(hProcessHeap, 0, pdmwInput);
+
+ if (pdmwOutput)
+ HeapFree(hProcessHeap, 0, pdmwOutput);
+
+ return bReturnValue;
}
static PRINTER_INFO_9W * get_devmodeW(HANDLE hprn)
BOOL WINAPI
EnumPrintersA(DWORD Flags, PSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
+ DWORD dwErrorCode;
+ DWORD cch;
+ PWSTR pwszName = NULL;
+ PSTR pszPrinterName = NULL;
+ PSTR pszServerName = NULL;
+ PSTR pszDescription = NULL;
+ PSTR pszName = NULL;
+ PSTR pszComment = NULL;
+ PSTR pszShareName = NULL;
+ PSTR pszPortName = NULL;
+ PSTR pszDriverName = NULL;
+ PSTR pszLocation = NULL;
+ PSTR pszSepFile = NULL;
+ PSTR pszPrintProcessor = NULL;
+ PSTR pszDatatype = NULL;
+ PSTR pszParameters = NULL;
+ DWORD i;
+ PPRINTER_INFO_1W ppi1w = NULL;
+ PPRINTER_INFO_1A ppi1a = NULL;
+ PPRINTER_INFO_2W ppi2w = NULL;
+ PPRINTER_INFO_2A ppi2a = NULL;
+ PPRINTER_INFO_4W ppi4w = NULL;
+ PPRINTER_INFO_4A ppi4a = NULL;
+ PPRINTER_INFO_5W ppi5w = NULL;
+ PPRINTER_INFO_5A ppi5a = NULL;
+
TRACE("EnumPrintersA(%lu, %s, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
- return FALSE;
+
+ // Check for invalid levels here for early error return. MSDN says that only 1, 2, 4, and 5 are allowable.
+ if (Level != 1 && Level != 2 && Level != 4 && Level != 5)
+ {
+ dwErrorCode = ERROR_INVALID_LEVEL;
+ ERR("Invalid Level!\n");
+ goto Cleanup;
+ }
+
+ if (Name)
+ {
+ // Convert pName to a Unicode string pwszName.
+ cch = strlen(Name);
+
+ pwszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
+ if (!pwszName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ MultiByteToWideChar(CP_ACP, 0, Name, -1, pwszName, cch + 1);
+ }
+
+ /* Ref: https://stackoverflow.com/questions/41147180/why-enumprintersa-and-enumprintersw-request-the-same-amount-of-memory */
+ if (!EnumPrintersW(Flags, pwszName, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned))
+ {
+ dwErrorCode = GetLastError();
+ goto Cleanup;
+ }
+
+ /* We are mapping multiple different pointers to the same pPrinterEnum pointer here so that */
+ /* we can do in-place conversion. We read the Unicode response from the EnumPrintersW and */
+ /* then we write back the ANSI conversion into the same buffer for our EnumPrintersA output */
+
+ /* mapping to pPrinterEnum for Unicode (w) characters for Levels 1, 2, 4, and 5 */
+ ppi1w = (PPRINTER_INFO_1W)pPrinterEnum;
+ ppi2w = (PPRINTER_INFO_2W)pPrinterEnum;
+ ppi4w = (PPRINTER_INFO_4W)pPrinterEnum;
+ ppi5w = (PPRINTER_INFO_5W)pPrinterEnum;
+ /* mapping to pPrinterEnum for ANSI (a) characters for Levels 1, 2, 4, and 5 */
+ ppi1a = (PPRINTER_INFO_1A)pPrinterEnum;
+ ppi2a = (PPRINTER_INFO_2A)pPrinterEnum;
+ ppi4a = (PPRINTER_INFO_4A)pPrinterEnum;
+ ppi5a = (PPRINTER_INFO_5A)pPrinterEnum;
+
+ for (i = 0; i < *pcReturned; i++)
+ {
+ switch (Level)
+ {
+ case 1:
+ {
+ if (ppi1w[i].pDescription)
+ {
+ // Convert Unicode pDescription to a ANSI string pszDescription.
+ cch = wcslen(ppi1w[i].pDescription);
+
+ pszDescription = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszDescription)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pDescription, -1, pszDescription, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi1a[i].pDescription, cch + 1, pszDescription);
+
+ HeapFree(hProcessHeap, 0, pszDescription);
+ }
+
+ if (ppi1w[i].pName)
+ {
+ // Convert Unicode pName to a ANSI string pszName.
+ cch = wcslen(ppi1w[i].pName);
+
+ pszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pName, -1, pszName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi1a[i].pName, cch + 1, pszName);
+
+ HeapFree(hProcessHeap, 0, pszName);
+ }
+
+ if (ppi1w[i].pComment)
+ {
+ // Convert Unicode pComment to a ANSI string pszComment.
+ cch = wcslen(ppi1w[i].pComment);
+
+ pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszComment)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pComment, -1, pszComment, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi1a[i].pComment, cch + 1, pszComment);
+
+ HeapFree(hProcessHeap, 0, pszComment);
+ }
+ break;
+ }
+
+
+ case 2:
+ {
+ if (ppi2w[i].pServerName)
+ {
+ // Convert Unicode pServerName to a ANSI string pszServerName.
+ cch = wcslen(ppi2w[i].pServerName);
+
+ pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszServerName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pServerName, -1, pszServerName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pServerName, cch + 1, pszServerName);
+
+ HeapFree(hProcessHeap, 0, pszServerName);
+ }
+
+ if (ppi2w[i].pPrinterName)
+ {
+ // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
+ cch = wcslen(ppi2w[i].pPrinterName);
+
+ pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPrinterName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pPrinterName, cch + 1, pszPrinterName);
+
+ HeapFree(hProcessHeap, 0, pszPrinterName);
+ }
+
+ if (ppi2w[i].pShareName)
+ {
+ // Convert Unicode pShareName to a ANSI string pszShareName.
+ cch = wcslen(ppi2w[i].pShareName);
+
+ pszShareName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszShareName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pShareName, -1, pszShareName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pShareName, cch + 1, pszShareName);
+
+ HeapFree(hProcessHeap, 0, pszShareName);
+ }
+
+ if (ppi2w[i].pPortName)
+ {
+ // Convert Unicode pPortName to a ANSI string pszPortName.
+ cch = wcslen(ppi2w[i].pPortName);
+
+ pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPortName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPortName, -1, pszPortName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pPortName, cch + 1, pszPortName);
+
+ HeapFree(hProcessHeap, 0, pszPortName);
+ }
+
+ if (ppi2w[i].pDriverName)
+ {
+ // Convert Unicode pDriverName to a ANSI string pszDriverName.
+ cch = wcslen(ppi2w[i].pDriverName);
+
+ pszDriverName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszDriverName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pDriverName, -1, pszDriverName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pDriverName, cch + 1, pszDriverName);
+
+ HeapFree(hProcessHeap, 0, pszDriverName);
+ }
+
+ if (ppi2w[i].pComment)
+ {
+ // Convert Unicode pComment to a ANSI string pszComment.
+ cch = wcslen(ppi2w[i].pComment);
+
+ pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszComment)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pComment, -1, pszComment, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pComment, cch + 1, pszComment);
+
+ HeapFree(hProcessHeap, 0, pszComment);
+ }
+
+ if (ppi2w[i].pLocation)
+ {
+ // Convert Unicode pLocation to a ANSI string pszLocation.
+ cch = wcslen(ppi2w[i].pLocation);
+
+ pszLocation = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszLocation)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pLocation, -1, pszLocation, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pLocation, cch + 1, pszLocation);
+
+ HeapFree(hProcessHeap, 0, pszLocation);
+ }
+
+
+ if (ppi2w[i].pSepFile)
+ {
+ // Convert Unicode pSepFile to a ANSI string pszSepFile.
+ cch = wcslen(ppi2w[i].pSepFile);
+
+ pszSepFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszSepFile)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pSepFile, -1, pszSepFile, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pSepFile, cch + 1, pszSepFile);
+
+ HeapFree(hProcessHeap, 0, pszSepFile);
+ }
+
+ if (ppi2w[i].pPrintProcessor)
+ {
+ // Convert Unicode pPrintProcessor to a ANSI string pszPrintProcessor.
+ cch = wcslen(ppi2w[i].pPrintProcessor);
+
+ pszPrintProcessor = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPrintProcessor)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPrintProcessor, -1, pszPrintProcessor, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pPrintProcessor, cch + 1, pszPrintProcessor);
+
+ HeapFree(hProcessHeap, 0, pszPrintProcessor);
+ }
+
+
+ if (ppi2w[i].pDatatype)
+ {
+ // Convert Unicode pDatatype to a ANSI string pszDatatype.
+ cch = wcslen(ppi2w[i].pDatatype);
+
+ pszDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszDatatype)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pDatatype, -1, pszDatatype, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pDatatype, cch + 1, pszDatatype);
+
+ HeapFree(hProcessHeap, 0, pszDatatype);
+ }
+
+ if (ppi2w[i].pParameters)
+ {
+ // Convert Unicode pParameters to a ANSI string pszParameters.
+ cch = wcslen(ppi2w[i].pParameters);
+
+ pszParameters = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszParameters)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pParameters, -1, pszParameters, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a[i].pParameters, cch + 1, pszParameters);
+
+ HeapFree(hProcessHeap, 0, pszParameters);
+ }
+ break;
+
+ }
+
+ case 4:
+ {
+ if (ppi4w[i].pPrinterName)
+ {
+ // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
+ cch = wcslen(ppi4w[i].pPrinterName);
+
+ pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPrinterName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi4w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi4a[i].pPrinterName, cch + 1, pszPrinterName);
+
+ HeapFree(hProcessHeap, 0, pszPrinterName);
+ }
+
+ if (ppi4w[i].pServerName)
+ {
+ // Convert Unicode pServerName to a ANSI string pszServerName.
+ cch = wcslen(ppi4w[i].pServerName);
+
+ pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszServerName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi4w[i].pServerName, -1, pszServerName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi4a[i].pServerName, cch + 1, pszServerName);
+
+ HeapFree(hProcessHeap, 0, pszServerName);
+ }
+ break;
+ }
+
+ case 5:
+ {
+ if (ppi5w[i].pPrinterName)
+ {
+ // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
+ cch = wcslen(ppi5w[i].pPrinterName);
+
+ pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPrinterName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi5w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi5a[i].pPrinterName, cch + 1, pszPrinterName);
+
+ HeapFree(hProcessHeap, 0, pszPrinterName);
+ }
+
+ if (ppi5w[i].pPortName)
+ {
+ // Convert Unicode pPortName to a ANSI string pszPortName.
+ cch = wcslen(ppi5w[i].pPortName);
+
+ pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPortName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi5w[i].pPortName, -1, pszPortName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi5a[i].pPortName, cch + 1, pszPortName);
+
+ HeapFree(hProcessHeap, 0, pszPortName);
+ }
+ break;
+ }
+
+ } // switch
+ } // for
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ if (pwszName)
+ {
+ HeapFree(hProcessHeap, 0, pwszName);
+ }
+
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
TRACE("EnumPrintersW(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
- // Dismiss invalid levels already at this point.
- if (Level == 3 || Level > 5)
- {
- dwErrorCode = ERROR_INVALID_LEVEL;
- goto Cleanup;
- }
+ // Dismiss invalid levels already at this point.
+ if (Level == 3 || Level > 5)
+ {
+ dwErrorCode = ERROR_INVALID_LEVEL;
+ goto Cleanup;
+ }
+
+ if (cbBuf && pPrinterEnum)
+ ZeroMemory(pPrinterEnum, cbBuf);
+
+ // Do the RPC call
+ RpcTryExcept
+ {
+ dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
+ }
+ RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+ {
+ dwErrorCode = RpcExceptionCode();
+ ERR("_RpcEnumPrinters failed with exception code %lu!\n", dwErrorCode);
+ }
+ RpcEndExcept;
+
+ if (dwErrorCode == ERROR_SUCCESS)
+ {
+ // Replace relative offset addresses in the output by absolute pointers.
+ ASSERT(Level <= 9);
+ MarshallUpStructuresArray(cbBuf, pPrinterEnum, *pcReturned, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
+ }
+
+Cleanup:
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
+{
+ TRACE("FlushPrinter(%p, %p, %lu, %p, %lu)\n", hPrinter, pBuf, cbBuf, pcWritten, cSleep);
+ UNIMPLEMENTED;
+ return FALSE;
+}
+
+BOOL WINAPI
+GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
+{
+ DWORD dwErrorCode;
+ PWSTR pwszBuffer = NULL;
+
+ TRACE("GetDefaultPrinterA(%p, %p)\n", pszBuffer, pcchBuffer);
+
+ // Sanity check.
+ if (!pcchBuffer)
+ {
+ dwErrorCode = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ // Check if an ANSI buffer was given and if so, allocate a Unicode buffer of the same size.
+ if (pszBuffer && *pcchBuffer)
+ {
+ pwszBuffer = HeapAlloc(hProcessHeap, 0, *pcchBuffer * sizeof(WCHAR));
+ if (!pwszBuffer)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+ }
+
+ if (!GetDefaultPrinterW(pwszBuffer, pcchBuffer))
+ {
+ dwErrorCode = GetLastError();
+ goto Cleanup;
+ }
+
+ // We successfully got a string in pwszBuffer, so convert the Unicode string to ANSI.
+ WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszBuffer, *pcchBuffer, NULL, NULL);
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ if (pwszBuffer)
+ HeapFree(hProcessHeap, 0, pwszBuffer);
+
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
+{
+ DWORD cbNeeded;
+ DWORD cchInputBuffer;
+ DWORD dwErrorCode;
+ HKEY hWindowsKey = NULL;
+ PWSTR pwszDevice = NULL;
+ PWSTR pwszComma;
+
+ TRACE("GetDefaultPrinterW(%p, %p)\n", pszBuffer, pcchBuffer);
+
+ // Sanity check.
+ if (!pcchBuffer)
+ {
+ dwErrorCode = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ cchInputBuffer = *pcchBuffer;
+
+ // Open the registry key where the default printer for the current user is stored.
+ dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_READ, &hWindowsKey);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
+ goto Cleanup;
+ }
+
+ // Determine the size of the required buffer.
+ dwErrorCode = (DWORD)RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, NULL, &cbNeeded);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
+ goto Cleanup;
+ }
+
+ // Allocate it.
+ pwszDevice = HeapAlloc(hProcessHeap, 0, cbNeeded);
+ if (!pwszDevice)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ // Now get the actual value.
+ dwErrorCode = RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, (PBYTE)pwszDevice, &cbNeeded);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
+ goto Cleanup;
+ }
+
+ // We get a string "<Printer Name>,winspool,<Port>:".
+ // Extract the printer name from it.
+ pwszComma = wcschr(pwszDevice, L',');
+ if (!pwszComma)
+ {
+ ERR("Found no or invalid default printer: %S!\n", pwszDevice);
+ dwErrorCode = ERROR_INVALID_NAME;
+ goto Cleanup;
+ }
+
+ // Store the length of the Printer Name (including the terminating NUL character!) in *pcchBuffer.
+ *pcchBuffer = pwszComma - pwszDevice + 1;
+
+ // Check if the supplied buffer is large enough.
+ if (cchInputBuffer < *pcchBuffer)
+ {
+ dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
+ goto Cleanup;
+ }
+
+ // Copy the default printer.
+ *pwszComma = 0;
+ CopyMemory(pszBuffer, pwszDevice, *pcchBuffer * sizeof(WCHAR));
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ if (hWindowsKey)
+ RegCloseKey(hWindowsKey);
+
+ if (pwszDevice)
+ HeapFree(hProcessHeap, 0, pwszDevice);
+
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
+{
+ DWORD dwErrorCode;
+ PPRINTER_INFO_1A ppi1a = (PPRINTER_INFO_1A)pPrinter;
+ PPRINTER_INFO_1W ppi1w = (PPRINTER_INFO_1W)pPrinter;
+ PPRINTER_INFO_2A ppi2a = (PPRINTER_INFO_2A)pPrinter;
+ PPRINTER_INFO_2W ppi2w = (PPRINTER_INFO_2W)pPrinter;
+ PPRINTER_INFO_4A ppi4a = (PPRINTER_INFO_4A)pPrinter;
+ PPRINTER_INFO_4W ppi4w = (PPRINTER_INFO_4W)pPrinter;
+ PPRINTER_INFO_5A ppi5a = (PPRINTER_INFO_5A)pPrinter;
+ PPRINTER_INFO_5W ppi5w = (PPRINTER_INFO_5W)pPrinter;
+ PPRINTER_INFO_7A ppi7a = (PPRINTER_INFO_7A)pPrinter;
+ PPRINTER_INFO_7W ppi7w = (PPRINTER_INFO_7W)pPrinter;
+ DWORD cch;
+
+ TRACE("GetPrinterA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
+
+ // Check for invalid levels here for early error return. Should be 1-9.
+ if (Level < 1 || Level > 9)
+ {
+ dwErrorCode = ERROR_INVALID_LEVEL;
+ ERR("Invalid Level!\n");
+ goto Cleanup;
+ }
+
+ if (!GetPrinterW(hPrinter, Level, pPrinter, cbBuf, pcbNeeded))
+ {
+ dwErrorCode = GetLastError();
+ goto Cleanup;
+ }
+
+ switch (Level)
+ {
+ case 1:
+ {
+ if (ppi1w->pDescription)
+ {
+ PSTR pszDescription;
+
+ // Convert Unicode pDescription to a ANSI string pszDescription.
+ cch = wcslen(ppi1w->pDescription);
+
+ pszDescription = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszDescription)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi1w->pDescription, -1, pszDescription, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi1a->pDescription, cch + 1, pszDescription);
+
+ HeapFree(hProcessHeap, 0, pszDescription);
+ }
+
+ if (ppi1w->pName)
+ {
+ PSTR pszName;
+
+ // Convert Unicode pName to a ANSI string pszName.
+ cch = wcslen(ppi1w->pName);
+
+ pszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi1w->pName, -1, pszName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi1a->pName, cch + 1, pszName);
+
+ HeapFree(hProcessHeap, 0, pszName);
+ }
+
+ if (ppi1w->pComment)
+ {
+ PSTR pszComment;
+
+ // Convert Unicode pComment to a ANSI string pszComment.
+ cch = wcslen(ppi1w->pComment);
+
+ pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszComment)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi1w->pComment, -1, pszComment, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi1a->pComment, cch + 1, pszComment);
+
+ HeapFree(hProcessHeap, 0, pszComment);
+ }
+ break;
+ }
+
+ case 2:
+ {
+ if (ppi2w->pServerName)
+ {
+ PSTR pszServerName;
+
+ // Convert Unicode pServerName to a ANSI string pszServerName.
+ cch = wcslen(ppi2w->pServerName);
+
+ pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszServerName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pServerName, -1, pszServerName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pServerName, cch + 1, pszServerName);
+
+ HeapFree(hProcessHeap, 0, pszServerName);
+ }
+
+ if (ppi2w->pPrinterName)
+ {
+ PSTR pszPrinterName;
+
+ // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
+ cch = wcslen(ppi2w->pPrinterName);
+
+ pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPrinterName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pPrinterName, cch + 1, pszPrinterName);
+
+ HeapFree(hProcessHeap, 0, pszPrinterName);
+ }
+
+ if (ppi2w->pShareName)
+ {
+ PSTR pszShareName;
+
+ // Convert Unicode pShareName to a ANSI string pszShareName.
+ cch = wcslen(ppi2w->pShareName);
+
+ pszShareName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszShareName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pShareName, -1, pszShareName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pShareName, cch + 1, pszShareName);
+
+ HeapFree(hProcessHeap, 0, pszShareName);
+ }
+
+ if (ppi2w->pPortName)
+ {
+ PSTR pszPortName;
+
+ // Convert Unicode pPortName to a ANSI string pszPortName.
+ cch = wcslen(ppi2w->pPortName);
+
+ pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPortName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pPortName, -1, pszPortName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pPortName, cch + 1, pszPortName);
+
+ HeapFree(hProcessHeap, 0, pszPortName);
+ }
+
+ if (ppi2w->pDriverName)
+ {
+ PSTR pszDriverName;
+
+ // Convert Unicode pDriverName to a ANSI string pszDriverName.
+ cch = wcslen(ppi2w->pDriverName);
+
+ pszDriverName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszDriverName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pDriverName, -1, pszDriverName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pDriverName, cch + 1, pszDriverName);
+
+ HeapFree(hProcessHeap, 0, pszDriverName);
+ }
+
+ if (ppi2w->pComment)
+ {
+ PSTR pszComment;
+
+ // Convert Unicode pComment to a ANSI string pszComment.
+ cch = wcslen(ppi2w->pComment);
+
+ pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszComment)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pComment, -1, pszComment, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pComment, cch + 1, pszComment);
+
+ HeapFree(hProcessHeap, 0, pszComment);
+ }
+
+ if (ppi2w->pLocation)
+ {
+ PSTR pszLocation;
+
+ // Convert Unicode pLocation to a ANSI string pszLocation.
+ cch = wcslen(ppi2w->pLocation);
+
+ pszLocation = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszLocation)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pLocation, -1, pszLocation, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pLocation, cch + 1, pszLocation);
+
+ HeapFree(hProcessHeap, 0, pszLocation);
+ }
+
+ if (ppi2w->pSepFile)
+ {
+ PSTR pszSepFile;
+
+ // Convert Unicode pSepFile to a ANSI string pszSepFile.
+ cch = wcslen(ppi2w->pSepFile);
+
+ pszSepFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszSepFile)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pSepFile, -1, pszSepFile, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pSepFile, cch + 1, pszSepFile);
+
+ HeapFree(hProcessHeap, 0, pszSepFile);
+ }
+
+ if (ppi2w->pPrintProcessor)
+ {
+ PSTR pszPrintProcessor;
+
+ // Convert Unicode pPrintProcessor to a ANSI string pszPrintProcessor.
+ cch = wcslen(ppi2w->pPrintProcessor);
+
+ pszPrintProcessor = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPrintProcessor)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pPrintProcessor, -1, pszPrintProcessor, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pPrintProcessor, cch + 1, pszPrintProcessor);
+
+ HeapFree(hProcessHeap, 0, pszPrintProcessor);
+ }
+
+ if (ppi2w->pDatatype)
+ {
+ PSTR pszDatatype;
+
+ // Convert Unicode pDatatype to a ANSI string pszDatatype.
+ cch = wcslen(ppi2w->pDatatype);
+
+ pszDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszDatatype)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pDatatype, -1, pszDatatype, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pDatatype, cch + 1, pszDatatype);
+
+ HeapFree(hProcessHeap, 0, pszDatatype);
+ }
+
+ if (ppi2w->pParameters)
+ {
+ PSTR pszParameters;
+
+ // Convert Unicode pParameters to a ANSI string pszParameters.
+ cch = wcslen(ppi2w->pParameters);
+
+ pszParameters = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszParameters)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi2w->pParameters, -1, pszParameters, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi2a->pParameters, cch + 1, pszParameters);
+
+ HeapFree(hProcessHeap, 0, pszParameters);
+ }
+ break;
+ }
+
+ case 4:
+ {
+ if (ppi4w->pPrinterName)
+ {
+ PSTR pszPrinterName;
+
+ // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
+ cch = wcslen(ppi4w->pPrinterName);
+
+ pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPrinterName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi4w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi4a->pPrinterName, cch + 1, pszPrinterName);
+
+ HeapFree(hProcessHeap, 0, pszPrinterName);
+ }
+
+ if (ppi4w->pServerName)
+ {
+ PSTR pszServerName;
+
+ // Convert Unicode pServerName to a ANSI string pszServerName.
+ cch = wcslen(ppi4w->pServerName);
+
+ pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszServerName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi4w->pServerName, -1, pszServerName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi4a->pServerName, cch + 1, pszServerName);
+
+ HeapFree(hProcessHeap, 0, pszServerName);
+ }
+ break;
+ }
+
+ case 5:
+ {
+ if (ppi5w->pPrinterName)
+ {
+ PSTR pszPrinterName;
+
+ // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
+ cch = wcslen(ppi5w->pPrinterName);
+
+ pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPrinterName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi5w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi5a->pPrinterName, cch + 1, pszPrinterName);
+
+ HeapFree(hProcessHeap, 0, pszPrinterName);
+ }
+
+ if (ppi5w->pPortName)
+ {
+ PSTR pszPortName;
+
+ // Convert Unicode pPortName to a ANSI string pszPortName.
+ cch = wcslen(ppi5w->pPortName);
+
+ pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszPortName)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi5w->pPortName, -1, pszPortName, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi5a->pPortName, cch + 1, pszPortName);
+
+ HeapFree(hProcessHeap, 0, pszPortName);
+ }
+ break;
+ }
+
+ case 7:
+ {
+ if (ppi7w->pszObjectGUID)
+ {
+ PSTR pszaObjectGUID;
+
+ // Convert Unicode pszObjectGUID to a ANSI string pszaObjectGUID.
+ cch = wcslen(ppi7w->pszObjectGUID);
+
+ pszaObjectGUID = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+ if (!pszaObjectGUID)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, ppi7w->pszObjectGUID, -1, pszaObjectGUID, cch + 1, NULL, NULL);
+ StringCchCopyA(ppi7a->pszObjectGUID, cch + 1, pszaObjectGUID);
+
+ HeapFree(hProcessHeap, 0, pszaObjectGUID);
+ }
+ break;
+ }
+ } // switch
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
+{
+ DWORD dwErrorCode;
+ /*
+ * We are mapping multiple different pointers to the same pDriverInfo pointer here so that
+ * we can use the same incoming pointer for different Levels
+ */
+ PDRIVER_INFO_1W pdi1w = (PDRIVER_INFO_1W)pDriverInfo;
+ PDRIVER_INFO_2W pdi2w = (PDRIVER_INFO_2W)pDriverInfo;
+ PDRIVER_INFO_3W pdi3w = (PDRIVER_INFO_3W)pDriverInfo;
+ PDRIVER_INFO_4W pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
+ PDRIVER_INFO_5W pdi5w = (PDRIVER_INFO_5W)pDriverInfo;
+ PDRIVER_INFO_6W pdi6w = (PDRIVER_INFO_6W)pDriverInfo;
+
+ DWORD cch;
+ PWSTR pwszEnvironment = NULL;
+
+ TRACE("GetPrinterDriverA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
+
+ // Check for invalid levels here for early error return. Should be 1-6.
+ if (Level < 1 || Level > 6)
+ {
+ dwErrorCode = ERROR_INVALID_LEVEL;
+ ERR("Invalid Level!\n");
+ goto Cleanup;
+ }
+
+ if (pEnvironment)
+ {
+ // Convert pEnvironment to a Unicode string pwszEnvironment.
+ cch = strlen(pEnvironment);
+
+ pwszEnvironment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
+ if (!pwszEnvironment)
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("HeapAlloc failed!\n");
+ goto Cleanup;
+ }
+
+ MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, pwszEnvironment, cch + 1);
+ }
+
+ if (!GetPrinterDriverW(hPrinter, pwszEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded))
+ {
+ dwErrorCode = GetLastError();
+ goto Cleanup;
+ }
+
+ // Do Unicode to ANSI conversions for strings based on Level
+ switch (Level)
+ {
+ case 1:
+ {
+ dwErrorCode = UnicodeToAnsiInPlace(pdi1w->pName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ break;
+ }
+
+ case 2:
+ {
+ dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pEnvironment);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pDriverPath);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pDataFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pConfigFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ break;
+ }
+
+ case 3:
+ {
+ dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pEnvironment);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pDriverPath);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pDataFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pConfigFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pHelpFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pDependentFiles);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pMonitorName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pDefaultDataType);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ break;
+ }
+
+ case 4:
+ {
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pEnvironment);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- if (cbBuf && pPrinterEnum)
- ZeroMemory(pPrinterEnum, cbBuf);
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pDriverPath);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Do the RPC call
- RpcTryExcept
- {
- dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
- }
- RpcExcept(EXCEPTION_EXECUTE_HANDLER)
- {
- dwErrorCode = RpcExceptionCode();
- ERR("_RpcEnumPrinters failed with exception code %lu!\n", dwErrorCode);
- }
- RpcEndExcept;
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pDataFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- if (dwErrorCode == ERROR_SUCCESS)
- {
- // Replace relative offset addresses in the output by absolute pointers.
- ASSERT(Level <= 9);
- MarshallUpStructuresArray(cbBuf, pPrinterEnum, *pcReturned, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pConfigFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
-Cleanup:
- SetLastError(dwErrorCode);
- return (dwErrorCode == ERROR_SUCCESS);
-}
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pHelpFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
-BOOL WINAPI
-FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
-{
- TRACE("FlushPrinter(%p, %p, %lu, %p, %lu)\n", hPrinter, pBuf, cbBuf, pcWritten, cSleep);
- UNIMPLEMENTED;
- return FALSE;
-}
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pDependentFiles);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
-BOOL WINAPI
-GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
-{
- DWORD dwErrorCode;
- PWSTR pwszBuffer = NULL;
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pMonitorName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pDefaultDataType);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- TRACE("GetDefaultPrinterA(%p, %p)\n", pszBuffer, pcchBuffer);
+ dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pszzPreviousNames);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Sanity check.
- if (!pcchBuffer)
- {
- dwErrorCode = ERROR_INVALID_PARAMETER;
- goto Cleanup;
- }
+ break;
+ }
- // Check if an ANSI buffer was given and if so, allocate a Unicode buffer of the same size.
- if (pszBuffer && *pcchBuffer)
- {
- pwszBuffer = HeapAlloc(hProcessHeap, 0, *pcchBuffer * sizeof(WCHAR));
- if (!pwszBuffer)
+ case 5:
{
- dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
- ERR("HeapAlloc failed!\n");
- goto Cleanup;
- }
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi5w->pName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- if (!GetDefaultPrinterW(pwszBuffer, pcchBuffer))
- {
- dwErrorCode = GetLastError();
- goto Cleanup;
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi5w->pEnvironment);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // We successfully got a string in pwszBuffer, so convert the Unicode string to ANSI.
- WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszBuffer, *pcchBuffer, NULL, NULL);
+ dwErrorCode = UnicodeToAnsiInPlace(pdi5w->pDriverPath);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- dwErrorCode = ERROR_SUCCESS;
+ dwErrorCode = UnicodeToAnsiInPlace(pdi5w->pDataFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
-Cleanup:
- if (pwszBuffer)
- HeapFree(hProcessHeap, 0, pwszBuffer);
+ dwErrorCode = UnicodeToAnsiInPlace(pdi5w->pConfigFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- SetLastError(dwErrorCode);
- return (dwErrorCode == ERROR_SUCCESS);
-}
+ break;
+ }
-BOOL WINAPI
-GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
-{
- DWORD cbNeeded;
- DWORD cchInputBuffer;
- DWORD dwErrorCode;
- HKEY hWindowsKey = NULL;
- PWSTR pwszDevice = NULL;
- PWSTR pwszComma;
+ case 6:
+ {
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- TRACE("GetDefaultPrinterW(%p, %p)\n", pszBuffer, pcchBuffer);
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pEnvironment);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Sanity check.
- if (!pcchBuffer)
- {
- dwErrorCode = ERROR_INVALID_PARAMETER;
- goto Cleanup;
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pDriverPath);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- cchInputBuffer = *pcchBuffer;
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pDataFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Open the registry key where the default printer for the current user is stored.
- dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_READ, &hWindowsKey);
- if (dwErrorCode != ERROR_SUCCESS)
- {
- ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
- goto Cleanup;
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pConfigFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Determine the size of the required buffer.
- dwErrorCode = (DWORD)RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, NULL, &cbNeeded);
- if (dwErrorCode != ERROR_SUCCESS)
- {
- ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
- goto Cleanup;
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pHelpFile);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Allocate it.
- pwszDevice = HeapAlloc(hProcessHeap, 0, cbNeeded);
- if (!pwszDevice)
- {
- dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
- ERR("HeapAlloc failed!\n");
- goto Cleanup;
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pDependentFiles);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Now get the actual value.
- dwErrorCode = RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, (PBYTE)pwszDevice, &cbNeeded);
- if (dwErrorCode != ERROR_SUCCESS)
- {
- ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
- goto Cleanup;
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pMonitorName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pDefaultDataType);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // We get a string "<Printer Name>,winspool,<Port>:".
- // Extract the printer name from it.
- pwszComma = wcschr(pwszDevice, L',');
- if (!pwszComma)
- {
- ERR("Found no or invalid default printer: %S!\n", pwszDevice);
- dwErrorCode = ERROR_INVALID_NAME;
- goto Cleanup;
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pszzPreviousNames);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Store the length of the Printer Name (including the terminating NUL character!) in *pcchBuffer.
- *pcchBuffer = pwszComma - pwszDevice + 1;
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pszMfgName);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Check if the supplied buffer is large enough.
- if (cchInputBuffer < *pcchBuffer)
- {
- dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
- goto Cleanup;
- }
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pszOEMUrl);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
- // Copy the default printer.
- *pwszComma = 0;
- CopyMemory(pszBuffer, pwszDevice, *pcchBuffer * sizeof(WCHAR));
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pszHardwareID);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ dwErrorCode = UnicodeToAnsiInPlace(pdi6w->pszProvider);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ goto Cleanup;
+ }
+ }
+ }
dwErrorCode = ERROR_SUCCESS;
Cleanup:
- if (hWindowsKey)
- RegCloseKey(hWindowsKey);
-
- if (pwszDevice)
- HeapFree(hProcessHeap, 0, pwszDevice);
+ if (pwszEnvironment)
+ {
+ HeapFree(hProcessHeap, 0, pwszEnvironment);
+ }
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
-BOOL WINAPI
-GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
-{
- TRACE("GetPrinterA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
- if(pcbNeeded) *pcbNeeded = 0;
- return FALSE;
-}
-
-BOOL WINAPI
-GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
-{
- TRACE("GetPrinterDriverA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
- if(pcbNeeded) *pcbNeeded = 0;
- return FALSE;
-}
-
BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
{
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
- ERR("_RpcGetPrinter failed with exception code %lu!\n", dwErrorCode);
+ ERR("_RpcGetPrinterDriver failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
if (dwErrorCode == ERROR_SUCCESS)
{
// Replace relative offset addresses in the output by absolute pointers.
- ASSERT(Level <= 3);
+ ASSERT(Level <= 5);
MarshallUpStructure(cbBuf, pDriverInfo, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
}
return FALSE;
}
+BOOL WINAPI
+SplDriverUnloadComplete(LPWSTR pDriverFile)
+{
+ TRACE("DriverUnloadComplete(%S)\n", pDriverFile);
+ UNIMPLEMENTED;
+ return TRUE; // return true for now.
+}
+
DWORD WINAPI
StartDocPrinterA(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
{