Commit 9c939184 authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

winspool: Use providor for WritePrinter implementation.

parent e164b8ce
......@@ -225,6 +225,7 @@ typedef struct {
WCHAR *port;
WCHAR *document_title;
DEVMODEW *devmode;
HANDLE hf;
} job_t;
typedef struct {
......@@ -531,6 +532,7 @@ static void free_job(job_t *job)
free(job->port);
free(job->document_title);
free(job->devmode);
CloseHandle(job->hf);
free(job);
}
......@@ -2087,32 +2089,6 @@ static BOOL WINAPI fpAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDrive
}
/******************************************************************************
* fpClosePrinter [exported through PRINTPROVIDOR]
*
* Close a printer handle and free associated resources
*
* PARAMS
* hPrinter [I] Printerhandle to close
*
* RESULTS
* Success: TRUE
* Failure: FALSE
*
*/
static BOOL WINAPI fpClosePrinter(HANDLE hPrinter)
{
printer_t *printer = (printer_t *) hPrinter;
TRACE("(%p)\n", hPrinter);
if (printer) {
printer_free(printer);
return TRUE;
}
return FALSE;
}
/******************************************************************************
* fpConfigurePort [exported through PRINTPROVIDOR]
*
* Display the Configuration-Dialog for a specific Port
......@@ -2907,7 +2883,7 @@ static size_t get_spool_filename(DWORD job_id, WCHAR *buf, size_t len)
return ret;
}
static job_t* add_job(printer_t *printer, DOC_INFO_1W *info)
static job_t* add_job(printer_t *printer, DOC_INFO_1W *info, BOOL create)
{
DWORD job_id, last_id;
size_t len;
......@@ -2941,6 +2917,21 @@ static job_t* add_job(printer_t *printer, DOC_INFO_1W *info)
job->id = job_id;
get_spool_filename(job_id, job->filename, len);
if (create)
{
job->hf = CreateFileW(job->filename, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (job->hf == INVALID_HANDLE_VALUE)
{
free(job->filename);
free(job);
return NULL;
}
}
else
{
job->hf = NULL;
}
job->document_title = wcsdup(info->pDocName);
job->devmode = dup_devmode(printer->devmode);
......@@ -2988,7 +2979,7 @@ static BOOL WINAPI fpAddJob(HANDLE hprinter, DWORD level, BYTE *data, DWORD size
memset(&doc_info, 0, sizeof(doc_info));
doc_info.pDocName = (WCHAR *)L"Local Downlevel Document";
job = add_job(printer, &doc_info);
job = add_job(printer, &doc_info, FALSE);
if (!job)
return FALSE;
......@@ -3025,10 +3016,31 @@ static DWORD WINAPI fpStartDocPrinter(HANDLE hprinter, DWORD level, BYTE *doc_in
return 0;
}
printer->doc = add_job(printer, info);
printer->doc = add_job(printer, info, TRUE);
return printer->doc ? printer->doc->id : 0;
}
static BOOL WINAPI fpWritePrinter(HANDLE hprinter, void *buf, DWORD size, DWORD *written)
{
printer_t *printer = (printer_t *)hprinter;
TRACE("(%p, %p, %ld, %p)\n", hprinter, buf, size, written);
if(!printer || !printer->info)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if(!printer->doc)
{
SetLastError(ERROR_SPL_NO_STARTDOC);
return FALSE;
}
return WriteFile(printer->doc->hf, buf, size, written, NULL);
}
static job_t * get_job(printer_info_t *info, DWORD job_id)
{
job_t *job;
......@@ -3362,11 +3374,41 @@ static BOOL WINAPI fpEndDocPrinter(HANDLE hprinter)
return FALSE;
}
CloseHandle(printer->doc->hf);
printer->doc->hf = NULL;
ret = fpScheduleJob(hprinter, printer->doc->id);
printer->doc = NULL;
return ret;
}
/******************************************************************************
* fpClosePrinter [exported through PRINTPROVIDOR]
*
* Close a printer handle and free associated resources
*
* PARAMS
* hPrinter [I] Printerhandle to close
*
* RESULTS
* Success: TRUE
* Failure: FALSE
*
*/
static BOOL WINAPI fpClosePrinter(HANDLE hprinter)
{
printer_t *printer = (printer_t *)hprinter;
TRACE("(%p)\n", hprinter);
if (!printer)
return FALSE;
if(printer->doc)
fpEndDocPrinter(hprinter);
printer_free(printer);
return TRUE;
}
static const PRINTPROVIDOR backend = {
fpOpenPrinter,
fpSetJob,
......@@ -3389,7 +3431,7 @@ static const PRINTPROVIDOR backend = {
NULL, /* fpEnumPrintProcessorDatatypes */
fpStartDocPrinter,
NULL, /* fpStartPagePrinter */
NULL, /* fpWritePrinter */
fpWritePrinter,
NULL, /* fpEndPagePrinter */
NULL, /* fpAbortPrinter */
NULL, /* fpReadPrinter */
......
......@@ -71,14 +71,8 @@ static CRITICAL_SECTION printer_handles_cs = { &printer_handles_cs_debug, -1, 0,
/* ############################### */
typedef struct {
DWORD job_id;
HANDLE hf;
} started_doc_t;
typedef struct {
LPWSTR name;
HANDLE backend_printer;
started_doc_t *doc;
} opened_printer_t;
typedef struct {
......@@ -2336,31 +2330,19 @@ BOOL WINAPI DeletePortW (LPWSTR pName, HWND hWnd, LPWSTR pPortName)
/******************************************************************************
* WritePrinter [WINSPOOL.@]
*/
BOOL WINAPI WritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD pcWritten)
BOOL WINAPI WritePrinter(HANDLE printer, void *buf, DWORD size, DWORD *written)
{
opened_printer_t *printer;
BOOL ret = FALSE;
HANDLE handle = get_backend_handle(printer);
TRACE("(%p, %p, %ld, %p)\n", hPrinter, pBuf, cbBuf, pcWritten);
TRACE("(%p, %p, %ld, %p)\n", printer, buf, size, written);
EnterCriticalSection(&printer_handles_cs);
printer = get_opened_printer(hPrinter);
if(!printer)
if (!handle)
{
SetLastError(ERROR_INVALID_HANDLE);
goto end;
}
if(!printer->doc)
{
SetLastError(ERROR_SPL_NO_STARTDOC);
goto end;
return FALSE;
}
ret = WriteFile(printer->doc->hf, pBuf, cbBuf, pcWritten, NULL);
end:
LeaveCriticalSection(&printer_handles_cs);
return ret;
return backend->fpWritePrinter(handle, buf, size, written);
}
/*****************************************************************************
......@@ -2768,11 +2750,7 @@ BOOL WINAPI ClosePrinter(HANDLE hPrinter)
if(printer)
{
TRACE("closing %s (doc: %p)\n", debugstr_w(printer->name), printer->doc);
if(printer->doc)
EndDocPrinter(hPrinter);
TRACE("closing %s\n", debugstr_w(printer->name));
if (printer->backend_printer) {
backend->fpClosePrinter(printer->backend_printer);
}
......@@ -3088,29 +3066,19 @@ BOOL WINAPI SetJobW(HANDLE printer, DWORD job_id, DWORD level,
/*****************************************************************************
* EndDocPrinter [WINSPOOL.@]
*/
BOOL WINAPI EndDocPrinter(HANDLE hprinter)
BOOL WINAPI EndDocPrinter(HANDLE printer)
{
opened_printer_t *printer = get_opened_printer(hprinter);
HANDLE handle = get_backend_handle(printer);
TRACE("(%p)\n", printer);
if (!printer || !printer->backend_printer)
if (!handle)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (!printer->doc)
{
SetLastError(ERROR_SPL_NO_STARTDOC);
return FALSE;
}
CloseHandle(printer->doc->hf);
free(printer->doc);
printer->doc = NULL;
return backend->fpEndDocPrinter(printer->backend_printer);
return backend->fpEndDocPrinter(handle);
}
/*****************************************************************************
......@@ -3162,71 +3130,25 @@ DWORD WINAPI StartDocPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
return ret;
}
static size_t get_spool_filename(DWORD job_id, WCHAR *buf, size_t len)
{
static const WCHAR spool_path[] = L"spool\\PRINTERS\\";
size_t ret;
ret = GetSystemDirectoryW(NULL, 0) + ARRAY_SIZE(spool_path) + 10;
if (len < ret)
return ret;
ret = GetSystemDirectoryW(buf, ret);
if (buf[ret - 1] != '\\')
buf[ret++] = '\\';
memcpy(buf + ret, spool_path, sizeof(spool_path));
ret += ARRAY_SIZE(spool_path) - 1;
swprintf(buf + ret, 10, L"%05d.SPL", job_id);
ret += 10;
return ret;
}
/*****************************************************************************
* StartDocPrinterW [WINSPOOL.@]
*/
DWORD WINAPI StartDocPrinterW(HANDLE hprinter, DWORD level, BYTE *doc_info)
DWORD WINAPI StartDocPrinterW(HANDLE printer, DWORD level, BYTE *doc_info)
{
opened_printer_t *printer = get_opened_printer(hprinter);
HANDLE handle = get_backend_handle(printer);
DOC_INFO_1W *info = (DOC_INFO_1W *)doc_info;
WCHAR filename[MAX_PATH];
HANDLE handle;
DWORD job_id;
HANDLE hf;
TRACE("(%p, %ld, %p {%s, %s, %s})\n", printer, level, doc_info,
debugstr_w(info->pDocName), debugstr_w(info->pOutputFile),
debugstr_w(info->pDatatype));
if (!printer || !printer->backend_printer)
if (!handle)
{
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
handle = printer->backend_printer;
job_id = backend->fpStartDocPrinter(handle, level, doc_info);
if (!job_id)
return 0;
/* TODO: remove when WritePrinter is implemented in providor */
if (get_spool_filename(job_id, filename, ARRAY_SIZE(filename)) > ARRAY_SIZE(filename))
{
backend->fpEndDocPrinter(handle);
SetLastError(ERROR_INTERNAL_ERROR);
return 0;
}
hf = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hf == INVALID_HANDLE_VALUE)
{
backend->fpEndDocPrinter(handle);
return 0;
}
printer->doc = malloc(sizeof(*printer->doc));
printer->doc->job_id = job_id;
printer->doc->hf = hf;
return job_id;
return backend->fpStartDocPrinter(handle, level, doc_info);
}
/*****************************************************************************
......
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