[WINSPOOL] Implement GetPrinterDriverA and a helper function UnicodeToAnsiInPlace...
authorDoug Lyons <douglyons@douglyons.com>
Wed, 12 Feb 2020 18:52:34 +0000 (12:52 -0600)
committerGitHub <noreply@github.com>
Wed, 12 Feb 2020 18:52:34 +0000 (19:52 +0100)
win32ss/printing/base/winspool/CMakeLists.txt
win32ss/printing/base/winspool/precomp.h
win32ss/printing/base/winspool/printers.c
win32ss/printing/base/winspool/utils.c [new file with mode: 0644]

index 9081819..34c3026 100644 (file)
@@ -17,6 +17,7 @@ list(APPEND SOURCE
     printers.c
     printprocessors.c
     printproviders.c
+    utils.c
     ${CMAKE_CURRENT_BINARY_DIR}/winspool_c.c)
 
 add_library(winspool MODULE
index 033b38d..2c8fe18 100644 (file)
@@ -40,4 +40,7 @@ SPOOLER_HANDLE, *PSPOOLER_HANDLE;
 // main.c
 extern HANDLE hProcessHeap;
 
+// utils.c
+extern BOOL UnicodeToAnsiInPlace(PWSTR pwszField);
+
 #endif
index e8a6da6..f661606 100644 (file)
@@ -1490,10 +1490,231 @@ Cleanup:
 
 BOOL WINAPI
 GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
-{
-    ERR("GetPrinterDriverA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
-    if (pcbNeeded) *pcbNeeded = 0;
-    return FALSE;
+{   
+    /*
+     * 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;
+
+    BOOL bReturnValue = FALSE;
+    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)
+    {
+        SetLastError(ERROR_INVALID_LEVEL);
+        ERR("Invalid Level!\n");
+        goto Exit;
+    }
+
+    if (pEnvironment)
+    {
+        // Convert pEnvironment to a Unicode string pwszEnvironment.
+        cch = strlen(pEnvironment);
+
+        pwszEnvironment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
+        if (!pwszEnvironment)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            ERR("HeapAlloc failed!\n");
+            goto Exit;
+        }
+
+        MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, pwszEnvironment, cch + 1);
+    }
+
+    bReturnValue = GetPrinterDriverW(hPrinter, pwszEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
+    TRACE("*pcbNeeded is '%d' and bReturnValue is '%d' and GetLastError is '%ld'.\n", *pcbNeeded, bReturnValue, GetLastError());
+
+    if (pwszEnvironment)
+    {
+        HeapFree(hProcessHeap, 0, pwszEnvironment);
+    }
+
+    if (!bReturnValue)
+    {
+        TRACE("GetPrinterDriverW failed!\n");
+        goto Exit;
+    }
+
+    // Do Unicode to ANSI conversions for strings based on Level
+    switch (Level)
+    {
+        case 1:
+        {
+            if (!UnicodeToAnsiInPlace(pdi1w->pName))
+                goto Exit;
+
+            break;
+        }
+
+        case 2:
+        {
+            if (!UnicodeToAnsiInPlace(pdi2w->pName))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi2w->pEnvironment))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi2w->pDriverPath))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi2w->pDataFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi2w->pConfigFile))
+                goto Exit;
+
+            break;
+        }
+
+        case 3:
+        {
+            if (!UnicodeToAnsiInPlace(pdi3w->pName))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi3w->pEnvironment))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi3w->pDriverPath))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi3w->pDataFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi3w->pConfigFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi3w->pHelpFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi3w->pDependentFiles))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi3w->pMonitorName))
+                goto Exit;
+            if (!UnicodeToAnsiInPlace(pdi3w->pDefaultDataType))
+                goto Exit;
+
+            break;
+        }
+
+        case 4:
+        {
+            if (!UnicodeToAnsiInPlace(pdi4w->pName))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi4w->pEnvironment))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi4w->pDriverPath))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi4w->pDataFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi4w->pConfigFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi4w->pHelpFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi4w->pDependentFiles))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi4w->pMonitorName))
+                goto Exit;
+            if (!UnicodeToAnsiInPlace(pdi4w->pDefaultDataType))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi4w->pszzPreviousNames))
+                goto Exit;
+
+            break;
+        }
+
+        case 5:
+        {
+            if (!UnicodeToAnsiInPlace(pdi5w->pName))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi5w->pEnvironment))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi5w->pDriverPath))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi5w->pDataFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi5w->pConfigFile))
+                goto Exit;
+
+            break;
+        }
+
+        case 6:
+        {
+            if (!UnicodeToAnsiInPlace(pdi6w->pName))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pEnvironment))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pDriverPath))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pDataFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pConfigFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pHelpFile))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pDependentFiles))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pMonitorName))
+                goto Exit;
+            if (!UnicodeToAnsiInPlace(pdi6w->pDefaultDataType))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pszzPreviousNames))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pszMfgName))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pszOEMUrl))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pszHardwareID))
+                goto Exit;
+
+            if (!UnicodeToAnsiInPlace(pdi6w->pszProvider))
+                goto Exit;
+        }
+    }
+
+    bReturnValue = TRUE;
+
+Exit:
+
+    return bReturnValue;
 }
 
 BOOL WINAPI
diff --git a/win32ss/printing/base/winspool/utils.c b/win32ss/printing/base/winspool/utils.c
new file mode 100644 (file)
index 0000000..0ba5e27
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+* PROJECT:     ReactOS Spooler API
+* LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+* PURPOSE:     Utility Functions related to Print Processors
+* COPYRIGHT:   Copyright 2020 Doug Lyons (douglyons@douglyons.com)
+*/
+
+#include <strsafe.h>
+
+BOOL UnicodeToAnsiInPlace(PWSTR pwszField)
+{
+    /*
+     * This converts an incoming Unicode string to an ANSI string.
+     * It returns FALSE on failure, otherwise it returns TRUE.
+     * It is only useful for "in-place" conversions where the ANSI string goes
+     * back into the same place where the Unicode string came into this function.
+     * It seems that many of the functions involving printing can use this.
+     */
+
+    PSTR pszTemp;
+    DWORD cch;
+
+    /*
+     * Map the incoming Unicode pwszField string to an ANSI one here so that we can do
+     * in-place conversion. We read the Unicode input and then we write back the ANSI
+     * conversion into the same buffer for use with our GetPrinterDriverA function
+     */
+    PSTR pszField = (PSTR)pwszField;
+
+    if (!pwszField)
+    {
+        return TRUE;
+    }
+
+    cch = wcslen(pwszField);
+    if (cch == 0)
+    {
+        return TRUE;
+    }
+
+    pszTemp = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
+    if (!pszField)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        ERR("HeapAlloc failed!\n");
+        return FALSE;   // indicates a failure to be handled by caller
+    }
+
+    WideCharToMultiByte(CP_ACP, 0, pwszField, -1, pszTemp, cch + 1, NULL, NULL);
+    StringCchCopyA(pszField, cch + 1, pszTemp);
+
+    HeapFree(hProcessHeap, 0, pszTemp);
+
+    return TRUE;
+}