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>
This commit is contained in:
parent
a8c4020029
commit
afc7c0c9d1
|
@ -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);
|
||||
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);
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue