[WINSPOOL] Add Implementation of EnumPrintersA (#2273)
authorDoug Lyons <douglyons@douglyons.com>
Fri, 31 Jan 2020 17:42:55 +0000 (11:42 -0600)
committerGitHub <noreply@github.com>
Fri, 31 Jan 2020 17:42:55 +0000 (18:42 +0100)
win32ss/printing/base/winspool/printers.c

index 3d02914..a3ee6e6 100644 (file)
@@ -8,6 +8,7 @@
 #include "precomp.h"
 #include <marshalling/printers.h>
 #include <marshalling/printerdrivers.h>
+#include <strsafe.h>
 
 // Local Constants
 
@@ -386,8 +387,451 @@ Cleanup:
 BOOL WINAPI
 EnumPrintersA(DWORD Flags, PSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 {
+    BOOL bReturnValue = FALSE;
+    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)
+    {
+        SetLastError(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)
+        {
+            SetLastError(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 */
+    bReturnValue = EnumPrintersW(Flags, pwszName, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
+    HeapFree(hProcessHeap, 0, pwszName);
+
+    TRACE("*pcReturned is '%d' and bReturnValue is '%d' and GetLastError is '%ld'.\n", *pcReturned, bReturnValue, GetLastError());
+
+    /* 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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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)
+                    {
+                        SetLastError(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
+
+Cleanup:
+
+    return bReturnValue;
 }
 
 BOOL WINAPI