From: Detlef Riekenberg Subject: wineps: Use winspool.drv for job management [fixes bug 3975] Message-Id: <1281619438.5561.1.camel@amd64.fritz.box> Date: Thu, 12 Aug 2010 15:23:58 +0200 wineps should be converted to use UNICODE, but such a patchset does not fit for Wine-1.2.1 -- By by ... Detlef From 3ebf11f64e44f87e4f887cf5608a16ab1c30a4c3 Mon Sep 17 00:00:00 2001 From: Detlef Riekenberg Date: Thu, 12 Aug 2010 14:37:36 +0200 Subject: [PATCH] wineps: Use winspool.drv for job management [fixes bug 3975] wineps should be converted to use UNICODE, but such a patchset does not fit for Wine-1.2.1 -- By by ... Detlef --- dlls/wineps.drv/escape.c | 152 +++++++++++----------------------------------- dlls/wineps.drv/psdrv.h | 1 + dlls/winspool.drv/info.c | 49 +++++++++++---- 3 files changed, 71 insertions(+), 131 deletions(-) diff --git a/dlls/wineps.drv/escape.c b/dlls/wineps.drv/escape.c index 1062b96..b5a3720 100644 --- a/dlls/wineps.drv/escape.c +++ b/dlls/wineps.drv/escape.c @@ -46,108 +46,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(psdrv); static const char psbegindocument[] = "%%BeginDocument: Wine passthrough\n"; -/* FIXME: should use winspool functions instead */ -static DWORD create_job(LPCSTR pszOutput) -{ - int fd = -1; - char psCmd[1024]; - const char *psCmdP = psCmd; - HKEY hkey; - - /* TTD convert the 'output device' into a spool file name */ - - if (pszOutput == NULL || *pszOutput == '\0') return 0; - - psCmd[0] = 0; - /* @@ Wine registry key: HKCU\Software\Wine\Printing\Spooler */ - if(!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Printing\\Spooler", &hkey)) - { - DWORD type, count = sizeof(psCmd); - RegQueryValueExA(hkey, pszOutput, 0, &type, (LPBYTE)psCmd, &count); - RegCloseKey(hkey); - } - if (!psCmd[0] && !strncmp("LPR:",pszOutput,4)) - sprintf(psCmd,"|lpr -P'%s'",pszOutput+4); - - TRACE("Got printerSpoolCommand '%s' for output device '%s'\n", - psCmd, pszOutput); - if (!*psCmd) - psCmdP = pszOutput; - else - { - while (*psCmdP && isspace(*psCmdP)) - { - psCmdP++; - } - if (!*psCmdP) return 0; - } - TRACE("command: '%s'\n", psCmdP); -#ifdef HAVE_FORK - if (*psCmdP == '|') - { - int fds[2]; - if (pipe(fds)) { - ERR("pipe() failed!\n"); - return 0; - } - if (fork() == 0) - { - psCmdP++; - - TRACE("In child need to exec %s\n",psCmdP); - close(0); - dup2(fds[0],0); - close (fds[1]); - - /* reset signals that we previously set to SIG_IGN */ - signal( SIGPIPE, SIG_DFL ); - signal( SIGCHLD, SIG_DFL ); - - execl("/bin/sh", "/bin/sh", "-c", psCmdP, NULL); - _exit(1); - - } - close (fds[0]); - fd = fds[1]; - TRACE("Need to execute a cmnd and pipe the output to it\n"); - } - else -#endif - { - char *buffer; - WCHAR psCmdPW[MAX_PATH]; - - TRACE("Just assume it's a file\n"); - - /** - * The file name can be dos based, we have to find its - * corresponding Unix file name. - */ - MultiByteToWideChar(CP_ACP, 0, psCmdP, -1, psCmdPW, MAX_PATH); - if ((buffer = wine_get_unix_file_name(psCmdPW))) - { - if ((fd = open(buffer, O_CREAT | O_TRUNC | O_WRONLY, 0666)) < 0) - { - ERR("Failed to create spool file '%s' ('%s'). (error %s)\n", - buffer, psCmdP, strerror(errno)); - } - HeapFree(GetProcessHeap(), 0, buffer); - } - } - return fd + 1; -} - -static int close_job( DWORD id ) -{ - int fd = id - 1; - close( fd ); - return TRUE; -} DWORD write_spool( PSDRV_PDEVICE *physDev, const void *data, DWORD num ) { - int fd = physDev->job.id - 1; - if (write( fd, data, num) != num) return SP_OUTOFDISK; + DWORD written; + if (!WritePrinter(physDev->job.hprinter, (LPBYTE) data, num, &written) || (written != num)) + return SP_OUTOFDISK; + return num; } @@ -500,33 +405,41 @@ INT CDECL PSDRV_EndPage( PSDRV_PDEVICE *physDev ) */ static INT PSDRV_StartDocA( PSDRV_PDEVICE *physDev, const DOCINFOA *doc ) { - LPCSTR output = "LPT1:"; - BYTE buf[300]; - HANDLE hprn = INVALID_HANDLE_VALUE; - PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A*)buf; - DWORD needed; + DOC_INFO_1A di; + + TRACE("(%p, %p) => %s, %s, %s\n", physDev, doc, debugstr_a(doc->lpszDocName), + debugstr_a(doc->lpszOutput), debugstr_a(doc->lpszDatatype)); if(physDev->job.id) { FIXME("hJob != 0. Now what?\n"); return 0; } + /* FIXME: use PRINTER_DEFAULTS here */ + if(!OpenPrinterA(physDev->pi->FriendlyName, &physDev->job.hprinter, NULL)) { + WARN("OpenPrinter(%s, ...) failed: %d\n", + debugstr_a(physDev->pi->FriendlyName), GetLastError()); + return 0; + } + + di.pDocName = (LPSTR) doc->lpszDocName; + di.pDatatype = NULL; + if(doc->lpszOutput) - output = doc->lpszOutput; + di.pOutputFile = (LPSTR) doc->lpszOutput; else if(physDev->job.output) - output = physDev->job.output; - else { - if(OpenPrinterA(physDev->pi->FriendlyName, &hprn, NULL) && - GetPrinterA(hprn, 5, buf, sizeof(buf), &needed)) { - output = pi5->pPortName; - } - if(hprn != INVALID_HANDLE_VALUE) - ClosePrinter(hprn); - } + di.pOutputFile = physDev->job.output; + else + di.pOutputFile = NULL; - physDev->job.id = create_job( output ); + TRACE("using output: %s\n", debugstr_a(di.pOutputFile)); + + /* redirection located in HKCU\Software\Wine\Printing\Spooler + is done during winspool.drv,ScheduleJob */ + physDev->job.id = StartDocPrinterA(physDev->job.hprinter, 1, (LPBYTE) &di); if(!physDev->job.id) { - WARN("OpenJob failed\n"); + WARN("StartDocPrinter() failed: %d\n", GetLastError()); + ClosePrinter(physDev->job.hprinter); return 0; } physDev->job.banding = FALSE; @@ -553,6 +466,9 @@ INT CDECL PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOW *doc ) INT ret, len; LPSTR docname = NULL, output = NULL, datatype = NULL; + TRACE("(%p, %p) => %d,%s,%s,%s\n", physDev, doc, doc->cbSize, debugstr_w(doc->lpszDocName), + debugstr_w(doc->lpszOutput), debugstr_w(doc->lpszDatatype)); + docA.cbSize = doc->cbSize; if (doc->lpszDocName) { @@ -603,7 +519,9 @@ INT CDECL PSDRV_EndDoc( PSDRV_PDEVICE *physDev ) } PSDRV_WriteFooter( physDev ); - ret = close_job( physDev->job.id ); + ret = EndDocPrinter(physDev->job.hprinter); + ClosePrinter(physDev->job.hprinter); + physDev->job.hprinter = NULL; physDev->job.id = 0; HeapFree(GetProcessHeap(), 0, physDev->job.DocName); physDev->job.DocName = NULL; diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h index 854cdd2..4ca6e70 100644 --- a/dlls/wineps.drv/psdrv.h +++ b/dlls/wineps.drv/psdrv.h @@ -340,6 +340,7 @@ typedef struct { typedef struct { DWORD id; /* Job id */ + HANDLE hprinter; /* Printer handle */ LPSTR output; /* Output file/port */ LPSTR DocName; /* Document Name */ BOOL banding; /* Have we received a NEXTBAND */ diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c index 885b8df..7bf1bcb 100644 --- a/dlls/winspool.drv/info.c +++ b/dlls/winspool.drv/info.c @@ -6,7 +6,7 @@ * Copyright 1999 Klaas van Gend * Copyright 1999, 2000 Huw D M Davies * Copyright 2001 Marcus Meissner - * Copyright 2005-2009 Detlef Riekenberg + * Copyright 2005-2010 Detlef Riekenberg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -97,6 +97,7 @@ typedef struct { struct list entry; DWORD job_id; WCHAR *filename; + WCHAR *portname; WCHAR *document_title; } job_t; @@ -325,6 +326,15 @@ static LPSTR strdupWtoA( LPCWSTR str ) } /****************************************************************** + * verify, that the filename is a local file + * + */ +static inline BOOL is_local_file(LPWSTR name) +{ + return (name[0] && (name[1] == ':') && (name[2] == '\\')); +} + +/****************************************************************** * Return the number of bytes for an multi_sz string. * The result includes all \0s * (specifically the extra \0, that is needed as multi_sz terminator). @@ -2975,6 +2985,7 @@ DWORD WINAPI StartDocPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo) DWORD needed, ret = 0; HANDLE hf; WCHAR *filename; + job_t *job; TRACE("(hPrinter = %p, Level = %d, pDocInfo = %p {pDocName = %s, pOutputFile = %s, pDatatype = %s}):\n", hPrinter, Level, doc, debugstr_w(doc->pDocName), debugstr_w(doc->pOutputFile), @@ -3009,7 +3020,8 @@ DWORD WINAPI StartDocPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo) goto end; } - if(doc->pOutputFile) + /* use pOutputFile only, when it is a real filename */ + if ((doc->pOutputFile) && is_local_file(doc->pOutputFile)) filename = doc->pOutputFile; else filename = addjob->Path; @@ -3025,6 +3037,9 @@ DWORD WINAPI StartDocPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo) printer->doc = HeapAlloc(GetProcessHeap(), 0, sizeof(*printer->doc)); printer->doc->hf = hf; ret = printer->doc->job_id = addjob->JobId; + job = get_job(hPrinter, ret); + job->portname = strdupW(doc->pOutputFile); + end: LeaveCriticalSection(&printer_handles_cs); @@ -7465,18 +7480,23 @@ BOOL WINAPI ScheduleJob( HANDLE hPrinter, DWORD dwJobID ) hf = CreateFileW(job->filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hf != INVALID_HANDLE_VALUE) { - PRINTER_INFO_5W *pi5; + PRINTER_INFO_5W *pi5 = NULL; + LPWSTR portname = job->portname; DWORD needed; HKEY hkey; WCHAR output[1024]; static const WCHAR spooler_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\', 'P','r','i','n','t','i','n','g','\\','S','p','o','o','l','e','r',0}; - GetPrinterW(hPrinter, 5, NULL, 0, &needed); - pi5 = HeapAlloc(GetProcessHeap(), 0, needed); - GetPrinterW(hPrinter, 5, (LPBYTE)pi5, needed, &needed); + if (!portname) + { + GetPrinterW(hPrinter, 5, NULL, 0, &needed); + pi5 = HeapAlloc(GetProcessHeap(), 0, needed); + GetPrinterW(hPrinter, 5, (LPBYTE)pi5, needed, &needed); + portname = pi5->pPortName; + } TRACE("need to schedule job %d filename %s to port %s\n", job->job_id, debugstr_w(job->filename), - debugstr_w(pi5->pPortName)); + debugstr_w(portname)); output[0] = 0; @@ -7484,7 +7504,7 @@ BOOL WINAPI ScheduleJob( HANDLE hPrinter, DWORD dwJobID ) if(RegOpenKeyW(HKEY_CURRENT_USER, spooler_key, &hkey) == ERROR_SUCCESS) { DWORD type, count = sizeof(output); - RegQueryValueExW(hkey, pi5->pPortName, NULL, &type, (LPBYTE)output, &count); + RegQueryValueExW(hkey, portname, NULL, &type, (LPBYTE)output, &count); RegCloseKey(hkey); } if(output[0] == '|') @@ -7495,21 +7515,21 @@ BOOL WINAPI ScheduleJob( HANDLE hPrinter, DWORD dwJobID ) { ret = schedule_unixfile(output, job->filename); } - else if(!strncmpW(pi5->pPortName, LPR_Port, strlenW(LPR_Port))) + else if(!strncmpW(portname, LPR_Port, strlenW(LPR_Port))) { - ret = schedule_lpr(pi5->pPortName + strlenW(LPR_Port), job->filename); + ret = schedule_lpr(portname + strlenW(LPR_Port), job->filename); } - else if(!strncmpW(pi5->pPortName, CUPS_Port, strlenW(CUPS_Port))) + else if(!strncmpW(portname, CUPS_Port, strlenW(CUPS_Port))) { - ret = schedule_cups(pi5->pPortName + strlenW(CUPS_Port), job->filename, job->document_title); + ret = schedule_cups(portname + strlenW(CUPS_Port), job->filename, job->document_title); } - else if(!strncmpW(pi5->pPortName, FILE_Port, strlenW(FILE_Port))) + else if(!strncmpW(portname, FILE_Port, strlenW(FILE_Port))) { ret = schedule_file(job->filename); } else { - FIXME("can't schedule to port %s\n", debugstr_w(pi5->pPortName)); + FIXME("can't schedule to port %s\n", debugstr_w(portname)); } HeapFree(GetProcessHeap(), 0, pi5); CloseHandle(hf); @@ -7517,6 +7537,7 @@ BOOL WINAPI ScheduleJob( HANDLE hPrinter, DWORD dwJobID ) } list_remove(cursor); HeapFree(GetProcessHeap(), 0, job->document_title); + HeapFree(GetProcessHeap(), 0, job->portname); HeapFree(GetProcessHeap(), 0, job->filename); HeapFree(GetProcessHeap(), 0, job); break; -- 1.7.0.4