spoolss: clear JobInfo on GetJob error
[obnox/samba/samba-obnox.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
index 552d4cb8b75c27c6abb71b30aae1f6a91e928cb2..c71eb911097f84292dd434ed73395943cd7e5f22 100644 (file)
@@ -4902,7 +4902,8 @@ static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
                                                  const char *arch,
                                                  int version)
 {
-       int i, num_strings = 0;
+       int i;
+       size_t num_strings = 0;
        const char **array = NULL;
 
        if (string_array == NULL) {
@@ -7057,6 +7058,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)
 {
@@ -7064,7 +7066,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);
@@ -7097,6 +7099,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)
@@ -7105,7 +7108,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);
@@ -7147,27 +7150,6 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
-/****************************************************************************
-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.
 ****************************************************************************/
@@ -7182,34 +7164,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;
+       }
+
+       pdb = get_print_db_byname(pinfo2->sharename);
+       if (pdb == NULL) {
+               result = WERR_INVALID_PARAM;
+               goto err_info_free;
+       }
 
-       *count = num_queues;
+       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;
 }
 
 /****************************************************************************
@@ -7226,45 +7230,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;
 }
 
 /****************************************************************************
@@ -7281,41 +7305,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;
 }
 
 /****************************************************************
@@ -9347,13 +9381,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; i<count; i++) {
-               if (queue[i].sysjob == (int)jobid) {
+               if (queue[i].sysjob == sysjob) {
                        found = true;
                        break;
                }
@@ -9367,6 +9402,7 @@ static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
        return fill_job_info1(mem_ctx,
                              r,
                              &queue[i],
+                             jobid,
                              i,
                              snum,
                              pinfo2);
@@ -9380,6 +9416,7 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
                             int count, int snum,
                             struct spoolss_PrinterInfo2 *pinfo2,
                             uint32_t jobid,
+                            int sysjob,
                             struct spoolss_JobInfo2 *r)
 {
        int i = 0;
@@ -9388,7 +9425,7 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
        WERROR result;
 
        for (i=0; i<count; i++) {
-               if (queue[i].sysjob == (int)jobid) {
+               if (queue[i].sysjob == sysjob) {
                        found = true;
                        break;
                }
@@ -9420,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,
@@ -9435,15 +9473,19 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
 {
        WERROR result = WERR_OK;
        struct spoolss_PrinterInfo2 *pinfo2 = NULL;
+       const char *svc_name;
+       int sysjob;
        int snum;
        int count;
+       struct tdb_print_db *pdb;
        print_queue_struct      *queue = NULL;
        print_status_struct prt_status;
 
        /* that's an [in out] buffer */
 
        if (!r->in.buffer && (r->in.offered != 0)) {
-               return WERR_INVALID_PARAM;
+               result = WERR_INVALID_PARAM;
+               goto err_jinfo_free;
        }
 
        DEBUG(5,("_spoolss_GetJob\n"));
@@ -9451,16 +9493,38 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
        *r->out.needed = 0;
 
        if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-               return WERR_BADFID;
+               result = WERR_BADFID;
+               goto err_jinfo_free;
+       }
+
+       svc_name = lp_const_servicename(snum);
+       if (svc_name == NULL) {
+               result = WERR_INVALID_PARAM;
+               goto err_jinfo_free;
        }
 
        result = winreg_get_printer_internal(p->mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
-                                   lp_const_servicename(snum),
+                                   svc_name,
                                    &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
-               return result;
+               goto err_jinfo_free;
+       }
+
+       pdb = get_print_db_byname(svc_name);
+       if (pdb == NULL) {
+               DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
+               result = WERR_INVALID_PARAM;
+               goto err_pinfo_free;
+       }
+
+       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));
+               result = WERR_INVALID_PARAM;
+               goto err_pinfo_free;
        }
 
        count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
@@ -9472,12 +9536,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;
@@ -9488,8 +9554,7 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
        TALLOC_FREE(pinfo2);
 
        if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(r->out.info);
-               return result;
+               goto err_jinfo_free;
        }
 
        *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
@@ -9497,6 +9562,12 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
        r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
 
        return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+
+err_pinfo_free:
+       TALLOC_FREE(pinfo2);
+err_jinfo_free:
+       TALLOC_FREE(r->out.info);
+       return result;
 }
 
 /****************************************************************