Jacek Caban : winspool: Use configuration file for DeviceCapabilitiesW.

Alexandre Julliard julliard at winehq.org
Mon Sep 13 16:12:33 CDT 2021


Module: wine
Branch: master
Commit: afc7c0c9d1dabe8a01af3518025d67245318c7dc
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=afc7c0c9d1dabe8a01af3518025d67245318c7dc

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Sep 13 13:48:52 2021 +0200

winspool: Use configuration file for DeviceCapabilitiesW.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winspool.drv/info.c | 228 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 155 insertions(+), 73 deletions(-)

diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c
index 8a17355f120..f14ab103ded 100644
--- a/dlls/winspool.drv/info.c
+++ b/dlls/winspool.drv/info.c
@@ -119,6 +119,7 @@
 #include "wine/unicode.h"
 #include "wine/debug.h"
 #include "wine/list.h"
+#include "wine/rbtree.h"
 #include "wine/heap.h"
 #include "winnls.h"
 
@@ -178,6 +179,18 @@ typedef struct {
     LPCWSTR  versionsubdir;
 } printenv_t;
 
+typedef struct
+{
+    struct wine_rb_entry entry;
+    HMODULE module;
+    LONG ref;
+
+    /* entry points */
+    DWORD (WINAPI *pDrvDeviceCapabilities)(HANDLE, const WCHAR *, WORD, void *, const DEVMODEW *);
+
+    WCHAR name[1];
+} config_module_t;
+
 /* ############################### */
 
 static opened_printer_t **printer_handles;
@@ -500,6 +513,127 @@ static inline const DWORD *form_string_info( DWORD level )
     return NULL;
 }
 
+/*****************************************************************************
+ *          WINSPOOL_OpenDriverReg [internal]
+ *
+ * opens the registry for the printer drivers depending on the given input
+ * variable pEnvironment
+ *
+ * RETURNS:
+ *    the opened hkey on success
+ *    NULL on error
+ */
+static HKEY WINSPOOL_OpenDriverReg(const void *pEnvironment)
+{
+    HKEY  retval = NULL;
+    LPWSTR buffer;
+    const printenv_t *env;
+
+    TRACE("(%s)\n", debugstr_w(pEnvironment));
+
+    env = validate_envW(pEnvironment);
+    if (!env) return NULL;
+
+    buffer = HeapAlloc( GetProcessHeap(), 0,
+                (strlenW(DriversW) + strlenW(env->envname) +
+                 strlenW(env->versionregpath) + 1) * sizeof(WCHAR));
+    if(buffer) {
+        wsprintfW(buffer, DriversW, env->envname, env->versionregpath);
+        RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval);
+        HeapFree(GetProcessHeap(), 0, buffer);
+    }
+    return retval;
+}
+
+static CRITICAL_SECTION config_modules_cs;
+static CRITICAL_SECTION_DEBUG config_modules_cs_debug =
+{
+    0, 0, &config_modules_cs,
+    { &config_modules_cs_debug.ProcessLocksList, &config_modules_cs_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": config_modules_cs") }
+};
+static CRITICAL_SECTION config_modules_cs = { &config_modules_cs_debug, -1, 0, 0, 0, 0 };
+
+static int compare_config_modules(const void *key, const struct wine_rb_entry *entry)
+{
+    config_module_t *module = WINE_RB_ENTRY_VALUE(entry, config_module_t, entry);
+    return lstrcmpiW(key, module->name);
+}
+
+static struct wine_rb_tree config_modules = { compare_config_modules };
+
+static void release_config_module(config_module_t *config_module)
+{
+    if (InterlockedDecrement(&config_module->ref)) return;
+    FreeLibrary(config_module->module);
+    HeapFree(GetProcessHeap(), 0, config_module);
+}
+
+static config_module_t *get_config_module(const WCHAR *device, BOOL grab)
+{
+    WCHAR driver[MAX_PATH];
+    DWORD size, len;
+    HKEY driver_key, device_key;
+    HMODULE driver_module;
+    config_module_t *ret = NULL;
+    struct wine_rb_entry *entry;
+    DWORD type;
+    LSTATUS res;
+
+    EnterCriticalSection(&config_modules_cs);
+    entry = wine_rb_get(&config_modules, device);
+    if (entry) {
+        ret = WINE_RB_ENTRY_VALUE(entry, config_module_t, entry);
+        if (grab) InterlockedIncrement(&ret->ref);
+        goto ret;
+    }
+    if (!grab) goto ret;
+
+    if (!(driver_key = WINSPOOL_OpenDriverReg(NULL))) goto ret;
+
+    res = RegOpenKeyW(driver_key, device, &device_key);
+    RegCloseKey(driver_key);
+    if (res) {
+        WARN("Device %s key not found\n", debugstr_w(device));
+        goto ret;
+    }
+
+    size = sizeof(driver);
+    if (!GetPrinterDriverDirectoryW(NULL, NULL, 1, (LPBYTE)driver, size, &size)) goto ret;
+
+    len = size / sizeof(WCHAR) - 1;
+    driver[len++] = '\\';
+    driver[len++] = '3';
+    driver[len++] = '\\';
+    size = sizeof(driver) - len * sizeof(WCHAR);
+    res = RegQueryValueExW(device_key, Configuration_FileW, NULL, &type,
+                           (BYTE *)(driver + len), &size);
+    RegCloseKey(device_key);
+    if (res || type != REG_SZ) {
+        WARN("no configuration file: %u\n", res);
+        goto ret;
+    }
+
+    if (!(driver_module = LoadLibraryW(driver))) {
+        WARN("Could not load %s\n", debugstr_w(driver));
+        goto ret;
+    }
+
+    len = lstrlenW(device);
+    if (!(ret = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(config_module_t, name[len + 1]))))
+        goto ret;
+
+    ret->ref = 2; /* one for config_module and one for the caller */
+    ret->module = driver_module;
+    ret->pDrvDeviceCapabilities = (void *)GetProcAddress(driver_module, "DrvDeviceCapabilities");
+    lstrcpyW(ret->name, device);
+
+    wine_rb_put(&config_modules, ret->name, &ret->entry);
+ret:
+    LeaveCriticalSection(&config_modules_cs);
+    return ret;
+}
+
 /******************************************************************
  * verify, that the filename is a local file
  *
@@ -2361,57 +2495,28 @@ INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap,
     return ret;
 }
 
-
 /*****************************************************************************
  *          DeviceCapabilitiesW        [WINSPOOL.@]
  *
- * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
- *
  */
 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
 			       WORD fwCapability, LPWSTR pOutput,
 			       const DEVMODEW *pDevMode)
 {
-    LPDEVMODEA dmA = DEVMODEdupWtoA(pDevMode);
-    LPSTR pDeviceA = strdupWtoA(pDevice);
-    LPSTR pPortA = strdupWtoA(pPort);
-    INT ret;
+    config_module_t *config;
+    int ret;
 
-    TRACE("%s,%s,%u,%p,%p\n", debugstr_w(pDevice), debugstr_w(pPort), fwCapability, pOutput, pDevMode);
-
-    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);
-    } else {
-        ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability,
-				  (LPSTR)pOutput, dmA);
+    TRACE("%s,%s,%u,%p,%p\n", debugstr_w(pDevice), debugstr_w(pPort), fwCapability,
+          pOutput, pDevMode);
+
+    if (!(config = get_config_module(pDevice, TRUE))) {
+        WARN("Could not load config module for %s\n", debugstr_w(pDevice));
+        return 0;
     }
