+
+ // 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;