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;
}
*/
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;
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)
{
}
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;
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 */
* 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
struct list entry;
DWORD job_id;
WCHAR *filename;
+ WCHAR *portname;
WCHAR *document_title;
} job_t;
return ret;
}
+/******************************************************************
+ * 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
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),
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;
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);
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;
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] == '|')
{
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);
}
list_remove(cursor);
HeapFree(GetProcessHeap(), 0, job->document_title);
+ HeapFree(GetProcessHeap(), 0, job->portname);
HeapFree(GetProcessHeap(), 0, job->filename);
HeapFree(GetProcessHeap(), 0, job);
break;