Gone back to explicit queue number passing as snum - removed encoding of
[tprouty/samba.git] / source / printing / printing.c
index f8dfea0a126bc07d078e9e709e57afe5fd21cfcd..9b0e8cdfb0aae849a759534f751a2874a401f591 100644 (file)
@@ -47,10 +47,11 @@ static struct printif *current_printif = &generic_printif;
 static TDB_CONTEXT *rap_tdb;
 static uint16 next_rap_jobid;
 
-uint16 pjobid_to_rap(uint32 jobid)
+uint16 pjobid_to_rap(int snum, uint32 jobid)
 {
        uint16 rap_jobid;
        TDB_DATA data, key;
+       char jinfo[8];
 
        if (!rap_tdb) {
                /* Create the in-memory tdb. */
@@ -59,8 +60,11 @@ uint16 pjobid_to_rap(uint32 jobid)
                        return 0;
        }
 
-       key.dptr = (char *)&jobid;
-       key.dsize = sizeof(jobid);
+       SIVAL(&jinfo,0,(int32)snum);
+       SIVAL(&jinfo,4,jobid);
+
+       key.dptr = (char *)&jinfo;
+       key.dsize = sizeof(jinfo);
        data = tdb_fetch(rap_tdb, key);
        if (data.dptr && data.dsize == sizeof(uint16)) {
                memcpy(&rap_jobid, data.dptr, sizeof(uint16));
@@ -78,33 +82,40 @@ uint16 pjobid_to_rap(uint32 jobid)
        return rap_jobid;
 }
 
-uint32 rap_to_pjobid(uint16 rap_jobid)
+BOOL rap_to_pjobid(uint16 rap_jobid, int *psnum, uint32 *pjobid)
 {
        TDB_DATA data, key;
-       uint32 jobid = 0;
+       char jinfo[8];
 
        if (!rap_tdb)
-               return 0;
+               return False;
 
        key.dptr = (char *)&rap_jobid;
        key.dsize = sizeof(rap_jobid);
        data = tdb_fetch(rap_tdb, key);
-       if (data.dptr && data.dsize == sizeof(uint32)) {
-               memcpy(&jobid, data.dptr, sizeof(uint32));
+       if (data.dptr && data.dsize == sizeof(jinfo)) {
+               *psnum = IVAL(&jinfo,0);
+               *pjobid = IVAL(&jinfo,4);
                SAFE_FREE(data.dptr);
+               return True;
        }
-       return jobid;
+       return False;
 }
 
-static void rap_jobid_delete(uint32 jobid)
+static void rap_jobid_delete(int snum, uint32 jobid)
 {
        TDB_DATA key, data;
        uint16 rap_jobid;
+       char jinfo[8];
 
        if (!rap_tdb)
                return;
-       key.dptr = (char *)&jobid;
-       key.dsize = sizeof(jobid);
+
+       SIVAL(&jinfo,0,(int32)snum);
+       SIVAL(&jinfo,4,jobid);
+
+       key.dptr = (char *)&jinfo;
+       key.dsize = sizeof(jinfo);
        data = tdb_fetch(rap_tdb, key);
        if (!data.dptr || (data.dsize != sizeof(uint16)))
                return;
@@ -119,96 +130,6 @@ static void rap_jobid_delete(uint32 jobid)
 
 static pid_t local_pid;
 
-/* Mapping between printer names and queue id's in job id's. */
-struct printer_queueid_map {
-       struct printer_queueid_map *next, *prev;
-       char *printername;
-       uint32 queueid;
-};
-
-static struct printer_queueid_map *printer_queueid_map_head;
-static uint32 last_queueid;
-
-#define QUEUEID_BITS 12
-#define QUEUEID_MASK ((1<<(QUEUEID_BITS))-1)
-#define QUEUEID_TO_JOBID(queueid) (((queueid) & QUEUEID_MASK) << 20 )
-
-/****************************************************************************
- Create an association between a printer name and a queueid. Used to encode
- the printer queueid in jobid's.
- This could be converted to use an internal tdb if searching the list is
- too slow. JRA.
-****************************************************************************/
-
-BOOL create_printer_queueid(const char *printername)
-{
-       struct printer_queueid_map *p;
-
-       for (p = printer_queueid_map_head; p; p = p->next) {
-               if (strequal(p->printername, printername))
-                       return True;
-       }
-
-       p = (struct printer_queueid_map *)malloc(sizeof(*p));
-       if (!p) {
-               DEBUG(0,("create_printer_queueid: malloc fail !\n"));
-               return False;
-       }
-       ZERO_STRUCTP(p);
-       p->printername = strdup(printername);
-       if (!p->printername) {
-               DEBUG(0,("create_printer_queueid: malloc fail !\n"));
-               SAFE_FREE(p);
-               return False;
-       }
-       p->queueid = (++last_queueid);
-       if (p->queueid > QUEUEID_MASK) {
-               DEBUG(0,("create_printer_queueid: malloc fail !\n"));
-               SAFE_FREE(p->printername);
-               SAFE_FREE(p);
-               return False;
-       }
-       DLIST_ADD(printer_queueid_map_head, p);
-       return True;
-}
-
-void set_register_printer_fn(void)
-{
-       extern BOOL (*register_printer_fn)(const char *);
-       register_printer_fn = create_printer_queueid;
-}
-
-/****************************************************************************
- Lookups.
-****************************************************************************/
-
-static uint32 get_printer_queueid_byname(const char *printername)
-{
-       struct printer_queueid_map *p;
-
-       for (p = printer_queueid_map_head; p; p = p->next) {
-               if (strequal(p->printername, printername))
-                       return p->queueid;
-       }
-       return 0;
-}
-
-/****************************************************************************
- Lookups.
-****************************************************************************/
-
-static const char *get_printer_name_byjobid(uint32 jobid)
-{
-       struct printer_queueid_map *p;
-       uint32 queueid = (((jobid)>>20) & QUEUEID_MASK);
-
-       for (p = printer_queueid_map_head; p; p = p->next) {
-               if (p->queueid == queueid)
-                       return p->printername;
-       }
-       return NULL;
-}
-
 static int get_queue_status(int, print_status_struct *);
 
 #define MAX_PRINT_DBS_OPEN 1
@@ -279,14 +200,6 @@ static struct tdb_print_db *get_print_db_byname(const char *printername)
        return p;
 }
 
-static struct tdb_print_db *get_print_db_byjobid( uint32 jobid)
-{
-       const char *printername = get_printer_name_byjobid(jobid);
-       if (!printername)
-               return NULL;
-       return get_print_db_byname(printername);
-}
-
 /****************************************************************************
  Initialise the printing backend. Called once at startup. 
  Does not survive a fork
@@ -294,9 +207,10 @@ static struct tdb_print_db *get_print_db_byjobid( uint32 jobid)
 
 BOOL print_backend_init(void)
 {
-       struct printer_queueid_map *p;
        char *sversion = "INFO/version";
        pstring printing_path;
+       int services = lp_numservices();
+       int snum;
 
        if (local_pid == sys_getpid())
                return True;
@@ -309,9 +223,12 @@ BOOL print_backend_init(void)
 
        /* handle a Samba upgrade */
 
-       for (p = printer_queueid_map_head; p; p = p->next) {
-               struct tdb_print_db *pdb = get_print_db_byname(p->printername);
+       for (snum = 0; snum < services; snum++) {
+               struct tdb_print_db *pdb;
+               if (!lp_print_ok(snum))
+                       continue;
 
+               pdb = get_print_db_byname(lp_const_servicename(snum));
                if (!pdb)
                        continue;
                tdb_lock_bystring(pdb->tdb, sversion);
@@ -369,11 +286,11 @@ static TDB_DATA print_key(uint32 jobid)
  Useful function to find a print job in the database.
 ****************************************************************************/
 
-static struct printjob *print_job_find(uint32 jobid)
+static struct printjob *print_job_find(int snum, uint32 jobid)
 {
        static struct printjob pjob;
        TDB_DATA ret;
-       struct tdb_print_db *pdb = get_print_db_byjobid(jobid);
+       struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
 
        if (!pdb)
                return NULL;
@@ -417,11 +334,16 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
 
 uint32 sysjob_to_jobid(int unix_jobid)
 {
-       struct printer_queueid_map *p;
+       int services = lp_numservices();
+       int snum;
+
        sysjob_to_jobid_value = (uint32)-1;
 
-       for (p = printer_queueid_map_head; p; p = p->next) {
-               struct tdb_print_db *pdb = get_print_db_byname(p->printername);
+       for (snum = 0; snum < services; snum++) {
+               struct tdb_print_db *pdb;
+               if (!lp_print_ok(snum))
+                       continue;
+               pdb = get_print_db_byname(lp_const_servicename(snum));
                if (pdb)
                        tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);
                if (sysjob_to_jobid_value != (uint32)-1)
@@ -468,14 +390,10 @@ static uint32 map_to_spoolss_status(uint32 lpq_status)
        return 0;
 }
 
-static void pjob_store_notify(uint32 jobid, struct printjob *old_data,
+static void pjob_store_notify(int snum, uint32 jobid, struct printjob *old_data,
                              struct printjob *new_data)
 {
        BOOL new_job = False;
-       int snum = print_job_snum(jobid);
-
-       if (snum == -1)
-               return;
 
        if (!old_data)
                new_job = True;
@@ -510,11 +428,11 @@ static void pjob_store_notify(uint32 jobid, struct printjob *old_data,
  Store a job structure back to the database.
 ****************************************************************************/
 
-static BOOL pjob_store(uint32 jobid, struct printjob *pjob)
+static BOOL pjob_store(int snum, uint32 jobid, struct printjob *pjob)
 {
        TDB_DATA old_data, new_data;
        BOOL ret;
-       struct tdb_print_db *pdb = get_print_db_byjobid(jobid);
+       struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
 
        if (!pdb)
                return False;
@@ -533,7 +451,7 @@ static BOOL pjob_store(uint32 jobid, struct printjob *pjob)
 
        if (ret && (old_data.dsize == 0 || old_data.dsize == sizeof(*pjob))) {
                pjob_store_notify(
-                       jobid, (struct printjob *)old_data.dptr,
+                       snum, jobid, (struct printjob *)old_data.dptr,
                        (struct printjob *)new_data.dptr);
                free(old_data.dptr);
        }
@@ -545,12 +463,11 @@ static BOOL pjob_store(uint32 jobid, struct printjob *pjob)
  Remove a job structure from the database.
 ****************************************************************************/
 
-static void pjob_delete(uint32 jobid)
+static void pjob_delete(int snum, uint32 jobid)
 {
-       int snum;
-       struct printjob *pjob = print_job_find(jobid);
+       struct printjob *pjob = print_job_find(snum, jobid);
        uint32 job_status = 0;
-       struct tdb_print_db *pdb = get_print_db_byjobid(jobid);
+       struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
 
        if (!pdb)
                return;
@@ -569,7 +486,6 @@ static void pjob_delete(uint32 jobid)
            JOB_STATUS_DELETED for the port monitor to delete the job
            properly. */
        
-       snum = print_job_snum(jobid);
        job_status |= JOB_STATUS_DELETING;
        notify_job_status(snum, jobid, job_status);
        
@@ -579,7 +495,7 @@ static void pjob_delete(uint32 jobid)
        /* Remove from printing.tdb */
 
        tdb_delete(pdb->tdb, print_key(jobid));
-       rap_jobid_delete(jobid);
+       rap_jobid_delete(snum, jobid);
 }
 
 /****************************************************************************
@@ -607,13 +523,12 @@ static uint32 print_parse_jobid(char *fname)
 
 static void print_unix_job(int snum, print_queue_struct *q)
 {
-       uint32 queueid = get_printer_queueid_byname(PRINTERNAME(snum));
-       uint32 jobid = (q->job + UNIX_JOB_START) | QUEUEID_TO_JOBID(queueid);
+       uint32 jobid = q->job + UNIX_JOB_START;
        struct printjob pj, *old_pj;
 
        /* Preserve the timestamp on an existing unix print job */
 
-       old_pj = print_job_find(jobid);
+       old_pj = print_job_find(snum, jobid);
 
        ZERO_STRUCT(pj);
 
@@ -630,7 +545,7 @@ static void print_unix_job(int snum, print_queue_struct *q)
        fstrcpy(pj.user, q->fs_user);
        fstrcpy(pj.queuename, lp_const_servicename(snum));
 
-       pjob_store(jobid, &pj);
+       pjob_store(snum, jobid, &pj);
 }
 
 
@@ -645,7 +560,6 @@ struct traverse_struct {
 
 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
 {
-       uint32 queueid;
        struct traverse_struct *ts = (struct traverse_struct *)state;
        struct printjob pjob;
        uint32 jobid;
@@ -661,18 +575,16 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
                return 0;
        }
 
-       queueid = get_printer_queueid_byname(pjob.queuename);
-
        if (!pjob.smbjob) {
                /* remove a unix job if it isn't in the system queue any more */
 
                for (i=0;i<ts->qcount;i++) {
-                       uint32 u_jobid = ((ts->queue[i].job + UNIX_JOB_START) | QUEUEID_TO_JOBID(queueid));
+                       uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
                        if (jobid == u_jobid)
                                break;
                }
                if (i == ts->qcount)
-                       pjob_delete(jobid);
+                       pjob_delete(ts->snum, jobid);
                else
                        ts->total_jobs++;
                return 0;
@@ -684,14 +596,14 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
                    exist then kill it. This cleans up after smbd
                    deaths */
                if (!process_exists(pjob.pid))
-                       pjob_delete(jobid);
+                       pjob_delete(ts->snum, jobid);
                else
                        ts->total_jobs++;
                return 0;
        }
 
        for (i=0;i<ts->qcount;i++) {
-               uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file) | QUEUEID_TO_JOBID(queueid);
+               uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
                if (jobid == curr_jobid)
                        break;
        }
@@ -711,7 +623,7 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
                   submitted less than lp_lpqcachetime() seconds ago. */
 
                if ((cur_t - pjob.starttime) > lp_lpqcachetime())
-                       pjob_delete(jobid);
+                       pjob_delete(ts->snum, jobid);
                else
                        ts->total_jobs++;
        }
@@ -772,7 +684,7 @@ static pid_t get_updating_pid(fstring printer_name)
  in the tdb.
 ****************************************************************************/
 
-static void set_updating_pid(fstring printer_name, BOOL delete)
+static void set_updating_pid(const fstring printer_name, BOOL delete)
 {
        fstring keystr;
        TDB_DATA key;
@@ -897,7 +809,7 @@ static void print_queue_update(int snum)
                }
 
                /* we have an active SMB print job - update its status */
-               pjob = print_job_find(jobid);
+               pjob = print_job_find(snum, jobid);
                if (!pjob) {
                        /* err, somethings wrong. Probably smbd was restarted
                           with jobs in the queue. All we can do is treat them
@@ -909,7 +821,7 @@ static void print_queue_update(int snum)
                pjob->sysjob = queue[i].job;
                pjob->status = queue[i].status;
 
-               pjob_store(jobid, pjob);
+               pjob_store(snum, jobid, pjob);
        }
 
        /* now delete any queued entries that don't appear in the
@@ -955,36 +867,21 @@ static void print_queue_update(int snum)
  Check if a jobid is valid. It is valid if it exists in the database.
 ****************************************************************************/
 
-BOOL print_job_exists(uint32 jobid)
+BOOL print_job_exists(int snum, uint32 jobid)
 {
-       struct tdb_print_db *pdb = get_print_db_byjobid(jobid);
+       struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
        if (!pdb)
                return False;
        return tdb_exists(pdb->tdb, print_key(jobid));
 }
 
-/****************************************************************************
- Work out which service a jobid is for.
- Note that we have to look up by queue name to ensure that it works for 
- other than the process that started the job.
-****************************************************************************/
-
-int print_job_snum(uint32 jobid)
-{
-       struct printjob *pjob = print_job_find(jobid);
-       if (!pjob)
-               return -1;
-
-       return find_service(pjob->queuename);
-}
-
 /****************************************************************************
  Give the fd used for a jobid.
 ****************************************************************************/
 
-int print_job_fd(uint32 jobid)
+int print_job_fd(int snum, uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(jobid);
+       struct printjob *pjob = print_job_find(snum, jobid);
        if (!pjob)
                return -1;
        /* don't allow another process to get this info - it is meaningless */
@@ -999,9 +896,9 @@ int print_job_fd(uint32 jobid)
  has not been spooled.
 ****************************************************************************/
 
-char *print_job_fname(uint32 jobid)
+char *print_job_fname(int snum, uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(jobid);
+       struct printjob *pjob = print_job_find(snum, jobid);
        if (!pjob || pjob->spooled || pjob->pid != local_pid)
                return NULL;
        return pjob->filename;
@@ -1011,7 +908,7 @@ char *print_job_fname(uint32 jobid)
  Set the place in the queue for a job.
 ****************************************************************************/
 
-BOOL print_job_set_place(uint32 jobid, int place)
+BOOL print_job_set_place(int snum, uint32 jobid, int place)
 {
        DEBUG(2,("print_job_set_place not implemented yet\n"));
        return False;
@@ -1021,24 +918,24 @@ BOOL print_job_set_place(uint32 jobid, int place)
  Set the name of a job. Only possible for owner.
 ****************************************************************************/
 
-BOOL print_job_set_name(uint32 jobid, char *name)
+BOOL print_job_set_name(int snum, uint32 jobid, char *name)
 {
-       struct printjob *pjob = print_job_find(jobid);
+       struct printjob *pjob = print_job_find(snum, jobid);
        if (!pjob || pjob->pid != local_pid)
                return False;
 
        fstrcpy(pjob->jobname, name);
-       return pjob_store(jobid, pjob);
+       return pjob_store(snum, jobid, pjob);
 }
 
 /****************************************************************************
  Delete a print job - don't update queue.
 ****************************************************************************/
 
-static BOOL print_job_delete1(uint32 jobid)
+static BOOL print_job_delete1(int snum, uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(jobid);
-       int snum, result = 0;
+       struct printjob *pjob = print_job_find(snum, jobid);
+       int result = 0;
 
        if (!pjob)
                return False;
@@ -1050,12 +947,6 @@ static BOOL print_job_delete1(uint32 jobid)
        if (pjob->status == LPQ_DELETING)
                return True;
 
-       snum = print_job_snum(jobid);
-       if (snum == -1) {
-               DEBUG(5,("print_job_delete1: unknown service number for jobid %u\n", (unsigned int)jobid));
-               return False;
-       }
-
        /* Hrm - we need to be able to cope with deleting a job before it
           has reached the spooler. */
 
@@ -1066,7 +957,7 @@ static BOOL print_job_delete1(uint32 jobid)
        /* Set the tdb entry to be deleting. */
 
        pjob->status = LPQ_DELETING;
-       pjob_store(jobid, pjob);
+       pjob_store(snum, jobid, pjob);
 
        if (pjob->spooled && pjob->sysjob != -1)
                result = (*(current_printif->job_delete))(snum, pjob);
@@ -1075,7 +966,7 @@ static BOOL print_job_delete1(uint32 jobid)
           been spooled. */
 
        if (result == 0)
-               pjob_delete(jobid);
+               pjob_delete(snum, jobid);
 
        return (result == 0);
 }
@@ -1084,9 +975,9 @@ static BOOL print_job_delete1(uint32 jobid)
  Return true if the current user owns the print job.
 ****************************************************************************/
 
-static BOOL is_owner(struct current_user *user, uint32 jobid)
+static BOOL is_owner(struct current_user *user, int snum, uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(jobid);
+       struct printjob *pjob = print_job_find(snum, jobid);
        user_struct *vuser;
 
        if (!pjob || !user)
@@ -1103,17 +994,11 @@ static BOOL is_owner(struct current_user *user, uint32 jobid)
  Delete a print job.
 ****************************************************************************/
 
-BOOL print_job_delete(struct current_user *user, uint32 jobid, WERROR *errcode)
+BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
 {
-       int snum = print_job_snum(jobid);
        BOOL owner;
 
-       if (snum == -1) {
-               DEBUG(5,("print_job_delete: unknown service number for jobid %d\n", jobid));
-               return False;
-       }
-
-       owner = is_owner(user, jobid);
+       owner = is_owner(user, snum, jobid);
        
        /* Check access against security descriptor or whether the user
           owns their job. */
@@ -1125,7 +1010,7 @@ BOOL print_job_delete(struct current_user *user, uint32 jobid, WERROR *errcode)
                return False;
        }
 
-       if (!print_job_delete1(jobid)) 
+       if (!print_job_delete1(snum, jobid)) 
                return False;
 
        /* force update the database and say the delete failed if the
@@ -1133,17 +1018,17 @@ BOOL print_job_delete(struct current_user *user, uint32 jobid, WERROR *errcode)
 
        print_queue_update(snum);
 
-       return !print_job_exists(jobid);
+       return !print_job_exists(snum, jobid);
 }
 
 /****************************************************************************
  Pause a job.
 ****************************************************************************/
 
-BOOL print_job_pause(struct current_user *user, uint32 jobid, WERROR *errcode)
+BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
 {
-       struct printjob *pjob = print_job_find(jobid);
-       int snum, ret = -1;
+       struct printjob *pjob = print_job_find(snum, jobid);
+       int ret = -1;
        
        if (!pjob || !user) 
                return False;
@@ -1151,13 +1036,7 @@ BOOL print_job_pause(struct current_user *user, uint32 jobid, WERROR *errcode)
        if (!pjob->spooled || pjob->sysjob == -1) 
                return False;
 
-       snum = print_job_snum(jobid);
-       if (snum == -1) {
-               DEBUG(5,("print_job_pause: unknown service number for jobid %u\n", (unsigned int)jobid));
-               return False;
-       }
-
-       if (!is_owner(user, jobid) &&
+       if (!is_owner(user, snum, jobid) &&
            !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
                DEBUG(3, ("pause denied by security descriptor\n"));
                *errcode = WERR_ACCESS_DENIED;
@@ -1188,10 +1067,10 @@ BOOL print_job_pause(struct current_user *user, uint32 jobid, WERROR *errcode)
  Resume a job.
 ****************************************************************************/
 
-BOOL print_job_resume(struct current_user *user, uint32 jobid, WERROR *errcode)
+BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
 {
-       struct printjob *pjob = print_job_find(jobid);
-       int snum, ret;
+       struct printjob *pjob = print_job_find(snum, jobid);
+       int ret;
        
        if (!pjob || !user)
                return False;
@@ -1199,13 +1078,7 @@ BOOL print_job_resume(struct current_user *user, uint32 jobid, WERROR *errcode)
        if (!pjob->spooled || pjob->sysjob == -1)
                return False;
 
-       snum = print_job_snum(jobid);
-       if (snum == -1) {
-               DEBUG(5,("print_job_resume: unknown service number for jobid %u\n", (unsigned int)jobid));
-               return False;
-       }
-
-       if (!is_owner(user, jobid) &&
+       if (!is_owner(user, snum, jobid) &&
            !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
                DEBUG(3, ("resume denied by security descriptor\n"));
                *errcode = WERR_ACCESS_DENIED;
@@ -1233,10 +1106,10 @@ BOOL print_job_resume(struct current_user *user, uint32 jobid, WERROR *errcode)
  Write to a print file.
 ****************************************************************************/
 
-int print_job_write(uint32 jobid, const char *buf, int size)
+int print_job_write(int snum, uint32 jobid, const char *buf, int size)
 {
        int return_code;
-       struct printjob *pjob = print_job_find(jobid);
+       struct printjob *pjob = print_job_find(snum, jobid);
 
        if (!pjob)
                return -1;
@@ -1247,7 +1120,7 @@ int print_job_write(uint32 jobid, const char *buf, int size)
        return_code = write(pjob->fd, buf, size);
        if (return_code>0) {
                pjob->size += size;
-               pjob_store(jobid, pjob);
+               pjob_store(snum, jobid, pjob);
        }
        return return_code;
 }
@@ -1345,17 +1218,23 @@ int print_queue_length(int snum, print_status_struct *pstatus)
 static int get_total_jobs(void)
 {
        int total_jobs;
-       struct printer_queueid_map *p;
+       int snum;
+       int services = lp_numservices();
 
-       for (p = printer_queueid_map_head; p; p = p->next) {
+       for (snum = 0; snum < services; snum++) {
+               struct tdb_print_db *pdb;
                int jobs;
-               struct tdb_print_db *pdb = get_print_db_byname(p->printername);
+
+               if (!lp_print_ok(snum))
+                       continue;
+
+               pdb = get_print_db_byname(lp_const_servicename(snum));
                if (!pdb)
                        continue;
 
                /* make sure the database is up to date */
-               if (print_cache_expired(lp_servicenumber(p->printername)))
-                       print_queue_update(lp_servicenumber(p->printername));
+               if (print_cache_expired(snum))
+                       print_queue_update(snum);
 
                jobs = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
                if (jobs > 0)
@@ -1378,7 +1257,6 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
        int njobs = 0;
        const char *printername = lp_const_servicename(snum);
        struct tdb_print_db *pdb = get_print_db_byname(printername);
-       uint32 queueid = queueid = get_printer_queueid_byname(printername);
 
        errno = 0;
 
@@ -1460,10 +1338,10 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
                next_jobid = 1;
 
        for (jobid = NEXT_JOBID(next_jobid); jobid != next_jobid; jobid = NEXT_JOBID(jobid)) {
-               if (!print_job_exists(jobid | QUEUEID_TO_JOBID(queueid)))
+               if (!print_job_exists(snum, jobid))
                        break;
        }
-       if (jobid == next_jobid || !pjob_store(jobid | QUEUEID_TO_JOBID(queueid), &pjob)) {
+       if (jobid == next_jobid || !pjob_store(snum, jobid, &pjob)) {
                DEBUG(3, ("print_job_start: either jobid (%d)==next_jobid(%d) or pjob_store failed.\n",
                                jobid, next_jobid ));
                jobid = -1;
@@ -1476,9 +1354,6 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
                goto fail;
        }
 
-       /* Ensure the queuid is added to the jobid. */
-       jobid |= QUEUEID_TO_JOBID(queueid);
-
        /* we have a job entry - now create the spool file */
        slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX", 
                 path, PRINT_SPOOL_PREFIX, (unsigned int)jobid);
@@ -1497,7 +1372,7 @@ to open spool file %s.\n", pjob.filename));
                goto fail;
        }
 
-       pjob_store(jobid, &pjob);
+       pjob_store(snum, jobid, &pjob);
 
        tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
 
@@ -1509,14 +1384,14 @@ to open spool file %s.\n", pjob.filename));
         * tim@fsg.com 09/06/94
         */
        if (lp_postscript(snum)) {
-               print_job_write(jobid, "%!\n",3);
+               print_job_write(snum, jobid, "%!\n",3);
        }
 
        return jobid;
 
  fail:
        if (jobid != -1)
-               pjob_delete(jobid);
+               pjob_delete(snum, jobid);
 
        tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
 
@@ -1528,9 +1403,9 @@ to open spool file %s.\n", pjob.filename));
  Update the number of pages spooled to jobid
 ****************************************************************************/
 
-void print_job_endpage(uint32 jobid)
+void print_job_endpage(int snum, uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(jobid);
+       struct printjob *pjob = print_job_find(snum, jobid);
        if (!pjob)
                return;
        /* don't allow another process to get this info - it is meaningless */
@@ -1538,7 +1413,7 @@ void print_job_endpage(uint32 jobid)
                return;
 
        pjob->page_count++;
-       pjob_store(jobid, pjob);
+       pjob_store(snum, jobid, pjob);
 }
 
 /****************************************************************************
@@ -1547,10 +1422,10 @@ void print_job_endpage(uint32 jobid)
  error.
 ****************************************************************************/
 
-BOOL print_job_end(uint32 jobid, BOOL normal_close)
+BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close)
 {
-       struct printjob *pjob = print_job_find(jobid);
-       int snum, ret;
+       struct printjob *pjob = print_job_find(snum, jobid);
+       int ret;
        SMB_STRUCT_STAT sbuf;
 
        if (!pjob)
@@ -1559,12 +1434,6 @@ BOOL print_job_end(uint32 jobid, BOOL normal_close)
        if (pjob->spooled || pjob->pid != local_pid)
                return False;
 
-       snum = print_job_snum(jobid);
-       if (snum == -1) {
-               DEBUG(5,("print_job_end: unknown service number for jobid %u\n", (unsigned int)jobid));
-               return False;
-       }
-
        if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) {
                pjob->size = sbuf.st_size;
                close(pjob->fd);
@@ -1589,7 +1458,7 @@ BOOL print_job_end(uint32 jobid, BOOL normal_close)
                DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
                        pjob->filename, pjob->size ? "deleted" : "zero length" ));
                unlink(pjob->filename);
-               pjob_delete(jobid);
+               pjob_delete(snum, jobid);
                return True;
        }
 
@@ -1602,7 +1471,7 @@ BOOL print_job_end(uint32 jobid, BOOL normal_close)
        
        pjob->spooled = True;
        pjob->status = LPQ_QUEUED;
-       pjob_store(jobid, pjob);
+       pjob_store(snum, jobid, pjob);
        
        /* make sure the database is up to date */
        if (print_cache_expired(snum))
@@ -1615,7 +1484,7 @@ fail:
        /* The print job was not succesfully started. Cleanup */
        /* Still need to add proper error return propagation! 010122:JRR */
        unlink(pjob->filename);
-       pjob_delete(jobid);
+       pjob_delete(snum, jobid);
        return False;
 }
 
@@ -1877,10 +1746,10 @@ BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
        njobs = print_queue_status(snum, &queue, &status);
 
        for (i=0;i<njobs;i++) {
-               BOOL owner = is_owner(user, queue[i].job);
+               BOOL owner = is_owner(user, snum, queue[i].job);
 
                if (owner || can_job_admin) {
-                       print_job_delete1(queue[i].job);
+                       print_job_delete1(snum, queue[i].job);
                }
        }