s3-printing: pass a talloc ctx to unpack_pjob
[ddiss/samba.git] / source3 / printing / printing.c
index 28ea4f04fe3c757808cc7a011583f7ce71b8092b..69281846dfa09ed918d6e76a96970c1351ecaf98 100644 (file)
 */
 
 #include "includes.h"
+#include "system/syslog.h"
+#include "system/filesys.h"
 #include "printing.h"
-#include "librpc/gen_ndr/messaging.h"
 #include "../librpc/gen_ndr/ndr_spoolss.h"
 #include "nt_printing.h"
 #include "../librpc/gen_ndr/netlogon.h"
+#include "printing/notify.h"
+#include "printing/pcap.h"
+#include "printing/printer_list.h"
+#include "printing/queue_process.h"
+#include "serverid.h"
+#include "smbd/smbd.h"
+#include "auth.h"
+#include "messages.h"
+#include "util_tdb.h"
+#include "lib/param/loadparm.h"
 
 extern struct current_user current_user;
 extern userdom_struct current_user_info;
 
 /* Current printer interface */
-static bool remove_from_jobs_changed(const char* sharename, uint32 jobid);
+static bool remove_from_jobs_added(const char* sharename, uint32 jobid);
 
 /*
    the printing backend revolves around a tdb database that stores the
@@ -80,7 +91,7 @@ uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
        key.dptr = (uint8 *)&jinfo;
        key.dsize = sizeof(jinfo);
 
-       data = tdb_fetch(rap_tdb, key);
+       data = tdb_fetch_compat(rap_tdb, key);
        if (data.dptr && data.dsize == sizeof(uint16)) {
                rap_jobid = SVAL(data.dptr, 0);
                SAFE_FREE(data.dptr);
@@ -117,7 +128,7 @@ bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
        SSVAL(buf,0,rap_jobid);
        key.dptr = buf;
        key.dsize = sizeof(rap_jobid);
-       data = tdb_fetch(rap_tdb, key);
+       data = tdb_fetch_compat(rap_tdb, key);
        if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
        {
                struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
@@ -155,7 +166,7 @@ void rap_jobid_delete(const char* sharename, uint32 jobid)
        key.dptr = (uint8 *)&jinfo;
        key.dsize = sizeof(jinfo);
 
-       data = tdb_fetch(rap_tdb, key);
+       data = tdb_fetch_compat(rap_tdb, key);
        if (!data.dptr || (data.dsize != sizeof(uint16))) {
                DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
                        (unsigned int)jobid ));
@@ -187,6 +198,10 @@ bool print_backend_init(struct messaging_context *msg_ctx)
        int services = lp_numservices();
        int snum;
 
+       if (!printer_list_parent_init()) {
+               return false;
+       }
+
        unlink(cache_path("printing.tdb"));
        mkdir(cache_path("printing"),0755);
 
@@ -200,7 +215,7 @@ bool print_backend_init(struct messaging_context *msg_ctx)
                pdb = get_print_db_byname(lp_const_servicename(snum));
                if (!pdb)
                        continue;
-               if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
+               if (tdb_lock_bystring(pdb->tdb, sversion) != 0) {
                        DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
                        release_print_db(pdb);
                        return False;
@@ -365,18 +380,21 @@ done:
  unpack a pjob from a tdb buffer
 ***********************************************************************/
 
-int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
+static int unpack_pjob(TALLOC_CTX *mem_ctx, uint8 *buf, int buflen,
+                      struct printjob *pjob)
 {
        int     len = 0;
        int     used;
-       uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
+       uint32 pjpid, pjjobid, pjsysjob, pjfd, pjstarttime, pjstatus;
        uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
 
-       if ( !buf || !pjob )
+       if (!buf || !pjob) {
                return -1;
+       }
 
-       len += tdb_unpack(buf+len, buflen-len, "dddddddddffff",
+       len += tdb_unpack(buf+len, buflen-len, "ddddddddddfffff",
                                &pjpid,
+                               &pjjobid,
                                &pjsysjob,
                                &pjfd,
                                &pjstarttime,
@@ -388,12 +406,14 @@ int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
                                pjob->filename,
                                pjob->jobname,
                                pjob->user,
+                               pjob->clientmachine,
                                pjob->queuename);
 
-       if ( len == -1 )
+       if (len == -1) {
                return -1;
+       }
 
-        used = unpack_devicemode(NULL, buf+len, buflen-len, &pjob->devmode);
+        used = unpack_devicemode(mem_ctx, buf+len, buflen-len, &pjob->devmode);
         if (used == -1) {
                return -1;
         }
@@ -401,6 +421,7 @@ int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
        len += used;
 
        pjob->pid = pjpid;
+       pjob->jobid = pjjobid;
        pjob->sysjob = pjsysjob;
        pjob->fd = pjfd;
        pjob->starttime = pjstarttime;
@@ -418,9 +439,11 @@ int unpack_pjob( uint8 *buf, int buflen, struct printjob *pjob )
  Useful function to find a print job in the database.
 ****************************************************************************/
 
-static struct printjob *print_job_find(const char *sharename, uint32 jobid)
+static struct printjob *print_job_find(TALLOC_CTX *mem_ctx,
+                                      const char *sharename,
+                                      uint32 jobid)
 {
-       static struct printjob  pjob;
+       struct printjob         *pjob;
        uint32_t tmp;
        TDB_DATA                ret;
        struct tdb_print_db     *pdb = get_print_db_byname(sharename);
@@ -432,30 +455,34 @@ static struct printjob *print_job_find(const char *sharename, uint32 jobid)
                return NULL;
        }
 
-       ret = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
+       ret = tdb_fetch_compat(pdb->tdb, print_key(jobid, &tmp));
        release_print_db(pdb);
 
        if (!ret.dptr) {
-               DEBUG(10,("print_job_find: failed to find jobid %u.\n", (unsigned int)jobid ));
+               DEBUG(10, ("print_job_find: failed to find jobid %u.\n",
+                          jobid));
                return NULL;
        }
 
-       talloc_free(pjob.devmode);
-
-       ZERO_STRUCT( pjob );
-
-       if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
-               DEBUG(10,("print_job_find: failed to unpack jobid %u.\n", (unsigned int)jobid ));
-               SAFE_FREE(ret.dptr);
-               return NULL;
+       pjob = talloc_zero(mem_ctx, struct printjob);
+       if (pjob == NULL) {
+               goto err_out;
        }
 
-       SAFE_FREE(ret.dptr);
+       if (unpack_pjob(mem_ctx, ret.dptr, ret.dsize, pjob) == -1) {
+               DEBUG(10, ("failed to unpack jobid %u.\n", jobid));
+               talloc_free(pjob);
+               pjob = NULL;
+               goto err_out;
+       }
 
        DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
-                       (int)pjob.sysjob, (unsigned int)jobid ));
+                 pjob->sysjob, jobid));
+       SMB_ASSERT(pjob->jobid == jobid);
 
-       return &pjob;
+err_out:
+       SAFE_FREE(ret.dptr);
+       return pjob;
 }
 
 /* Convert a unix jobid to a smb jobid */
@@ -480,15 +507,25 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
                return 0;
 
        if (state->sysjob == pjob->sysjob) {
-               uint32 jobid = IVAL(key.dptr,0);
-
-               state->sysjob_to_jobid_value = jobid;
+               state->sysjob_to_jobid_value = pjob->jobid;
                return 1;
        }
 
        return 0;
 }
 
