spoolss: clear FormInfo on GetForm error
[obnox/samba/samba-obnox.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
index 71ae93766a2a604c859bbdbd705e0d02bf5d9cdd..9b898d0ab539a3aafe0481b91e7756c9bd25e3be 100644 (file)
@@ -38,7 +38,6 @@
 #include "../libcli/security/security.h"
 #include "librpc/gen_ndr/ndr_security.h"
 #include "registry.h"
-#include "registry/reg_objects.h"
 #include "include/printing.h"
 #include "secrets.h"
 #include "../librpc/gen_ndr/netlogon.h"
@@ -56,6 +55,7 @@
 #include "printing/printer_list.h"
 #include "../lib/tsocket/tsocket.h"
 #include "rpc_client/cli_winreg_spoolss.h"
+#include "../libcli/smb/smbXcli_base.h"
 
 /* macros stolen from s4 spoolss server */
 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
@@ -138,7 +138,7 @@ struct notify_back_channel {
 
        /* print notify back-channel pipe handle*/
        struct rpc_pipe_client *cli_pipe;
-       struct dcerpc_binding_handle *binding_handle;
+       struct cli_state *cli;
        uint32_t active_connections;
 };
 
@@ -251,6 +251,8 @@ static void srv_spoolss_replycloseprinter(int snum,
 
        /* weird if the test succeeds !!! */
        if (prn_hnd->notify.cli_chan == NULL ||
+           prn_hnd->notify.cli_chan->cli_pipe == NULL ||
+           prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
            prn_hnd->notify.cli_chan->active_connections == 0) {
                DEBUG(0, ("Trying to close unexisting backchannel!\n"));
                DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
@@ -259,7 +261,7 @@ static void srv_spoolss_replycloseprinter(int snum,
        }
 
        status = dcerpc_spoolss_ReplyClosePrinter(
-                                       prn_hnd->notify.cli_chan->binding_handle,
+                                       prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
                                        talloc_tos(),
                                        &prn_hnd->notify.cli_hnd,
                                        &result);
@@ -275,28 +277,19 @@ static void srv_spoolss_replycloseprinter(int snum,
        /* if it's the last connection, deconnect the IPC$ share */
        if (prn_hnd->notify.cli_chan->active_connections == 1) {
 
-               prn_hnd->notify.cli_chan->binding_handle = NULL;
-               cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
+               cli_shutdown(prn_hnd->notify.cli_chan->cli);
                DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
                TALLOC_FREE(prn_hnd->notify.cli_chan);
 
                if (prn_hnd->notify.msg_ctx != NULL) {
                        messaging_deregister(prn_hnd->notify.msg_ctx,
                                             MSG_PRINTER_NOTIFY2, NULL);
-
-                       /*
-                        * Tell the serverid.tdb we're no longer
-                        * interested in printer notify messages.
-                        */
-
-                       serverid_register_msg_flags(
-                               messaging_server_id(prn_hnd->notify.msg_ctx),
-                               false, FLAG_MSG_PRINT_NOTIFY);
                }
        }
 
        if (prn_hnd->notify.cli_chan) {
                prn_hnd->notify.cli_chan->active_connections--;
+               prn_hnd->notify.cli_chan = NULL;
        }
 }
 
@@ -382,7 +375,7 @@ static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
                                  const char *sharename,
                                  struct messaging_context *msg_ctx)
 {
-       char *cmd = lp_deleteprinter_cmd();
+       char *cmd = lp_deleteprinter_command(talloc_tos());
        char *command = NULL;
        int ret;
        bool is_print_op = false;
@@ -425,14 +418,6 @@ static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
        if (ret != 0)
                return WERR_BADFID; /* What to return here? */
 
-       /* go ahead and re-read the services immediately */
-       become_root();
-       reload_services(msg_ctx, -1, false);
-       unbecome_root();
-
-       if ( lp_servicenumber( sharename ) >= 0 )
-               return WERR_ACCESS_DENIED;
-
        return WERR_OK;
 }
 
@@ -554,7 +539,7 @@ static void prune_printername_cache(void)
 ****************************************************************************/
 
 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
-                                  const struct auth3_session_info *session_info,
+                                  const struct auth_session_info *session_info,
                                   struct messaging_context *msg_ctx,
                                   struct printer_handle *Printer,
                                   const char *handlename)
@@ -646,16 +631,17 @@ static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
 
        cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
                                    aprinter);
-       if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
+       if ((cache_key != NULL) &&
+           gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
 
                found = (strcmp(tmp, printer_not_found) != 0);
                if (!found) {
                        DEBUG(4, ("Printer %s not found\n", aprinter));
-                       SAFE_FREE(tmp);
+                       TALLOC_FREE(tmp);
                        return WERR_INVALID_PRINTER_NAME;
                }
                fstrcpy(sname, tmp);
-               SAFE_FREE(tmp);
+               TALLOC_FREE(tmp);
        }
 
        /* Search all sharenames first as this is easier than pulling
@@ -667,7 +653,7 @@ static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
                const char *printer = lp_const_servicename(snum);
 
                /* no point going on if this is not a printer */
-               if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
+               if (!(lp_snum_ok(snum) && lp_printable(snum))) {
                        continue;
                }
 
@@ -860,14 +846,6 @@ static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
        _data->data.devmode.devmode = _devmode;
 
-#define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
-       _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
-       if (!_data->data.sd.sd) { \
-               _data->data.sd.sd_size = 0; \
-       } \
-       _data->data.sd.sd_size = \
-               ndr_size_security_descriptor(_data->data.sd.sd, 0);
-
 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
                                   struct tm *t,
                                   const char **pp,
