From: Piotr Caban piotr@codeweavers.com
--- dlls/localspl/provider.c | 80 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index f3881ba7269..79a68729b3e 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -245,6 +245,7 @@ typedef struct { HANDLE_SERVER, HANDLE_PRINTER, HANDLE_XCV, + HANDLE_PORT, HANDLE_JOB, } type; } handle_header_t; @@ -257,6 +258,12 @@ typedef struct { HANDLE hxcv; } xcv_t;
+typedef struct { + handle_header_t header; + monitor_t *mon; + HANDLE hport; +} port_t; + typedef struct { handle_header_t header; HANDLE hf; @@ -1648,6 +1655,66 @@ static HANDLE xcv_alloc_handle(const WCHAR *name, PRINTER_DEFAULTSW *def, BOOL * return (HANDLE)xcv; }
+static HANDLE port_alloc_handle(const WCHAR *name, BOOL *stop_search) +{ + static const WCHAR portW[] = L"Port"; + + unsigned int i, name_len; + WCHAR *port_name; + port_t *port; + + *stop_search = FALSE; + for (name_len = 0; name[name_len] != ','; name_len++) + { + if (!name[name_len]) + return NULL; + } + + for (i = name_len + 1; name[i] == ' '; i++); + if (wcscmp(name + i, portW)) + return NULL; + + *stop_search = TRUE; + port_name = malloc((name_len + 1) * sizeof(WCHAR)); + if (!port_name) + return NULL; + memcpy(port_name, name, name_len * sizeof(WCHAR)); + port_name[name_len] = 0; + + port = calloc(1, sizeof(*port)); + if (!port) + { + free(port_name); + return NULL; + } + port->header.type = HANDLE_PORT; + + port->mon = monitor_load_by_port(port_name); + if (!port->mon) + { + free(port_name); + free(port); + return NULL; + } + if (!port->mon->monitor.pfnOpenPort || !port->mon->monitor.pfnWritePort + || !port->mon->monitor.pfnClosePort) + { + FIXME("port not supported: %s\n", debugstr_w(name)); + free(port_name); + fpClosePrinter((HANDLE)port); + return NULL; + } + + port->mon->monitor.pfnOpenPort(port->mon->hmon, port_name, &port->hport); + free(port_name); + if (!port->hport) + { + fpClosePrinter((HANDLE)port); + return NULL; + } + return (HANDLE)port; +} + static HANDLE job_alloc_handle(const WCHAR *name, BOOL *stop_search) { static const WCHAR jobW[] = L"Job "; @@ -1658,7 +1725,6 @@ static HANDLE job_alloc_handle(const WCHAR *name, BOOL *stop_search) job_t *job;
*stop_search = FALSE; - name_len = 0; for (name_len = 0; name[name_len] != ','; name_len++) { if (!name[name_len]) @@ -2764,6 +2830,8 @@ static BOOL WINAPI fpOpenPrinter(WCHAR *name, HANDLE *hprinter, *hprinter = server_alloc_handle(basename, &stop_search); if (!*hprinter && !stop_search) *hprinter = xcv_alloc_handle(basename, def, &stop_search); + if (!*hprinter && !stop_search) + *hprinter = port_alloc_handle(basename, &stop_search); if (!*hprinter && !stop_search) *hprinter = job_alloc_handle(basename, &stop_search); if (!*hprinter && !stop_search) @@ -3553,6 +3621,16 @@ static BOOL WINAPI fpClosePrinter(HANDLE hprinter) monitor_unload(xcv->pm); free(xcv); } + else if (header->type == HANDLE_PORT) + { + port_t *port = (port_t *)hprinter; + + if (port->hport) + port->mon->monitor.pfnClosePort(port->hport); + if (port->mon) + monitor_unload(port->mon); + free(port); + } else if (header->type == HANDLE_JOB) { job_t *job = (job_t *)hprinter;
From: Piotr Caban piotr@codeweavers.com
--- dlls/localspl/provider.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index 79a68729b3e..b8e06fad99d 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -3223,23 +3223,38 @@ static DWORD WINAPI fpStartDocPrinter(HANDLE hprinter, DWORD level, BYTE *doc_in
static BOOL WINAPI fpWritePrinter(HANDLE hprinter, void *buf, DWORD size, DWORD *written) { - printer_t *printer = (printer_t *)hprinter; + handle_header_t *header = (handle_header_t *)hprinter;
TRACE("(%p, %p, %ld, %p)\n", hprinter, buf, size, written);
- if(!printer || printer->header.type != HANDLE_PRINTER) + if (!header) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; }
- if(!printer->doc) + if (header->type == HANDLE_PORT) { - SetLastError(ERROR_SPL_NO_STARTDOC); - return FALSE; + port_t *port = (port_t *)hprinter; + + return port->mon->monitor.pfnWritePort(port->hport, buf, size, written); + } + + if (header->type == HANDLE_PRINTER) + { + printer_t *printer = (printer_t *)hprinter; + + if(!printer->doc) + { + SetLastError(ERROR_SPL_NO_STARTDOC); + return FALSE; + } + + return WriteFile(printer->doc->hf, buf, size, written, NULL); }
- return WriteFile(printer->doc->hf, buf, size, written, NULL); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; }
static BOOL WINAPI fpSetJob(HANDLE hprinter, DWORD job_id,
From: Piotr Caban piotr@codeweavers.com
--- dlls/localspl/provider.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index b8e06fad99d..069fef18f00 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -1697,7 +1697,7 @@ static HANDLE port_alloc_handle(const WCHAR *name, BOOL *stop_search) return NULL; } if (!port->mon->monitor.pfnOpenPort || !port->mon->monitor.pfnWritePort - || !port->mon->monitor.pfnClosePort) + || !port->mon->monitor.pfnClosePort || !port->mon->monitor.pfnStartDocPort) { FIXME("port not supported: %s\n", debugstr_w(name)); free(port_name); @@ -3199,7 +3199,21 @@ static DWORD WINAPI fpStartDocPrinter(HANDLE hprinter, DWORD level, BYTE *doc_in hprinter, level, doc_info, debugstr_w(info->pDocName), debugstr_w(info->pOutputFile), debugstr_w(info->pDatatype));
- if (!printer || printer->header.type != HANDLE_PRINTER) + if (!printer) + { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + + if (printer->header.type == HANDLE_PORT) + { + port_t *port = (port_t *)hprinter; + /* TODO: pass printer name and job_id */ + return port->mon->monitor.pfnStartDocPort(port->hport, + NULL, 0, level, doc_info); + } + + if (printer->header.type != HANDLE_PRINTER) { SetLastError(ERROR_INVALID_HANDLE); return 0;
From: Piotr Caban piotr@codeweavers.com
--- dlls/localspl/provider.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index 069fef18f00..d78a6d62db5 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -1697,7 +1697,8 @@ static HANDLE port_alloc_handle(const WCHAR *name, BOOL *stop_search) return NULL; } if (!port->mon->monitor.pfnOpenPort || !port->mon->monitor.pfnWritePort - || !port->mon->monitor.pfnClosePort || !port->mon->monitor.pfnStartDocPort) + || !port->mon->monitor.pfnClosePort || !port->mon->monitor.pfnStartDocPort + || !port->mon->monitor.pfnEndDocPort) { FIXME("port not supported: %s\n", debugstr_w(name)); free(port_name); @@ -3595,7 +3596,19 @@ static BOOL WINAPI fpEndDocPrinter(HANDLE hprinter)
TRACE("%p\n", hprinter);
- if (!printer || printer->header.type != HANDLE_PRINTER) + if (!printer) + { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + + if (printer->header.type == HANDLE_PORT) + { + port_t *port = (port_t *)hprinter; + return port->mon->monitor.pfnEndDocPort(port->hport); + } + + if (printer->header.type != HANDLE_PRINTER) { SetLastError(ERROR_INVALID_HANDLE); return FALSE;
From: Piotr Caban piotr@codeweavers.com
--- dlls/winspool.drv/info.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c index e58ae925c2b..258d67c5788 100644 --- a/dlls/winspool.drv/info.c +++ b/dlls/winspool.drv/info.c @@ -2568,6 +2568,37 @@ static void set_devices_and_printerports(PRINTER_INFO_2W *pi) } }
+static BOOL validate_print_proc(WCHAR *server, const WCHAR *name) +{ + PRINTPROCESSOR_INFO_1W *ppi; + DWORD size, i, no; + + if (!EnumPrintProcessorsW(server, NULL, 1, NULL, 0, &size, &no) + && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + return FALSE; + } + ppi = malloc(size); + if (!ppi) + { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + if (!EnumPrintProcessorsW(server, NULL, 1, (BYTE*)ppi, size, &size, &no)) + { + free(ppi); + return FALSE; + } + + for (i = 0; i < no; i++) + { + if (!wcsicmp(ppi[i].pName, name)) + break; + } + free(ppi); + return i != no; +} + /***************************************************************************** * AddPrinterW [WINSPOOL.@] */ @@ -2628,7 +2659,7 @@ HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter) RegCloseKey(hkeyDriver); RegCloseKey(hkeyDrivers);
- if (wcsicmp( pi->pPrintProcessor, L"WinPrint" )) + if (!validate_print_proc(pName, pi->pPrintProcessor)) { FIXME("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor)); SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
From: Piotr Caban piotr@codeweavers.com
--- dlls/localspl/provider.c | 51 +++++++++++++++++++++++++++++++++++++++- dlls/winspool.drv/info.c | 17 ++++++++++---- 2 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index d78a6d62db5..81c6406799a 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -2627,6 +2627,55 @@ emP_cleanup: return (res); }
+static BOOL WINAPI fpAddPrintProcessor(WCHAR *name, WCHAR *environment, WCHAR *path, + WCHAR *print_proc) +{ + const printenv_t * env; + HKEY hroot = NULL; + WCHAR *regpath; + LSTATUS s; + + TRACE("(%s, %s, %s, %s)\n", debugstr_w(name), debugstr_w(environment), + debugstr_w(path), debugstr_w(print_proc)); + + if (!path || !print_proc) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (name && name[0]) { + FIXME("server %s not supported\n", debugstr_w(name)); + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + + env = validate_envW(environment); + if (!env) + return FALSE; + + regpath = malloc(sizeof(fmt_printprocessorsW) + + wcslen(env->envname) * sizeof(WCHAR)); + if (!regpath) + return FALSE; + wsprintfW(regpath, fmt_printprocessorsW, env->envname); + + s = RegCreateKeyW(HKEY_LOCAL_MACHINE, regpath, &hroot); + free(regpath); + if (!s) + { + s = RegSetKeyValueW(hroot, print_proc, L"Driver", REG_SZ, path, + (wcslen(path) + 1) * sizeof(WCHAR)); + } + RegCloseKey(hroot); + if (s) + { + SetLastError(s); + return FALSE; + } + + return TRUE; +} + /***************************************************************************** * fpEnumPrintProcessors [exported through PRINTPROVIDOR] * @@ -3715,7 +3764,7 @@ static const PRINTPROVIDOR backend = { NULL, /* fpGetPrinterDriver */ fpGetPrinterDriverDirectory, NULL, /* fpDeletePrinterDriver */ - NULL, /* fpAddPrintProcessor */ + fpAddPrintProcessor, fpEnumPrintProcessors, fpGetPrintProcessorDirectory, NULL, /* fpDeletePrintProcessor */ diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c index 258d67c5788..8abfc9b0887 100644 --- a/dlls/winspool.drv/info.c +++ b/dlls/winspool.drv/info.c @@ -4799,12 +4799,19 @@ BOOL WINAPI AddPrintProcessorA(LPSTR pName, LPSTR pEnvironment, LPSTR pPathName, /***************************************************************************** * AddPrintProcessorW [WINSPOOL.@] */ -BOOL WINAPI AddPrintProcessorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pPathName, - LPWSTR pPrintProcessorName) +BOOL WINAPI AddPrintProcessorW(WCHAR *name, WCHAR *env, WCHAR *path, WCHAR *print_proc) { - FIXME("(%s,%s,%s,%s): stub\n", debugstr_w(pName), debugstr_w(pEnvironment), - debugstr_w(pPathName), debugstr_w(pPrintProcessorName)); - return TRUE; + TRACE("(%s,%s,%s,%s)\n", debugstr_w(name), debugstr_w(env), + debugstr_w(path), debugstr_w(print_proc)); + + if (!path || !print_proc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if ((backend == NULL) && !load_backend()) return FALSE; + return backend->fpAddPrintProcessor(name, env, path, print_proc); }
/*****************************************************************************