+static uint32 sysjob_to_jobid_pdb(struct tdb_print_db *pdb, int sysjob)
+{
+       struct unixjob_traverse_state state;
+
+       state.sysjob = sysjob;
+       state.sysjob_to_jobid_value = (uint32)-1;
+
+       tdb_traverse(pdb->tdb, unixjob_traverse_fn, &state);
+
+       return state.sysjob_to_jobid_value;
+}
+
 /****************************************************************************
  This is a *horribly expensive call as we have to iterate through all the
  current printer tdb's. Don't do this often ! JRA.
@@ -524,8 +561,8 @@ uint32 sysjob_to_jobid(int unix_jobid)
 ****************************************************************************/
 
 static const struct {
-       uint32 lpq_status;
-       uint32 spoolss_status;
+       uint32_t lpq_status;
+       uint32_t spoolss_status;
 } lpq_to_spoolss_status_map[] = {
        { LPQ_QUEUED, JOB_STATUS_QUEUED },
        { LPQ_PAUSED, JOB_STATUS_PAUSED },
@@ -538,7 +575,7 @@ static const struct {
        { LPQ_DELETED, JOB_STATUS_DELETED },
        { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
        { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
-       { -1, 0 }
+       { (uint32_t)-1, 0 }
 };
 
 /* Convert a lpq status value stored in printing.tdb into the
@@ -557,16 +594,97 @@ static uint32 map_to_spoolss_status(uint32 lpq_status)
        return 0;
 }
 
-static void pjob_store_notify(const char* sharename, uint32 jobid, struct printjob *old_data,
-                             struct printjob *new_data)
+/***************************************************************************
+ Append a jobid to the 'jobs changed' list.
+***************************************************************************/
+
+static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32_t jobid)
+{
+       TDB_DATA data;
+       uint32_t store_jobid;
+
+       SIVAL(&store_jobid, 0, jobid);
+       data.dptr = (uint8 *) &store_jobid;
+       data.dsize = 4;
+
+       DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
+
+       return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
+                          data) == 0);
+}
+
+/***************************************************************************
+ Remove a jobid from the 'jobs changed' list.
+***************************************************************************/
+
+static bool remove_from_jobs_changed(const char* sharename, uint32_t jobid)
 {
-       bool new_job = False;
+       struct tdb_print_db *pdb = get_print_db_byname(sharename);
+       TDB_DATA data, key;
+       size_t job_count, i;
+       bool ret = False;
+       bool gotlock = False;
+
+       if (!pdb) {
+               return False;
+       }
+
+       ZERO_STRUCT(data);
+
+       key = string_tdb_data("INFO/jobs_changed");
+
+       if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
+               goto out;
+
+       gotlock = True;
+
+       data = tdb_fetch_compat(pdb->tdb, key);
+
+       if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
+               goto out;
+
+       job_count = data.dsize / 4;
+       for (i = 0; i < job_count; i++) {
+               uint32 ch_jobid;
+
+               ch_jobid = IVAL(data.dptr, i*4);
+               if (ch_jobid == jobid) {
+                       if (i < job_count -1 )
+                               memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
+                       data.dsize -= 4;
+                       if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
+                               goto out;
+                       break;
+               }
+       }
 
-       if (!old_data)
-               new_job = True;
+       ret = True;
+  out:
 
-       /* Job attributes that can't be changed.  We only send
-          notification for these on a new job. */
+       if (gotlock)
+               tdb_chainunlock(pdb->tdb, key);
+       SAFE_FREE(data.dptr);
+       release_print_db(pdb);
+       if (ret)
+               DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
+       else
+               DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
+       return ret;
+}
+
+static void pjob_store_notify(struct tevent_context *ev,
+                             struct messaging_context *msg_ctx,
+                             const char* sharename, uint32 jobid,
+                             struct printjob *old_data,
+                             struct printjob *new_data,
+                             bool *pchanged)
+{
+       bool new_job = false;
+       bool changed = false;
+
+       if (old_data == NULL) {
+               new_job = true;
+       }
 
        /* ACHTUNG!  Due to a bug in Samba's spoolss parsing of the
           NOTIFY_INFO_DATA buffer, we *have* to send the job submission
@@ -576,34 +694,54 @@ static void pjob_store_notify(const char* sharename, uint32 jobid, struct printj
           --jerry (i'll feel dirty for this) */
 
        if (new_job) {
-               notify_job_submitted(sharename, jobid, new_data->starttime);
-               notify_job_username(sharename, jobid, new_data->user);
-       }
-
-       if (new_job || !strequal(old_data->jobname, new_data->jobname))
-               notify_job_name(sharename, jobid, new_data->jobname);
-
-       /* Job attributes of a new job or attributes that can be
-          modified. */
+               notify_job_submitted(ev, msg_ctx,
+                                    sharename, jobid, new_data->starttime);
+               notify_job_username(ev, msg_ctx,
+                                   sharename, jobid, new_data->user);
+               notify_job_name(ev, msg_ctx,
+                               sharename, jobid, new_data->jobname);
+               notify_job_status(ev, msg_ctx,
+                                 sharename, jobid, map_to_spoolss_status(new_data->status));
+               notify_job_total_bytes(ev, msg_ctx,
+                                      sharename, jobid, new_data->size);
+               notify_job_total_pages(ev, msg_ctx,
+                                      sharename, jobid, new_data->page_count);
+       } else {
+               if (!strequal(old_data->jobname, new_data->jobname)) {
+                       notify_job_name(ev, msg_ctx, sharename,
+                                       jobid, new_data->jobname);
+                       changed = true;
+               }
 
-       if (new_job || !strequal(old_data->jobname, new_data->jobname))
-               notify_job_name(sharename, jobid, new_data->jobname);
+               if (old_data->status != new_data->status) {
+                       notify_job_status(ev, msg_ctx,
+                                         sharename, jobid,
+                                         map_to_spoolss_status(new_data->status));
+               }
 
-       if (new_job || old_data->status != new_data->status)
-               notify_job_status(sharename, jobid, map_to_spoolss_status(new_data->status));
+               if (old_data->size != new_data->size) {
+                       notify_job_total_bytes(ev, msg_ctx,
+                                              sharename, jobid, new_data->size);
+               }
 
-       if (new_job || old_data->size != new_data->size)
-               notify_job_total_bytes(sharename, jobid, new_data->size);
+               if (old_data->page_count != new_data->page_count) {
+                       notify_job_total_pages(ev, msg_ctx,
+                                              sharename, jobid,
+                                              new_data->page_count);
+               }
+       }
 
-       if (new_job || old_data->page_count != new_data->page_count)
-               notify_job_total_pages(sharename, jobid, new_data->page_count);
+       *pchanged = changed;
 }
 
 /****************************************************************************
  Store a job structure back to the database.
 ****************************************************************************/
 