@@ -1255,6 +1233,8 @@ static int send_notify2_printer(TALLOC_CTX *mem_ctx,
 
        /* Is there notification on this handle? */
        if (prn_hnd->notify.cli_chan == NULL ||
+           prn_hnd->notify.cli_chan->cli_pipe == NULL ||
+           prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
            prn_hnd->notify.cli_chan->active_connections == 0) {
                return 0;
        }
@@ -1287,7 +1267,7 @@ static int send_notify2_printer(TALLOC_CTX *mem_ctx,
        info.info0 = &info0;
 
        status = dcerpc_spoolss_RouterReplyPrinterEx(
-                               prn_hnd->notify.cli_chan->binding_handle,
+                               prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
                                mem_ctx,
                                &prn_hnd->notify.cli_hnd,
                                prn_hnd->notify.change, /* color */
@@ -1527,6 +1507,7 @@ void srv_spoolss_cleanup(void)
 /**********************************************************************
  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
  over all printers, upgrading ones as necessary
+ This is now *ONLY* called inside the background lpq updater. JRA.
  **********************************************************************/
 
 void do_drv_upgrade_printer(struct messaging_context *msg,
@@ -1536,9 +1517,8 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
                            DATA_BLOB *data)
 {
        TALLOC_CTX *tmp_ctx;
-       struct auth3_session_info *session_info = NULL;
+       const struct auth_session_info *session_info = get_session_info_system();
        struct spoolss_PrinterInfo2 *pinfo2;
-       NTSTATUS status;
        WERROR result;
        const char *drivername;
        int snum;
@@ -1548,13 +1528,6 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
        tmp_ctx = talloc_new(NULL);
        if (!tmp_ctx) return;
 
-       status = make_session_info_system(tmp_ctx, &session_info);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("do_drv_upgrade_printer: "
-                         "Could not create system session_info\n"));
-               goto done;
-       }
-
        drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
        if (!drivername) {
                DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
@@ -1567,7 +1540,7 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
        /* Iterate the printer list */
 
        for (snum = 0; snum < n_services; snum++) {
-               if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
+               if (!lp_snum_ok(snum) || !lp_printable(snum)) {
                        continue;
                }
 
@@ -1654,15 +1627,17 @@ WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
                            struct spoolss_OpenPrinter *r)
 {
        struct spoolss_OpenPrinterEx e;
+       struct spoolss_UserLevel1 level1;
        WERROR werr;
 
-       ZERO_STRUCT(e.in.userlevel);
+       ZERO_STRUCT(level1);
 
        e.in.printername        = r->in.printername;
        e.in.datatype           = r->in.datatype;
        e.in.devmode_ctr        = r->in.devmode_ctr;
        e.in.access_mask        = r->in.access_mask;
-       e.in.level              = 0;
+       e.in.userlevel_ctr.level                = 1;
+       e.in.userlevel_ctr.user_info.level1     = &level1;
 
        e.out.handle            = r->out.handle;
 
@@ -1732,15 +1707,29 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
                return WERR_INVALID_PARAM;
        }
 
-       if (r->in.level > 3) {
+       if (!*r->in.printername) {
                return WERR_INVALID_PARAM;
        }
-       if ((r->in.level == 1 && !r->in.userlevel.level1) ||
-           (r->in.level == 2 && !r->in.userlevel.level2) ||
-           (r->in.level == 3 && !r->in.userlevel.level3)) {
+
+       if (r->in.userlevel_ctr.level > 3) {
+               return WERR_INVALID_PARAM;
+       }
+       if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
+           (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
+           (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
                return WERR_INVALID_PARAM;
        }
 
+       /*
+        * The printcap printer share inventory is updated on client
+        * enumeration. For clients that do not perform enumeration prior to
+        * access, such as cupssmbadd, we reinitialise the printer share
+        * inventory on open as well.
+        */
+       become_root();
+       delete_and_reload_printers(server_event_context(), p->msg_ctx);
+       unbecome_root();
+
        /* some sanity check because you can open a printer or a print server */
        /* aka: \\server\printer or \\server */
 
@@ -1748,7 +1737,7 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 
        result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
        if (!W_ERROR_IS_OK(result)) {
-               DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
+               DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
                        "for printer %s\n", r->in.printername));
                ZERO_STRUCTP(r->out.handle);
                return result;
@@ -1818,7 +1807,7 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 
                if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
                {
-                       if (!lp_ms_add_printer_wizard()) {
+                       if (!lp_show_add_printer_wizard()) {
                                close_printer_handle(p, r->out.handle);
                                ZERO_STRUCTP(r->out.handle);
                                return WERR_ACCESS_DENIED;
@@ -1829,13 +1818,8 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 
                        if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
                            !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
-                           !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
-                           !token_contains_name_in_list(
-                                   uidtoname(p->session_info->unix_token->uid),
-                                   p->session_info->info->domain_name,
-                                   NULL,
-                                   p->session_info->security_token,
-                                   lp_printer_admin(snum))) {
+                           !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
+                                               p->session_info->security_token)) {
                                close_printer_handle(p, r->out.handle);
                                ZERO_STRUCTP(r->out.handle);
                                DEBUG(3,("access DENIED as user is not root, "
@@ -1907,7 +1891,7 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
                        rhost = raddr;
                }
 
-               if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
+               if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
                                  rhost, raddr)) {
                        DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
                        ZERO_STRUCTP(r->out.handle);
@@ -1916,10 +1900,10 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 
                if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
                                   p->session_info->security_token, snum) ||
-                   !print_access_check(p->session_info,
-                                       p->msg_ctx,
-                                       snum,
-                                       r->in.access_mask)) {
+                   !W_ERROR_IS_OK(print_access_check(p->session_info,
+                                                     p->msg_ctx,
+                                                     snum,
+                                                     r->in.access_mask))) {
                        DEBUG(3, ("access DENIED for printer open\n"));
                        close_printer_handle(p, r->out.handle);
                        ZERO_STRUCTP(r->out.handle);
@@ -1961,24 +1945,12 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
         * save it here in case we get a job submission on this handle
         */
 
-        if ((Printer->printer_type != SPLHND_SERVER) &&
-            r->in.devmode_ctr.devmode) {
+        if ((Printer->printer_type != SPLHND_SERVER)
+         && (r->in.devmode_ctr.devmode != NULL)) {
                copy_devicemode(NULL, r->in.devmode_ctr.devmode,
                                &Printer->devmode);
         }
 
-#if 0  /* JERRY -- I'm doubtful this is really effective */
-       /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
-          optimization in Windows 2000 clients  --jerry */
-
-       if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
-               && (RA_WIN2K == get_remote_arch()) )
-       {
-               DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
-               sys_usleep( 500000 );
-       }
-#endif
-
        return WERR_OK;
 }
 
@@ -2061,6 +2033,12 @@ static const struct print_architecture_table_node archi_table[]= {
        {NULL,                   "",            -1 }
 };
 
+static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
+                                  SPOOLSS_DRIVER_VERSION_NT35,
+                                  SPOOLSS_DRIVER_VERSION_NT4,
+                                  SPOOLSS_DRIVER_VERSION_200X,
+                                  -1};
+
 static int get_version_id(const char *arch)
 {
        int i;
@@ -2083,98 +2061,135 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
 {
 
        struct spoolss_DriverInfo8 *info = NULL;
-       struct spoolss_DriverInfo8 *info_win2k = NULL;
        int                             version;
        WERROR                          status;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx = NULL;
+       int i;
+       bool found;
 
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
 
-       if ( (p->session_info->unix_token->uid != sec_initial_uid())
-            && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
-               && !token_contains_name_in_list(
-                       uidtoname(p->session_info->unix_token->uid),
-                       p->session_info->info->domain_name,
-                       NULL,
-                       p->session_info->security_token,
-                       lp_printer_admin(-1)) )
-       {
+       if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
+           !security_token_has_privilege(p->session_info->security_token,
+                                         SEC_PRIV_PRINT_OPERATOR)) {
                return WERR_ACCESS_DENIED;
        }
 
        /* check that we have a valid driver name first */
 
-       if ((version = get_version_id(r->in.architecture)) == -1)
+       if ((version = get_version_id(r->in.architecture)) == -1) {
                return WERR_INVALID_ENVIRONMENT;
+       }
+
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
 
-       status = winreg_printer_binding_handle(p->mem_ctx,
+       status = winreg_printer_binding_handle(tmp_ctx,
                                               get_session_info_system(),
                                               p->msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(status)) {
-               return status;
+               goto done;
        }
 
-       status = winreg_get_driver(p->mem_ctx, b,
-                                  r->in.architecture, r->in.driver,
-                                  version, &info);
-       if (!W_ERROR_IS_OK(status)) {
-               /* try for Win2k driver if "Windows NT x86" */
-
-               if ( version == 2 ) {
-                       version = 3;
-
-                       status = winreg_get_driver(p->mem_ctx, b,
-                                                  r->in.architecture,
-                                                  r->in.driver,
-                                                  version, &info);
-                       if (!W_ERROR_IS_OK(status)) {
-                               status = WERR_UNKNOWN_PRINTER_DRIVER;
-                               goto done;
-                       }
+       for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
+               status = winreg_get_driver(tmp_ctx, b,
+                                          r->in.architecture, r->in.driver,
+                                          drv_cversion[i], &info);
+               if (!W_ERROR_IS_OK(status)) {
+                       DEBUG(5, ("skipping del of driver with version %d\n",
+                                 drv_cversion[i]));
+                       continue;
                }
-               /* otherwise it was a failure */
-               else {
-                       status = WERR_UNKNOWN_PRINTER_DRIVER;
+               found = true;
+
+               if (printer_driver_in_use(tmp_ctx, b, info)) {
+                       status = WERR_PRINTER_DRIVER_IN_USE;
                        goto done;
                }
 
+               status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
+               if (!W_ERROR_IS_OK(status)) {
+                       DEBUG(0, ("failed del of driver with version %d\n",
+                                 drv_cversion[i]));
+                       goto done;
+               }
+       }
+       if (found == false) {
+               DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
+               status = WERR_UNKNOWN_PRINTER_DRIVER;
+       } else {
+               status = WERR_OK;
        }
 
-       if (printer_driver_in_use(p->mem_ctx,
-                                 get_session_info_system(),
-                                 p->msg_ctx,
-                                 info)) {
+done:
+       talloc_free(tmp_ctx);
+
+       return status;
+}
+
+static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
+                                 struct pipes_struct *p,
+                                 struct spoolss_DeletePrinterDriverEx *r,
+                                 struct dcerpc_binding_handle *b,
+                                 struct spoolss_DriverInfo8 *info)
+{
+       WERROR status;
+       bool delete_files;
+
+       if (printer_driver_in_use(mem_ctx, b, info)) {
                status = WERR_PRINTER_DRIVER_IN_USE;
                goto done;
        }
 
-       if (version == 2) {
-               status = winreg_get_driver(p->mem_ctx, b,
-                                          r->in.architecture,
-                                          r->in.driver, 3, &info_win2k);
-               if (W_ERROR_IS_OK(status)) {
-                       /* if we get to here, we now have 2 driver info structures to remove */
-                       /* remove the Win2k driver first*/
+       /*
+        * we have a couple of cases to consider.
+        * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
+        *     then the delete should fail if **any** files overlap with
+        *     other drivers
+        * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
+        *     non-overlapping files
+        * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
+        *     are set, then do not delete any files
+        * Refer to MSDN docs on DeletePrinterDriverEx() for details.
+        */
+
+       delete_files = r->in.delete_flags
+                       & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
 
-                       status = winreg_del_driver(p->mem_ctx, b,
-                                                  info_win2k, 3);
-                       talloc_free(info_win2k);
 
-                       /* this should not have failed---if it did, report to client */
-                       if (!W_ERROR_IS_OK(status)) {
-                               goto done;
-                       }
+       if (delete_files) {
+               bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
+               if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
+                       status = WERR_PRINTER_DRIVER_IN_USE;
+                       goto done;
                }
+               /*
+                * printer_driver_files_in_use() has trimmed overlapping files
+                * from info so they are not removed on DPD_DELETE_UNUSED_FILES
+                */
        }
 
-       status = winreg_del_driver(p->mem_ctx, b,
-                                  info, version);
 
-done:
-       talloc_free(info);
+       status = winreg_del_driver(mem_ctx, b, info, info->version);
+       if (!W_ERROR_IS_OK(status)) {
+               goto done;
+       }
+
+       /*
+        * now delete any associated files if delete_files is
+        * true. Even if this part failes, we return succes
+        * because the driver doesn not exist any more
+        */
+       if (delete_files) {
+               delete_driver_files(p->session_info, info);
+       }
 
+done:
        return status;
 }
 
@@ -2185,173 +2200,74 @@ done:
 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
                                      struct spoolss_DeletePrinterDriverEx *r)
 {
-       struct spoolss_DriverInfo8      *info = NULL;
-       struct spoolss_DriverInfo8      *info_win2k = NULL;
-       int                             version;
-       bool                            delete_files;
+       struct spoolss_DriverInfo8 *info = NULL;
        WERROR                          status;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx = NULL;
+       int i;
+       bool found;
 
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
 
-       if ( (p->session_info->unix_token->uid != sec_initial_uid())
-               && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
-               && !token_contains_name_in_list(
-                       uidtoname(p->session_info->unix_token->uid),
-                       p->session_info->info->domain_name,
-                       NULL,
-                       p->session_info->security_token, lp_printer_admin(-1)) )
-       {
+       if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
+           !security_token_has_privilege(p->session_info->security_token,
+                                         SEC_PRIV_PRINT_OPERATOR)) {
                return WERR_ACCESS_DENIED;
        }
 
        /* check that we have a valid driver name first */
-       if ((version = get_version_id(r->in.architecture)) == -1) {
+       if (get_version_id(r->in.architecture) == -1) {
                /* this is what NT returns */
                return WERR_INVALID_ENVIRONMENT;
        }
 
-       if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
-               version = r->in.version;
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
 
-       status = winreg_printer_binding_handle(p->mem_ctx,
+       status = winreg_printer_binding_handle(tmp_ctx,
                                               get_session_info_system(),
                                               p->msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(status)) {
-               return status;
+               goto done;
        }
 
-       status = winreg_get_driver(p->mem_ctx, b,
-                                  r->in.architecture,
-                                  r->in.driver,
-                                  version,
-                                  &info);
-       if (!W_ERROR_IS_OK(status)) {
-               status = WERR_UNKNOWN_PRINTER_DRIVER;
-
-               /*
-                * if the client asked for a specific version,
-                * or this is something other than Windows NT x86,
-                * then we've failed
-                */
-
-               if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
-                       goto done;
-
-               /* try for Win2k driver if "Windows NT x86" */
+       for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
+               if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
+                && (drv_cversion[i] != r->in.version)) {
+                       continue;
+               }
 
-               version = 3;
-               status = winreg_get_driver(info, b,
-                                          r->in.architecture,
-                                          r->in.driver,
-                                          version, &info);
+               /* check if a driver with this version exists before delete */
+               status = winreg_get_driver(tmp_ctx, b,
+                                          r->in.architecture, r->in.driver,
+                                          drv_cversion[i], &info);
                if (!W_ERROR_IS_OK(status)) {
-                       status = WERR_UNKNOWN_PRINTER_DRIVER;
-                       goto done;
+                       DEBUG(5, ("skipping del of driver with version %d\n",
+                                 drv_cversion[i]));
+                       continue;
                }
-       }
-
-       if (printer_driver_in_use(info,
-                                 get_session_info_system(),
-                                 p->msg_ctx,
-                                 info)) {
-               status = WERR_PRINTER_DRIVER_IN_USE;
-               goto done;
-       }
-
-       /*
-        * we have a couple of cases to consider.
-        * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
-        *     then the delete should fail if **any** files overlap with
-        *     other drivers
-        * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
-        *     non-overlapping files
-        * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
-        *     is set, the do not delete any files
-        * Refer to MSDN docs on DeletePrinterDriverEx() for details.
-        */
-
-       delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
-
-       /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
-
-       if (delete_files &&
-           (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
-           printer_driver_files_in_use(info,
-                                       get_session_info_system(),
-                                       p->msg_ctx,
-                                       info)) {
-               /* no idea of the correct error here */
-               status = WERR_ACCESS_DENIED;
-               goto done;
-       }
-
-
-       /* also check for W32X86/3 if necessary; maybe we already have? */
-
-       if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
-               status = winreg_get_driver(info, b,
-                                          r->in.architecture,
-                                          r->in.driver, 3, &info_win2k);
-               if (W_ERROR_IS_OK(status)) {
-
-                       if (delete_files &&
-                           (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
-                           printer_driver_files_in_use(info,
-                                                       get_session_info_system(),
-                                                       p->msg_ctx,
-                                                       info_win2k)) {
-                               /* no idea of the correct error here */
-                               talloc_free(info_win2k);
-                               status = WERR_ACCESS_DENIED;
-                               goto done;
-                       }
-
-                       /* if we get to here, we now have 2 driver info structures to remove */
-                       /* remove the Win2k driver first*/
-
-                       status = winreg_del_driver(info, b,
-                                                  info_win2k,
-                                                  3);
-
-                       /* this should not have failed---if it did, report to client */
-
-                       if (!W_ERROR_IS_OK(status)) {
-                               goto done;
-                       }
+               found = true;
 
-                       /*
-                        * now delete any associated files if delete_files is
-                        * true. Even if this part failes, we return succes
-                        * because the driver doesn not exist any more
-                        */
-                       if (delete_files) {
-                               delete_driver_files(get_session_info_system(),
-                                                   info_win2k);
-                       }
+               status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
+               if (!W_ERROR_IS_OK(status)) {
+                       DEBUG(0, ("failed to delete driver with version %d\n",
+                                 drv_cversion[i]));
+                       goto done;
                }
        }
-
-       status = winreg_del_driver(info, b,
-                                  info,
-                                  version);
-       if (!W_ERROR_IS_OK(status)) {
-               goto done;
-       }
-
-       /*
-        * now delete any associated files if delete_files is
-        * true. Even if this part failes, we return succes
-        * because the driver doesn not exist any more
-        */
-       if (delete_files) {
-               delete_driver_files(get_session_info_system(), info);
+       if (found == false) {
+               DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
+               status = WERR_UNKNOWN_PRINTER_DRIVER;
+       } else {
+               status = WERR_OK;
        }
 
 done:
-       talloc_free(info);
+       talloc_free(tmp_ctx);
        return status;
 }
 
@@ -2369,26 +2285,26 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
 
        if (!strcasecmp_m(value, "W3SvcInstalled")) {
                *type = REG_DWORD;
-               data->value = 0x00;
+               SIVAL(&data->value, 0, 0x00);
                return WERR_OK;
        }
 
        if (!strcasecmp_m(value, "BeepEnabled")) {
                *type = REG_DWORD;
-               data->value = 0x00;
+               SIVAL(&data->value, 0, 0x00);
                return WERR_OK;
        }
 
        if (!strcasecmp_m(value, "EventLog")) {
                *type = REG_DWORD;
                /* formally was 0x1b */
-               data->value = 0x00;
+               SIVAL(&data->value, 0, 0x00);
                return WERR_OK;
        }
 
        if (!strcasecmp_m(value, "NetPopup")) {
                *type = REG_DWORD;
-               data->value = 0x00;
+               SIVAL(&data->value, 0, 0x00);
                return WERR_OK;
        }
 
@@ -2401,9 +2317,9 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
                   -- jerry */
 
                if (RA_WINNT == get_remote_arch()) {
-                       data->value = 0x02;
+                       SIVAL(&data->value, 0, 0x02);
                } else {
-                       data->value = 0x03;
+                       SIVAL(&data->value, 0, 0x03);
                }
 
                return WERR_OK;
@@ -2411,7 +2327,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
 
        if (!strcasecmp_m(value, "MinorVersion")) {
                *type = REG_DWORD;
-               data->value = 0x00;
+               SIVAL(&data->value, 0, 0x00);
                return WERR_OK;
        }
 
@@ -2427,9 +2343,13 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
                enum ndr_err_code ndr_err;
                struct spoolss_OSVersion os;
 
-               os.major                = 5;    /* Windows 2000 == 5.0 */
-               os.minor                = 0;
-               os.build                = 2195; /* build */
+               os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
+                                                     "spoolss", "os_major", 5);
+                                                     /* Windows 2000 == 5.0 */
+               os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
+                                                     "spoolss", "os_minor", 0);
+               os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
+                                                     "spoolss", "os_build", 2195);
                os.extra_string         = "";   /* leave extra string empty */
 
                ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
@@ -2438,6 +2358,10 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
                        return WERR_GENERAL_FAILURE;
                }
 
+               if (DEBUGLEVEL >= 10) {
+                       NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
+               }
+
                *type = REG_BINARY;
                data->binary = blob;
 
@@ -2470,9 +2394,9 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
                   member of a AD domain */
 
                if (lp_security() == SEC_ADS) {
-                       data->value = 0x01;
+                       SIVAL(&data->value, 0, 0x01);
                } else {
-                       data->value = 0x00;
+                       SIVAL(&data->value, 0, 0x00);
                }
                return WERR_OK;
        }
@@ -2520,11 +2444,10 @@ WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
  Connect to the client machine.
 **********************************************************/
 
-static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
-                       struct sockaddr_storage *client_ss, const char *remote_machine)
+static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
+                                     struct sockaddr_storage *client_ss, const char *remote_machine)
 {
        NTSTATUS ret;
-       struct cli_state *the_cli;
        struct sockaddr_storage rm_addr;
        char addr[INET6_ADDRSTRLEN];
 
@@ -2550,7 +2473,7 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
        }
 
        /* setup the connection */
-       ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
+       ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
                &rm_addr, 0, "IPC$", "IPC",
                "", /* username */
                "", /* domain */
@@ -2563,9 +2486,9 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
                return false;
        }
 
-       if ( the_cli->protocol != PROTOCOL_NT1 ) {
+       if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
                DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
-               cli_shutdown(the_cli);
+               cli_shutdown(*pp_cli);
                return false;
        }
 
@@ -2574,11 +2497,11 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
         * Now start the NT Domain stuff :-).
         */
 
-       ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
+       ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
        if (!NT_STATUS_IS_OK(ret)) {
                DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
                        remote_machine, nt_errstr(ret)));
-               cli_shutdown(the_cli);
+               cli_shutdown(*pp_cli);
                return false;
        }
 
@@ -2618,26 +2541,31 @@ static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
                /* the +2 is to strip the leading 2 backslashs */
                fstrcpy(unix_printer, printer + 2);
 
-               chan = talloc_zero(back_channels, struct notify_back_channel);
+               chan = talloc_zero(NULL, struct notify_back_channel);
                if (!chan) {
                        return false;
                }
                chan->client_address = *client_ss;
 
-               if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
+               if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
                        TALLOC_FREE(chan);
                        return false;
                }
