From d502bda23c544785682868f248eaff86d2e60457 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:46 +0100 Subject: [PATCH 1/6] printing: add jobid_to_sysjob helper function Samba needs to deal with two types of print job identifiers, those allocated by the printing backend (sysjob ids), and those allocated by Samba's spoolss server (jobids). This change adds a helper function to map spoolss jobids to sysjob ids, to go alongside the corresponding sysjob to jobid mapping function. Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 77b5be1742ee7aa2733a25bfa6a3af369f5c9401) --- source3/include/printing.h | 1 + source3/printing/printing.c | 70 +++++++++++++++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/source3/include/printing.h b/source3/include/printing.h index ec5a53b..563659a 100644 --- a/source3/include/printing.h +++ b/source3/include/printing.h @@ -195,6 +195,7 @@ uint16_t print_spool_rap_jobid(struct print_file_data *print_file); uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob); uint32 sysjob_to_jobid(int unix_jobid); +int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid); bool print_notify_register_pid(int snum); bool print_notify_deregister_pid(int snum); bool print_job_exists(const char* sharename, uint32 jobid); diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 52d24dc..3129e10 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -490,19 +490,18 @@ err_out: return pjob; } -/* Convert a unix jobid to a smb jobid */ - -struct unixjob_traverse_state { +struct job_traverse_state { int sysjob; - uint32 sysjob_to_jobid_value; + uint32_t jobid; }; -static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, - TDB_DATA data, void *private_data) +/* find spoolss jobid based on sysjob */ +static int sysjob_to_jobid_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, + TDB_DATA data, void *private_data) { struct printjob *pjob; - struct unixjob_traverse_state *state = - (struct unixjob_traverse_state *)private_data; + struct job_traverse_state *state = + (struct job_traverse_state *)private_data; if (!data.dptr || data.dsize == 0) return 0; @@ -512,7 +511,7 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, return 0; if (state->sysjob == pjob->sysjob) { - state->sysjob_to_jobid_value = pjob->jobid; + state->jobid = pjob->jobid; return 1; } @@ -521,14 +520,14 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob) { - struct unixjob_traverse_state state; + struct job_traverse_state state; state.sysjob = sysjob; - state.sysjob_to_jobid_value = (uint32)-1; + state.jobid = (uint32_t)-1; - tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state); + tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state); - return state.sysjob_to_jobid_value; + return state.jobid; } /**************************************************************************** @@ -540,10 +539,10 @@ uint32 sysjob_to_jobid(int unix_jobid) { int services = lp_numservices(); int snum; - struct unixjob_traverse_state state; + struct job_traverse_state state; state.sysjob = unix_jobid; - state.sysjob_to_jobid_value = (uint32)-1; + state.jobid = (uint32_t)-1; for (snum = 0; snum < services; snum++) { struct tdb_print_db *pdb; @@ -553,14 +552,49 @@ uint32 sysjob_to_jobid(int unix_jobid) if (!pdb) { continue; } - tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state); + tdb_traverse(pdb->tdb, sysjob_to_jobid_traverse_fn, &state); release_print_db(pdb); - if (state.sysjob_to_jobid_value != (uint32)-1) - return state.sysjob_to_jobid_value; + if (state.jobid != (uint32_t)-1) + return state.jobid; } return (uint32)-1; } +/* find sysjob based on spoolss jobid */ +static int jobid_to_sysjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, + TDB_DATA data, void *private_data) +{ + struct printjob *pjob; + struct job_traverse_state *state = + (struct job_traverse_state *)private_data; + + if (!data.dptr || data.dsize == 0) + return 0; + + pjob = (struct printjob *)data.dptr; + if (key.dsize != sizeof(uint32_t)) + return 0; + + if (state->jobid == pjob->jobid) { + state->sysjob = pjob->sysjob; + return 1; + } + + return 0; +} + +int jobid_to_sysjob_pdb(struct tdb_print_db *pdb, uint32_t jobid) +{ + struct job_traverse_state state; + + state.sysjob = -1; + state.jobid = jobid; + + tdb_traverse(pdb->tdb, jobid_to_sysjob_traverse_fn, &state); + + return state.sysjob; +} + /**************************************************************************** Send notifications based on what has changed after a pjob_store. ****************************************************************************/ -- 1.8.4.5 From aad2ce1737dad57c852ad721d9e7d2142f3aff39 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:47 +0100 Subject: [PATCH 2/6] spoolss: fix GetJob jobid lookups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clients issue GetJob requests using the jobid assigned by the spoolss server. The corresponding printing backend (sysjob) identifier needs to be resolved to locate the correct print queue entry. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10905 Reported-by: Franz Pförtsch Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 3a28ae56977235d3c9e3abcd1f24b220e536c50d) --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 37 +++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index 335647b..55f0a84 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -9337,13 +9337,14 @@ static WERROR getjob_level_1(TALLOC_CTX *mem_ctx, int count, int snum, struct spoolss_PrinterInfo2 *pinfo2, uint32_t jobid, + int sysjob, struct spoolss_JobInfo1 *r) { int i = 0; bool found = false; for (i=0; imem_ctx, get_session_info_system(), p->msg_ctx, - lp_const_servicename(snum), + svc_name, &pinfo2); if (!W_ERROR_IS_OK(result)) { return result; } + pdb = get_print_db_byname(svc_name); + if (pdb == NULL) { + DEBUG(3, ("failed to get print db for svc %s\n", svc_name)); + TALLOC_FREE(pinfo2); + return WERR_INVALID_PARAM; + } + + sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id); + release_print_db(pdb); + if (sysjob == -1) { + DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id)); + TALLOC_FREE(pinfo2); + return WERR_INVALID_PARAM; + } + count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status); DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n", @@ -9462,12 +9487,14 @@ WERROR _spoolss_GetJob(struct pipes_struct *p, case 1: result = getjob_level_1(p->mem_ctx, queue, count, snum, pinfo2, - r->in.job_id, &r->out.info->info1); + r->in.job_id, sysjob, + &r->out.info->info1); break; case 2: result = getjob_level_2(p->mem_ctx, queue, count, snum, pinfo2, - r->in.job_id, &r->out.info->info2); + r->in.job_id, sysjob, + &r->out.info->info2); break; default: result = WERR_UNKNOWN_LEVEL; -- 1.8.4.5 From 47c734126fb06758228c1974b90842d9689f7dfa Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:48 +0100 Subject: [PATCH 3/6] spoolss: fix jobid in level 1 GetJob and EnumJobs responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now, these responses have incorrectly carried the printing backend job identifier (sysjob), rather than the one allocated and returned by Samba on job submission. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10905 Reported-by: Franz Pförtsch Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 4d7f5d2af6ef6960dccaccf89c6e88947e2591bf) --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 48 +++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index 55f0a84..914688b 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -7052,6 +7052,7 @@ fill_job_info1 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx, struct spoolss_JobInfo1 *r, const print_queue_struct *queue, + uint32_t jobid, int position, int snum, struct spoolss_PrinterInfo2 *pinfo2) { @@ -7059,7 +7060,7 @@ static WERROR fill_job_info1(TALLOC_CTX *mem_ctx, t = gmtime(&queue->time); - r->job_id = queue->sysjob; + r->job_id = jobid; r->printer_name = lp_servicename(mem_ctx, snum); W_ERROR_HAVE_NO_MEMORY(r->printer_name); @@ -7177,34 +7178,56 @@ static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx, union spoolss_JobInfo *info; int i; WERROR result = WERR_OK; + uint32_t num_filled; + struct tdb_print_db *pdb; info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues); - W_ERROR_HAVE_NO_MEMORY(info); + if (info == NULL) { + result = WERR_NOMEM; + goto err_out; + } - *count = num_queues; + pdb = get_print_db_byname(pinfo2->sharename); + if (pdb == NULL) { + result = WERR_INVALID_PARAM; + goto err_info_free; + } + + num_filled = 0; + for (i = 0; i < num_queues; i++) { + uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob); + if (jobid == (uint32_t)-1) { + DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob)); + continue; + } - for (i=0; i<*count; i++) { result = fill_job_info1(info, - &info[i].info1, + &info[num_filled].info1, &queue[i], + jobid, i, snum, pinfo2); if (!W_ERROR_IS_OK(result)) { - goto out; + goto err_pdb_drop; } - } - out: - if (!W_ERROR_IS_OK(result)) { - TALLOC_FREE(info); - *count = 0; - return result; + num_filled++; } + release_print_db(pdb); *info_p = info; + *count = num_filled; return WERR_OK; + +err_pdb_drop: + release_print_db(pdb); +err_info_free: + TALLOC_FREE(info); +err_out: + *count = 0; + return result; } /**************************************************************************** @@ -9358,6 +9381,7 @@ static WERROR getjob_level_1(TALLOC_CTX *mem_ctx, return fill_job_info1(mem_ctx, r, &queue[i], + jobid, i, snum, pinfo2); -- 1.8.4.5 From 3ba4c7410a12882840d5aae116688a431455c4ed Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:49 +0100 Subject: [PATCH 4/6] spoolss: fix jobid in level 2 GetJob and EnumJobs responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now, these responses have incorrectly carried the printing backend job identifier (sysjob), rather than the one allocated and returned by Samba on job submission. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10905 Reported-by: Franz Pförtsch Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 45abaf81c67b62bab571df208931241afa660802) --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 50 +++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index 914688b..434d955 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -7093,6 +7093,7 @@ fill_job_info2 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx, struct spoolss_JobInfo2 *r, const print_queue_struct *queue, + uint32_t jobid, int position, int snum, struct spoolss_PrinterInfo2 *pinfo2, struct spoolss_DeviceMode *devmode) @@ -7101,7 +7102,7 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx, t = gmtime(&queue->time); - r->job_id = queue->sysjob; + r->job_id = jobid; r->printer_name = lp_servicename(mem_ctx, snum); W_ERROR_HAVE_NO_MEMORY(r->printer_name); @@ -7244,45 +7245,65 @@ static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx, union spoolss_JobInfo *info; int i; WERROR result = WERR_OK; + uint32_t num_filled; + struct tdb_print_db *pdb; info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues); - W_ERROR_HAVE_NO_MEMORY(info); + if (info == NULL) { + result = WERR_NOMEM; + goto err_out; + } - *count = num_queues; + pdb = get_print_db_byname(pinfo2->sharename); + if (pdb == NULL) { + result = WERR_INVALID_PARAM; + goto err_info_free; + } - for (i=0; i<*count; i++) { + num_filled = 0; + for (i = 0; i< num_queues; i++) { struct spoolss_DeviceMode *devmode; + uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob); + if (jobid == (uint32_t)-1) { + DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob)); + continue; + } result = spoolss_create_default_devmode(info, pinfo2->printername, &devmode); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Can't proceed w/o a devmode!")); - goto out; + goto err_pdb_drop; } result = fill_job_info2(info, - &info[i].info2, + &info[num_filled].info2, &queue[i], + jobid, i, snum, pinfo2, devmode); if (!W_ERROR_IS_OK(result)) { - goto out; + goto err_pdb_drop; } + num_filled++; } - out: - if (!W_ERROR_IS_OK(result)) { - TALLOC_FREE(info); - *count = 0; - return result; - } - + release_print_db(pdb); *info_p = info; + *count = num_filled; return WERR_OK; + +err_pdb_drop: + release_print_db(pdb); +err_info_free: + TALLOC_FREE(info); +err_out: + *count = 0; + return result; } /**************************************************************************** @@ -9436,6 +9457,7 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx, return fill_job_info2(mem_ctx, r, &queue[i], + jobid, i, snum, pinfo2, -- 1.8.4.5 From 77609af0eaf46f5f4f35a6b3674f514a4d1bb15c Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:50 +0100 Subject: [PATCH 5/6] spoolss: fix jobid in level 3 EnumJobs response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now, these responses have incorrectly carried the printing backend job identifier (sysjob), rather than the one allocated and returned by Samba on job submission. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10905 Reported-by: Franz Pförtsch Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit 5e7ab3d2f4f7950099561eb22d6a9a1536297442) --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 56 +++++++++++++++++------------ 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index 434d955..113a9f0 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -7320,41 +7320,51 @@ static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx, union spoolss_JobInfo *info; int i; WERROR result = WERR_OK; + uint32_t num_filled; + struct tdb_print_db *pdb; info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues); - W_ERROR_HAVE_NO_MEMORY(info); - - *count = num_queues; + if (info == NULL) { + result = WERR_NOMEM; + goto err_out; + } - for (i=0; i<*count; i++) { - const print_queue_struct *next_queue = NULL; + pdb = get_print_db_byname(pinfo2->sharename); + if (pdb == NULL) { + result = WERR_INVALID_PARAM; + goto err_info_free; + } - if (i+1 < *count) { - next_queue = &queue[i+1]; + num_filled = 0; + for (i = 0; i < num_queues; i++) { + uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob); + if (jobid == (uint32_t)-1) { + DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob)); + continue; } - result = fill_job_info3(info, - &info[i].info3, - &queue[i], - next_queue, - i, - snum, - pinfo2); - if (!W_ERROR_IS_OK(result)) { - goto out; - } - } + info[num_filled].info3.job_id = jobid; + /* next_job_id is overwritten on next iteration */ + info[num_filled].info3.next_job_id = 0; + info[num_filled].info3.reserved = 0; - out: - if (!W_ERROR_IS_OK(result)) { - TALLOC_FREE(info); - *count = 0; - return result; + if (num_filled > 0) { + info[num_filled - 1].info3.next_job_id = jobid; + } + num_filled++; } + release_print_db(pdb); *info_p = info; + *count = num_filled; return WERR_OK; + +err_info_free: + TALLOC_FREE(info); +err_out: + *count = 0; + return result; } /**************************************************************** -- 1.8.4.5 From 030585d932b9c0b0fee8b677eebd0a1e751cd388 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Oct 2014 01:37:51 +0100 Subject: [PATCH 6/6] spoolss: remove unused fill_job_info3() This logic has been moved into the previous EnumJobs(level=3) caller. The info3 structure only contains two fields that are used, so it doesn't make sense to have a separate helper for it. Signed-off-by: David Disseldorp Reviewed-by: Jeremy Allison (cherry picked from commit d772b98283f289917a6a8370808d4d0912899384) --- source3/rpc_server/spoolss/srv_spoolss_nt.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index 113a9f0..e1292ee 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -7145,27 +7145,6 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx, } /**************************************************************************** -fill_job_info3 -****************************************************************************/ - -static WERROR fill_job_info3(TALLOC_CTX *mem_ctx, - struct spoolss_JobInfo3 *r, - const print_queue_struct *queue, - const print_queue_struct *next_queue, - int position, int snum, - struct spoolss_PrinterInfo2 *pinfo2) -{ - r->job_id = queue->sysjob; - r->next_job_id = 0; - if (next_queue) { - r->next_job_id = next_queue->sysjob; - } - r->reserved = 0; - - return WERR_OK; -} - -/**************************************************************************** Enumjobs at level 1. ****************************************************************************/ -- 1.8.4.5