localspl: Add support for Job handles.

This commit is contained in:
Piotr Caban 2022-12-01 19:24:38 +01:00 committed by Alexandre Julliard
parent 4d74944a62
commit f4dbb3e8a4

View file

@ -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,6 +496,24 @@ static void monitor_unloadall(void)
LeaveCriticalSection(&monitor_handles_cs);
}
static printer_info_t *find_printer_info(const WCHAR *name, unsigned int len)
{
printer_info_t *info;
EnterCriticalSection(&printers_cs);
LIST_FOR_EACH_ENTRY(info, &printers, printer_info_t, entry)
{
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;
@ -499,14 +523,11 @@ static printer_info_t* get_printer_info(const WCHAR *name)
DWORD size;
EnterCriticalSection(&printers_cs);
LIST_FOR_EACH_ENTRY(info, &printers, printer_info_t, entry)
info = find_printer_info(name, -1);
if (info)
{
if (!wcscmp(info->name, name))
{
InterlockedIncrement(&info->ref);
LeaveCriticalSection(&printers_cs);
return info;
}
LeaveCriticalSection(&printers_cs);
return info;
}
ret = RegCreateKeyW(HKEY_LOCAL_MACHINE, printersW, &hkey);
@ -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)
{
@ -2662,6 +2764,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);
@ -3070,18 +3174,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)
{
@ -3446,6 +3538,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;