-               chan->binding_handle = chan->cli_pipe->binding_handle;
 
                DLIST_ADD(back_channels, chan);
 
                messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
                                   receive_notify2_message_list);
-               /* Tell the connections db we're now interested in printer
-                * notify messages. */
-               serverid_register_msg_flags(messaging_server_id(msg_ctx),
-                                           true, FLAG_MSG_PRINT_NOTIFY);
+       }
+
+       if (chan->cli_pipe == NULL ||
+           chan->cli_pipe->binding_handle == NULL) {
+               DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
+                       "NULL %s for printer %s\n",
+                       chan->cli_pipe == NULL ?
+                       "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
+                       printer));
+               return false;
        }
 
        /*
@@ -2650,7 +2578,7 @@ static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
                          printer));
        }
 
-       status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
+       status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
                                                 talloc_tos(),
                                                 printer,
                                                 localprinter,
@@ -2739,7 +2667,7 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
        int snum = -1;
        struct spoolss_NotifyOption *option = r->in.notify_options;
        struct sockaddr_storage client_ss;
-       socklen_t client_len;
+       ssize_t client_len;
 
        /* store the notify value in the printer struct */
 
@@ -2846,7 +2774,7 @@ static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
                                      struct spoolss_PrinterInfo2 *pinfo2,
                                      TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
 }
 
 /*******************************************************************
@@ -2892,7 +2820,7 @@ static void spoolss_notify_comment(struct messaging_context *msg_ctx,
        const char *p;
 
        if (*pinfo2->comment == '\0') {
-               p = lp_comment(snum);
+               p = lp_comment(talloc_tos(), snum);
        } else {
                p = pinfo2->comment;
        }
@@ -3017,7 +2945,14 @@ static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
                                         struct spoolss_PrinterInfo2 *pinfo2,
                                         TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
+       if (pinfo2->secdesc == NULL) {
+               data->data.sd.sd = NULL;
+       } else {
+               data->data.sd.sd = security_descriptor_copy(mem_ctx,
+                                                           pinfo2->secdesc);
+       }
+       data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
+                                                            0);
 }
 
 /*******************************************************************
@@ -3286,7 +3221,7 @@ static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
                                        struct spoolss_PrinterInfo2 *pinfo2,
                                        TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
 }
 
 /*******************************************************************
@@ -3459,7 +3394,7 @@ static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
 
        DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
                (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
-               option_type->count, lp_servicename(snum)));
+               option_type->count, lp_servicename(talloc_tos(), snum)));
 
        for(field_num=0; field_num < option_type->count; field_num++) {
                field = option_type->fields[field_num].field;
@@ -3618,7 +3553,7 @@ static WERROR printserver_notify_info(struct pipes_struct *p,
                for (snum = 0; snum < n_services; snum++) {
                        if (!lp_browseable(snum) ||
                            !lp_snum_ok(snum) ||
-                           !lp_print_ok(snum)) {
+                           !lp_printable(snum)) {
                                continue; /* skip */
                        }
 
@@ -3626,12 +3561,12 @@ static WERROR printserver_notify_info(struct pipes_struct *p,
                        result = winreg_get_printer_internal(mem_ctx,
                                                    get_session_info_system(),
                                                    p->msg_ctx,
-                                                   lp_servicename(snum),
+                                                   lp_servicename(talloc_tos(), snum),
                                                    &pinfo2);
                        if (!W_ERROR_IS_OK(result)) {
                                DEBUG(4, ("printserver_notify_info: "
                                          "Failed to get printer [%s]\n",
-                                         lp_servicename(snum)));
+                                         lp_servicename(talloc_tos(), snum)));
                                continue;
                        }
 