-static bool pjob_store(const char* sharename, uint32 jobid, struct printjob *pjob)
+static bool pjob_store(struct tevent_context *ev,
+                      struct messaging_context *msg_ctx,
+                      const char* sharename, uint32 jobid,
+                      struct printjob *pjob)
 {
        uint32_t tmp;
        TDB_DATA                old_data, new_data;
@@ -618,7 +756,7 @@ static bool pjob_store(const char* sharename, uint32 jobid, struct printjob *pjo
 
        /* Get old data */
 
-       old_data = tdb_fetch(pdb->tdb, print_key(jobid, &tmp));
+       old_data = tdb_fetch_compat(pdb->tdb, print_key(jobid, &tmp));
 
        /* Doh!  Now we have to pack/unpack data since the NT_DEVICEMODE was added */
 
@@ -627,8 +765,9 @@ static bool pjob_store(const char* sharename, uint32 jobid, struct printjob *pjo
        do {
                len = 0;
                buflen = newlen;
-               len += tdb_pack(buf+len, buflen-len, "dddddddddffff",
+               len += tdb_pack(buf+len, buflen-len, "ddddddddddfffff",
                                (uint32)pjob->pid,
+                               (uint32)pjob->jobid,
                                (uint32)pjob->sysjob,
                                (uint32)pjob->fd,
                                (uint32)pjob->starttime,
@@ -640,6 +779,7 @@ static bool pjob_store(const char* sharename, uint32 jobid, struct printjob *pjo
                                pjob->filename,
                                pjob->jobname,
                                pjob->user,
+                               pjob->clientmachine,
                                pjob->queuename);
 
                len += pack_devicemode(pjob->devmode, buf+len, buflen-len);
@@ -662,28 +802,41 @@ static bool pjob_store(const char* sharename, uint32 jobid, struct printjob *pjo
        ret = (tdb_store(pdb->tdb, print_key(jobid, &tmp), new_data,
                         TDB_REPLACE) == 0);
 
-       release_print_db(pdb);
-
        /* Send notify updates for what has changed */
 
-       if ( ret ) {
+       if (ret) {
+               bool changed = false;
                struct printjob old_pjob;
 
-               if ( old_data.dsize )
-               {
-                       if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
-                       {
-                               pjob_store_notify( sharename, jobid, &old_pjob , pjob );
-                               talloc_free(old_pjob.devmode);
+               if (old_data.dsize) {
+                       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+                       if (tmp_ctx == NULL)
+                               goto done;
+
+                       len = unpack_pjob(tmp_ctx, old_data.dptr,
+                                         old_data.dsize, &old_pjob);
+                       if (len != -1 ) {
+                               pjob_store_notify(ev,
+                                                 msg_ctx,
+                                                 sharename, jobid, &old_pjob,
+                                                 pjob,
+                                                 &changed);
+                               if (changed) {
+                                       add_to_jobs_changed(pdb, jobid);
+                               }
                        }
-               }
-               else {
+                       talloc_free(tmp_ctx);
+
+               } else {
                        /* new job */
-                       pjob_store_notify( sharename, jobid, NULL, pjob );
+                       pjob_store_notify(ev, msg_ctx,
+                                         sharename, jobid, NULL, pjob,
+                                         &changed);
                }
        }
 
 done:
+       release_print_db(pdb);
        SAFE_FREE( old_data.dptr );
        SAFE_FREE( buf );
 
@@ -694,25 +847,29 @@ done:
  Remove a job structure from the database.
 ****************************************************************************/
 
-void pjob_delete(const char* sharename, uint32 jobid)
+static void pjob_delete(struct tevent_context *ev,
+                       struct messaging_context *msg_ctx,
+                       const char* sharename, uint32 jobid)
 {
        uint32_t tmp;
        struct printjob *pjob;
        uint32 job_status = 0;
        struct tdb_print_db *pdb;
-
-       pdb = get_print_db_byname( sharename );
-
-       if (!pdb)
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
                return;
+       }
 
-       pjob = print_job_find( sharename, jobid );
+       pdb = get_print_db_byname(sharename);
+       if (!pdb) {
+               goto err_out;
+       }
 
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (!pjob) {
-               DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
-                                       (unsigned int)jobid));
-               release_print_db(pdb);
-               return;
+               DEBUG(5, ("we were asked to delete nonexistent job %u\n",
+                         jobid));
+               goto err_release;
        }
 
        /* We must cycle through JOB_STATUS_DELETING and
@@ -720,35 +877,47 @@ void pjob_delete(const char* sharename, uint32 jobid)
            properly. */
 
        job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
-       notify_job_status(sharename, jobid, job_status);
+       notify_job_status(ev, msg_ctx, sharename, jobid, job_status);
 
        /* Remove from printing.tdb */
 
        tdb_delete(pdb->tdb, print_key(jobid, &tmp));
-       remove_from_jobs_changed(sharename, jobid);
-       release_print_db( pdb );
+       remove_from_jobs_added(sharename, jobid);
        rap_jobid_delete(sharename, jobid);
+err_release:
+       release_print_db(pdb);
+err_out:
+       talloc_free(tmp_ctx);
 }
 
 /****************************************************************************
  List a unix job in the print database.
 ****************************************************************************/
 
-static void print_unix_job(const char *sharename, print_queue_struct *q, uint32 jobid)
+static void print_unix_job(struct tevent_context *ev,
+                          struct messaging_context *msg_ctx,
+                          const char *sharename, print_queue_struct *q,
+                          uint32 jobid)
 {
        struct printjob pj, *old_pj;
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
+               return;
+       }
 
-       if (jobid == (uint32)-1)
-               jobid = q->job + UNIX_JOB_START;
+       if (jobid == (uint32)-1) {
+               jobid = q->sysjob + UNIX_JOB_START;
+       }
 
        /* Preserve the timestamp on an existing unix print job */
 
-       old_pj = print_job_find(sharename, jobid);
+       old_pj = print_job_find(tmp_ctx, sharename, jobid);
 
        ZERO_STRUCT(pj);
 
        pj.pid = (pid_t)-1;
-       pj.sysjob = q->job;
+       pj.jobid = jobid;
+       pj.sysjob = q->sysjob;
        pj.fd = -1;
        pj.starttime = old_pj ? old_pj->starttime : q->time;
        pj.status = q->status;
@@ -765,7 +934,8 @@ static void print_unix_job(const char *sharename, print_queue_struct *q, uint32
        fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
        fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
 
-       pjob_store(sharename, jobid, &pj);
+       pjob_store(ev, msg_ctx, sharename, jobid, &pj);
+       talloc_free(tmp_ctx);
 }
 
 
@@ -776,6 +946,9 @@ struct traverse_struct {
        time_t lpq_time;
        const char *lprm_command;
        struct printif *print_if;
+       struct tevent_context *ev;
+       struct messaging_context *msg_ctx;
+       TALLOC_CTX *mem_ctx;
 };
 
 /****************************************************************************
@@ -792,24 +965,23 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
        if (  key.dsize != sizeof(jobid) )
                return 0;
 
-       jobid = IVAL(key.dptr, 0);
-       if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
+       if (unpack_pjob(ts->mem_ctx, data.dptr, data.dsize, &pjob) == -1)
                return 0;
        talloc_free(pjob.devmode);
-
+       jobid = pjob.jobid;
 
        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);
-                       if (jobid == u_jobid)
+                       if (ts->queue[i].sysjob == pjob.sysjob) {
                                break;
+                       }
                }
                if (i == ts->qcount) {
                        DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
                                                (unsigned int)jobid ));
-                       pjob_delete(ts->sharename, jobid);
+                       pjob_delete(ts->ev, ts->msg_ctx,
+                                   ts->sharename, jobid);
                        return 0;
                }
 
@@ -825,7 +997,8 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
                if (!process_exists_by_pid(pjob.pid)) {
                        DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
                                                (unsigned int)jobid, (unsigned int)pjob.pid ));
-                       pjob_delete(ts->sharename, jobid);
+                       pjob_delete(ts->ev, ts->msg_ctx,
+                                   ts->sharename, jobid);
                } else
                        ts->total_jobs++;
                return 0;
@@ -833,16 +1006,12 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
 
        /* this check only makes sense for jobs submitted from Windows clients */
 
-       if ( pjob.smbjob ) {
+       if (pjob.smbjob) {
                for (i=0;i<ts->qcount;i++) {
-                       uint32 curr_jobid;
-
                        if ( pjob.status == LPQ_DELETED )
                                continue;
 
-                       curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
-
-                       if (jobid == curr_jobid) {
+                       if (ts->queue[i].sysjob == pjob.sysjob) {
 
                                /* try to clean up any jobs that need to be deleted */
 
@@ -855,11 +1024,14 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
                                        if ( result != 0 ) {
                                                /* if we can't delete, then reset the job status */
                                                pjob.status = LPQ_QUEUED;
-                                               pjob_store(ts->sharename, jobid, &pjob);
+                                               pjob_store(ts->ev, ts->msg_ctx,
+                                                          ts->sharename, jobid, &pjob);
                                        }
                                        else {
                                                /* if we deleted the job, the remove the tdb record */
-                                               pjob_delete(ts->sharename, jobid);
+                                               pjob_delete(ts->ev,
+                                                           ts->msg_ctx,
+                                                           ts->sharename, jobid);
                                                pjob.status = LPQ_DELETED;
                                        }
 
@@ -887,17 +1059,15 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
                                                (unsigned int)jobid,
                                                (unsigned int)pjob.starttime,
                                                (unsigned int)ts->lpq_time ));
-                       pjob_delete(ts->sharename, jobid);
+                       pjob_delete(ts->ev, ts->msg_ctx,
+                                   ts->sharename, jobid);
                } else
                        ts->total_jobs++;
                return 0;
        }
 
-       /* Save the pjob attributes we will store.
-          FIXME!!! This is the only place where queue->job
-          represents the SMB jobid      --jerry */
-
-       ts->queue[i].job = jobid;
+       /* Save the pjob attributes we will store. */
+       ts->queue[i].sysjob = pjob.sysjob;
        ts->queue[i].size = pjob.size;
        ts->queue[i].page_count = pjob.page_count;
        ts->queue[i].status = pjob.status;
@@ -943,7 +1113,7 @@ static pid_t get_updating_pid(const char *sharename)
        slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
        key = string_tdb_data(keystr);
 
-       data = tdb_fetch(pdb->tdb, key);
+       data = tdb_fetch_compat(pdb->tdb, key);
        release_print_db(pdb);
        if (!data.dptr || data.dsize != sizeof(pid_t)) {
                SAFE_FREE(data.dptr);
@@ -969,7 +1139,7 @@ static void set_updating_pid(const fstring sharename, bool updating)
        fstring keystr;
        TDB_DATA key;
        TDB_DATA data;
-       pid_t updating_pid = sys_getpid();
+       pid_t updating_pid = getpid();
        uint8 buffer[4];
 
        struct tdb_print_db *pdb = get_print_db_byname(sharename);
@@ -1048,7 +1218,7 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
 
                qcount++;
                data.dsize += tdb_pack(NULL, 0, "ddddddff",
-                               (uint32)queue[i].job,
+                               (uint32)queue[i].sysjob,
                                (uint32)queue[i].size,
                                (uint32)queue[i].page_count,
                                (uint32)queue[i].status,
@@ -1068,7 +1238,7 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
                        continue;
 
                len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
-                               (uint32)queue[i].job,
+                               (uint32)queue[i].sysjob,
                                (uint32)queue[i].size,
                                (uint32)queue[i].page_count,
                                (uint32)queue[i].status,
@@ -1084,13 +1254,13 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
        return;
 }
 
-static TDB_DATA get_jobs_changed_data(struct tdb_print_db *pdb)
+static TDB_DATA get_jobs_added_data(struct tdb_print_db *pdb)
 {
        TDB_DATA data;
 
        ZERO_STRUCT(data);
 
-       data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
+       data = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_added"));
        if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
                SAFE_FREE(data.dptr);
                ZERO_STRUCT(data);
@@ -1099,7 +1269,7 @@ static TDB_DATA get_jobs_changed_data(struct tdb_print_db *pdb)
        return data;
 }
 
-static void check_job_changed(const char *sharename, TDB_DATA data, uint32 jobid)
+static void check_job_added(const char *sharename, TDB_DATA data, uint32 jobid)
 {
        unsigned int i;
        unsigned int job_count = data.dsize / 4;
@@ -1109,7 +1279,7 @@ static void check_job_changed(const char *sharename, TDB_DATA data, uint32 jobid
 
                ch_jobid = IVAL(data.dptr, i*4);
                if (ch_jobid == jobid)
-                       remove_from_jobs_changed(sharename, jobid);
+                       remove_from_jobs_added(sharename, jobid);
        }
 }
 
@@ -1179,12 +1349,14 @@ done:
 }
 
 /****************************************************************************
- main work for updating the lpq cahe for a printer queue
+ main work for updating the lpq cache for a printer queue
 ****************************************************************************/
 
-static void print_queue_update_internal( const char *sharename,
-                                         struct printif *current_printif,
-                                         char *lpq_command, char *lprm_command )
+static void print_queue_update_internal(struct tevent_context *ev,
+                                       struct messaging_context *msg_ctx,
+                                       const char *sharename,
+                                        struct printif *current_printif,
+                                        char *lpq_command, char *lprm_command)
 {
        int i, qcount;
        print_queue_struct *queue = NULL;
@@ -1196,8 +1368,9 @@ static void print_queue_update_internal( const char *sharename,
        TDB_DATA jcdata;
        fstring keystr, cachestr;
        struct tdb_print_db *pdb = get_print_db_byname(sharename);
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
 
-       if (!pdb) {
+       if ((pdb == NULL) || (tmp_ctx == NULL)) {
                return;
        }
 
@@ -1238,38 +1411,38 @@ static void print_queue_update_internal( const char *sharename,
 
          fill in any system job numbers as we go
        */
-
-       jcdata = get_jobs_changed_data(pdb);
+       jcdata = get_jobs_added_data(pdb);
 
        for (i=0; i<qcount; i++) {
-               uint32 jobid = print_parse_jobid(queue[i].fs_file);
-
+               uint32 jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
                if (jobid == (uint32)-1) {
                        /* assume its a unix print job */
-                       print_unix_job(sharename, &queue[i], jobid);
+                       print_unix_job(ev, msg_ctx,
+                                      sharename, &queue[i], jobid);
                        continue;
                }
 
                /* we have an active SMB print job - update its status */
-               pjob = print_job_find(sharename, jobid);
+               pjob = print_job_find(tmp_ctx, sharename, jobid);
                if (!pjob) {
                        /* err, somethings wrong. Probably smbd was restarted
                           with jobs in the queue. All we can do is treat them
                           like unix jobs. Pity. */
-                       print_unix_job(sharename, &queue[i], jobid);
+                       DEBUG(1, ("queued print job %d not found in jobs list, "
+                                 "assuming unix job\n", jobid));
+                       print_unix_job(ev, msg_ctx,
+                                      sharename, &queue[i], jobid);
                        continue;
                }
 
-               pjob->sysjob = queue[i].job;
-
                /* don't reset the status on jobs to be deleted */
 
                if ( pjob->status != LPQ_DELETING )
                        pjob->status = queue[i].status;
 
-               pjob_store(sharename, jobid, pjob);
+               pjob_store(ev, msg_ctx, sharename, jobid, pjob);
 
-               check_job_changed(sharename, jcdata, jobid);
+               check_job_added(sharename, jcdata, jobid);
        }
 
        SAFE_FREE(jcdata.dptr);
@@ -1284,6 +1457,9 @@ static void print_queue_update_internal( const char *sharename,
        tstruct.sharename = sharename;
        tstruct.lprm_command = lprm_command;
        tstruct.print_if = current_printif;
+       tstruct.ev = ev;
+       tstruct.msg_ctx = msg_ctx;
+       tstruct.mem_ctx = tmp_ctx;
 
        tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
 
@@ -1291,6 +1467,7 @@ static void print_queue_update_internal( const char *sharename,
        store_queue_struct(pdb, &tstruct);
 
        SAFE_FREE(tstruct.queue);
+       talloc_free(tmp_ctx);
 
        DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
                                sharename, tstruct.total_jobs ));
@@ -1341,7 +1518,9 @@ static void print_queue_update_internal( const char *sharename,
  smbd processes maytry to update the lpq cache concurrently).
 ****************************************************************************/
 
-static void print_queue_update_with_lock( const char *sharename,
+static void print_queue_update_with_lock( struct tevent_context *ev,
+                                         struct messaging_context *msg_ctx,
+                                         const char *sharename,
                                           struct printif *current_printif,
                                           char *lpq_command, char *lprm_command )
 {
@@ -1373,7 +1552,7 @@ static void print_queue_update_with_lock( const char *sharename,
 
        slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
        /* Only wait 10 seconds for this. */
-       if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) == -1) {
+       if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) != 0) {
                DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
                release_print_db(pdb);
                return;
@@ -1410,8 +1589,9 @@ static void print_queue_update_with_lock( const char *sharename,
 
        /* do the main work now */
 
-       print_queue_update_internal( sharename, current_printif,
-               lpq_command, lprm_command );
+       print_queue_update_internal(ev, msg_ctx,
+                                   sharename, current_printif,
+                                   lpq_command, lprm_command);
 
        /* Delete our pid from the db. */
        set_updating_pid(sharename, False);
@@ -1421,7 +1601,7 @@ static void print_queue_update_with_lock( const char *sharename,
 /****************************************************************************
 this is the receive function of the background lpq updater
 ****************************************************************************/
-static void print_queue_receive(struct messaging_context *msg,
+void print_queue_receive(struct messaging_context *msg,
                                void *private_data,
                                uint32_t msg_type,
                                struct server_id server_id,
@@ -1445,7 +1625,7 @@ static void print_queue_receive(struct messaging_context *msg,
                return;
        }
 
-       print_queue_update_with_lock(sharename,
+       print_queue_update_with_lock(server_event_context(), msg, sharename,
                get_printer_fns_from_type((enum printing_types)printing_type),
                lpqcommand, lprmcommand );
 
@@ -1454,128 +1634,14 @@ static void print_queue_receive(struct messaging_context *msg,
        return;
 }
 
-static void printing_pause_fd_handler(struct tevent_context *ev,
-                                     struct tevent_fd *fde,
-                                     uint16_t flags,
-                                     void *private_data)
-{
-       /*
-        * If pause_pipe[1] is closed it means the parent smbd
-        * and children exited or aborted.
-        */
-       exit_server_cleanly(NULL);
-}
-
-extern struct child_pid *children;
-extern int num_children;
-
-static void add_child_pid(pid_t pid)
-{
-       struct child_pid *child;
-
-        child = SMB_MALLOC_P(struct child_pid);
-        if (child == NULL) {
-                DEBUG(0, ("Could not add child struct -- malloc failed\n"));
-                return;
-        }
-        child->pid = pid;
-        DLIST_ADD(children, child);
-        num_children += 1;
-}
-
-static pid_t background_lpq_updater_pid = -1;
-
-/****************************************************************************
-main thread of the background lpq updater
-****************************************************************************/
-void start_background_queue(void)
-{
-       /* Use local variables for this as we don't
-        * need to save the parent side of this, just
-        * ensure it closes when the process exits.
-        */
-       int pause_pipe[2];
-
-       DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
-
-       if (pipe(pause_pipe) == -1) {
-               DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) ));
-               exit(1);
-       }
-
-       background_lpq_updater_pid = sys_fork();
-
-       if (background_lpq_updater_pid == -1) {
-               DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
-               exit(1);
-       }
-
-       /* Track the printing pid along with other smbd children */
-       add_child_pid(background_lpq_updater_pid);
-
-       if(background_lpq_updater_pid == 0) {
-               struct tevent_fd *fde;
-               int ret;
-               NTSTATUS status;
-
-               /* Child. */
-               DEBUG(5,("start_background_queue: background LPQ thread started\n"));
-
-               close(pause_pipe[0]);
-               pause_pipe[0] = -1;
-
-               status = reinit_after_fork(server_messaging_context(),
-                                          server_event_context(),
-                                          procid_self(), true);
-
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("reinit_after_fork() failed\n"));
-                       smb_panic("reinit_after_fork() failed");
-               }
-
-               smbd_setup_sig_term_handler();
-               smbd_setup_sig_hup_handler(server_event_context(),
-                                          server_messaging_context());
-
-               if (!serverid_register(procid_self(),
-                                      FLAG_MSG_GENERAL|FLAG_MSG_SMBD
-                                      |FLAG_MSG_PRINT_GENERAL)) {
-                       exit(1);
-               }
-
-               if (!locking_init()) {
-                       exit(1);
-               }
-
-               messaging_register(server_messaging_context(), NULL,
-                                  MSG_PRINTER_UPDATE, print_queue_receive);
-
-               fde = tevent_add_fd(server_event_context(),
-                                   server_event_context(),
-                                   pause_pipe[1], TEVENT_FD_READ,
-                                   printing_pause_fd_handler,
-                                   NULL);
-               if (!fde) {
-                       DEBUG(0,("tevent_add_fd() failed for pause_pipe\n"));
-                       smb_panic("tevent_add_fd() failed for pause_pipe");
-               }
-
-               DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
-               ret = tevent_loop_wait(server_event_context());
-               /* should not be reached */
-               DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
-                        ret, (ret == 0) ? "out of events" : strerror(errno)));
-               exit(1);
-       }
-
-       close(pause_pipe[1]);
-}
-
 /****************************************************************************
 update the internal database from the system print queue for a queue
 ****************************************************************************/
 
-static void print_queue_update(int snum, bool force)
+extern pid_t background_lpq_updater_pid;
+
+static void print_queue_update(struct messaging_context *msg_ctx,
+                              int snum, bool force)
 {
        fstring key;
        fstring sharename;
@@ -1641,7 +1707,9 @@ static void print_queue_update(int snum, bool force)
        if ( force || background_lpq_updater_pid == -1 ) {
                DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
                current_printif = get_printer_fns( snum );
-               print_queue_update_with_lock( sharename, current_printif, lpqcommand, lprmcommand );
+               print_queue_update_with_lock(server_event_context(), msg_ctx,
+                                            sharename, current_printif,
+                                            lpqcommand, lprmcommand);
 
                return;
        }
@@ -1694,8 +1762,7 @@ static void print_queue_update(int snum, bool force)
 
        /* finally send the message */
 
-       messaging_send_buf(server_messaging_context(),
-                          pid_to_procid(background_lpq_updater_pid),
+       messaging_send_buf(msg_ctx, pid_to_procid(background_lpq_updater_pid),
                           MSG_PRINTER_UPDATE, (uint8 *)buffer, len);
 
        SAFE_FREE( buffer );
@@ -1714,7 +1781,7 @@ bool print_notify_register_pid(int snum)
        struct tdb_print_db *pdb = NULL;
        TDB_CONTEXT *tdb = NULL;
        const char *printername;
-       uint32 mypid = (uint32)sys_getpid();
+       uint32_t mypid = (uint32_t)getpid();
        bool ret = False;
        size_t i;
 
@@ -1743,7 +1810,7 @@ bool print_notify_register_pid(int snum)
                tdb = pdb->tdb;
        }
 
-       if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
+       if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
                DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
                                        printername));
                if (pdb)
@@ -1777,7 +1844,7 @@ bool print_notify_register_pid(int snum)
        }
 
        /* Store back the record. */
-       if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
+       if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
                DEBUG(0,("print_notify_register_pid: Failed to update pid \
 list for printer %s\n", printername));
                goto done;
@@ -1805,7 +1872,7 @@ bool print_notify_deregister_pid(int snum)
        struct tdb_print_db *pdb = NULL;
        TDB_CONTEXT *tdb = NULL;
        const char *printername;
-       uint32 mypid = (uint32)sys_getpid();
+       uint32_t mypid = (uint32_t)getpid();
        size_t i;
        bool ret = False;
 
@@ -1833,7 +1900,7 @@ bool print_notify_deregister_pid(int snum)
                tdb = pdb->tdb;
        }
 
-       if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
+       if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) != 0) {
                DEBUG(0,("print_notify_register_pid: Failed to lock \
 printer %s database\n", printername));
                if (pdb)
@@ -1867,7 +1934,7 @@ printer %s database\n", printername));
                SAFE_FREE(data.dptr);
 
        /* Store back the record. */
-       if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
+       if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) != 0) {
                DEBUG(0,("print_notify_register_pid: Failed to update pid \
 list for printer %s\n", printername));
                goto done;
@@ -1909,8 +1976,8 @@ bool print_job_exists(const char* sharename, uint32 jobid)
 
 char *print_job_fname(const char* sharename, uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(sharename, jobid);
-       if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
+       struct printjob *pjob = print_job_find(NULL, sharename, jobid);
+       if (!pjob || pjob->spooled || pjob->pid != getpid())
                return NULL;
        return pjob->filename;
 }
@@ -1922,12 +1989,14 @@ char *print_job_fname(const char* sharename, uint32 jobid)
  has not been spooled.
 ****************************************************************************/
 
-struct spoolss_DeviceMode *print_job_devmode(const char* sharename, uint32 jobid)
+struct spoolss_DeviceMode *print_job_devmode(TALLOC_CTX *mem_ctx,
+                                            const char *sharename,
+                                            uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(sharename, jobid);
-
-       if ( !pjob )
+       struct printjob *pjob = print_job_find(mem_ctx, sharename, jobid);
+       if (pjob == NULL) {
                return NULL;
+       }
 
        return pjob->devmode;
 }
@@ -1936,16 +2005,28 @@ struct spoolss_DeviceMode *print_job_devmode(const char* sharename, uint32 jobid
  Set the name of a job. Only possible for owner.
 ****************************************************************************/
 
-bool print_job_set_name(const char *sharename, uint32 jobid, const char *name)
+bool print_job_set_name(struct tevent_context *ev,
+                       struct messaging_context *msg_ctx,
+                       const char *sharename, uint32 jobid, const char *name)
 {
        struct printjob *pjob;
+       bool ret;
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
+               return false;
+       }
 
-       pjob = print_job_find(sharename, jobid);
-       if (!pjob || pjob->pid != sys_getpid())
-               return False;
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob || pjob->pid != getpid()) {
+               ret = false;
+               goto err_out;
+       }
 
        fstrcpy(pjob->jobname, name);
-       return pjob_store(sharename, jobid, pjob);
+       ret = pjob_store(ev, msg_ctx, sharename, jobid, pjob);
+err_out:
+       talloc_free(tmp_ctx);
+       return ret;
 }
 
 /****************************************************************************
@@ -1956,25 +2037,20 @@ bool print_job_get_name(TALLOC_CTX *mem_ctx, const char *sharename, uint32_t job
 {
        struct printjob *pjob;
 
-       pjob = print_job_find(sharename, jobid);
-       if (!pjob || pjob->pid != sys_getpid()) {
+       pjob = print_job_find(mem_ctx, sharename, jobid);
+       if (!pjob || pjob->pid != getpid()) {
                return false;
        }
 
-       *name = talloc_strdup(mem_ctx, pjob->jobname);
-       if (!*name) {
-               return false;
-       }
-
-       return true;
+       return pjob->jobname;
 }
 
 
 /***************************************************************************
- Remove a jobid from the 'jobs changed' list.
+ Remove a jobid from the 'jobs added' list.
 ***************************************************************************/
 
-static bool remove_from_jobs_changed(const char* sharename, uint32 jobid)
+static bool remove_from_jobs_added(const char* sharename, uint32 jobid)
 {
        struct tdb_print_db *pdb = get_print_db_byname(sharename);
        TDB_DATA data, key;
@@ -1988,14 +2064,14 @@ static bool remove_from_jobs_changed(const char* sharename, uint32 jobid)
 
        ZERO_STRUCT(data);
 
-       key = string_tdb_data("INFO/jobs_changed");
+       key = string_tdb_data("INFO/jobs_added");
 
-       if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
+       if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) != 0)
                goto out;
 
        gotlock = True;
 
-       data = tdb_fetch(pdb->tdb, key);
+       data = tdb_fetch_compat(pdb->tdb, key);
 
        if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
                goto out;
@@ -2009,7 +2085,7 @@ static bool remove_from_jobs_changed(const char* sharename, uint32 jobid)
                        if (i < job_count -1 )
                                memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
                        data.dsize -= 4;
-                       if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
+                       if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) != 0)
                                goto out;
                        break;
                }
@@ -2023,9 +2099,9 @@ static bool remove_from_jobs_changed(const char* sharename, uint32 jobid)
        SAFE_FREE(data.dptr);
        release_print_db(pdb);
        if (ret)
-               DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
+               DEBUG(10,("remove_from_jobs_added: removed jobid %u\n", (unsigned int)jobid ));
        else
-               DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
+               DEBUG(10,("remove_from_jobs_added: Failed to remove jobid %u\n", (unsigned int)jobid ));
        return ret;
 }
 
@@ -2033,22 +2109,34 @@ static bool remove_from_jobs_changed(const char* sharename, uint32 jobid)
  Delete a print job - don't update queue.
 ****************************************************************************/
 
-static bool print_job_delete1(int snum, uint32 jobid)
+static bool print_job_delete1(struct tevent_context *ev,
+                             struct messaging_context *msg_ctx,
+                             int snum, uint32 jobid)
 {
        const char* sharename = lp_const_servicename(snum);
-       struct printjob *pjob = print_job_find(sharename, jobid);
+       struct printjob *pjob;
        int result = 0;
        struct printif *current_printif = get_printer_fns( snum );
+       bool ret;
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
+               return false;
+       }
 
-       if (!pjob)
-               return False;
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob) {
+               ret = false;
+               goto err_out;
+       }
 
        /*
         * If already deleting just return.
         */
 
-       if (pjob->status == LPQ_DELETING)
-               return True;
+       if (pjob->status == LPQ_DELETING) {
+               ret = true;
+               goto err_out;
+       }
 
        /* Hrm - we need to be able to cope with deleting a job before it
           has reached the spooler.  Just mark it as LPQ_DELETING and
@@ -2062,7 +2150,7 @@ static bool print_job_delete1(int snum, uint32 jobid)
        /* Set the tdb entry to be deleting. */
 
        pjob->status = LPQ_DELETING;
-       pjob_store(sharename, jobid, pjob);
+       pjob_store(ev, msg_ctx, sharename, jobid, pjob);
 
        if (pjob->spooled && pjob->sysjob != -1)
        {
@@ -2078,48 +2166,68 @@ static bool print_job_delete1(int snum, uint32 jobid)
                        struct tdb_print_db *pdb = get_print_db_byname(sharename);
                        int njobs = 1;
 
-                       if (!pdb)
-                               return False;
-                       pjob_delete(sharename, jobid);
+                       if (!pdb) {
+                               ret = false;
+                               goto err_out;
+                       }
+                       pjob_delete(ev, msg_ctx, sharename, jobid);
                        /* Ensure we keep a rough count of the number of total jobs... */
                        tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
                        release_print_db(pdb);
                }
        }
 
-       remove_from_jobs_changed( sharename, jobid );
+       remove_from_jobs_added( sharename, jobid );
 
-       return (result == 0);
+       ret = (result == 0);
+err_out:
+       talloc_free(tmp_ctx);
+       return ret;
 }
 
 /****************************************************************************
  Return true if the current user owns the print job.
 ****************************************************************************/
 
-static bool is_owner(struct auth_serversupplied_info *server_info,
+static bool is_owner(const struct auth_session_info *server_info,
                     const char *servicename,
                     uint32 jobid)
 {
-       struct printjob *pjob = print_job_find(servicename, jobid);
+       struct printjob *pjob;
+       bool ret;
+       TALLOC_CTX *tmp_ctx = talloc_new(server_info);
+       if (tmp_ctx == NULL) {
+               return false;
+       }
 
-       if (!pjob || !server_info)
-               return False;
+       pjob = print_job_find(tmp_ctx, servicename, jobid);
+       if (!pjob || !server_info) {
+               ret = false;
+               goto err_out;
+       }
 
-       return strequal(pjob->user, server_info->sanitized_username);
+       ret = strequal(pjob->user, server_info->unix_info->sanitized_username);
+err_out:
+       talloc_free(tmp_ctx);
+       return ret;
 }
 
 /****************************************************************************
  Delete a print job.
 ****************************************************************************/
 
-WERROR print_job_delete(struct auth_serversupplied_info *server_info,
+WERROR print_job_delete(const struct auth_session_info *server_info,
                        struct messaging_context *msg_ctx,
                        int snum, uint32_t jobid)
 {
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
        bool    owner;
-       char    *fname;
+       WERROR werr;
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
+               return WERR_NOT_ENOUGH_MEMORY;
+       }
 
        owner = is_owner(server_info, lp_const_servicename(snum), jobid);
 
@@ -2135,11 +2243,12 @@ WERROR print_job_delete(struct auth_serversupplied_info *server_info,
                sys_adminlog( LOG_ERR,
                              "Permission denied-- user not allowed to delete, \
 pause, or resume print job. User name: %s. Printer name: %s.",
-                             uidtoname(server_info->utok.uid),
+                             uidtoname(server_info->unix_token->uid),
                              lp_printername(snum) );
                /* END_ADMIN_LOG */
 
-               return WERR_ACCESS_DENIED;
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
 
        /*
@@ -2149,58 +2258,70 @@ pause, or resume print job. User name: %s. Printer name: %s.",
         * spool file & return.
         */
 
-       fname = print_job_fname(sharename, jobid);
-       if (fname != NULL) {
-               /* remove the spool file */
-               DEBUG(10, ("print_job_delete: "
-                          "Removing spool file [%s]\n", fname));
-               if (unlink(fname) == -1) {
-                       return map_werror_from_unix(errno);
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob || pjob->spooled || pjob->pid != getpid()) {
+               DEBUG(10, ("Skipping spool file removal for job %u\n", jobid));
+       } else {
+               DEBUG(10, ("Removing spool file [%s]\n", pjob->filename));
+               if (unlink(pjob->filename) == -1) {
+                       werr = map_werror_from_unix(errno);
+                       goto err_out;
                }
        }
 
-       if (!print_job_delete1(snum, jobid)) {
-               return WERR_ACCESS_DENIED;
+       if (!print_job_delete1(server_event_context(), msg_ctx, snum, jobid)) {
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
 
        /* force update the database and say the delete failed if the
            job still exists */
 
-       print_queue_update(snum, True);
+       print_queue_update(msg_ctx, snum, True);
 
-       pjob = print_job_find(sharename, jobid);
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (pjob && (pjob->status != LPQ_DELETING)) {
-               return WERR_ACCESS_DENIED;
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
+       werr = WERR_PRINTER_HAS_JOBS_QUEUED;
 
-       return WERR_PRINTER_HAS_JOBS_QUEUED;
+err_out:
+       talloc_free(tmp_ctx);
+       return werr;
 }
 
 /****************************************************************************
  Pause a job.
 ****************************************************************************/
 
-bool print_job_pause(struct auth_serversupplied_info *server_info,
+WERROR print_job_pause(const struct auth_session_info *server_info,
                     struct messaging_context *msg_ctx,
-                    int snum, uint32 jobid, WERROR *errcode)
+                    int snum, uint32 jobid)
 {
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
        int ret = -1;
        struct printif *current_printif = get_printer_fns( snum );
+       WERROR werr;
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
+               return WERR_NOT_ENOUGH_MEMORY;
+       }
 
-       pjob = print_job_find(sharename, jobid);
-
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (!pjob || !server_info) {
                DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
                        (unsigned int)jobid ));
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        if (!pjob->spooled || pjob->sysjob == -1) {
                DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
                        (int)pjob->sysjob, (unsigned int)jobid ));
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
@@ -2212,20 +2333,20 @@ bool print_job_pause(struct auth_serversupplied_info *server_info,
                sys_adminlog( LOG_ERR,
                        "Permission denied-- user not allowed to delete, \
 pause, or resume print job. User name: %s. Printer name: %s.",
-                             uidtoname(server_info->utok.uid),
+                             uidtoname(server_info->unix_token->uid),
                              lp_printername(snum) );
                /* END_ADMIN_LOG */
 
-               *errcode = WERR_ACCESS_DENIED;
-               return False;
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
 
        /* need to pause the spooled entry */
        ret = (*(current_printif->job_pause))(snum, pjob);
 
        if (ret != 0) {
-               *errcode = WERR_INVALID_PARAM;
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        /* force update the database */
@@ -2233,61 +2354,69 @@ pause, or resume print job. User name: %s. Printer name: %s.",
 
        /* Send a printer notify message */
 
-       notify_job_status(sharename, jobid, JOB_STATUS_PAUSED);
+       notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
+                         JOB_STATUS_PAUSED);
 
        /* how do we tell if this succeeded? */
-
-       return True;
+       werr = WERR_OK;
+err_out:
+       talloc_free(tmp_ctx);
+       return werr;
 }
 
 /****************************************************************************
  Resume a job.
 ****************************************************************************/
 
-bool print_job_resume(struct auth_serversupplied_info *server_info,
+WERROR print_job_resume(const struct auth_session_info *server_info,
                      struct messaging_context *msg_ctx,
-                     int snum, uint32 jobid, WERROR *errcode)
+                     int snum, uint32 jobid)
 {
        const char *sharename = lp_const_servicename(snum);
        struct printjob *pjob;
        int ret;
        struct printif *current_printif = get_printer_fns( snum );
+       WERROR werr;
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL)
+               return WERR_NOT_ENOUGH_MEMORY;
 
-       pjob = print_job_find(sharename, jobid);
-
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (!pjob || !server_info) {
                DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
                        (unsigned int)jobid ));
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        if (!pjob->spooled || pjob->sysjob == -1) {
                DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
                        (int)pjob->sysjob, (unsigned int)jobid ));
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        if (!is_owner(server_info, lp_const_servicename(snum), jobid) &&
            !print_access_check(server_info, msg_ctx, snum,
                                JOB_ACCESS_ADMINISTER)) {
                DEBUG(3, ("resume denied by security descriptor\n"));
-               *errcode = WERR_ACCESS_DENIED;
 
                /* BEGIN_ADMIN_LOG */
                sys_adminlog( LOG_ERR,
                         "Permission denied-- user not allowed to delete, \
 pause, or resume print job. User name: %s. Printer name: %s.",
-                             uidtoname(server_info->utok.uid),
+                             uidtoname(server_info->unix_token->uid),
                              lp_printername(snum) );
                /* END_ADMIN_LOG */
-               return False;
+               werr = WERR_ACCESS_DENIED;
+               goto err_out;
        }
 
        ret = (*(current_printif->job_resume))(snum, pjob);
 
        if (ret != 0) {
-               *errcode = WERR_INVALID_PARAM;
-               return False;
+               werr = WERR_INVALID_PARAM;
+               goto err_out;
        }
 
        /* force update the database */
@@ -2295,40 +2424,56 @@ pause, or resume print job. User name: %s. Printer name: %s.",
 
        /* Send a printer notify message */
 
-       notify_job_status(sharename, jobid, JOB_STATUS_QUEUED);
+       notify_job_status(server_event_context(), msg_ctx, sharename, jobid,
+                         JOB_STATUS_QUEUED);
 
-       return True;
+       werr = WERR_OK;
+err_out:
+       talloc_free(tmp_ctx);
+       return werr;
 }
 
 /****************************************************************************
  Write to a print file.
 ****************************************************************************/
 
-ssize_t print_job_write(int snum, uint32 jobid, const char *buf, SMB_OFF_T pos, size_t size)
+ssize_t print_job_write(struct tevent_context *ev,
+                       struct messaging_context *msg_ctx,
+                       int snum, uint32 jobid, const char *buf, size_t size)
 {
        const char* sharename = lp_const_servicename(snum);
        ssize_t return_code;
        struct printjob *pjob;
+       TALLOC_CTX *tmp_ctx = talloc_new(ev);
+       if (tmp_ctx == NULL) {
+               return -1;
+       }
 
-       pjob = print_job_find(sharename, jobid);
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob) {
+               return_code = -1;
+               goto err_out;
+       }
 
-       if (!pjob)
-               return -1;
        /* don't allow another process to get this info - it is meaningless */
-       if (pjob->pid != sys_getpid())
-               return -1;
+       if (pjob->pid != getpid()) {
+               return_code = -1;
+               goto err_out;
+       }
 
        /* if SMBD is spooling this can't be allowed */
        if (pjob->status == PJOB_SMBD_SPOOLING) {
-               return -1;
+               return_code = -1;
+               goto err_out;
        }
 
-       return_code = write_data_at_offset(pjob->fd, buf, size, pos);
-
-       if (return_code>0) {
+       return_code = write_data(pjob->fd, buf, size);
+       if (return_code > 0) {
                pjob->size += size;
-               pjob_store(sharename, jobid, pjob);
+               pjob_store(ev, msg_ctx, sharename, jobid, pjob);
        }
+err_out:
+       talloc_free(tmp_ctx);
        return return_code;
 }
 
@@ -2352,7 +2497,7 @@ static int get_queue_status(const char* sharename, print_status_struct *status)
 
        if (status) {
                fstr_sprintf(keystr, "STATUS/%s", sharename);
-               data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
+               data = tdb_fetch_compat(pdb->tdb, string_tdb_data(keystr));
                if (data.dptr) {
                        if (data.dsize == sizeof(print_status_struct))
                                /* this memcpy is ok since the status struct was
@@ -2370,7 +2515,8 @@ static int get_queue_status(const char* sharename, print_status_struct *status)
  Determine the number of jobs in a queue.
 ****************************************************************************/
 
-int print_queue_length(int snum, print_status_struct *pstatus)
+int print_queue_length(struct messaging_context *msg_ctx, int snum,
+                      print_status_struct *pstatus)
 {
        const char* sharename = lp_const_servicename( snum );
        print_status_struct status;
@@ -2380,7 +2526,7 @@ int print_queue_length(int snum, print_status_struct *pstatus)
 
        /* make sure the database is up to date */
        if (print_cache_expired(lp_const_servicename(snum), True))
-               print_queue_update(snum, False);
+               print_queue_update(msg_ctx, snum, False);
 
        /* also fetch the queue status */
        memset(&status, 0, sizeof(status));
@@ -2410,7 +2556,7 @@ static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
                /* Lock the database - only wait 20 seconds. */
                ret = tdb_lock_bystring_with_timeout(pdb->tdb,
                                                     "INFO/nextjob", 20);
-               if (ret == -1) {
+               if (ret != 0) {
                        DEBUG(0, ("allocate_print_jobid: "
                                  "Failed to lock printing database %s\n",
                                  sharename));
@@ -2438,7 +2584,7 @@ static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
                jobid = NEXT_JOBID(jobid);
 
                ret = tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid);
-               if (ret == -1) {
+               if (ret != 0) {
                        terr = tdb_error(pdb->tdb);
                        DEBUG(3, ("allocate_print_jobid: "
                                  "Failed to store INFO/nextjob.\n"));
@@ -2471,7 +2617,7 @@ static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
                dum.dptr = NULL;
                dum.dsize = 0;
                if (tdb_store(pdb->tdb, print_key(jobid, &tmp), dum,
-                             TDB_INSERT) == -1) {
+                             TDB_INSERT) != 0) {
                        DEBUG(3, ("allocate_print_jobid: "
                                  "jobid (%d) failed to store placeholder.\n",
                                  jobid ));
@@ -2485,10 +2631,10 @@ static WERROR allocate_print_jobid(struct tdb_print_db *pdb, int snum,
 }
 
 /***************************************************************************
- Append a jobid to the 'jobs changed' list.
+ Append a jobid to the 'jobs added' list.
 ***************************************************************************/
 
-static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
+static bool add_to_jobs_added(struct tdb_print_db *pdb, uint32 jobid)
 {
        TDB_DATA data;
        uint32 store_jobid;
@@ -2497,9 +2643,9 @@ static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
        data.dptr = (uint8 *)&store_jobid;
        data.dsize = 4;
 
-       DEBUG(10,("add_to_jobs_changed: Added jobid %u\n", (unsigned int)jobid ));
+       DEBUG(10,("add_to_jobs_added: Added jobid %u\n", (unsigned int)jobid ));
 
-       return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
+       return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_added"),
                           data) == 0);
 }
 
@@ -2508,7 +2654,7 @@ static bool add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
  Do all checks needed to determine if we can start a job.
 ***************************************************************************/
 
-static WERROR print_job_checks(struct auth_serversupplied_info *server_info,
+static WERROR print_job_checks(const struct auth_session_info *server_info,
                               struct messaging_context *msg_ctx,
                               int snum, int *njobs)
 {
@@ -2549,7 +2695,7 @@ static WERROR print_job_checks(struct auth_serversupplied_info *server_info,
        }
 
        /* Insure the maximum queue size is not violated */
-       *njobs = print_queue_length(snum, NULL);
+       *njobs = print_queue_length(msg_ctx, snum, NULL);
        if (*njobs > lp_maxprintjobs(snum)) {
                DEBUG(3, ("print_job_checks: Queue %s number of jobs (%d) "
                          "larger than max printjobs per queue (%d).\n",
@@ -2634,8 +2780,9 @@ static WERROR print_job_spool_file(int snum, uint32_t jobid,
  Start spooling a job - return the jobid.
 ***************************************************************************/
 
-WERROR print_job_start(struct auth_serversupplied_info *server_info,
+WERROR print_job_start(const struct auth_session_info *server_info,
                       struct messaging_context *msg_ctx,
+                      const char *clientmachine,
                       int snum, const char *docname, const char *filename,
                       struct spoolss_DeviceMode *devmode, uint32_t *_jobid)
 {
@@ -2672,7 +2819,8 @@ WERROR print_job_start(struct auth_serversupplied_info *server_info,
 
        ZERO_STRUCT(pjob);
 
-       pjob.pid = sys_getpid();
+       pjob.pid = getpid();
+       pjob.jobid = jobid;
        pjob.sysjob = -1;
        pjob.fd = -1;
        pjob.starttime = time(NULL);
@@ -2684,14 +2832,14 @@ WERROR print_job_start(struct auth_serversupplied_info *server_info,
 
        fstrcpy(pjob.jobname, docname);
 
+       fstrcpy(pjob.clientmachine, clientmachine);
+
        fstrcpy(pjob.user, lp_printjob_username(snum));
-       standard_sub_advanced(sharename, server_info->sanitized_username,
-                             path, server_info->utok.gid,
-                             server_info->sanitized_username,
-                             server_info->info3->base.domain.string,
-                             pjob.user, sizeof(pjob.user)-1);
-       /* ensure NULL termination */
-       pjob.user[sizeof(pjob.user)-1] = '\0';
+       standard_sub_advanced(sharename, server_info->unix_info->sanitized_username,
+                             path, server_info->unix_token->gid,
+                             server_info->unix_info->sanitized_username,
+                             server_info->info->domain_name,
+                             pjob.user, sizeof(pjob.user));
 
        fstrcpy(pjob.queuename, lp_const_servicename(snum));
 
@@ -2701,10 +2849,10 @@ WERROR print_job_start(struct auth_serversupplied_info *server_info,
                goto fail;
        }
 
-       pjob_store(sharename, jobid, &pjob);
+       pjob_store(server_event_context(), msg_ctx, sharename, jobid, &pjob);
 
-       /* Update the 'jobs changed' entry used by print_queue_status. */
-       add_to_jobs_changed(pdb, jobid);
+       /* Update the 'jobs added' entry used by print_queue_status. */
+       add_to_jobs_added(pdb, jobid);
 
        /* Ensure we keep a rough count of the number of total jobs... */
        tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
@@ -2716,7 +2864,7 @@ WERROR print_job_start(struct auth_serversupplied_info *server_info,
 
 fail:
        if (jobid != -1) {
-               pjob_delete(sharename, jobid);
+               pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
        }
 
        release_print_db(pdb);
@@ -2730,20 +2878,29 @@ fail:
  Update the number of pages spooled to jobid
 ****************************************************************************/
 
-void print_job_endpage(int snum, uint32 jobid)
+void print_job_endpage(struct messaging_context *msg_ctx,
+                      int snum, uint32 jobid)
 {
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
-
-       pjob = print_job_find(sharename, jobid);
-       if (!pjob)
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
                return;
+       }
+
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
+       if (!pjob) {
+               goto err_out;
+       }
        /* don't allow another process to get this info - it is meaningless */
-       if (pjob->pid != sys_getpid())
-               return;
+       if (pjob->pid != getpid()) {
+               goto err_out;
+       }
 
        pjob->page_count++;
-       pjob_store(sharename, jobid, pjob);
+       pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
+err_out:
+       talloc_free(tmp_ctx);
 }
 
 /****************************************************************************
@@ -2752,23 +2909,29 @@ void print_job_endpage(int snum, uint32 jobid)
  error.
 ****************************************************************************/
 
-NTSTATUS print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
+NTSTATUS print_job_end(struct messaging_context *msg_ctx, int snum,
+                      uint32 jobid, enum file_close_type close_type)
 {
        const char* sharename = lp_const_servicename(snum);
        struct printjob *pjob;
        int ret;
        SMB_STRUCT_STAT sbuf;
-       struct printif *current_printif = get_printer_fns( snum );
+       struct printif *current_printif = get_printer_fns(snum);
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       pjob = print_job_find(sharename, jobid);
-
+       pjob = print_job_find(tmp_ctx, sharename, jobid);
        if (!pjob) {
-               return NT_STATUS_PRINT_CANCELLED;
+               status = NT_STATUS_PRINT_CANCELLED;
+               goto err_out;
        }
 
-       if (pjob->spooled || pjob->pid != sys_getpid()) {
-               return NT_STATUS_ACCESS_DENIED;
+       if (pjob->spooled || pjob->pid != getpid()) {
+               status = NT_STATUS_ACCESS_DENIED;
+               goto err_out;
        }
 
        if (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) {
@@ -2818,7 +2981,7 @@ NTSTATUS print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
                DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
                        pjob->filename, pjob->size ? "deleted" : "zero length" ));
                unlink(pjob->filename);
-               pjob_delete(sharename, jobid);
+               pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
                return NT_STATUS_OK;
        }
 
@@ -2833,11 +2996,11 @@ NTSTATUS print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
 
        pjob->spooled = True;
        pjob->status = LPQ_QUEUED;
-       pjob_store(sharename, jobid, pjob);
+       pjob_store(server_event_context(), msg_ctx, sharename, jobid, pjob);
 
        /* make sure the database is up to date */
        if (print_cache_expired(lp_const_servicename(snum), True))
-               print_queue_update(snum, False);
+               print_queue_update(msg_ctx, snum, False);
 
        return NT_STATUS_OK;
 
@@ -2847,7 +3010,9 @@ fail:
        /* Still need to add proper error return propagation! 010122:JRR */
        pjob->fd = -1;
        unlink(pjob->filename);
-       pjob_delete(sharename, jobid);
+       pjob_delete(server_event_context(), msg_ctx, sharename, jobid);
+err_out:
+       talloc_free(tmp_ctx);
        return status;
 }
 
@@ -2855,22 +3020,29 @@ fail:
  Get a snapshot of jobs in the system without traversing.
 ****************************************************************************/
 
-static bool get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcount, print_queue_struct **ppqueue)
+static bool get_stored_queue_info(struct messaging_context *msg_ctx,
+                                 struct tdb_print_db *pdb, int snum,
+                                 int *pcount, print_queue_struct **ppqueue)
 {
-       TDB_DATA data, cgdata;
+       TDB_DATA data, cgdata, jcdata;
        print_queue_struct *queue = NULL;
        uint32 qcount = 0;
        uint32 extra_count = 0;
+       uint32_t changed_count = 0;
        int total_count = 0;
        size_t len = 0;
        uint32 i;
        int max_reported_jobs = lp_max_reported_jobs(snum);
        bool ret = False;
        const char* sharename = lp_servicename(snum);
+       TALLOC_CTX *tmp_ctx = talloc_new(msg_ctx);
+       if (tmp_ctx == NULL) {
+               return false;
+       }
 
        /* make sure the database is up to date */
        if (print_cache_expired(lp_const_servicename(snum), True))
-               print_queue_update(snum, False);
+               print_queue_update(msg_ctx, snum, False);
 
        *pcount = 0;
        *ppqueue = NULL;
@@ -2879,16 +3051,21 @@ static bool get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun
        ZERO_STRUCT(cgdata);
 
        /* Get the stored queue data. */
-       data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
+       data = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
 
        if (data.dptr && data.dsize >= sizeof(qcount))
                len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
 
-       /* Get the changed jobs list. */
-       cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
+       /* Get the added jobs list. */
+       cgdata = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_added"));
        if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
                extra_count = cgdata.dsize/4;
 
+       /* Get the changed jobs list. */
+       jcdata = tdb_fetch_compat(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
+       if (jcdata.dptr != NULL && (jcdata.dsize % 4 == 0))
+               changed_count = jcdata.dsize / 4;
+
        DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
 
        /* Allocate the queue size. */
@@ -2911,7 +3088,7 @@ static bool get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun
                                &qtime,
                                queue[i].fs_user,
                                queue[i].fs_file);
-               queue[i].job = qjob;
+               queue[i].sysjob = qjob;
                queue[i].size = qsize;
                queue[i].page_count = qpage_count;
                queue[i].status = qstatus;
@@ -2921,21 +3098,21 @@ static bool get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun
 
        total_count = qcount;
 
-       /* Add in the changed jobids. */
+       /* Add new jobids to the queue. */
        for( i  = 0; i < extra_count; i++) {
                uint32 jobid;
                struct printjob *pjob;
 
                jobid = IVAL(cgdata.dptr, i*4);
-               DEBUG(5,("get_stored_queue_info: changed job = %u\n", (unsigned int)jobid));
-               pjob = print_job_find(lp_const_servicename(snum), jobid);
+               DEBUG(5,("get_stored_queue_info: added job = %u\n", (unsigned int)jobid));
+               pjob = print_job_find(tmp_ctx, lp_const_servicename(snum), jobid);
                if (!pjob) {
-                       DEBUG(5,("get_stored_queue_info: failed to find changed job = %u\n", (unsigned int)jobid));
-                       remove_from_jobs_changed(sharename, jobid);
+                       DEBUG(5,("get_stored_queue_info: failed to find added job = %u\n", (unsigned int)jobid));
+                       remove_from_jobs_added(sharename, jobid);
                        continue;
                }
 
-               queue[total_count].job = jobid;
+               queue[total_count].sysjob = jobid;
                queue[total_count].size = pjob->size;
                queue[total_count].page_count = pjob->page_count;
                queue[total_count].status = pjob->status;
@@ -2944,6 +3121,52 @@ static bool get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun
                fstrcpy(queue[total_count].fs_user, pjob->user);
                fstrcpy(queue[total_count].fs_file, pjob->jobname);
                total_count++;
+               talloc_free(pjob);
+       }
+
+       /* Update the changed jobids. */
+       for (i = 0; i < changed_count; i++) {
+               uint32_t jobid = IVAL(jcdata.dptr, i * 4);
+               uint32_t j;
+               bool found = false;
+
+               for (j = 0; j < total_count; j++) {
+                       if (queue[j].sysjob == jobid) {
+                               found = true;
+                               break;
+                       }
+               }
+
+               if (found) {
+                       struct printjob *pjob;
+
+                       DEBUG(5,("get_stored_queue_info: changed job: %u\n",
+                                (unsigned int) jobid));
+
+                       pjob = print_job_find(tmp_ctx, sharename, jobid);
+                       if (pjob == NULL) {
+                               DEBUG(5,("get_stored_queue_info: failed to find "
+                                        "changed job = %u\n",
+                                        (unsigned int) jobid));
+                               remove_from_jobs_changed(sharename, jobid);
+                               continue;
+                       }
+
+                       queue[j].sysjob = jobid;
+                       queue[j].size = pjob->size;
+                       queue[j].page_count = pjob->page_count;
+                       queue[j].status = pjob->status;
+                       queue[j].priority = 1;
+                       queue[j].time = pjob->starttime;
+                       fstrcpy(queue[j].fs_user, pjob->user);
+                       fstrcpy(queue[j].fs_file, pjob->jobname);
+                       talloc_free(pjob);
+
+                       DEBUG(5,("get_stored_queue_info: updated queue[%u], jobid: %u, jobname: %s\n",
+                                (unsigned int) j, (unsigned int) jobid, pjob->jobname));
+               }
+
+               remove_from_jobs_changed(sharename, jobid);
        }
 
        /* Sort the queue by submission time otherwise they are displayed
@@ -2965,6 +3188,7 @@ static bool get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun
 
        SAFE_FREE(data.dptr);
        SAFE_FREE(cgdata.dptr);
+       talloc_free(tmp_ctx);
        return ret;
 }
 
@@ -2973,7 +3197,7 @@ static bool get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun
  set queue = NULL and status = NULL if you just want to update the cache
 ****************************************************************************/
 
-int print_queue_status(int snum,
+int print_queue_status(struct messaging_context *msg_ctx, int snum,
                       print_queue_struct **ppqueue,
                       print_status_struct *status)
 {
@@ -2986,7 +3210,7 @@ int print_queue_status(int snum,
        /* make sure the database is up to date */
 
        if (print_cache_expired(lp_const_servicename(snum), True))
-               print_queue_update(snum, False);
+               print_queue_update(msg_ctx, snum, False);
 
        /* return if we are done */
        if ( !ppqueue || !status )
@@ -3008,7 +3232,7 @@ int print_queue_status(int snum,
        slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
        key = string_tdb_data(keystr);
 
-       data = tdb_fetch(pdb->tdb, key);
+       data = tdb_fetch_compat(pdb->tdb, key);
        if (data.dptr) {
                if (data.dsize == sizeof(*status)) {
                        /* this memcpy is ok since the status struct was
@@ -3023,7 +3247,7 @@ int print_queue_status(int snum,
         * of entries, and then only retrieve the queue if necessary.
         */
 
-       if (!get_stored_queue_info(pdb, snum, &count, ppqueue)) {
+       if (!get_stored_queue_info(msg_ctx, pdb, snum, &count, ppqueue)) {
                release_print_db(pdb);
                return 0;
        }
@@ -3036,7 +3260,7 @@ int print_queue_status(int snum,
  Pause a queue.
 ****************************************************************************/
 
-WERROR print_queue_pause(struct auth_serversupplied_info *server_info,
+WERROR print_queue_pause(const struct auth_session_info *server_info,
                         struct messaging_context *msg_ctx, int snum)
 {
        int ret;
@@ -3063,7 +3287,8 @@ WERROR print_queue_pause(struct auth_serversupplied_info *server_info,
 
        /* Send a printer notify message */
 
-       notify_printer_status(snum, PRINTER_STATUS_PAUSED);
+       notify_printer_status(server_event_context(), msg_ctx, snum,
+                             PRINTER_STATUS_PAUSED);
 
        return WERR_OK;
 }
@@ -3072,7 +3297,7 @@ WERROR print_queue_pause(struct auth_serversupplied_info *server_info,
  Resume a queue.
 ****************************************************************************/
 
-WERROR print_queue_resume(struct auth_serversupplied_info *server_info,
+WERROR print_queue_resume(const struct auth_session_info *server_info,
                          struct messaging_context *msg_ctx, int snum)
 {
        int ret;
@@ -3095,11 +3320,12 @@ WERROR print_queue_resume(struct auth_serversupplied_info *server_info,
 
        /* make sure the database is up to date */
        if (print_cache_expired(lp_const_servicename(snum), True))
-               print_queue_update(snum, True);
+               print_queue_update(msg_ctx, snum, True);
 
        /* Send a printer notify message */
 
-       notify_printer_status(snum, PRINTER_STATUS_OK);
+       notify_printer_status(server_event_context(), msg_ctx, snum,
+                             PRINTER_STATUS_OK);
 
        return WERR_OK;
 }
@@ -3108,7 +3334,7 @@ WERROR print_queue_resume(struct auth_serversupplied_info *server_info,
  Purge a queue - implemented by deleting all jobs that we can delete.
 ****************************************************************************/
 
-WERROR print_queue_purge(struct auth_serversupplied_info *server_info,
+WERROR print_queue_purge(const struct auth_session_info *server_info,
                         struct messaging_context *msg_ctx, int snum)
 {
        print_queue_struct *queue;
@@ -3117,23 +3343,24 @@ WERROR print_queue_purge(struct auth_serversupplied_info *server_info,
        bool can_job_admin;
 
        /* Force and update so the count is accurate (i.e. not a cached count) */
-       print_queue_update(snum, True);
+       print_queue_update(msg_ctx, snum, True);
 
        can_job_admin = print_access_check(server_info,
                                           msg_ctx,
                                           snum,
                                           JOB_ACCESS_ADMINISTER);
-       njobs = print_queue_status(snum, &queue, &status);
+       njobs = print_queue_status(msg_ctx, snum, &queue, &status);
 
        if ( can_job_admin )
                become_root();
 
        for (i=0;i<njobs;i++) {
                bool owner = is_owner(server_info, lp_const_servicename(snum),
-                                     queue[i].job);
+                                     queue[i].sysjob);
 
                if (owner || can_job_admin) {
-                       print_job_delete1(snum, queue[i].job);
+                       print_job_delete1(server_event_context(), msg_ctx,
+                                         snum, queue[i].sysjob);
                }
        }
 
@@ -3141,7 +3368,7 @@ WERROR print_queue_purge(struct auth_serversupplied_info *server_info,
                unbecome_root();
 
        /* update the cache */
-       print_queue_update( snum, True );
+       print_queue_update(msg_ctx, snum, True);
 
        SAFE_FREE(queue);