-    HeapFree(GetProcessHeap(),0,pPortA);
-    HeapFree(GetProcessHeap(),0,pDeviceA);
-    HeapFree(GetProcessHeap(),0,dmA);
+
+    ret = config->pDrvDeviceCapabilities(NULL /* FIXME */, pDevice, fwCapability,
+                                         pOutput, pDevMode);
+    release_config_module(config);
     return ret;
 }
 
@@ -3186,38 +3291,6 @@ BOOL WINAPI GetPrintProcessorDirectoryW(LPWSTR server, LPWSTR env,
     return backend->fpGetPrintProcessorDirectory(server, env, level, Info, cbBuf, pcbNeeded);
 }
 
-/*****************************************************************************
- *          WINSPOOL_OpenDriverReg [internal]
- *
- * opens the registry for the printer drivers depending on the given input
- * variable pEnvironment
- *
- * RETURNS:
- *    the opened hkey on success
- *    NULL on error
- */
-static HKEY WINSPOOL_OpenDriverReg( LPCVOID pEnvironment)
-{   
-    HKEY  retval = NULL;
-    LPWSTR buffer;
-    const printenv_t * env;
-
-    TRACE("(%s)\n", debugstr_w(pEnvironment));
-
-    env = validate_envW(pEnvironment);
-    if (!env) return NULL;
-
-    buffer = HeapAlloc( GetProcessHeap(), 0,
-                (strlenW(DriversW) + strlenW(env->envname) + 
-                 strlenW(env->versionregpath) + 1) * sizeof(WCHAR));
-    if(buffer) {
-        wsprintfW(buffer, DriversW, env->envname, env->versionregpath);
-        RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval);
-        HeapFree(GetProcessHeap(), 0, buffer);
-    }
-    return retval;
-}
-
 /*****************************************************************************
  * set_devices_and_printerports [internal]
  *
@@ -3499,6 +3572,7 @@ BOOL WINAPI DeleteFormW( HANDLE printer, WCHAR *name )
 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
 {
     LPCWSTR lpNameW = get_opened_printer_name(hPrinter);
+    config_module_t *config_module;
     HKEY hkeyPrinters, hkey;
     WCHAR def[MAX_PATH];
     DWORD size = ARRAY_SIZE(def);
@@ -3507,6 +3581,14 @@ BOOL WINAPI DeletePrinter(HANDLE hPrinter)
         SetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
+
+    EnterCriticalSection(&config_modules_cs);
+    if ((config_module = get_config_module(lpNameW, FALSE))) {
+        wine_rb_remove(&config_modules, &config_module->entry);
+        release_config_module(config_module);
+    }
+    LeaveCriticalSection(&config_modules_cs);
+
     if(RegOpenKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) == ERROR_SUCCESS) {
         RegDeleteTreeW(hkeyPrinters, lpNameW);
         RegCloseKey(hkeyPrinters);




More information about the wine-cvs mailing list