@@ -3687,6 +3622,7 @@ static WERROR printer_notify_info(struct pipes_struct *p,
        print_status_struct status;
        struct spoolss_PrinterInfo2 *pinfo2 = NULL;
        WERROR result;
+       struct tdb_print_db *pdb;
 
        DEBUG(4,("printer_notify_info\n"));
 
@@ -3710,16 +3646,32 @@ static WERROR printer_notify_info(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
+       pdb = get_print_db_byname(Printer->sharename);
+       if (pdb == NULL) {
+               return WERR_BADFID;
+       }
+
        /* Maybe we should use the SYSTEM session_info here... */
        result = winreg_get_printer_internal(mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
-                                   lp_servicename(snum), &pinfo2);
+                                   lp_servicename(talloc_tos(), snum), &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
-               return WERR_BADFID;
+               result = WERR_BADFID;
+               goto err_pdb_drop;
        }
 
-       for (i=0; i<option->count; i++) {
+       /*
+        * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
+        * correct servername.
+        */
+       pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
+       if (pinfo2->servername == NULL) {
+               result = WERR_NOMEM;
+               goto err_pdb_drop;
+       }
+
+       for (i = 0; i < option->count; i++) {
                option_type = option->types[i];
 
                switch (option_type.type) {
@@ -3738,12 +3690,21 @@ static WERROR printer_notify_info(struct pipes_struct *p,
                        count = print_queue_status(p->msg_ctx, snum, &queue,
                                                   &status);
 
-                       for (j=0; j<count; j++) {
+                       for (j = 0; j < count; j++) {
+                               uint32_t jobid;
+                               jobid = sysjob_to_jobid_pdb(pdb,
+                                                           queue[j].sysjob);
+                               if (jobid == (uint32_t)-1) {
+                                       DEBUG(2, ("ignoring untracked job %d\n",
+                                                 queue[j].sysjob));
+                                       continue;
+                               }
+                               /* FIXME check return value */
                                construct_notify_jobs_info(p->msg_ctx,
                                                           &queue[j], info,
                                                           pinfo2, snum,
                                                           &option_type,
-                                                          queue[j].job,
+                                                          jobid,
                                                           mem_ctx);
                        }
 
@@ -3768,7 +3729,10 @@ static WERROR printer_notify_info(struct pipes_struct *p,
        */
 
        talloc_free(pinfo2);
-       return WERR_OK;
+       result = WERR_OK;
+err_pdb_drop:
+       release_print_db(pdb);
+       return result;
 }
 
 /****************************************************************
@@ -3887,7 +3851,7 @@ static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
  ********************************************************************/
 
 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
-                                     const struct auth3_session_info *session_info,
+                                     const struct auth_session_info *session_info,
                                      struct messaging_context *msg_ctx,
                                      struct spoolss_PrinterInfo2 *info2,
                                      const char *servername,
@@ -3994,7 +3958,7 @@ static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
        r->flags                = flags;
 
        if (info2->comment == NULL || info2->comment[0] == '\0') {
-               r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
+               r->comment      = lp_comment(mem_ctx, snum);
        } else {
                r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
        }
@@ -4044,7 +4008,7 @@ static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
                return result;
        }
 
-       r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
+       r->sharename            = lp_servicename(mem_ctx, snum);
        W_ERROR_HAVE_NO_MEMORY(r->sharename);
        r->portname             = talloc_strdup(mem_ctx, info2->portname);
        W_ERROR_HAVE_NO_MEMORY(r->portname);
@@ -4052,7 +4016,7 @@ static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
        W_ERROR_HAVE_NO_MEMORY(r->drivername);
 
        if (info2->comment[0] == '\0') {
-               r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
+               r->comment      = lp_comment(mem_ctx, snum);
        } else {
                r->comment      = talloc_strdup(mem_ctx, info2->comment);
        }
@@ -4095,8 +4059,22 @@ static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
        r->cjobs                = count;
        r->averageppm           = info2->averageppm;
 
-       copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
-       if (!r->devmode) {
+       if (info2->devmode != NULL) {
+               result = copy_devicemode(mem_ctx,
+                                        info2->devmode,
+                                        &r->devmode);
+               if (!W_ERROR_IS_OK(result)) {
+                       return result;
+               }
+       } else if (lp_default_devmode(snum)) {
+               result = spoolss_create_default_devmode(mem_ctx,
+                                                       info2->printername,
+                                                       &r->devmode);
+               if (!W_ERROR_IS_OK(result)) {
+                       return result;
+               }
+       } else {
+               r->devmode = NULL;
                DEBUG(8,("Returning NULL Devicemode!\n"));
        }
 
@@ -4108,7 +4086,10 @@ static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
                /* don't use talloc_steal() here unless you do a deep steal of all
                   the SEC_DESC members */
 
-               r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
+               r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
+               if (r->secdesc == NULL) {
+                       return WERR_NOMEM;
+               }
        }
 
        return WERR_OK;
@@ -4131,8 +4112,10 @@ static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
                /* don't use talloc_steal() here unless you do a deep steal of all
                   the SEC_DESC members */
 
-               r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
-               W_ERROR_HAVE_NO_MEMORY(r->secdesc);
+               r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
+               if (r->secdesc == NULL) {
+                       return WERR_NOMEM;
+               }
        }
 
        return WERR_OK;
@@ -4230,30 +4213,47 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
                                      struct spoolss_PrinterInfo7 *r,
                                      int snum)
 {
-       struct auth3_session_info *session_info;
-       struct GUID guid;
-       NTSTATUS status;
-
-       status = make_session_info_system(mem_ctx, &session_info);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("construct_printer_info7: "
-                         "Could not create system session_info\n"));
+       const struct auth_session_info *session_info;
+       char *printer;
+       WERROR werr;
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+       if (tmp_ctx == NULL) {
                return WERR_NOMEM;
        }
 
-       if (is_printer_published(mem_ctx, session_info, msg_ctx,
-                                servername,
-                                lp_servicename(snum), &guid, NULL)) {
+       session_info = get_session_info_system();
+       SMB_ASSERT(session_info != NULL);
+
+       printer = lp_servicename(tmp_ctx, snum);
+       if (printer == NULL) {
+               DEBUG(0, ("invalid printer snum %d\n", snum));
+               werr = WERR_INVALID_PARAM;
+               goto out_tmp_free;
+       }
+
+       if (is_printer_published(tmp_ctx, session_info, msg_ctx,
+                                servername, printer, NULL)) {
+               struct GUID guid;
+               werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
+                                          printer, &guid);
+               if (!W_ERROR_IS_OK(werr)) {
+                       goto out_tmp_free;
+               }
                r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
                r->action = DSPRINT_PUBLISH;
        } else {
                r->guid = talloc_strdup(mem_ctx, "");
                r->action = DSPRINT_UNPUBLISH;
        }
-       W_ERROR_HAVE_NO_MEMORY(r->guid);
+       if (r->guid == NULL) {
+               werr = WERR_NOMEM;
+               goto out_tmp_free;
+       }
 
-       TALLOC_FREE(session_info);
-       return WERR_OK;
+       werr = WERR_OK;
+out_tmp_free:
+       talloc_free(tmp_ctx);
+       return werr;
 }
 
 /********************************************************************
@@ -4275,8 +4275,22 @@ static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
                return result;
        }
 
-       copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
-       if (!r->devmode) {
+       if (info2->devmode != NULL) {
+               result = copy_devicemode(mem_ctx,
+                                        info2->devmode,
+                                        &r->devmode);
+               if (!W_ERROR_IS_OK(result)) {
+                       return result;
+               }
+       } else if (lp_default_devmode(snum)) {
+               result = spoolss_create_default_devmode(mem_ctx,
+                                                       info2->printername,
+                                                       &r->devmode);
+               if (!W_ERROR_IS_OK(result)) {
+                       return result;
+               }
+       } else {
+               r->devmode = NULL;
                DEBUG(8,("Returning NULL Devicemode!\n"));
        }
 
@@ -4285,21 +4299,12 @@ static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
-
-/********************************************************************
-********************************************************************/
-
-static bool snum_is_shared_printer(int snum)
-{
-       return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
-}
-
 /********************************************************************
  Spoolss_enumprinters.
 ********************************************************************/
 
 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
-                                          const struct auth3_session_info *session_info,
+                                          const struct auth_session_info *session_info,
                                           struct messaging_context *msg_ctx,
                                           const char *servername,
                                           uint32_t level,
@@ -4308,12 +4313,27 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                                           uint32_t *count_p)
 {
        int snum;
-       int n_services = lp_numservices();
+       int n_services;
        union spoolss_PrinterInfo *info = NULL;
        uint32_t count = 0;
        WERROR result = WERR_OK;
        struct dcerpc_binding_handle *b = NULL;
+       TALLOC_CTX *tmp_ctx = NULL;
+
+       tmp_ctx = talloc_new(mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
+       /*
+        * printer shares are updated on client enumeration. The background
+        * printer process updates printer_list.tdb at regular intervals.
+        */
+       become_root();
+       delete_and_reload_printers(server_event_context(), msg_ctx);
+       unbecome_root();
 
+       n_services = lp_numservices();
        *count_p = 0;
        *info_p = NULL;
 
@@ -4332,7 +4352,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                        printer, snum));
 
                if (b == NULL) {
-                       result = winreg_printer_binding_handle(mem_ctx,
+                       result = winreg_printer_binding_handle(tmp_ctx,
                                                               session_info,
                                                               msg_ctx,
                                                               &b);
@@ -4341,13 +4361,13 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                        }
                }
 
-               result = winreg_create_printer(mem_ctx, b,
+               result = winreg_create_printer(tmp_ctx, b,
                                               printer);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
                }
 
-               info = talloc_realloc(mem_ctx, info,
+               info = talloc_realloc(tmp_ctx, info,
                                            union spoolss_PrinterInfo,
                                            count + 1);
                if (!info) {
@@ -4355,7 +4375,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                        goto out;
                }
 
-               result = winreg_get_printer(mem_ctx, b,
+               result = winreg_get_printer(tmp_ctx, b,
                                            printer, &info2);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
@@ -4401,18 +4421,15 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                count++;
        }
 
-       *count_p = count;
-       *info_p = info;
-
- out:
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               return result;
+out:
+       if (W_ERROR_IS_OK(result)) {
+               *info_p = talloc_move(mem_ctx, &info);
+               *count_p = count;
        }
 
-       *info_p = info;
+       talloc_free(tmp_ctx);
 
-       return WERR_OK;
+       return result;
 }
 
 /********************************************************************
@@ -4420,7 +4437,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
-                                 const struct auth3_session_info *session_info,
+                                 const struct auth_session_info *session_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
                                  const char *servername,
@@ -4438,7 +4455,7 @@ static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
 ********************************************************************/
 
 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
-                                      const struct auth3_session_info *session_info,
+                                      const struct auth_session_info *session_info,
                                       struct messaging_context *msg_ctx,
                                       const char *servername,
                                       uint32_t flags,
@@ -4456,7 +4473,7 @@ static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
 *********************************************************************/
 
 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
-                                            const struct auth3_session_info *session_info,
+                                            const struct auth_session_info *session_info,
                                             struct messaging_context *msg_ctx,
                                             const char *servername,
                                             union spoolss_PrinterInfo **info,
@@ -4473,7 +4490,7 @@ static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
 *********************************************************************/
 
 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
-                                           const struct auth3_session_info *session_info,
+                                           const struct auth_session_info *session_info,
                                            struct messaging_context *msg_ctx,
                                            const char *servername,
                                            union spoolss_PrinterInfo **info,
@@ -4483,7 +4500,8 @@ static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
 
        DEBUG(4,("enum_all_printers_info_1_name\n"));
 
-       if ((servername[0] == '\\') && (servername[1] == '\\')) {
+       if (servername != NULL &&
+           (servername[0] == '\\') && (servername[1] == '\\')) {
                s = servername + 2;
        }
 
@@ -4500,7 +4518,7 @@ static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
 *********************************************************************/
 
 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
-                                              const struct auth3_session_info *session_info,
+                                              const struct auth_session_info *session_info,
                                               struct messaging_context *msg_ctx,
                                               const char *servername,
                                               union spoolss_PrinterInfo **info,
@@ -4518,7 +4536,8 @@ static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
           listed. Windows responds to this call with a
           WERR_CAN_NOT_COMPLETE so we should do the same. */
 
-       if (servername[0] == '\\' && servername[1] == '\\') {
+       if (servername != NULL &&
+           (servername[0] == '\\') && (servername[1] == '\\')) {
                 s = servername + 2;
        }
 
@@ -4537,7 +4556,7 @@ static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
-                                      const struct auth3_session_info *session_info,
+                                      const struct auth_session_info *session_info,
                                       struct messaging_context *msg_ctx,
                                       const char *servername,
                                       union spoolss_PrinterInfo **info,
@@ -4554,7 +4573,7 @@ static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
-                                 const struct auth3_session_info *session_info,
+                                 const struct auth_session_info *session_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
                                  const char *servername,
@@ -4588,7 +4607,7 @@ static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
-                                 const struct auth3_session_info *session_info,
+                                 const struct auth_session_info *session_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
                                  const char *servername,
@@ -4624,7 +4643,7 @@ static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
-                                 const struct auth3_session_info *session_info,
+                                 const struct auth_session_info *session_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
                                  const char *servername,
@@ -4643,7 +4662,7 @@ static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
-                                 const struct auth3_session_info *session_info,
+                                 const struct auth_session_info *session_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
                                  const char *servername,
@@ -4663,7 +4682,7 @@ static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
                             struct spoolss_EnumPrinters *r)
 {
-       const struct auth3_session_info *session_info = get_session_info_system();
+       const struct auth_session_info *session_info = get_session_info_system();
        WERROR result;
 
        /* that's an [in out] buffer */
@@ -4836,6 +4855,7 @@ WERROR _spoolss_GetPrinter(struct pipes_struct *p,
                result = WERR_UNKNOWN_LEVEL;
                break;
        }
+       TALLOC_FREE(info2);
 
  out:
        if (!W_ERROR_IS_OK(result)) {
@@ -4882,7 +4902,8 @@ static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
                                                  const char *arch,
                                                  int version)
 {
-       int i, num_strings = 0;
+       int i;
+       size_t num_strings = 0;
        const char **array = NULL;
 
        if (string_array == NULL) {
@@ -4909,8 +4930,10 @@ static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
                             &array, &num_strings);
        }
 
-       if (presult) {
+       if (presult != NULL) {
                *presult = array;
+       } else {
+               talloc_free(array);
        }
 
        return WERR_OK;
@@ -5533,7 +5556,7 @@ static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
-                                                 const struct auth3_session_info *session_info,
+                                                 const struct auth_session_info *session_info,
                                                  struct messaging_context *msg_ctx,
                                                  uint32_t level,
                                                  union spoolss_DriverInfo *r,
@@ -5546,20 +5569,26 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
        struct spoolss_DriverInfo8 *driver;
        WERROR result;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx = NULL;
 
        if (level == 101) {
                return WERR_UNKNOWN_LEVEL;
        }
 
-       result = winreg_printer_binding_handle(mem_ctx,
+       tmp_ctx = talloc_new(mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
+       result = winreg_printer_binding_handle(tmp_ctx,
                                               session_info,
                                               msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(result)) {
-               return result;
+               goto done;
        }
 
-       result = winreg_get_printer(mem_ctx, b,
+       result = winreg_get_printer(tmp_ctx, b,
                                    lp_const_servicename(snum),
                                    &pinfo2);
 
@@ -5567,10 +5596,11 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
                win_errstr(result)));
 
        if (!W_ERROR_IS_OK(result)) {
-               return WERR_INVALID_PRINTER_NAME;
+               result = WERR_INVALID_PRINTER_NAME;
+               goto done;
        }
 
-       result = winreg_get_driver(mem_ctx, b,
+       result = winreg_get_driver(tmp_ctx, b,
                                   architecture,
                                   pinfo2->drivername, version, &driver);
 
@@ -5583,24 +5613,26 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
                 */
 
                if (version < 3) {
-                       talloc_free(pinfo2);
-                       return WERR_UNKNOWN_PRINTER_DRIVER;
+                       result = WERR_UNKNOWN_PRINTER_DRIVER;
+                       goto done;
                }
 
                /* Yes - try again with a WinNT driver. */
                version = 2;
-               result = winreg_get_driver(mem_ctx, b,
+               result = winreg_get_driver(tmp_ctx, b,
                                           architecture,
                                           pinfo2->drivername,
                                           version, &driver);
                DEBUG(8,("construct_printer_driver_level: status: %s\n",
                        win_errstr(result)));
                if (!W_ERROR_IS_OK(result)) {
-                       talloc_free(pinfo2);
-                       return WERR_UNKNOWN_PRINTER_DRIVER;
+                       result = WERR_UNKNOWN_PRINTER_DRIVER;
+                       goto done;
                }
        }
 
+       /* these are allocated on mem_ctx and not tmp_ctx because they are
+        * the 'return value' and need to utlive this call */
        switch (level) {
        case 1:
                result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
@@ -5633,9 +5665,8 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
                break;
        }
 
-       talloc_free(pinfo2);
-       talloc_free(driver);
-
+done:
+       talloc_free(tmp_ctx);
        return result;
 }
 
@@ -5648,20 +5679,23 @@ WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
 {
        struct printer_handle *printer;
        WERROR result;
+       uint32_t version = r->in.client_major_version;
 
        int snum;
 
        /* that's an [in out] buffer */
 
        if (!r->in.buffer && (r->in.offered != 0)) {
-               return WERR_INVALID_PARAM;
+               result = WERR_INVALID_PARAM;
+               goto err_info_free;
        }
 
        DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
 
        if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
                DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
-               return WERR_INVALID_PRINTER_NAME;
+               result = WERR_INVALID_PRINTER_NAME;
+               goto err_info_free;
        }
 
        *r->out.needed = 0;
@@ -5669,7 +5703,14 @@ WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
        *r->out.server_minor_version = 0;
 
        if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-               return WERR_BADFID;
+               result = WERR_BADFID;
+               goto err_info_free;
+       }
+
+       if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
+               DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
+                       "downgrading to v3\n"));
+               version = SPOOLSS_DRIVER_VERSION_200X;
        }
 
        result = construct_printer_driver_info_level(p->mem_ctx,
@@ -5678,10 +5719,9 @@ WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
                                                     r->in.level, r->out.info,
                                                     snum, printer->servername,
                                                     r->in.architecture,
-                                                    r->in.client_major_version);
+                                                    version);
        if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(r->out.info);
-               return result;
+               goto err_info_free;
        }
 
        *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
@@ -5689,6 +5729,10 @@ WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
        r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
 
        return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+
+err_info_free:
+       TALLOC_FREE(r->out.info);
+       return result;
 }
 
 
@@ -5765,11 +5809,11 @@ WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
                return WERR_INVALID_HANDLE;
        }
 
