Commit bd1941c3 authored by Detlef Riekenberg's avatar Detlef Riekenberg Committed by Alexandre Julliard

wineps: Use winspool.drv for job management.

parent 364b804d
......@@ -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;
TRACE("using output: %s\n", debugstr_a(di.pOutputFile));
physDev->job.id = create_job( output );
/* 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;
......
......@@ -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 */
......
......@@ -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};
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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment