Module: wine Branch: master Commit: afc7c0c9d1dabe8a01af3518025d67245318c7dc URL: https://source.winehq.org/git/wine.git/?a=commit;h=afc7c0c9d1dabe8a01af35180...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Sep 13 13:48:52 2021 +0200
winspool: Use configuration file for DeviceCapabilitiesW.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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);