-       if (r->in.level != 1) {
+       if (r->in.info_ctr->level != 1) {
                return WERR_UNKNOWN_LEVEL;
        }
 
-       info_1 = r->in.info.info1;
+       info_1 = r->in.info_ctr->info.info1;
 
        /*
         * a nice thing with NT is it doesn't listen to what you tell it.
@@ -5780,7 +5824,13 @@ WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
         */
 
        if (info_1->datatype) {
-               if (strcmp(info_1->datatype, "RAW") != 0) {
+               /*
+                * The v4 driver model used in Windows 8 declares print jobs
+                * intended to bypass the XPS processing layer by setting
+                * datatype to "XPS_PASS" instead of "RAW".
+                */
+                if ((strcmp(info_1->datatype, "RAW") != 0)
+                 && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
                        *r->out.job_id = 0;
                        return WERR_INVALID_DATATYPE;
                }
@@ -5908,7 +5958,7 @@ WERROR _spoolss_WritePrinter(struct pipes_struct *p,
 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
                              struct pipes_struct *p)
 {
-       const struct auth3_session_info *session_info = p->session_info;
+       const struct auth_session_info *session_info = p->session_info;
        int snum;
        WERROR errcode = WERR_BADFUNC;
        struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
@@ -5991,6 +6041,7 @@ static WERROR update_printer_sec(struct policy_handle *handle,
        int snum;
        struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx = NULL;
 
        if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
                DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
@@ -6018,7 +6069,12 @@ static WERROR update_printer_sec(struct policy_handle *handle,
                goto done;
        }
 
-       result = winreg_printer_binding_handle(p->mem_ctx,
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
+       result = winreg_printer_binding_handle(tmp_ctx,
                                               get_session_info_system(),
                                               p->msg_ctx,
                                               &b);
@@ -6028,7 +6084,7 @@ static WERROR update_printer_sec(struct policy_handle *handle,
 
        /* NT seems to like setting the security descriptor even though
           nothing may have actually changed. */
-       result = winreg_get_printer_secdesc(p->mem_ctx, b,
+       result = winreg_get_printer_secdesc(tmp_ctx, b,
                                            printer,
                                            &old_secdesc);
        if (!W_ERROR_IS_OK(result)) {
@@ -6067,7 +6123,7 @@ static WERROR update_printer_sec(struct policy_handle *handle,
                }
        }
 
-       new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
+       new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
        if (new_secdesc == NULL) {
                result = WERR_NOMEM;
                goto done;
@@ -6078,11 +6134,12 @@ static WERROR update_printer_sec(struct policy_handle *handle,
                goto done;
        }
 
-       result = winreg_set_printer_secdesc(p->mem_ctx, b,
+       result = winreg_set_printer_secdesc(tmp_ctx, b,
                                            printer,
                                            new_secdesc);
 
- done:
+done:
+       talloc_free(tmp_ctx);
        return result;
 }
 
@@ -6144,7 +6201,7 @@ static bool check_printer_ok(TALLOC_CTX *mem_ctx,
 
 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
 {
-       char *cmd = lp_addport_cmd();
+       char *cmd = lp_addport_command(talloc_tos());
        char *command = NULL;
        int ret;
        bool is_print_op = false;
@@ -6190,12 +6247,22 @@ static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const
 /****************************************************************************
 ****************************************************************************/
 
+static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
+                                  int snum)
+{
+       /*
+        * As we do not know if we are embedded in the file server process
+        * or not, we have to pretend that all shares are in use.
+        */
+       return true;
+}
+
 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
                             struct spoolss_SetPrinterInfo2 *info2,
                             const char *remote_machine,
                             struct messaging_context *msg_ctx)
 {
-       char *cmd = lp_addprinter_cmd();
+       char *cmd = lp_addprinter_command(talloc_tos());
        char **qlines;
        char *command = NULL;
        int numlines;
@@ -6248,7 +6315,7 @@ static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
 
        /* reload our services immediately */
        become_root();
-       reload_services(msg_ctx, -1, false);
+       reload_services(NULL, spoolss_conn_snum_used, false);
        unbecome_root();
 
        numlines = 0;
@@ -6271,7 +6338,7 @@ static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
 }
 
 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
-                              const struct auth3_session_info *session_info,
+                              const struct auth_session_info *session_info,
                               struct messaging_context *msg_ctx,
                               int snum,
                               struct spoolss_SetPrinterInfo2 *printer,
@@ -6285,24 +6352,42 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
        DATA_BLOB buffer;
        WERROR result = WERR_OK;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx;
+       bool ok;
+
+       tmp_ctx = talloc_new(mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
 
-       result = winreg_printer_binding_handle(mem_ctx,
+       result = winreg_printer_binding_handle(tmp_ctx,
                                               session_info,
                                               msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(result)) {
-               return result;
+               goto done;
        }
 
-       if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
-               push_reg_sz(mem_ctx, &buffer, printer->drivername);
-               winreg_set_printer_dataex(mem_ctx, b,
+       if (printer->drivername != NULL &&
+           (force_update ||
+            !strequal(printer->drivername, old_printer->drivername))) {
+               ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
+               if (!ok) {
+                       DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
+                       result = WERR_INVALID_DATA;
+                       goto done;
+               }
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_DRIVERNAME,
                                          REG_SZ,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
+                       goto done;
+               }
 
                if (!force_update) {
                        DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
@@ -6314,15 +6399,26 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                }
        }
 
-       if (force_update || !strequal(printer->comment, old_printer->comment)) {
-               push_reg_sz(mem_ctx, &buffer, printer->comment);
-               winreg_set_printer_dataex(mem_ctx, b,
+       if (printer->comment != NULL &&
+           (force_update ||
+            !strequal(printer->comment, old_printer->comment))) {
+               ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
+               if (!ok) {
+                       DEBUG(0, ("comment data corrupted\n"));
+                       result = WERR_INVALID_DATA;
+                       goto done;
+               }
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_DESCRIPTION,
                                          REG_SZ,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
+                       goto done;
+               }
 
                if (!force_update) {
                        notify_printer_comment(server_event_context(), msg_ctx,
@@ -6331,15 +6427,26 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                }
        }
 
-       if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
-               push_reg_sz(mem_ctx, &buffer, printer->sharename);
-               winreg_set_printer_dataex(mem_ctx, b,
+       if (printer->sharename != NULL &&
+           (force_update ||
+            !strequal(printer->sharename, old_printer->sharename))) {
+               ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
+               if (!ok) {
+                       DEBUG(0, ("sharename data corrupted\n"));
+                       result = WERR_INVALID_DATA;
+                       goto done;
+               }
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTSHARENAME,
                                          REG_SZ,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
+                       goto done;
+               }
 
                if (!force_update) {
                        notify_printer_sharename(server_event_context(),
@@ -6349,7 +6456,9 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                }
        }
 
-       if (force_update || !strequal(printer->printername, old_printer->printername)) {
+       if (printer->printername != NULL &&
+           (force_update ||
+            !strequal(printer->printername, old_printer->printername))) {
                const char *p;
 
                p = strrchr(printer->printername, '\\' );
@@ -6359,14 +6468,23 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                        p = printer->printername;
                }
 
-               push_reg_sz(mem_ctx, &buffer, p);
-               winreg_set_printer_dataex(mem_ctx, b,
+               ok = push_reg_sz(tmp_ctx, &buffer, p);
+               if (!ok) {
+                       DEBUG(0, ("printername data corrupted\n"));
+                       result = WERR_INVALID_DATA;
+                       goto done;
+               }
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTERNAME,
                                          REG_SZ,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
+                       goto done;
+               }
 
                if (!force_update) {
                        notify_printer_printername(server_event_context(),
@@ -6374,15 +6492,26 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                }
        }
 
-       if (force_update || !strequal(printer->portname, old_printer->portname)) {
-               push_reg_sz(mem_ctx, &buffer, printer->portname);
-               winreg_set_printer_dataex(mem_ctx, b,
+       if (printer->portname != NULL &&
+           (force_update ||
+            !strequal(printer->portname, old_printer->portname))) {
+               ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
+               if (!ok) {
+                       DEBUG(0, ("portname data corrupted\n"));
+                       result = WERR_INVALID_DATA;
+                       goto done;
+               }
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PORTNAME,
                                          REG_SZ,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
+                       goto done;
+               }
 
                if (!force_update) {
                        notify_printer_port(server_event_context(),
@@ -6391,15 +6520,26 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                }
        }
 
-       if (force_update || !strequal(printer->location, old_printer->location)) {
-               push_reg_sz(mem_ctx, &buffer, printer->location);
-               winreg_set_printer_dataex(mem_ctx, b,
+       if (printer->location != NULL &&
+           (force_update ||
+            !strequal(printer->location, old_printer->location))) {
+               ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
+               if (!ok) {
+                       DEBUG(0, ("location data corrupted\n"));
+                       result = WERR_INVALID_DATA;
+                       goto done;
+               }
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_LOCATION,
                                          REG_SZ,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
+                       goto done;
+               }
 
                if (!force_update) {
                        notify_printer_location(server_event_context(),
@@ -6409,15 +6549,26 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                }
        }
 
-       if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
-               push_reg_sz(mem_ctx, &buffer, printer->sepfile);
-               winreg_set_printer_dataex(mem_ctx, b,
+       if (printer->sepfile != NULL &&
+           (force_update ||
+            !strequal(printer->sepfile, old_printer->sepfile))) {
+               ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
+               if (!ok) {
+                       DEBUG(0, ("sepfile data corrupted\n"));
+                       result = WERR_INVALID_DATA;
+                       goto done;
+               }
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTSEPARATORFILE,
                                          REG_SZ,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
+                       goto done;
+               }
 
                if (!force_update) {
                        notify_printer_sepfile(server_event_context(),
@@ -6427,53 +6578,73 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                }
        }
 
-       if (force_update || printer->starttime != old_printer->starttime) {
-               buffer = data_blob_talloc(mem_ctx, NULL, 4);
+       if (printer->starttime != 0 &&
+           (force_update ||
+            printer->starttime != old_printer->starttime)) {
+               buffer = data_blob_talloc(tmp_ctx, NULL, 4);
                SIVAL(buffer.data, 0, printer->starttime);
-               winreg_set_printer_dataex(mem_ctx, b,
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTSTARTTIME,
                                          REG_DWORD,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
+                       goto done;
+               }
        }
 
-       if (force_update || printer->untiltime != old_printer->untiltime) {
-               buffer = data_blob_talloc(mem_ctx, NULL, 4);
+       if (printer->untiltime != 0 &&
+           (force_update ||
+            printer->untiltime != old_printer->untiltime)) {
+               buffer = data_blob_talloc(tmp_ctx, NULL, 4);
                SIVAL(buffer.data, 0, printer->untiltime);
-               winreg_set_printer_dataex(mem_ctx, b,
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTENDTIME,
                                          REG_DWORD,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
+                       goto done;
+               }
        }
 
        if (force_update || printer->priority != old_printer->priority) {
-               buffer = data_blob_talloc(mem_ctx, NULL, 4);
+               buffer = data_blob_talloc(tmp_ctx, NULL, 4);
                SIVAL(buffer.data, 0, printer->priority);
-               winreg_set_printer_dataex(mem_ctx, b,
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRIORITY,
                                          REG_DWORD,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
+                       goto done;
+               }
        }
 
        if (force_update || printer->attributes != old_printer->attributes) {
-               buffer = data_blob_talloc(mem_ctx, NULL, 4);
+               buffer = data_blob_talloc(tmp_ctx, NULL, 4);
                SIVAL(buffer.data, 0, (printer->attributes &
                                       PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
-               winreg_set_printer_dataex(mem_ctx, b,
+               result = winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTKEEPPRINTEDJOBS,
                                          REG_DWORD,
                                          buffer.data,
                                          buffer.length);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
+                       goto done;
+               }
 
                switch (printer->attributes & 0x3) {
                        case 0:
@@ -6488,8 +6659,13 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                        default:
                                spooling = "unknown";
                }
-               push_reg_sz(mem_ctx, &buffer, spooling);
-               winreg_set_printer_dataex(mem_ctx, b,
+               ok = push_reg_sz(tmp_ctx, &buffer, spooling);
+               if (!ok) {
+                       DEBUG(0, ("printSpooling data corrupted\n"));
+                       result = WERR_INVALID_DATA;
+                       goto done;
+               }
+               winreg_set_printer_dataex(tmp_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTSPOOLING,
@@ -6498,47 +6674,75 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                          buffer.length);
        }
 
-       push_reg_sz(mem_ctx, &buffer, lp_netbios_name());
-       winreg_set_printer_dataex(mem_ctx, b,
+       ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
+       if (!ok) {
+               DEBUG(0, ("shortServerName data corrupted\n"));
+               result = WERR_INVALID_DATA;
+               goto done;
+       }
+       result = winreg_set_printer_dataex(tmp_ctx, b,
                                  printer->sharename,
                                  SPOOL_DSSPOOLER_KEY,
                                  SPOOL_REG_SHORTSERVERNAME,
                                  REG_SZ,
                                  buffer.data,
                                  buffer.length);
+       if (!W_ERROR_IS_OK(result)) {
+               DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
+               goto done;
+       }
 
        dnsdomname = get_mydnsfullname();
        if (dnsdomname != NULL && dnsdomname[0] != '\0') {
-               longname = talloc_strdup(mem_ctx, dnsdomname);
+               longname = talloc_strdup(tmp_ctx, dnsdomname);
        } else {
-               longname = talloc_strdup(mem_ctx, lp_netbios_name());
+               longname = talloc_strdup(tmp_ctx, lp_netbios_name());
        }
        if (longname == NULL) {
                result = WERR_NOMEM;
                goto done;
        }
 
-       push_reg_sz(mem_ctx, &buffer, longname);
-       winreg_set_printer_dataex(mem_ctx, b,
-                                 printer->sharename,
-                                 SPOOL_DSSPOOLER_KEY,
-                                 SPOOL_REG_SERVERNAME,
-                                 REG_SZ,
-                                 buffer.data,
-                                 buffer.length);
+       ok = push_reg_sz(tmp_ctx, &buffer, longname);
+       if (!ok) {
+               DEBUG(0, ("longname data corrupted\n"));
+               result = WERR_INVALID_DATA;
+               goto done;
+       }
+       result = winreg_set_printer_dataex(tmp_ctx, b,
+                                          printer->sharename,
+                                          SPOOL_DSSPOOLER_KEY,
+                                          SPOOL_REG_SERVERNAME,
+                                          REG_SZ,
+                                          buffer.data,
+                                          buffer.length);
+       if (!W_ERROR_IS_OK(result)) {
+               DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
+               goto done;
+       }
 
-       uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
+       uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
                                  lp_netbios_name(), printer->sharename);
-       push_reg_sz(mem_ctx, &buffer, uncname);
-       winreg_set_printer_dataex(mem_ctx, b,
+       ok = push_reg_sz(tmp_ctx, &buffer, uncname);
+       if (!ok) {
+               DEBUG(0, ("uncName data corrupted\n"));
+               result = WERR_INVALID_DATA;
+               goto done;
+       }
+       result = winreg_set_printer_dataex(tmp_ctx, b,
                                  printer->sharename,
                                  SPOOL_DSSPOOLER_KEY,
                                  SPOOL_REG_UNCNAME,
                                  REG_SZ,
                                  buffer.data,
                                  buffer.length);
+       if (!W_ERROR_IS_OK(result)) {
+               DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
+               goto done;
+       }
 
 done:
+       talloc_free(tmp_ctx);
        return result;
 }
 
@@ -6613,7 +6817,7 @@ static WERROR update_printer(struct pipes_struct *p,
        /* Call addprinter hook */
        /* Check changes to see if this is really needed */
 
-       if (*lp_addprinter_cmd() &&
+       if (*lp_addprinter_command(talloc_tos()) &&
                        (!strequal(printer->drivername, old_printer->drivername) ||
                         !strequal(printer->comment, old_printer->comment) ||
                         !strequal(printer->portname, old_printer->portname) ||
@@ -6636,12 +6840,15 @@ static WERROR update_printer(struct pipes_struct *p,
                }
        }
 
-       update_dsspooler(tmp_ctx,
-                        get_session_info_system(),
-                        p->msg_ctx,
-                        snum,
-                        printer,
-                        old_printer);
+       result = update_dsspooler(tmp_ctx,
+                                 get_session_info_system(),
+                                 p->msg_ctx,
+                                 snum,
+                                 printer,
+                                 old_printer);
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
 
        printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
 
@@ -6690,7 +6897,7 @@ static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
        result = winreg_get_printer_internal(p->mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
-                                   lp_servicename(snum),
+                                   lp_servicename(talloc_tos(), snum),
                                    &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
                return WERR_BADFID;
@@ -6857,6 +7064,7 @@ fill_job_info1
 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
                             struct spoolss_JobInfo1 *r,
                             const print_queue_struct *queue,
+                            uint32_t jobid,
                             int position, int snum,
                             struct spoolss_PrinterInfo2 *pinfo2)
 {
@@ -6864,9 +7072,9 @@ static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
 
        t = gmtime(&queue->time);
 
-       r->job_id               = queue->job;
+       r->job_id               = jobid;
 
-       r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
+       r->printer_name         = lp_servicename(mem_ctx, snum);
        W_ERROR_HAVE_NO_MEMORY(r->printer_name);
        r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
        W_ERROR_HAVE_NO_MEMORY(r->server_name);
@@ -6897,6 +7105,7 @@ fill_job_info2
 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
                             struct spoolss_JobInfo2 *r,
                             const print_queue_struct *queue,
+                            uint32_t jobid,
                             int position, int snum,
                             struct spoolss_PrinterInfo2 *pinfo2,
                             struct spoolss_DeviceMode *devmode)
@@ -6905,9 +7114,9 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
 
        t = gmtime(&queue->time);
 
-       r->job_id               = queue->job;
+       r->job_id               = jobid;
 
-       r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
+       r->printer_name         = lp_servicename(mem_ctx, snum);
        W_ERROR_HAVE_NO_MEMORY(r->printer_name);
        r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
        W_ERROR_HAVE_NO_MEMORY(r->server_name);
@@ -6947,27 +7156,6 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
-/****************************************************************************
-fill_job_info3
-****************************************************************************/
-
-static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
-                            struct spoolss_JobInfo3 *r,
-                            const print_queue_struct *queue,
-                            const print_queue_struct *next_queue,
-                            int position, int snum,
-                            struct spoolss_PrinterInfo2 *pinfo2)
-{
-       r->job_id               = queue->job;
-       r->next_job_id          = 0;
-       if (next_queue) {
-               r->next_job_id  = next_queue->job;
-       }
-       r->reserved             = 0;
-
-       return WERR_OK;
-}
-
 /****************************************************************************
  Enumjobs at level 1.
 ****************************************************************************/
@@ -6982,34 +7170,56 @@ static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
        union spoolss_JobInfo *info;
        int i;
        WERROR result = WERR_OK;
+       uint32_t num_filled;
+       struct tdb_print_db *pdb;
 
        info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
-       W_ERROR_HAVE_NO_MEMORY(info);
+       if (info == NULL) {
+               result = WERR_NOMEM;
+               goto err_out;
+       }
 
-       *count = num_queues;
+       pdb = get_print_db_byname(pinfo2->sharename);
+       if (pdb == NULL) {
+               result = WERR_INVALID_PARAM;
+               goto err_info_free;
+       }
+
+       num_filled = 0;
+       for (i = 0; i < num_queues; i++) {
+               uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
+               if (jobid == (uint32_t)-1) {
+                       DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
+                       continue;
+               }
 
-       for (i=0; i<*count; i++) {
                result = fill_job_info1(info,
-                                       &info[i].info1,
+                                       &info[num_filled].info1,
                                        &queue[i],
+                                       jobid,
                                        i,
                                        snum,
                                        pinfo2);
                if (!W_ERROR_IS_OK(result)) {
-                       goto out;
+                       goto err_pdb_drop;
                }
-       }
 
- out:
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               *count = 0;
-               return result;
+               num_filled++;
        }
 
+       release_print_db(pdb);
        *info_p = info;
+       *count = num_filled;
 
        return WERR_OK;
+
+err_pdb_drop:
+       release_print_db(pdb);
+err_info_free:
+       TALLOC_FREE(info);
+err_out:
+       *count = 0;
+       return result;
 }
 
 /****************************************************************************
@@ -7026,45 +7236,65 @@ static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
        union spoolss_JobInfo *info;
        int i;
        WERROR result = WERR_OK;
+       uint32_t num_filled;
+       struct tdb_print_db *pdb;
 
        info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
-       W_ERROR_HAVE_NO_MEMORY(info);
+       if (info == NULL) {
+               result = WERR_NOMEM;
+               goto err_out;
+       }
 
-       *count = num_queues;
+       pdb = get_print_db_byname(pinfo2->sharename);
+       if (pdb == NULL) {
+               result = WERR_INVALID_PARAM;
+               goto err_info_free;
+       }
 
-       for (i=0; i<*count; i++) {
+       num_filled = 0;
+       for (i = 0; i< num_queues; i++) {
                struct spoolss_DeviceMode *devmode;
+               uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
+               if (jobid == (uint32_t)-1) {
+                       DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
+                       continue;
+               }
 
                result = spoolss_create_default_devmode(info,
                                                        pinfo2->printername,
                                                        &devmode);
                if (!W_ERROR_IS_OK(result)) {
                        DEBUG(3, ("Can't proceed w/o a devmode!"));
-                       goto out;
+                       goto err_pdb_drop;
                }
 
                result = fill_job_info2(info,
-                                       &info[i].info2,
+                                       &info[num_filled].info2,
                                        &queue[i],
+                                       jobid,
                                        i,
                                        snum,
                                        pinfo2,
                                        devmode);
                if (!W_ERROR_IS_OK(result)) {
-                       goto out;
+                       goto err_pdb_drop;
                }
+               num_filled++;
        }
 
- out:
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               *count = 0;
-               return result;
-       }
-
+       release_print_db(pdb);
        *info_p = info;
+       *count = num_filled;
 
        return WERR_OK;
+
+err_pdb_drop:
+       release_print_db(pdb);
+err_info_free:
+       TALLOC_FREE(info);
+err_out:
+       *count = 0;
+       return result;
 }
 
 /****************************************************************************
@@ -7081,41 +7311,51 @@ static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
        union spoolss_JobInfo *info;
        int i;
        WERROR result = WERR_OK;
+       uint32_t num_filled;
+       struct tdb_print_db *pdb;
 
        info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
-       W_ERROR_HAVE_NO_MEMORY(info);
-
-       *count = num_queues;
+       if (info == NULL) {
+               result = WERR_NOMEM;
+               goto err_out;
+       }
 
-       for (i=0; i<*count; i++) {
-               const print_queue_struct *next_queue = NULL;
+       pdb = get_print_db_byname(pinfo2->sharename);
+       if (pdb == NULL) {
+               result = WERR_INVALID_PARAM;
+               goto err_info_free;
+       }
 
-               if (i+1 < *count) {
-                       next_queue = &queue[i+1];
+       num_filled = 0;
+       for (i = 0; i < num_queues; i++) {
+               uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
+               if (jobid == (uint32_t)-1) {
+                       DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
+                       continue;
                }
 
-               result = fill_job_info3(info,
-                                       &info[i].info3,
-                                       &queue[i],
-                                       next_queue,
-                                       i,
-                                       snum,
-                                       pinfo2);
-               if (!W_ERROR_IS_OK(result)) {
-                       goto out;
-               }
-       }
+               info[num_filled].info3.job_id = jobid;
+               /* next_job_id is overwritten on next iteration */
+               info[num_filled].info3.next_job_id = 0;
+               info[num_filled].info3.reserved = 0;
 
- out:
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               *count = 0;
-               return result;
+               if (num_filled > 0) {
+                       info[num_filled - 1].info3.next_job_id = jobid;
+               }
+               num_filled++;
        }
 
+       release_print_db(pdb);
        *info_p = info;
+       *count = num_filled;
 
        return WERR_OK;
+
+err_info_free:
+       TALLOC_FREE(info);
+err_out:
+       *count = 0;
+       return result;
 }
 
 /****************************************************************
@@ -7138,6 +7378,11 @@ WERROR _spoolss_EnumJobs(struct pipes_struct *p,
                return WERR_INVALID_PARAM;
        }
 
+       if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
+               DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
+               return WERR_UNKNOWN_LEVEL;
+       }
+
        DEBUG(4,("_spoolss_EnumJobs\n"));
 
        *r->out.needed = 0;
@@ -7183,7 +7428,7 @@ WERROR _spoolss_EnumJobs(struct pipes_struct *p,
                                         pinfo2, r->out.info, r->out.count);
                break;
        default:
-               result = WERR_UNKNOWN_LEVEL;
+               SMB_ASSERT(false);      /* level checked on entry */
                break;
        }
 
@@ -7248,7 +7493,7 @@ static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
 WERROR _spoolss_SetJob(struct pipes_struct *p,
                       struct spoolss_SetJob *r)
 {
-       const struct auth3_session_info *session_info = p->session_info;
+       const struct auth_session_info *session_info = p->session_info;
        int snum;
        WERROR errcode = WERR_BADFUNC;
 
@@ -7270,17 +7515,13 @@ WERROR _spoolss_SetJob(struct pipes_struct *p,
                }
                break;
        case SPOOLSS_JOB_CONTROL_PAUSE:
-               if (print_job_pause(session_info, p->msg_ctx,
-                                   snum, r->in.job_id, &errcode)) {
-                       errcode = WERR_OK;
-               }
+               errcode = print_job_pause(session_info, p->msg_ctx,
+                                         snum, r->in.job_id);
                break;
        case SPOOLSS_JOB_CONTROL_RESTART:
        case SPOOLSS_JOB_CONTROL_RESUME:
-               if (print_job_resume(session_info, p->msg_ctx,
-                                    snum, r->in.job_id, &errcode)) {
-                       errcode = WERR_OK;
-               }
+               errcode = print_job_resume(session_info, p->msg_ctx,
+                                          snum, r->in.job_id);
                break;
        case 0:
                errcode = WERR_OK;
@@ -7319,7 +7560,7 @@ WERROR _spoolss_SetJob(struct pipes_struct *p,
 ****************************************************************************/
 
 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
-                                                      const struct auth3_session_info *session_info,
+                                                      const struct auth_session_info *session_info,
                                                       struct messaging_context *msg_ctx,
                                                       const char *servername,
                                                       const char *architecture,
@@ -7336,11 +7577,17 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
        uint32_t num_drivers;
        const char **drivers;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx = NULL;
 
        *count_p = 0;
        *info_p = NULL;
 
-       result = winreg_printer_binding_handle(mem_ctx,
+       tmp_ctx = talloc_new(mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
+       result = winreg_printer_binding_handle(tmp_ctx,
                                               session_info,
                                               msg_ctx,
                                               &b);
@@ -7349,7 +7596,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
        }
 
        for (version=0; version<DRIVER_MAX_VERSION; version++) {
-               result = winreg_get_driver_list(mem_ctx, b,
+               result = winreg_get_driver_list(tmp_ctx, b,
                                                architecture, version,
                                                &num_drivers, &drivers);
                if (!W_ERROR_IS_OK(result)) {
@@ -7360,7 +7607,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                          num_drivers, architecture, version));
 
                if (num_drivers != 0) {
-                       info = talloc_realloc(mem_ctx, info,
+                       info = talloc_realloc(tmp_ctx, info,
                                                    union spoolss_DriverInfo,
                                                    count + num_drivers);
                        if (!info) {
@@ -7374,7 +7621,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                for (i = 0; i < num_drivers; i++) {
                        DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
 
-                       result = winreg_get_driver(mem_ctx, b,
+                       result = winreg_get_driver(tmp_ctx, b,
                                                   architecture, drivers[i],
                                                   version, &driver);
                        if (!W_ERROR_IS_OK(result)) {
@@ -7426,18 +7673,14 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                TALLOC_FREE(drivers);
        }
 
- out:
-       TALLOC_FREE(drivers);
-
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               return result;
+out:
+       if (W_ERROR_IS_OK(result)) {
+               *info_p = talloc_move(mem_ctx, &info);
+               *count_p = count;
        }
 
-       *info_p = info;
-       *count_p = count;
-
-       return WERR_OK;
+       talloc_free(tmp_ctx);
+       return result;
 }
 
 /****************************************************************************
@@ -7445,7 +7688,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
 ****************************************************************************/
 
 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
-                                      const struct auth3_session_info *session_info,
+                                      const struct auth_session_info *session_info,
                                       struct messaging_context *msg_ctx,
                                       const char *servername,
                                       const char *architecture,
@@ -7610,6 +7853,7 @@ WERROR _spoolss_GetForm(struct pipes_struct *p,
        /* that's an [in out] buffer */
 
        if (!r->in.buffer && (r->in.offered != 0)) {
+               TALLOC_FREE(r->out.info);
                return WERR_INVALID_PARAM;
        }
 
@@ -7686,7 +7930,7 @@ static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
 
 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
 {
-       char *cmd = lp_enumports_cmd();
+       char *cmd = lp_enumports_command(talloc_tos());
        char **qlines = NULL;
        char *command = NULL;
        int numlines;
@@ -7950,7 +8194,7 @@ static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
        /* FIXME!!!  smbd should check to see if the driver is installed before
           trying to add a printer like this  --jerry */
 
-       if (*lp_addprinter_cmd() ) {
+       if (*lp_addprinter_command(talloc_tos()) ) {
                char *raddr;
 
                raddr = tsocket_address_inet_addr_string(p->remote_address,
@@ -7976,10 +8220,10 @@ static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
        }
 
        /* you must be a printer admin to add a new printer */
-       if (!print_access_check(p->session_info,
-                               p->msg_ctx,
-                               snum,
-                               PRINTER_ACCESS_ADMINISTER)) {
+       if (!W_ERROR_IS_OK(print_access_check(p->session_info,
+                                             p->msg_ctx,
+                                             snum,
+                                             PRINTER_ACCESS_ADMINISTER))) {
                return WERR_ACCESS_DENIED;
        }
 
@@ -7995,12 +8239,15 @@ static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
                info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
        }
 
-       update_dsspooler(p->mem_ctx,
-                        get_session_info_system(),
-                        p->msg_ctx,
-                        0,
-                        info2,
-                        NULL);
+       err = update_dsspooler(p->mem_ctx,
+                              get_session_info_system(),
+                              p->msg_ctx,
+                              0,
+                              info2,
+                              NULL);
+       if (!W_ERROR_IS_OK(err)) {
+               return err;
+       }
 
        err = winreg_update_printer_internal(p->mem_ctx,
                                    get_session_info_system(),
@@ -8204,7 +8451,7 @@ static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
                                          char **path)
 {
        const char *pservername = NULL;
-       const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
+       const char *long_archi;
        const char *short_archi;
 
        *path = NULL;
@@ -8212,6 +8459,10 @@ static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
        /* environment may be empty */
        if (environment && strlen(environment)) {
                long_archi = environment;
+       } else {
+               long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
+                                                 "spoolss", "architecture",
+                                                 SPOOLSS_ARCHITECTURE_NT_X86);
        }
 
        /* servername may be empty */
@@ -8533,11 +8784,12 @@ WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
 WERROR _spoolss_AddForm(struct pipes_struct *p,
                        struct spoolss_AddForm *r)
 {
-       struct spoolss_AddFormInfo1 *form = r->in.info.info1;
+       struct spoolss_AddFormInfo1 *form;
        int snum = -1;
        WERROR status = WERR_OK;
        struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx = NULL;
 
        DEBUG(5,("_spoolss_AddForm\n"));
 
@@ -8551,16 +8803,21 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
           and not a printer admin, then fail */
 
        if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
-           !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
-           !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
-                                         p->session_info->info->domain_name,
-                                         NULL,
-                                         p->session_info->security_token,
-                                         lp_printer_admin(snum))) {
+           !security_token_has_privilege(p->session_info->security_token,
+                                         SEC_PRIV_PRINT_OPERATOR)) {
                DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
                return WERR_ACCESS_DENIED;
        }
 
+       if (r->in.info_ctr->level != 1) {
+               return WERR_INVALID_LEVEL;
+       }
+
+       form = r->in.info_ctr->info.info1;
+       if (!form) {
+               return WERR_INVALID_PARAM;
+       }
+
        switch (form->flags) {
        case SPOOLSS_FORM_USER:
        case SPOOLSS_FORM_BUILTIN:
@@ -8570,18 +8827,22 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
                return WERR_INVALID_PARAM;
        }
 
-       status = winreg_printer_binding_handle(p->mem_ctx,
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
+       status = winreg_printer_binding_handle(tmp_ctx,
                                               get_session_info_system(),
                                               p->msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(status)) {
-               return status;
+               goto done;
        }
 
-       status = winreg_printer_addform1(p->mem_ctx, b,
-                                        form);
+       status = winreg_printer_addform1(tmp_ctx, b, form);
        if (!W_ERROR_IS_OK(status)) {
-               return status;
+               goto done;
        }
 
        /*
@@ -8589,16 +8850,16 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
         */
        if (Printer->printer_type == SPLHND_PRINTER) {
                if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-                       return WERR_BADFID;
+                       status = WERR_BADFID;
+                       goto done;
                }
 
-               status = winreg_printer_update_changeid(p->mem_ctx, b,
+               status = winreg_printer_update_changeid(tmp_ctx, b,
                                                        lp_const_servicename(snum));
-               if (!W_ERROR_IS_OK(status)) {
-                       return status;
-               }
        }
 
+done:
+       talloc_free(tmp_ctx);
        return status;
 }
 
@@ -8614,6 +8875,7 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
        int snum = -1;
        WERROR status = WERR_OK;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx = NULL;
 
        DEBUG(5,("_spoolss_DeleteForm\n"));
 
@@ -8624,28 +8886,28 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
        }
 
        if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
-           !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
-           !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
-                                         p->session_info->info->domain_name,
-                                         NULL,
-                                         p->session_info->security_token,
-                                         lp_printer_admin(snum))) {
+           !security_token_has_privilege(p->session_info->security_token,
+                                         SEC_PRIV_PRINT_OPERATOR)) {
                DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
                return WERR_ACCESS_DENIED;
        }
 
-       status = winreg_printer_binding_handle(p->mem_ctx,
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
+       status = winreg_printer_binding_handle(tmp_ctx,
                                               get_session_info_system(),
                                               p->msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(status)) {
-               return status;
+               goto done;
        }
 
-       status = winreg_printer_deleteform1(p->mem_ctx, b,
-                                           form_name);
+       status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
        if (!W_ERROR_IS_OK(status)) {
-               return status;
+               goto done;
        }
 
        /*
@@ -8653,16 +8915,16 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
         */
        if (Printer->printer_type == SPLHND_PRINTER) {
                if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-                       return WERR_BADFID;
+                       status = WERR_BADFID;
+                       goto done;
                }
 
-               status = winreg_printer_update_changeid(p->mem_ctx, b,
+               status = winreg_printer_update_changeid(tmp_ctx, b,
                                                        lp_const_servicename(snum));
-               if (!W_ERROR_IS_OK(status)) {
-                       return status;
-               }
        }
 
+done:
+       talloc_free(tmp_ctx);
        return status;
 }
 
@@ -8673,11 +8935,12 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
 WERROR _spoolss_SetForm(struct pipes_struct *p,
                        struct spoolss_SetForm *r)
 {
-       struct spoolss_AddFormInfo1 *form = r->in.info.info1;
+       struct spoolss_AddFormInfo1 *form;
        const char *form_name = r->in.form_name;
        int snum = -1;
        WERROR status = WERR_OK;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx = NULL;
 
        struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
@@ -8693,29 +8956,39 @@ WERROR _spoolss_SetForm(struct pipes_struct *p,
           and not a printer admin, then fail */
 
        if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
-            !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
-            !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
-                                         p->session_info->info->domain_name,
-                                         NULL,
-                                         p->session_info->security_token,
-                                         lp_printer_admin(snum))) {
+            !security_token_has_privilege(p->session_info->security_token,
+                                          SEC_PRIV_PRINT_OPERATOR)) {
                DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
                return WERR_ACCESS_DENIED;
        }
 
-       status = winreg_printer_binding_handle(p->mem_ctx,
+       if (r->in.info_ctr->level != 1) {
+               return WERR_INVALID_LEVEL;
+       }
+
+       form = r->in.info_ctr->info.info1;
+       if (!form) {
+               return WERR_INVALID_PARAM;
+       }
+
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
+       status = winreg_printer_binding_handle(tmp_ctx,
                                               get_session_info_system(),
                                               p->msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(status)) {
-               return status;
+               goto done;
        }
 
-       status = winreg_printer_setform1(p->mem_ctx, b,
+       status = winreg_printer_setform1(tmp_ctx, b,
                                         form_name,
                                         form);
        if (!W_ERROR_IS_OK(status)) {
-               return status;
+               goto done;
        }
 
        /*
@@ -8723,16 +8996,16 @@ WERROR _spoolss_SetForm(struct pipes_struct *p,
         */
        if (Printer->printer_type == SPLHND_PRINTER) {
                if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-                       return WERR_BADFID;
+                       status = WERR_BADFID;
+                       goto done;
                }
 
-               status = winreg_printer_update_changeid(p->mem_ctx, b,
+               status = winreg_printer_update_changeid(tmp_ctx, b,
                                                        lp_const_servicename(snum));
-               if (!W_ERROR_IS_OK(status)) {
-                       return status;
-               }
        }
 
+done:
+       talloc_free(tmp_ctx);
        return status;
 }
 
@@ -9115,13 +9388,14 @@ static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
                             int count, int snum,
                             struct spoolss_PrinterInfo2 *pinfo2,
                             uint32_t jobid,
+                            int sysjob,
                             struct spoolss_JobInfo1 *r)
 {
        int i = 0;
        bool found = false;
 
        for (i=0; i<count; i++) {
-               if (queue[i].job == (int)jobid) {
+               if (queue[i].sysjob == sysjob) {
                        found = true;
                        break;
                }
@@ -9135,6 +9409,7 @@ static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
        return fill_job_info1(mem_ctx,
                              r,
                              &queue[i],
+                             jobid,
                              i,
                              snum,
                              pinfo2);
@@ -9148,6 +9423,7 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
                             int count, int snum,
                             struct spoolss_PrinterInfo2 *pinfo2,
                             uint32_t jobid,
+                            int sysjob,
                             struct spoolss_JobInfo2 *r)
 {
        int i = 0;
@@ -9156,7 +9432,7 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
        WERROR result;
 
        for (i=0; i<count; i++) {
-               if (queue[i].job == (int)jobid) {
+               if (queue[i].sysjob == sysjob) {
                        found = true;
                        break;
                }
@@ -9174,7 +9450,7 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
         *  a failure condition
         */
 
-       devmode = print_job_devmode(lp_const_servicename(snum), jobid);
+       devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
        if (!devmode) {
                result = spoolss_create_default_devmode(mem_ctx,
                                                pinfo2->printername,
@@ -9188,6 +9464,7 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
        return fill_job_info2(mem_ctx,
                              r,
                              &queue[i],
+                             jobid,
                              i,
                              snum,
                              pinfo2,
@@ -9203,15 +9480,19 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
 {
        WERROR result = WERR_OK;
        struct spoolss_PrinterInfo2 *pinfo2 = NULL;
+       const char *svc_name;
+       int sysjob;
        int snum;
        int count;
+       struct tdb_print_db *pdb;
        print_queue_struct      *queue = NULL;
        print_status_struct prt_status;
 
        /* that's an [in out] buffer */
 
        if (!r->in.buffer && (r->in.offered != 0)) {
-               return WERR_INVALID_PARAM;
+               result = WERR_INVALID_PARAM;
+               goto err_jinfo_free;
        }
 
        DEBUG(5,("_spoolss_GetJob\n"));
@@ -9219,16 +9500,38 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
        *r->out.needed = 0;
 
        if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-               return WERR_BADFID;
+               result = WERR_BADFID;
+               goto err_jinfo_free;
+       }
+
+       svc_name = lp_const_servicename(snum);
+       if (svc_name == NULL) {
+               result = WERR_INVALID_PARAM;
+               goto err_jinfo_free;
        }
 
        result = winreg_get_printer_internal(p->mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
-                                   lp_const_servicename(snum),
+                                   svc_name,
                                    &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
-               return result;
+               goto err_jinfo_free;
+       }
+
+       pdb = get_print_db_byname(svc_name);
+       if (pdb == NULL) {
+               DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
+               result = WERR_INVALID_PARAM;
+               goto err_pinfo_free;
+       }
+
+       sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
+       release_print_db(pdb);
+       if (sysjob == -1) {
+               DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
+               result = WERR_INVALID_PARAM;
+               goto err_pinfo_free;
        }
 
        count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
@@ -9240,12 +9543,14 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
        case 1:
                result = getjob_level_1(p->mem_ctx,
                                        queue, count, snum, pinfo2,
-                                       r->in.job_id, &r->out.info->info1);
+                                       r->in.job_id, sysjob,
+                                       &r->out.info->info1);
                break;
        case 2:
                result = getjob_level_2(p->mem_ctx,
                                        queue, count, snum, pinfo2,
-                                       r->in.job_id, &r->out.info->info2);
+                                       r->in.job_id, sysjob,
+                                       &r->out.info->info2);
                break;
        default:
                result = WERR_UNKNOWN_LEVEL;
@@ -9256,8 +9561,7 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
        TALLOC_FREE(pinfo2);
 
        if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(r->out.info);
-               return result;
+               goto err_jinfo_free;
        }
 
        *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
@@ -9265,6 +9569,12 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
        r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
 
        return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
+
+err_pinfo_free:
+       TALLOC_FREE(pinfo2);
+err_jinfo_free:
+       TALLOC_FREE(r->out.info);
+       return result;
 }
 
 /****************************************************************
@@ -9284,6 +9594,7 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
        uint8_t *val_data = NULL;
        uint32_t val_size = 0;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx;
 
        DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
 
@@ -9295,6 +9606,11 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
        *r->out.needed  = 0;
        *r->out.type    = REG_NONE;
 
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
        if (!Printer) {
                DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
                        OUR_HANDLE(r->in.handle)));
@@ -9302,24 +9618,30 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                goto done;
        }
 
+       /* check to see if the keyname is valid */
+       if (!strlen(r->in.key_name)) {
+               result = WERR_INVALID_PARAM;
+               goto done;
+       }
+
        /* Is the handle to a printer or to the server? */
 
        if (Printer->printer_type == SPLHND_SERVER) {
 
                union spoolss_PrinterData data;
 
-               result = getprinterdata_printer_server(p->mem_ctx,
+               result = getprinterdata_printer_server(tmp_ctx,
                                                       r->in.value_name,
                                                       r->out.type,
                                                       &data);
                if (!W_ERROR_IS_OK(result)) {
-                       return result;
+                       goto done;
                }
 
-               result = push_spoolss_PrinterData(p->mem_ctx, &blob,
+               result = push_spoolss_PrinterData(tmp_ctx, &blob,
                                                  *r->out.type, &data);
                if (!W_ERROR_IS_OK(result)) {
-                       return result;
+                       goto done;
                }
 
                *r->out.needed = blob.length;
@@ -9328,25 +9650,22 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                        memcpy(r->out.data, blob.data, blob.length);
                }
 
-               return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
+               result = WERR_OK;
+               goto done;
        }
 
        if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-               return WERR_BADFID;
+               result = WERR_BADFID;
+               goto done;
        }
        printer = lp_const_servicename(snum);
 
-       /* check to see if the keyname is valid */
-       if (!strlen(r->in.key_name)) {
-               return WERR_INVALID_PARAM;
-       }
-
-       result = winreg_printer_binding_handle(p->mem_ctx,
+       result = winreg_printer_binding_handle(tmp_ctx,
                                               get_session_info_system(),
                                               p->msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(result)) {
-               return result;
+               goto done;
        }
 
        /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
@@ -9357,11 +9676,11 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                if (r->in.offered >= *r->out.needed) {
                        uint32_t changeid = 0;
 
-                       result = winreg_printer_get_changeid(p->mem_ctx, b,
+                       result = winreg_printer_get_changeid(tmp_ctx, b,
                                                             printer,
                                                             &changeid);
                        if (!W_ERROR_IS_OK(result)) {
-                               return result;
+                               goto done;
                        }
 
                        SIVAL(r->out.data, 0, changeid);
@@ -9370,7 +9689,7 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                goto done;
        }
 
-       result = winreg_get_printer_dataex(p->mem_ctx, b,
+       result = winreg_get_printer_dataex(tmp_ctx, b,
                                           printer,
                                           r->in.key_name,
                                           r->in.value_name,
@@ -9378,7 +9697,7 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                                           &val_data,
                                           &val_size);
        if (!W_ERROR_IS_OK(result)) {
-               return result;
+               goto done;
        }
 
        *r->out.needed = val_size;
@@ -9388,11 +9707,15 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                memcpy(r->out.data, val_data, val_size);
        }
 
- done:
-       /* retain type when returning WERR_MORE_DATA */
-       r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
+done:
+       /* NOTE: do not replace type when returning WERR_MORE_DATA */
 
-       return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
+       if (W_ERROR_IS_OK(result)) {
+               result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
+       }
+
+       talloc_free(tmp_ctx);
+       return result;
 }
 
 /****************************************************************
@@ -9408,6 +9731,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
        struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        char                    *oid_string;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx;
 
        DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
 
@@ -9444,19 +9768,24 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       result = winreg_printer_binding_handle(p->mem_ctx,
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
+       result = winreg_printer_binding_handle(tmp_ctx,
                                               get_session_info_system(),
                                               p->msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(result)) {
-               return result;
+               goto done;
        }
 
-       result = winreg_get_printer(Printer, b,
-                                   lp_servicename(snum),
+       result = winreg_get_printer(tmp_ctx, b,
+                                   lp_servicename(talloc_tos(), snum),
                                    &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
-               return result;
+               goto done;
        }
 
        /* check for OID in valuename */
@@ -9469,7 +9798,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
 
        /* save the registry data */
 
-       result = winreg_set_printer_dataex(p->mem_ctx, b,
+       result = winreg_set_printer_dataex(tmp_ctx, b,
                                           pinfo2->sharename,
                                           r->in.key_name,
                                           r->in.value_name,
@@ -9480,7 +9809,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
        if (W_ERROR_IS_OK(result)) {
                /* save the OID if one was specified */
                if (oid_string) {
-                       char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
+                       char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
                                r->in.key_name, SPOOL_OID_KEY);
                        if (!str) {
                                result = WERR_NOMEM;
@@ -9493,7 +9822,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
                         * previous set_printer_dataex() call.  I have no idea if
                         * this is right.    --jerry
                         */
-                       winreg_set_printer_dataex(p->mem_ctx, b,
+                       winreg_set_printer_dataex(tmp_ctx, b,
                                                  pinfo2->sharename,
                                                  str,
                                                  r->in.value_name,
@@ -9502,13 +9831,13 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
                                                  strlen(oid_string) + 1);
                }
 
-               result = winreg_printer_update_changeid(p->mem_ctx, b,
+               result = winreg_printer_update_changeid(tmp_ctx, b,
                                                        lp_const_servicename(snum));
 
        }
 
 done:
-       talloc_free(pinfo2);
+       talloc_free(tmp_ctx);
        return result;
 }
 
@@ -9639,6 +9968,7 @@ WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
        WERROR                  status;
        const char *printer;
        struct dcerpc_binding_handle *b;
+       TALLOC_CTX *tmp_ctx;
 
        DEBUG(5,("_spoolss_DeletePrinterKey\n"));
 
@@ -9664,23 +9994,30 @@ WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
 
        printer = lp_const_servicename(snum);
 
-       status = winreg_printer_binding_handle(p->mem_ctx,
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (!tmp_ctx) {
+               return WERR_NOMEM;
+       }
+
+       status = winreg_printer_binding_handle(tmp_ctx,
                                               get_session_info_system(),
                                               p->msg_ctx,
                                               &b);
        if (!W_ERROR_IS_OK(status)) {
-               return status;
+               goto done;
        }
 
        /* delete the key and all subkeys */
-       status = winreg_delete_printer_key(p->mem_ctx, b,
+       status = winreg_delete_printer_key(tmp_ctx, b,
                                           printer,
                                           r->in.key_name);
        if (W_ERROR_IS_OK(status)) {
-               status = winreg_printer_update_changeid(p->mem_ctx, b,
+               status = winreg_printer_update_changeid(tmp_ctx, b,
                                                        printer);
        }
 
+done:
+       talloc_free(tmp_ctx);
        return status;
 }
 
@@ -10199,7 +10536,7 @@ WERROR _spoolss_AddPort(struct pipes_struct *p,
 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
                                 struct spoolss_GetPrinterDriver *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10210,7 +10547,7 @@ WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
                            struct spoolss_ReadPrinter *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10221,7 +10558,7 @@ WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
                                     struct spoolss_WaitForPrinterChange *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10232,7 +10569,7 @@ WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
                              struct spoolss_ConfigurePort *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10243,7 +10580,7 @@ WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
 WERROR _spoolss_DeletePort(struct pipes_struct *p,
                           struct spoolss_DeletePort *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10254,7 +10591,7 @@ WERROR _spoolss_DeletePort(struct pipes_struct *p,
 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
                                struct spoolss_CreatePrinterIC *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10265,7 +10602,7 @@ WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
                                         struct spoolss_PlayGDIScriptOnPrinterIC *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10276,7 +10613,7 @@ WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
                                struct spoolss_DeletePrinterIC *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10287,7 +10624,7 @@ WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
                                     struct spoolss_AddPrinterConnection *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10298,7 +10635,7 @@ WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
                                        struct spoolss_DeletePrinterConnection *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10309,7 +10646,7 @@ WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
                                  struct spoolss_PrinterMessageBox *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10320,7 +10657,7 @@ WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
                           struct spoolss_AddMonitor *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10331,7 +10668,7 @@ WERROR _spoolss_AddMonitor(struct pipes_struct *p,
 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
                              struct spoolss_DeleteMonitor *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10342,7 +10679,7 @@ WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
                                     struct spoolss_DeletePrintProcessor *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10353,7 +10690,7 @@ WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
                                 struct spoolss_AddPrintProvidor *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10364,7 +10701,7 @@ WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
                                    struct spoolss_DeletePrintProvidor *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10375,7 +10712,7 @@ WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
                                                   struct spoolss_FindFirstPrinterChangeNotification *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10386,7 +10723,7 @@ WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
                                                  struct spoolss_FindNextPrinterChangeNotification *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10397,7 +10734,7 @@ WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
                                                            struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10408,7 +10745,7 @@ WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct
 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
                                 struct spoolss_ReplyOpenPrinter *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10419,7 +10756,7 @@ WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
                                   struct spoolss_RouterReplyPrinter *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10430,7 +10767,7 @@ WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
                                  struct spoolss_ReplyClosePrinter *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10441,7 +10778,7 @@ WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
                          struct spoolss_AddPortEx *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10452,7 +10789,7 @@ WERROR _spoolss_AddPortEx(struct pipes_struct *p,
 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
                                                         struct spoolss_RouterFindFirstPrinterChangeNotification *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10463,7 +10800,7 @@ WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
                            struct spoolss_SpoolerInit *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10474,7 +10811,7 @@ WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
                               struct spoolss_ResetPrinterEx *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10485,7 +10822,7 @@ WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
                                     struct spoolss_RouterReplyPrinterEx *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10496,7 +10833,7 @@ WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
 WERROR _spoolss_44(struct pipes_struct *p,
                   struct spoolss_44 *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10507,7 +10844,7 @@ WERROR _spoolss_44(struct pipes_struct *p,
 WERROR _spoolss_SetPort(struct pipes_struct *p,
                        struct spoolss_SetPort *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10518,7 +10855,7 @@ WERROR _spoolss_SetPort(struct pipes_struct *p,
 WERROR _spoolss_4a(struct pipes_struct *p,
                   struct spoolss_4a *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10529,7 +10866,7 @@ WERROR _spoolss_4a(struct pipes_struct *p,
 WERROR _spoolss_4b(struct pipes_struct *p,
                   struct spoolss_4b *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10540,7 +10877,7 @@ WERROR _spoolss_4b(struct pipes_struct *p,
 WERROR _spoolss_4c(struct pipes_struct *p,
                   struct spoolss_4c *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10551,7 +10888,7 @@ WERROR _spoolss_4c(struct pipes_struct *p,
 WERROR _spoolss_53(struct pipes_struct *p,
                   struct spoolss_53 *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10562,7 +10899,7 @@ WERROR _spoolss_53(struct pipes_struct *p,
 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
                                        struct spoolss_AddPerMachineConnection *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10573,7 +10910,7 @@ WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
                                           struct spoolss_DeletePerMachineConnection *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10584,7 +10921,7 @@ WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
                                          struct spoolss_EnumPerMachineConnections *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10595,7 +10932,7 @@ WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
 WERROR _spoolss_5a(struct pipes_struct *p,
                   struct spoolss_5a *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10606,7 +10943,7 @@ WERROR _spoolss_5a(struct pipes_struct *p,
 WERROR _spoolss_5b(struct pipes_struct *p,
                   struct spoolss_5b *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10617,7 +10954,7 @@ WERROR _spoolss_5b(struct pipes_struct *p,
 WERROR _spoolss_5c(struct pipes_struct *p,
                   struct spoolss_5c *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10628,7 +10965,7 @@ WERROR _spoolss_5c(struct pipes_struct *p,
 WERROR _spoolss_5d(struct pipes_struct *p,
                   struct spoolss_5d *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10639,7 +10976,7 @@ WERROR _spoolss_5d(struct pipes_struct *p,
 WERROR _spoolss_5e(struct pipes_struct *p,
                   struct spoolss_5e *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10650,7 +10987,7 @@ WERROR _spoolss_5e(struct pipes_struct *p,
 WERROR _spoolss_5f(struct pipes_struct *p,
                   struct spoolss_5f *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10661,18 +10998,18 @@ WERROR _spoolss_5f(struct pipes_struct *p,
 WERROR _spoolss_60(struct pipes_struct *p,
                   struct spoolss_60 *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
 /****************************************************************
- _spoolss_61
+ _spoolss_RpcSendRecvBidiData
 ****************************************************************/
 
-WERROR _spoolss_61(struct pipes_struct *p,
-                  struct spoolss_61 *r)
+WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
+                                   struct spoolss_RpcSendRecvBidiData *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10683,7 +11020,7 @@ WERROR _spoolss_61(struct pipes_struct *p,
 WERROR _spoolss_62(struct pipes_struct *p,
                   struct spoolss_62 *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10694,7 +11031,7 @@ WERROR _spoolss_62(struct pipes_struct *p,
 WERROR _spoolss_63(struct pipes_struct *p,
                   struct spoolss_63 *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10705,7 +11042,7 @@ WERROR _spoolss_63(struct pipes_struct *p,
 WERROR _spoolss_64(struct pipes_struct *p,
                   struct spoolss_64 *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10716,7 +11053,7 @@ WERROR _spoolss_64(struct pipes_struct *p,
 WERROR _spoolss_65(struct pipes_struct *p,
                   struct spoolss_65 *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10727,7 +11064,7 @@ WERROR _spoolss_65(struct pipes_struct *p,
 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
                                      struct spoolss_GetCorePrinterDrivers *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10738,7 +11075,7 @@ WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
 WERROR _spoolss_67(struct pipes_struct *p,
                   struct spoolss_67 *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10749,7 +11086,7 @@ WERROR _spoolss_67(struct pipes_struct *p,
 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
                                            struct spoolss_GetPrinterDriverPackagePath *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10760,7 +11097,7 @@ WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
 WERROR _spoolss_69(struct pipes_struct *p,
                   struct spoolss_69 *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10771,7 +11108,7 @@ WERROR _spoolss_69(struct pipes_struct *p,
 WERROR _spoolss_6a(struct pipes_struct *p,
                   struct spoolss_6a *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10782,7 +11119,7 @@ WERROR _spoolss_6a(struct pipes_struct *p,
 WERROR _spoolss_6b(struct pipes_struct *p,
                   struct spoolss_6b *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10793,7 +11130,7 @@ WERROR _spoolss_6b(struct pipes_struct *p,
 WERROR _spoolss_6c(struct pipes_struct *p,
                   struct spoolss_6c *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }
 
@@ -10804,6 +11141,50 @@ WERROR _spoolss_6c(struct pipes_struct *p,
 WERROR _spoolss_6d(struct pipes_struct *p,
                   struct spoolss_6d *r)
 {
-       p->rng_fault_state = true;
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_RpcGetJobNamedPropertyValue
+****************************************************************/
+
+WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
+                                           struct spoolss_RpcGetJobNamedPropertyValue *r)
+{
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_RpcSetJobNamedProperty
+****************************************************************/
+
+WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
+                                      struct spoolss_RpcSetJobNamedProperty *r)
+{
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_RpcDeleteJobNamedProperty
+****************************************************************/
+
+WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
+                                         struct spoolss_RpcDeleteJobNamedProperty *r)
+{
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_RpcEnumJobNamedProperties
+****************************************************************/
+
+WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
+                                         struct spoolss_RpcEnumJobNamedProperties *r)
+{
+       p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
        return WERR_NOT_SUPPORTED;
 }