[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