From: Piotr Caban piotr@codeweavers.com
--- dlls/localspl/provider.c | 135 +++++++++++++++++++++++++++++++++------ 1 file changed, 117 insertions(+), 18 deletions(-)
diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index 94ac8b6e3d0..8380f53aacc 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -245,6 +245,7 @@ typedef struct { HANDLE_SERVER, HANDLE_PRINTER, HANDLE_XCV, + HANDLE_JOB, } type; } handle_header_t;
@@ -256,6 +257,11 @@ typedef struct { HANDLE hxcv; } xcv_t;
+typedef struct { + handle_header_t header; + HANDLE hf; +} job_t; + typedef struct { handle_header_t header; printer_info_t *info; @@ -490,24 +496,39 @@ static void monitor_unloadall(void) LeaveCriticalSection(&monitor_handles_cs); }
-static printer_info_t* get_printer_info(const WCHAR *name) +static printer_info_t *find_printer_info(const WCHAR *name, unsigned int len) { - HKEY hkey, hprinter = NULL; printer_info_t *info; - WCHAR port[MAX_PATH]; - LSTATUS ret; - DWORD size;
EnterCriticalSection(&printers_cs); LIST_FOR_EACH_ENTRY(info, &printers, printer_info_t, entry) { - if (!wcscmp(info->name, name)) + if (!wcsncmp(info->name, name, len) && (len == -1 || !info->name[len])) { InterlockedIncrement(&info->ref); LeaveCriticalSection(&printers_cs); return info; } } + LeaveCriticalSection(&printers_cs); + return NULL; +} + +static printer_info_t* get_printer_info(const WCHAR *name) +{ + HKEY hkey, hprinter = NULL; + printer_info_t *info; + WCHAR port[MAX_PATH]; + LSTATUS ret; + DWORD size; + + EnterCriticalSection(&printers_cs); + info = find_printer_info(name, -1); + if (info) + { + LeaveCriticalSection(&printers_cs); + return info; + }
ret = RegCreateKeyW(HKEY_LOCAL_MACHINE, printersW, &hkey); if (ret == ERROR_SUCCESS) @@ -1538,6 +1559,18 @@ static HMODULE driver_load(const printenv_t * env, LPWSTR dllname) return hui; }
+static job_info_t * get_job(printer_info_t *info, DWORD job_id) +{ + job_info_t *job; + + LIST_FOR_EACH_ENTRY(job, &info->jobs, job_info_t, entry) + { + if(job->id == job_id) + return job; + } + return NULL; +} + static HANDLE server_alloc_handle(const WCHAR *name, BOOL *stop_search) { server_t *server; @@ -1615,6 +1648,75 @@ static HANDLE xcv_alloc_handle(const WCHAR *name, PRINTER_DEFAULTSW *def, BOOL * return (HANDLE)xcv; }
+static HANDLE job_alloc_handle(const WCHAR *name, BOOL *stop_search) +{ + static const WCHAR jobW[] = L"Job "; + + unsigned int name_len, job_id; + printer_info_t *printer_info; + job_info_t *job_info; + job_t *job; + + *stop_search = FALSE; + name_len = 0; + for (name_len = 0; name[name_len] != ','; name_len++) + { + if (!name[name_len]) + return NULL; + } + + for (job_id = name_len + 1; name[job_id] == ' '; job_id++); + if (!name[job_id]) + return NULL; + + if (wcsncmp(name + job_id, jobW, ARRAY_SIZE(jobW) - 1)) + return NULL; + + *stop_search = TRUE; + job_id += ARRAY_SIZE(jobW) - 1; + job_id = wcstoul(name + job_id, NULL, 10); + + printer_info = find_printer_info(name, name_len); + if (!printer_info) + { + SetLastError(ERROR_INVALID_PRINTER_NAME); + return NULL; + } + + EnterCriticalSection(&printer_info->jobs_cs); + + job_info = get_job(printer_info, job_id); + if (!job_info) + { + LeaveCriticalSection(&printer_info->jobs_cs); + release_printer_info(printer_info); + SetLastError(ERROR_INVALID_PRINTER_NAME); + return NULL; + } + + job = malloc(sizeof(*job)); + if (!job) + { + LeaveCriticalSection(&printer_info->jobs_cs); + release_printer_info(printer_info); + return NULL; + } + job->header.type = HANDLE_JOB; + job->hf = CreateFileW(job_info->filename, GENERIC_READ, + FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, 0, NULL); + + LeaveCriticalSection(&printer_info->jobs_cs); + release_printer_info(printer_info); + + if (job->hf == INVALID_HANDLE_VALUE) + { + free(job); + return NULL; + } + return (HANDLE)job; +} + static HANDLE printer_alloc_handle(const WCHAR *name, const WCHAR *basename, PRINTER_DEFAULTSW *def) { @@ -2660,6 +2762,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 = job_alloc_handle(basename, &stop_search); if (!*hprinter && !stop_search) *hprinter = printer_alloc_handle(name, basename, def);
@@ -3068,18 +3172,6 @@ static BOOL WINAPI fpWritePrinter(HANDLE hprinter, void *buf, DWORD size, DWORD return WriteFile(printer->doc->hf, buf, size, written, NULL); }
-static job_info_t * get_job(printer_info_t *info, DWORD job_id) -{ - job_info_t *job; - - LIST_FOR_EACH_ENTRY(job, &info->jobs, job_info_t, entry) - { - if(job->id == job_id) - return job; - } - return NULL; -} - static BOOL WINAPI fpSetJob(HANDLE hprinter, DWORD job_id, DWORD level, BYTE *data, DWORD command) { @@ -3444,6 +3536,13 @@ static BOOL WINAPI fpClosePrinter(HANDLE hprinter) monitor_unload(xcv->pm); free(xcv); } + else if (header->type == HANDLE_JOB) + { + job_t *job = (job_t *)hprinter; + + CloseHandle(job->hf); + free(job); + } else if (header->type == HANDLE_PRINTER) { printer_t *printer = (printer_t *)hprinter;