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