[PATCH] winspool: Don't use 16Bit gdi.exe function for DeviceCapabilities

Detlef Riekenberg wine.dev at web.de
Fri Nov 20 06:46:31 CST 2009


---
 dlls/winspool.drv/info.c |  273 ++++++++++++++++++++++++++++++++++------------
 1 files changed, 202 insertions(+), 71 deletions(-)

diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c
index 7dac2b6..3633efd 100644
--- a/dlls/winspool.drv/info.c
+++ b/dlls/winspool.drv/info.c
@@ -115,9 +115,6 @@ static opened_printer_t **printer_handles;
 static UINT nb_printer_handles;
 static LONG next_job_id = 1;
 
-static DWORD (WINAPI *GDI_CallDeviceCapabilities16)( LPCSTR lpszDevice, LPCSTR lpszPort,
-                                                     WORD fwCapability, LPSTR lpszOutput,
-                                                     LPDEVMODEA lpdm );
 static INT (WINAPI *GDI_CallExtDeviceMode16)( HWND hwnd, LPDEVMODEA lpdmOutput,
                                               LPSTR lpszDevice, LPSTR lpszPort,
                                               LPDEVMODEA lpdmInput, LPSTR lpszProfile,
@@ -285,6 +282,44 @@ static const  printenv_t * validate_envW(LPCWSTR env)
     return result;
 }
 
+/******************************************************************
+ * driver_load [internal]
+ *
+ * load a driver user interface dll
+ *
+ * On failure, NULL is returned
+ *
+ */
+
+static HMODULE driver_load(const printenv_t * env, LPWSTR dllname)
+{
+    WCHAR fullname[MAX_PATH];
+    HMODULE hui;
+    DWORD len;
+
+    TRACE("(%p, %s)\n", env, debugstr_w(dllname));
+
+    /* build the driverdir */
+    len = sizeof(fullname) -
+          (lstrlenW(env->versionsubdir) + 1 + lstrlenW(dllname) + 1) * sizeof(WCHAR);
+
+    if (GetPrinterDriverDirectoryW(NULL, (LPWSTR) env->envname, 1,
+                                   (LPBYTE) fullname, len, &len)) {
+
+        lstrcatW(fullname, env->versionsubdir);
+        lstrcatW(fullname, backslashW);
+        lstrcatW(fullname, dllname);
+
+        hui = LoadLibraryW(fullname);
+        TRACE("==> %p: %s %d\n", hui, debugstr_w(fullname), GetLastError());
+
+        return hui;
+    }
+
+    /* GetPrinterDriverDirectory should never Fail */
+    return NULL;
+}
+
 
 /* RtlCreateUnicodeStringFromAsciiz will return an empty string in the buffer
    if passed a NULL string. This returns NULLs to the result. 
@@ -1417,90 +1452,186 @@ static void FREE_PRINTER_INFO_2W(HANDLE heap, LPPRINTER_INFO_2W piW)
     return;
 }
 
-/******************************************************************
- *              DeviceCapabilities     [WINSPOOL.@]
- *              DeviceCapabilitiesA    [WINSPOOL.@]
+/*****************************************************************************
+ * DeviceCapabilitiesW [WINSPOOL.@]
+ *
+ * Get a specific capability for a Printer from the driver userinterface dll
+ *
+ * PARAMS
+ *  pDevice      [I]  Printer name to get the capability from
+ *  pPort        [I]  Portname to use for the Printer
+ *  fwCapability [I]  capability to get for the selected printer
+ *  pOutput      [IO] User allocated buffer to return an array of entries for a capability
+ *  pDevMode     [I]  DEVMODE to specify some settings to use
+ *
+ * RETURNS
+ *  FAILURE: GDI_ERROR
+ *  SUCCESS: The capability or the number of entries in the output buffer
  *
  */
-INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap,
-			       LPSTR pOutput, LPDEVMODEA lpdm)
+INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability,
+                               LPWSTR pOutput, const DEVMODEW *pDevMode)
 {
-    INT ret;
+    DWORD (CDECL *pDeviceCapabilities)(LPSTR, LPSTR, LPSTR, WORD, LPSTR, LPDEVMODEA);
+    INT (WINAPI *pDrvDeviceCapabilities)(HANDLE, PWSTR, WORD, VOID *, PDEVMODEW);
+    DRIVER_INFO_2W * di = NULL;
+    const printenv_t * env;
+    HMODULE hui = NULL;
+    HANDLE hPrinter = 0;
+    DWORD needed;
+    DWORD result;
+    INT res = GDI_ERROR;
+
+    TRACE("(%s, %s, 0x%x/%d, %p, %p)\n", debugstr_w(pDevice), debugstr_w(pPort),
+                                         fwCapability, fwCapability, pOutput, pDevMode);
+
+    result = OpenPrinterW((LPWSTR)pDevice, &hPrinter, NULL);
+    if (result) {
+        result = GetPrinterDriverW(hPrinter, NULL, 2, NULL, 0, &needed);
+        if (!result && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
+           di = HeapAlloc(GetProcessHeap(), 0, needed);
+           result = GetPrinterDriverW(hPrinter, NULL, 2, (LPBYTE) di, needed, &needed);
+        }
 
-    if (!GDI_CallDeviceCapabilities16)
-    {
-        GDI_CallDeviceCapabilities16 = (void*)GetProcAddress( GetModuleHandleA("gdi32"),
-                                                              (LPCSTR)104 );
-        if (!GDI_CallDeviceCapabilities16) return -1;
-    }
-    ret = GDI_CallDeviceCapabilities16(pDevice, pPort, cap, pOutput, lpdm);
-
-    /* If DC_PAPERSIZE map POINT16s to POINTs */
-    if(ret != -1 && cap == DC_PAPERSIZE && pOutput) {
-        POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) );
-        POINT *pt = (POINT *)pOutput;
-	INT i;
-	memcpy(tmp, pOutput, ret * sizeof(POINT16));
-	for(i = 0; i < ret; i++, pt++)
-        {
-            pt->x = tmp[i].x;
-            pt->y = tmp[i].y;
+        if (result && (di != NULL)) {
+            env = validate_envW(di->pEnvironment);
+            hui = driver_load(env, di->pConfigFile);
         }
-	HeapFree( GetProcessHeap(), 0, tmp );
+
+        pDrvDeviceCapabilities = (void *) GetProcAddress(hui, "DrvDeviceCapabilities");
+        pDeviceCapabilities = (void *) GetProcAddress(hui, "DeviceCapabilities");
+        TRACE("%s loaded: %p (%p / %p)\n", debugstr_w(di->pConfigFile), hui,
+                    pDrvDeviceCapabilities, pDeviceCapabilities);
+
+        HeapFree(GetProcessHeap(), 0, di);
+
+        if (pDrvDeviceCapabilities) {
+            /* Windows driver API */
+            res = pDrvDeviceCapabilities(hPrinter, (PWSTR) pDevice, fwCapability,
+                                         (VOID *)pOutput, (PDEVMODEW) pDevMode);
+        }
+        else if (pDeviceCapabilities) {
+            /* Wine driver API */
+            LPDEVMODEA dmA = DEVMODEdupWtoA(pDevMode);
+            LPSTR pDeviceA = strdupWtoA(pDevice);
+            LPSTR pPortA = strdupWtoA(pPort);
+
+            if (pOutput && (fwCapability == DC_BINNAMES ||
+                            fwCapability == DC_FILEDEPENDENCIES ||
+                            fwCapability == DC_PAPERNAMES)) {
+                /* These need A -> W translation */
+                INT size = 0, i;
+                LPSTR pOutputA;
+                res = pDeviceCapabilities(NULL, pDeviceA, pPortA, fwCapability, NULL, dmA);
+
+                if (res == -1)
+                    goto cleanup;
+
+                switch (fwCapability) {
+                case DC_BINNAMES:
+                    size = 24;
+                    break;
+                case DC_PAPERNAMES:
+                case DC_FILEDEPENDENCIES:
+                    size = 64;
+                    break;
+                }
+
+                pOutputA = HeapAlloc(GetProcessHeap(), 0, size * res);
+                res = pDeviceCapabilities(NULL, pDeviceA, pPortA, fwCapability, pOutputA, dmA);
+
+                for(i = 0; i < res; i++)
+                    MultiByteToWideChar(CP_ACP, 0, pOutputA + (i * size), -1, pOutput + (i * size), size);
+
+                HeapFree(GetProcessHeap(), 0, pOutputA);
+
+            } else {
+                res = pDeviceCapabilities(NULL, pDeviceA, pPortA, fwCapability, (LPSTR)pOutput, dmA);
+            }
+
+cleanup:
+            HeapFree(GetProcessHeap(),0,pPortA);
+            HeapFree(GetProcessHeap(),0,pDeviceA);
+            HeapFree(GetProcessHeap(),0,dmA);
+        }
+        FreeModule(hui);
+        ClosePrinter(hPrinter);
     }
-    return ret;
-}
 
+    TRACE("==> %d\n", res);
+    return res;
+}
 
-/*****************************************************************************
- *          DeviceCapabilitiesW        [WINSPOOL.@]
+/******************************************************************
+ * DeviceCapabilities  [WINSPOOL.@]
+ * DeviceCapabilitiesA [WINSPOOL.@]
  *
- * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
+ * See DeviceCapabilitiesW
  *
  */
-INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
-			       WORD fwCapability, LPWSTR pOutput,
-			       const DEVMODEW *pDevMode)
+INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD fwCapability,
+                               LPSTR pOutput, LPDEVMODEA pDevMode)
 {
-    LPDEVMODEA dmA = DEVMODEdupWtoA(pDevMode);
-    LPSTR pDeviceA = strdupWtoA(pDevice);
-    LPSTR pPortA = strdupWtoA(pPort);
-    INT ret;
+    LPDEVMODEW dmW = pDevMode ? GdiConvertToDevmodeW(pDevMode) : NULL;
+    LPWSTR pDeviceW = NULL;
+    LPWSTR pPortW = NULL;
+    INT res;
+    INT i;
+
+    TRACE("(%s, %s, 0x%x/%d, %p, %p)\n", debugstr_a(pDevice), debugstr_a(pPort),
+                                         fwCapability, fwCapability, pOutput, pDevMode);
+
+    if (pDevice) {
+        i = MultiByteToWideChar(CP_ACP, 0, pDevice, -1, NULL, 0);
+        pDeviceW = HeapAlloc(GetProcessHeap(), 0, i);
+        MultiByteToWideChar(CP_ACP, 0, pDevice, -1, pDeviceW, i);
+    }
+    if (pPort) {
+        i = MultiByteToWideChar(CP_ACP, 0, pPort, -1, NULL, 0);
+        pPortW = HeapAlloc(GetProcessHeap(), 0, i);
+        MultiByteToWideChar(CP_ACP, 0, pPort, -1, pPortW, i);
+    }
+
 
     if(pOutput && (fwCapability == DC_BINNAMES ||
-		   fwCapability == DC_FILEDEPENDENCIES ||
-		   fwCapability == DC_PAPERNAMES)) {
-      /* These need A -> W translation */
-        INT size = 0, i;
-	LPSTR pOutputA;
-        ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, NULL,
-				  dmA);
-	if(ret == -1)
-	    return ret;
-	switch(fwCapability) {
-	case DC_BINNAMES:
-	    size = 24;
-	    break;
-	case DC_PAPERNAMES:
-	case DC_FILEDEPENDENCIES:
-	    size = 64;
-	    break;
-	}
-	pOutputA = HeapAlloc(GetProcessHeap(), 0, size * ret);
-	ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, pOutputA,
-				  dmA);
-	for(i = 0; i < ret; i++)
-	    MultiByteToWideChar(CP_ACP, 0, pOutputA + (i * size), -1,
-				pOutput + (i * size), size);
-	HeapFree(GetProcessHeap(), 0, pOutputA);
+                   fwCapability == DC_FILEDEPENDENCIES ||
+                   fwCapability == DC_PAPERNAMES)) {
+
+        /* These need W -> A translation */
+        INT size = 0;
+        LPWSTR pOutputW;
+        res = DeviceCapabilitiesW(pDeviceW, pPortW, fwCapability, NULL, dmW);
+        if (res == -1)
+            goto cleanup;
+
+        switch (fwCapability) {
+        case DC_BINNAMES:
+            size = 24;
+            break;
+        case DC_PAPERNAMES:
+        case DC_FILEDEPENDENCIES:
+            size = 64;
+            break;
+        }
+
+        pOutputW = HeapAlloc(GetProcessHeap(), 0, size * res * sizeof(WCHAR));
+        if (pOutputW == NULL)
+            goto cleanup;
+        res = DeviceCapabilitiesW(pDeviceW, pPortW, fwCapability, pOutputW, dmW);
+        for (i = 0; i < res; i++)
+           WideCharToMultiByte(CP_ACP, 0, pOutputW + (i * size), -1,
+                               pOutput + (i * size), size, NULL, NULL);
+
+         HeapFree(GetProcessHeap(), 0, pOutputW);
     } else {
-        ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability,
-				  (LPSTR)pOutput, dmA);
+        res = DeviceCapabilitiesW(pDeviceW, pPortW, fwCapability, (LPWSTR)pOutput, dmW);
     }
-    HeapFree(GetProcessHeap(),0,pPortA);
-    HeapFree(GetProcessHeap(),0,pDeviceA);
-    HeapFree(GetProcessHeap(),0,dmA);
-    return ret;
+
+cleanup:
+    HeapFree(GetProcessHeap(),0,pPortW);
+    HeapFree(GetProcessHeap(),0,pDeviceW);
+    HeapFree(GetProcessHeap(),0,dmW);
+    return res;
 }
 
 /******************************************************************
-- 
1.5.4.3


--=-+IvsQDWctMWodslL7KJl--




More information about the wine-patches mailing list