[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