[PATCH] wineps: Use winspool.drv for job management [fixes bug 3975]
Detlef Riekenberg
wine.dev at web.de
Thu Aug 12 07:37:36 CDT 2010
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
--=-rtYhBCcMS1KsmbuUEQ5q--
More information about the wine-patches
mailing list