s3-spoolss: make it possible to have and announce a [prnproc$] share on the printserver.
[mat/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
index 7ec0162f1a936fd56163ee7528560937a1eeb12c..c05ba66e427d354f11bf51e079fca1f68acc550e 100644 (file)
@@ -40,6 +40,7 @@
 #include "include/printing.h"
 #include "secrets.h"
 #include "../librpc/gen_ndr/netlogon.h"
+#include "rpc_misc.h"
 
 /* macros stolen from s4 spoolss server */
 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
-static Printer_entry *printers_list;
+#ifndef MAX_OPEN_PRINTER_EXS
+#define MAX_OPEN_PRINTER_EXS 50
+#endif
+
+struct notify_back_channel;
+
+/* structure to store the printer handles */
+/* and a reference to what it's pointing to */
+/* and the notify info asked about */
+/* that's the central struct */
+struct printer_handle {
+       struct printer_handle *prev, *next;
+       bool document_started;
+       bool page_started;
+       uint32 jobid; /* jobid in printing backend */
+       int printer_type;
+       const char *servername;
+       fstring sharename;
+       uint32 type;
+       uint32 access_granted;
+       struct {
+               uint32 flags;
+               uint32 options;
+               fstring localmachine;
+               uint32 printerlocal;
+               struct spoolss_NotifyOption *option;
+               struct policy_handle cli_hnd;
+               struct notify_back_channel *cli_chan;
+               uint32 change;
+               /* are we in a FindNextPrinterChangeNotify() call? */
+               bool fnpcn;
+               struct messaging_context *msg_ctx;
+       } notify;
+       struct {
+               fstring machine;
+               fstring user;
+       } client;
+
+       /* devmode sent in the OpenPrinter() call */
+       struct spoolss_DeviceMode *devmode;
+
+       /* TODO cache the printer info2 structure */
+       struct spoolss_PrinterInfo2 *info2;
+
+};
+
+static struct printer_handle *printers_list;
 
-typedef struct _counter_printer_0 {
-       struct _counter_printer_0 *next;
-       struct _counter_printer_0 *prev;
+struct printer_session_counter {
+       struct printer_session_counter *next;
+       struct printer_session_counter *prev;
 
        int snum;
        uint32_t counter;
-} counter_printer_0;
+};
+
+static struct printer_session_counter *counter_list;
+
+struct notify_back_channel {
+       struct notify_back_channel *prev, *next;
 
-static counter_printer_0 *counter_list;
+       /* associated client */
+       struct sockaddr_storage client_address;
 
-static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
-static uint32_t smb_connections = 0;
+       /* print notify back-channel pipe handle*/
+       struct rpc_pipe_client *cli_pipe;
+       uint32_t active_connections;
+};
 
+static struct notify_back_channel *back_channels;
 
 /* Map generic permissions to printer object specific permissions */
 
@@ -94,9 +150,11 @@ const struct standard_mapping printserver_std_mapping = {
 
 struct xcv_api_table {
        const char *name;
-       WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
+       WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
 };
 
+static void prune_printername_cache(void);
+
 /********************************************************************
  * Canonicalize servername.
  ********************************************************************/
@@ -159,9 +217,8 @@ static int nt_printq_status(int v)
  Disconnect from the client
 ****************************************************************************/
 
-static void srv_spoolss_replycloseprinter(
-       int snum, struct policy_handle *handle,
-       struct messaging_context *msg_ctx)
+static void srv_spoolss_replycloseprinter(int snum,
+                                         struct printer_handle *prn_hnd)
 {
        WERROR result;
        NTSTATUS status;
@@ -171,34 +228,40 @@ static void srv_spoolss_replycloseprinter(
         * by deregistering our PID.
         */
 
-       if (!print_notify_deregister_pid(snum))
-               DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
+       if (!print_notify_deregister_pid(snum)) {
+               DEBUG(0, ("Failed to register our pid for printer %s\n",
+                         lp_const_servicename(snum)));
+       }
 
        /* weird if the test succeeds !!! */
-       if (smb_connections==0) {
-               DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
+       if (prn_hnd->notify.cli_chan == 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);
+               TALLOC_FREE(prn_hnd->notify.cli_chan);
                return;
        }
 
-       status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
-                                                 handle,
-                                                 &result);
-       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
-               DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
-                       win_errstr(result)));
+       status = rpccli_spoolss_ReplyClosePrinter(
+                                       prn_hnd->notify.cli_chan->cli_pipe,
+                                       talloc_tos(),
+                                       &prn_hnd->notify.cli_hnd,
+                                       &result);
+       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+               DEBUG(0, ("reply_close_printer failed [%s].\n",
+                         win_errstr(result)));
+       }
 
        /* if it's the last connection, deconnect the IPC$ share */
-       if (smb_connections==1) {
+       if (prn_hnd->notify.cli_chan->active_connections == 1) {
 
-               cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
-               /*
-                * The above call shuts down the pipe also.
-                */
-               notify_cli_pipe = NULL;
+               cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
+               DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
+               TALLOC_FREE(prn_hnd->notify.cli_chan);
 
-               if (msg_ctx != NULL) {
-                       messaging_deregister(msg_ctx, MSG_PRINTER_NOTIFY2,
-                                            NULL);
+               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
@@ -206,34 +269,39 @@ static void srv_spoolss_replycloseprinter(
                         */
 
                        serverid_register_msg_flags(
-                               messaging_server_id(msg_ctx),
+                               messaging_server_id(prn_hnd->notify.msg_ctx),
                                false, FLAG_MSG_PRINT_NOTIFY);
                }
        }
 
-       smb_connections--;
+       if (prn_hnd->notify.cli_chan) {
+               prn_hnd->notify.cli_chan->active_connections--;
+       }
 }
 
 /****************************************************************************
  Functions to free a printer entry datastruct.
 ****************************************************************************/
 
-static int printer_entry_destructor(Printer_entry *Printer)
+static int printer_entry_destructor(struct printer_handle *Printer)
 {
-       if (Printer->notify.client_connected == true) {
+       if (Printer->notify.cli_chan != NULL &&
+           Printer->notify.cli_chan->active_connections > 0) {
                int snum = -1;
 
-               if ( Printer->printer_type == SPLHND_SERVER) {
-                       snum = -1;
-                       srv_spoolss_replycloseprinter(
-                               snum, &Printer->notify.client_hnd,
-                               Printer->notify.msg_ctx);
-               } else if (Printer->printer_type == SPLHND_PRINTER) {
+               switch(Printer->printer_type) {
+               case SPLHND_SERVER:
+                       srv_spoolss_replycloseprinter(snum, Printer);
+                       break;
+
+               case SPLHND_PRINTER:
                        snum = print_queue_snum(Printer->sharename);
-                       if (snum != -1)
-                               srv_spoolss_replycloseprinter(
-                                       snum, &Printer->notify.client_hnd,
-                                       Printer->notify.msg_ctx);
+                       if (snum != -1) {
+                               srv_spoolss_replycloseprinter(snum, Printer);
+                       }
+                       break;
+               default:
+                       break;
                }
        }
 
@@ -242,8 +310,6 @@ static int printer_entry_destructor(Printer_entry *Printer)
        Printer->notify.localmachine[0]='\0';
        Printer->notify.printerlocal=0;
        TALLOC_FREE(Printer->notify.option);
-       Printer->notify.client_connected = false;
-
        TALLOC_FREE(Printer->devmode);
 
        /* Remove from the internal list. */
@@ -255,10 +321,10 @@ static int printer_entry_destructor(Printer_entry *Printer)
   find printer index by handle
 ****************************************************************************/
 
-static Printer_entry *find_printer_index_by_hnd(struct pipes_struct *p,
-                                               struct policy_handle *hnd)
+static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
+                                                       struct policy_handle *hnd)
 {
-       Printer_entry *find_printer = NULL;
+       struct printer_handle *find_printer = NULL;
 
        if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
                DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
@@ -274,7 +340,7 @@ static Printer_entry *find_printer_index_by_hnd(struct pipes_struct *p,
 
 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
 
        if (!Printer) {
                DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
@@ -291,14 +357,13 @@ static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *h
  Delete a printer given a handle.
 ****************************************************************************/
 
-static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
+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 *command = NULL;
        int ret;
-       SE_PRIV se_printop = SE_PRINT_OPERATOR;
        bool is_print_op = false;
 
        /* can't fail if we don't try */
@@ -313,7 +378,7 @@ static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
                return WERR_NOMEM;
        }
        if ( token )
-               is_print_op = user_has_privileges( token, &se_printop );
+               is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
 
        DEBUG(10,("Running [%s]\n", command));
 
@@ -341,10 +406,10 @@ static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
 
        /* go ahead and re-read the services immediately */
        become_root();
-       reload_services(false);
+       reload_services(msg_ctx, -1, false);
        unbecome_root();
 
-       if ( lp_servicenumber( sharename )  > 0 )
+       if ( lp_servicenumber( sharename ) >= 0 )
                return WERR_ACCESS_DENIED;
 
        return WERR_OK;
@@ -356,7 +421,7 @@ static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
 
 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
        WERROR result;
 
        if (!Printer) {
@@ -380,15 +445,23 @@ static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle
        /* this does not need a become root since the access check has been
           done on the handle already */
 
-       result = winreg_delete_printer_key(p->mem_ctx, p->server_info,
-                                          p->msg_ctx, Printer->sharename, "");
+       result = winreg_delete_printer_key(p->mem_ctx,
+                                          get_server_info_system(),
+                                          p->msg_ctx,
+                                          Printer->sharename,
+                                          "");
        if (!W_ERROR_IS_OK(result)) {
                DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
                return WERR_BADFID;
        }
 
-       return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
-                                  Printer->sharename, p->msg_ctx);
+       result = delete_printer_hook(p->mem_ctx, p->server_info->ptok,
+                                    Printer->sharename, p->msg_ctx);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+       prune_printername_cache();
+       return WERR_OK;
 }
 
 /****************************************************************************
@@ -398,7 +471,7 @@ static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle
 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
                             int *number, struct share_params **params)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
 
        if (!Printer) {
                DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
@@ -423,17 +496,12 @@ static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
  Check if it's \\server or \\server\printer
 ****************************************************************************/
 
-static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
+static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
 {
        DEBUG(3,("Setting printer type=%s\n", handlename));
 
-       if ( strlen(handlename) < 3 ) {
-               DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
-               return false;
-       }
-
        /* it's a print server */
-       if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
+       if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
                DEBUGADD(4,("Printer is a print server\n"));
                Printer->printer_type = SPLHND_SERVER;
        }
@@ -446,6 +514,17 @@ static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *hand
        return true;
 }
 
+static void prune_printername_cache_fn(const char *key, const char *value,
+                                      time_t timeout, void *private_data)
+{
+       gencache_del(key);
+}
+
+static void prune_printername_cache(void)
+{
+       gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
+}
+
 /****************************************************************************
  Set printer handle name..  Accept names like \\server, \\server\printer,
  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
@@ -454,9 +533,9 @@ static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *hand
 ****************************************************************************/
 
 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
-                                struct auth_serversupplied_info *server_info,
+                                const struct auth_serversupplied_info *server_info,
                                 struct messaging_context *msg_ctx,
-                                Printer_entry *Printer,
+                                struct printer_handle *Printer,
                                 const char *handlename)
 {
        int snum;
@@ -468,6 +547,15 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
        bool found = false;
        struct spoolss_PrinterInfo2 *info2 = NULL;
        WERROR result;
+       char *p;
+
+       /*
+        * Hopefully nobody names his printers like this. Maybe \ or ,
+        * are illegal in printer names even?
+        */
+       const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
+       char *cache_key;
+       char *tmp;
 
        DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
                (unsigned long)strlen(handlename)));
@@ -482,8 +570,10 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
                if (!is_myname_or_ipaddr(servername)) {
                        return false;
                }
-
-               fstrcpy(Printer->servername, servername);
+               Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
+               if (Printer->servername == NULL) {
+                       return false;
+               }
        }
 
        if (Printer->printer_type == SPLHND_SERVER) {
@@ -496,6 +586,18 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
 
        DEBUGADD(5, ("searching for [%s]\n", aprinter));
 
+       if ((p = strchr(aprinter, ',')) != NULL) {
+               if (*p == ' ')
+                       p++;
+               if (strnequal(p+1, "DrvConvert", strlen("DrvConvert")) ||
+                   strnequal(p+1, " DrvConvert", strlen(" DrvConvert"))) {
+                       *p = '\0';
+               } else if (strnequal(p+1, "LocalOnly", strlen("LocalOnly")) ||
+                          strnequal(p+1, " LocalOnly", strlen(" LocalOnly"))) {
+                       *p = '\0';
+               }
+       }
+
        /* check for the Port Monitor Interface */
        if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
                Printer->printer_type = SPLHND_PORTMON_TCP;
@@ -508,6 +610,27 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
                found = true;
        }
 
+       /*
+        * With hundreds of printers, the "for" loop iterating all
+        * shares can be quite expensive, as it is done on every
+        * OpenPrinter. The loop maps "aprinter" to "sname", the
+        * result of which we cache in gencache.
+        */
+
+       cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
+                                   aprinter);
+       if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
+
+               found = (strcmp(tmp, printer_not_found) != 0);
+               if (!found) {
+                       DEBUG(4, ("Printer %s not found\n", aprinter));
+                       SAFE_FREE(tmp);
+                       return false;
+               }
+               fstrcpy(sname, tmp);
+               SAFE_FREE(tmp);
+       }
+
        /* Search all sharenames first as this is easier than pulling
           the printer_info_2 off of disk. Don't use find_service() since
           that calls out to map_username() */
@@ -541,7 +664,6 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
                result = winreg_get_printer(mem_ctx,
                                            server_info,
                                            msg_ctx,
-                                           servername,
                                            sname,
                                            &info2);
                if ( !W_ERROR_IS_OK(result) ) {
@@ -568,10 +690,20 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
        }
 
        if ( !found ) {
+               if (cache_key != NULL) {
+                       gencache_set(cache_key, printer_not_found,
+                                    time(NULL)+300);
+                       TALLOC_FREE(cache_key);
+               }
                DEBUGADD(4,("Printer not found\n"));
                return false;
        }
 
+       if (cache_key != NULL) {
+               gencache_set(cache_key, sname, time(NULL)+300);
+               TALLOC_FREE(cache_key);
+       }
+
        DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
 
        fstrcpy(Printer->sharename, sname);
@@ -586,16 +718,17 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
 static bool open_printer_hnd(struct pipes_struct *p, struct policy_handle *hnd,
                             const char *name, uint32_t access_granted)
 {
-       Printer_entry *new_printer;
+       struct printer_handle *new_printer;
 
        DEBUG(10,("open_printer_hnd: name [%s]\n", name));
 
-       new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
+       new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
        if (new_printer == NULL) {
                return false;
        }
        talloc_set_destructor(new_printer, printer_entry_destructor);
 
+       /* This also steals the printer_handle on the policy_handle */
        if (!create_policy_hnd(p, hnd, new_printer)) {
                TALLOC_FREE(new_printer);
                return false;
@@ -611,7 +744,9 @@ static bool open_printer_hnd(struct pipes_struct *p, struct policy_handle *hnd,
                return false;
        }
 
-       if (!set_printer_hnd_name(p->mem_ctx, p->server_info, p->msg_ctx,
+       if (!set_printer_hnd_name(p->mem_ctx,
+                                 get_server_info_system(),
+                                 p->msg_ctx,
                                  new_printer, name)) {
                close_printer_handle(p, hnd);
                return false;
@@ -636,7 +771,7 @@ static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
        return true;
 }
 
-static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
+static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
                                uint16_t notify_field)
 {
        struct spoolss_NotifyOption *option = p->notify.option;
@@ -975,165 +1110,205 @@ static void construct_info_data(struct spoolss_Notify *info_data,
  back registered
  **********************************************************************/
 
-static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
+static int build_notify2_messages(TALLOC_CTX *mem_ctx,
+                                 struct printer_handle *prn_hnd,
+                                 SPOOLSS_NOTIFY_MSG *messages,
+                                 uint32_t num_msgs,
+                                 struct spoolss_Notify **_notifies,
+                                 int *_count)
 {
-       Printer_entry            *p;
-       TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
-       SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
-       SPOOLSS_NOTIFY_MSG       *messages;
-       int                      sending_msg_count;
-
-       if ( !msg_group ) {
-               DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
-               return;
-       }
-
-       messages = msg_group->msgs;
+       struct spoolss_Notify *notifies;
+       SPOOLSS_NOTIFY_MSG *msg;
+       int count = 0;
+       uint32_t id;
+       int i;
 
-       if ( !messages ) {
-               DEBUG(5,("send_notify2_changes() called with no messages!\n"));
-               return;
+       notifies = talloc_zero_array(mem_ctx,
+                                    struct spoolss_Notify, num_msgs);
+       if (!notifies) {
+               return ENOMEM;
        }
 
-       DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
+       for (i = 0; i < num_msgs; i++) {
 
-       /* loop over all printers */
+               msg = &messages[i];
 
-       for (p = printers_list; p; p = p->next) {
-               struct spoolss_Notify *notifies;
-               uint32_t count = 0;
-               uint32_t id;
-               int     i;
+               /* Are we monitoring this event? */
 
-               /* Is there notification on this handle? */
-
-               if ( !p->notify.client_connected )
+               if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
                        continue;
+               }
 
-               DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
+               DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
+                          "for printer [%s]\n",
+                          msg->type, msg->field, prn_hnd->sharename));
 
-               /* For this printer?  Print servers always receive
-                   notifications. */
+               /*
+                * if the is a printer notification handle and not a job
+                * notification type, then set the id to 0.
+                * Otherwise just use what was specified in the message.
+                *
+                * When registering change notification on a print server
+                * handle we always need to send back the id (snum) matching
+                * the printer for which the change took place.
+                * For change notify registered on a printer handle,
+                * this does not matter and the id should be 0.
+                *
+                * --jerry
+                */
 
-               if ( ( p->printer_type == SPLHND_PRINTER )  &&
-                   ( !strequal(msg_group->printername, p->sharename) ) )
-                       continue;
+               if ((msg->type == PRINTER_NOTIFY_TYPE) &&
+                   (prn_hnd->printer_type == SPLHND_PRINTER)) {
+                       id = 0;
+               } else {
+                       id = msg->id;
+               }
 
-               DEBUG(10,("Our printer\n"));
+               /* Convert unix jobid to smb jobid */
 
-               /* allocate the max entries possible */
+               if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
+                       id = sysjob_to_jobid(msg->id);
 
-               notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
-               if (!notifies) {
-                       return;
+                       if (id == -1) {
+                               DEBUG(3, ("no such unix jobid %d\n",
+                                         msg->id));
+                               continue;
+                       }
                }
 
-               /* build the array of change notifications */
+               construct_info_data(&notifies[count],
+                                   msg->type, msg->field, id);
 
-               sending_msg_count = 0;
+               switch(msg->type) {
+               case PRINTER_NOTIFY_TYPE:
+                       if (printer_notify_table[msg->field].fn) {
+                               printer_notify_table[msg->field].fn(msg,
+                                               &notifies[count], mem_ctx);
+                       }
+                       break;
 
-               for ( i=0; i<msg_group->num_msgs; i++ ) {
-                       SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
+               case JOB_NOTIFY_TYPE:
+                       if (job_notify_table[msg->field].fn) {
+                               job_notify_table[msg->field].fn(msg,
+                                               &notifies[count], mem_ctx);
+                       }
+                       break;
 
-                       /* Are we monitoring this event? */
+               default:
+                       DEBUG(5, ("Unknown notification type %d\n",
+                                 msg->type));
+                       continue;
+               }
 
-                       if (!is_monitoring_event(p, msg->type, msg->field))
-                               continue;
+               count++;
+       }
 
-                       sending_msg_count++;
+       *_notifies = notifies;
+       *_count = count;
 
+       return 0;
+}
 
-                       DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
-                               msg->type, msg->field, p->sharename));
+static int send_notify2_printer(TALLOC_CTX *mem_ctx,
+                               struct printer_handle *prn_hnd,
+                               SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
+{
+       struct spoolss_Notify *notifies;
+       int count = 0;
+       union spoolss_ReplyPrinterInfo info;
+       struct spoolss_NotifyInfo info0;
+       uint32_t reply_result;
+       NTSTATUS status;
+       WERROR werr;
+       int ret;
 
-                       /*
-                        * if the is a printer notification handle and not a job notification
-                        * type, then set the id to 0.  Other wise just use what was specified
-                        * in the message.
-                        *
-                        * When registering change notification on a print server handle
-                        * we always need to send back the id (snum) matching the printer
-                        * for which the change took place.  For change notify registered
-                        * on a printer handle, this does not matter and the id should be 0.
-                        *
-                        * --jerry
-                        */
+       /* Is there notification on this handle? */
+       if (prn_hnd->notify.cli_chan == NULL ||
+           prn_hnd->notify.cli_chan->active_connections == 0) {
+               return 0;
+       }
 
-                       if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
-                               id = 0;
-                       else
-                               id = msg->id;
+       DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
+                  prn_hnd->servername, prn_hnd->sharename));
 
+       /* For this printer? Print servers always receive notifications. */
+       if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
+           (!strequal(msg_group->printername, prn_hnd->sharename))) {
+               return 0;
+       }
 
-                       /* Convert unix jobid to smb jobid */
+       DEBUG(10,("Our printer\n"));
+
+       /* build the array of change notifications */
+       ret = build_notify2_messages(mem_ctx, prn_hnd,
+                                    msg_group->msgs,
+                                    msg_group->num_msgs,
+                                    &notifies, &count);
+       if (ret) {
+               return ret;
+       }
+
+       info0.version   = 0x2;
+       info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
+       info0.count     = count;
+       info0.notifies  = notifies;
+
+       info.info0 = &info0;
+
+       status = rpccli_spoolss_RouterReplyPrinterEx(
+                               prn_hnd->notify.cli_chan->cli_pipe,
+                               mem_ctx,
+                               &prn_hnd->notify.cli_hnd,
+                               prn_hnd->notify.change, /* color */
+                               prn_hnd->notify.flags,
+                               &reply_result,
+                               0, /* reply_type, must be 0 */
+                               info, &werr);
+       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
+               DEBUG(1, ("RouterReplyPrinterEx to client: %s "
+                         "failed: %s\n",
+                         prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
+                         win_errstr(werr)));
+       }
+       switch (reply_result) {
+       case 0:
+               break;
+       case PRINTER_NOTIFY_INFO_DISCARDED:
+       case PRINTER_NOTIFY_INFO_DISCARDNOTED:
+       case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
+               break;
+       default:
+               break;
+       }
 
-                       if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
-                               id = sysjob_to_jobid(msg->id);
+       return 0;
+}
 
-                               if (id == -1) {
-                                       DEBUG(3, ("no such unix jobid %d\n", msg->id));
-                                       goto done;
-                               }
-                       }
+static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
+{
+       struct printer_handle    *p;
+       TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
+       SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
+       int ret;
 
-                       construct_info_data( &notifies[count], msg->type, msg->field, id );
+       if ( !msg_group ) {
+               DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
+               return;
+       }
 
-                       switch(msg->type) {
-                       case PRINTER_NOTIFY_TYPE:
-                               if ( printer_notify_table[msg->field].fn )
-                                       printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
-                               break;
+       if (!msg_group->msgs) {
+               DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
+               return;
+       }
 
-                       case JOB_NOTIFY_TYPE:
-                               if ( job_notify_table[msg->field].fn )
-                                       job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
-                               break;
+       DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
 
-                       default:
-                               DEBUG(5, ("Unknown notification type %d\n", msg->type));
-                               goto done;
-                       }
+       /* loop over all printers */
 
-                       count++;
-               }
-
-               if ( sending_msg_count ) {
-                       NTSTATUS status;
-                       WERROR werr;
-                       union spoolss_ReplyPrinterInfo info;
-                       struct spoolss_NotifyInfo info0;
-                       uint32_t reply_result;
-
-                       info0.version   = 0x2;
-                       info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
-                       info0.count     = count;
-                       info0.notifies  = notifies;
-
-                       info.info0 = &info0;
-
-                       status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
-                                                                    &p->notify.client_hnd,
-                                                                    p->notify.change, /* color */
-                                                                    p->notify.flags,
-                                                                    &reply_result,
-                                                                    0, /* reply_type, must be 0 */
-                                                                    info,
-                                                                    &werr);
-                       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
-                               DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
-                                       notify_cli_pipe->srv_name_slash,
-                                       win_errstr(werr)));
-                       }
-                       switch (reply_result) {
-                               case 0:
-                                       break;
-                               case PRINTER_NOTIFY_INFO_DISCARDED:
-                               case PRINTER_NOTIFY_INFO_DISCARDNOTED:
-                               case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
-                                       break;
-                               default:
-                                       break;
-                       }
+       for (p = printers_list; p; p = p->next) {
+               ret = send_notify2_printer(mem_ctx, p, msg_group);
+               if (ret) {
+                       goto done;
                }
        }
 
@@ -1300,6 +1475,18 @@ static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
        return true;
 }
 
+void srv_spoolss_cleanup(void)
+{
+       struct printer_session_counter *session_counter;
+
+       for (session_counter = counter_list;
+            session_counter != NULL;
+            session_counter = counter_list) {
+               DLIST_REMOVE(counter_list, session_counter);
+               TALLOC_FREE(session_counter);
+       }
+}
+
 /**********************************************************************
  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
  over all printers, upgrading ones as necessary
@@ -1319,7 +1506,6 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
        const char *drivername;
        int snum;
        int n_services = lp_numservices();
-       size_t len;
 
        tmp_ctx = talloc_new(NULL);
        if (!tmp_ctx) return;
@@ -1331,8 +1517,7 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
                goto done;
        }
 
-       len = MIN(data->length,sizeof(drivername)-1);
-       drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
+       drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
        if (!drivername) {
                DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
                goto done;
@@ -1348,8 +1533,12 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
                        continue;
                }
 
+               /* ignore [printers] share */
+               if (strequal(lp_const_servicename(snum), "printers")) {
+                       continue;
+               }
+
                result = winreg_get_printer(tmp_ctx, server_info, msg,
-                                           NULL,
                                            lp_const_servicename(snum),
                                            &pinfo2);
 
@@ -1390,20 +1579,19 @@ done:
  connection
  ********************************************************************/
 
-void update_monitored_printq_cache( void )
+void update_monitored_printq_cache(struct messaging_context *msg_ctx)
 {
-       Printer_entry *printer = printers_list;
+       struct printer_handle *printer = printers_list;
        int snum;
 
        /* loop through all printers and update the cache where
-          client_connected == true */
-       while ( printer )
-       {
-               if ( (printer->printer_type == SPLHND_PRINTER)
-                       && printer->notify.client_connected )
-               {
+          a client is connected */
+       while (printer) {
+               if ((printer->printer_type == SPLHND_PRINTER) &&
+                   ((printer->notify.cli_chan != NULL) &&
+                    (printer->notify.cli_chan->active_connections > 0))) {
                        snum = print_queue_snum(printer->sharename);
-                       print_queue_status( snum, NULL, NULL );
+                       print_queue_status(msg_ctx, snum, NULL, NULL);
                }
 
                printer = printer->next;
@@ -1488,7 +1676,7 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
                              struct spoolss_OpenPrinterEx *r)
 {
        int snum;
-       Printer_entry *Printer=NULL;
+       struct printer_handle *Printer=NULL;
 
        if (!r->in.printername) {
                return WERR_INVALID_PARAM;
@@ -1501,7 +1689,7 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 
        if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
                DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
-                       " for printer %s\n", r->in.printername));
+                       "for printer %s\n", r->in.printername));
                ZERO_STRUCTP(r->out.handle);
                return WERR_INVALID_PARAM;
        }
@@ -1570,8 +1758,6 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 
                if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
                {
-                       SE_PRIV se_printop = SE_PRINT_OPERATOR;
-
                        if (!lp_ms_add_printer_wizard()) {
                                close_printer_handle(p, r->out.handle);
                                ZERO_STRUCTP(r->out.handle);
@@ -1582,8 +1768,7 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
                           and not a printer admin, then fail */
 
                        if ((p->server_info->utok.uid != sec_initial_uid()) &&
-                           !user_has_privileges(p->server_info->ptok,
-                                                &se_printop ) &&
+                           !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
                            !token_contains_name_in_list(
                                    uidtoname(p->server_info->utok.uid),
                                    p->server_info->info3->base.domain.string,
@@ -1642,7 +1827,8 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 
                /* check smb.conf parameters and the the sec_desc */
 
-               if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
+               if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
+                                 p->client_id->name, p->client_id->addr)) {
                        DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
                        ZERO_STRUCTP(r->out.handle);
                        return WERR_ACCESS_DENIED;
@@ -1650,7 +1836,9 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 
                if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
                                   p->server_info->ptok, snum) ||
-                   !print_access_check(p->server_info, p->msg_ctx, snum,
+                   !print_access_check(p->server_info,
+                                       p->msg_ctx,
+                                       snum,
                                        r->in.access_mask)) {
                        DEBUG(3, ("access DENIED for printer open\n"));
                        close_printer_handle(p, r->out.handle);
@@ -1674,9 +1862,8 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
                        ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
 
                winreg_create_printer(p->mem_ctx,
-                                     p->server_info,
+                                     get_server_info_system(),
                                      p->msg_ctx,
-                                     Printer->servername,
                                      lp_const_servicename(snum));
 
                break;
@@ -1722,7 +1909,7 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
                             struct spoolss_ClosePrinter *r)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (Printer && Printer->document_started) {
                struct spoolss_EndDocPrinter e;
@@ -1752,7 +1939,7 @@ WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
                              struct spoolss_DeletePrinter *r)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        WERROR result;
        int snum;
 
@@ -1766,7 +1953,7 @@ WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
 
        if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
                winreg_delete_printer_key(p->mem_ctx,
-                                         p->server_info,
+                                         get_server_info_system(),
                                          p->msg_ctx,
                                          lp_const_servicename(snum),
                                          "");
@@ -1819,13 +2006,12 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
        struct spoolss_DriverInfo8 *info_win2k = NULL;
        int                             version;
        WERROR                          status;
-       SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
 
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
 
        if ( (p->server_info->utok.uid != sec_initial_uid())
-               && !user_has_privileges(p->server_info->ptok, &se_printop )
+            && !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR)
                && !token_contains_name_in_list(
                        uidtoname(p->server_info->utok.uid),
                        p->server_info->info3->base.domain.string,
@@ -1841,7 +2027,9 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
        if ((version = get_version_id(r->in.architecture)) == -1)
                return WERR_INVALID_ENVIRONMENT;
 
-       status = winreg_get_driver(p->mem_ctx, p->server_info, p->msg_ctx,
+       status = winreg_get_driver(p->mem_ctx,
+                                  get_server_info_system(),
+                                  p->msg_ctx,
                                   r->in.architecture, r->in.driver,
                                   version, &info);
        if (!W_ERROR_IS_OK(status)) {
@@ -1850,7 +2038,8 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
                if ( version == 2 ) {
                        version = 3;
 
-                       status = winreg_get_driver(p->mem_ctx, p->server_info,
+                       status = winreg_get_driver(p->mem_ctx,
+                                                  get_server_info_system(),
                                                   p->msg_ctx,
                                                   r->in.architecture,
                                                   r->in.driver,
@@ -1868,14 +2057,17 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
 
        }
 
-       if (printer_driver_in_use(p->mem_ctx, p->server_info, p->msg_ctx,
+       if (printer_driver_in_use(p->mem_ctx,
+                                 get_server_info_system(),
+                                 p->msg_ctx,
                                  info)) {
                status = WERR_PRINTER_DRIVER_IN_USE;
                goto done;
        }
 
        if (version == 2) {
-               status = winreg_get_driver(p->mem_ctx, p->server_info,
+               status = winreg_get_driver(p->mem_ctx,
+                                          get_server_info_system(),
                                           p->msg_ctx,
                                           r->in.architecture,
                                           r->in.driver, 3, &info_win2k);
@@ -1884,7 +2076,7 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
                        /* remove the Win2k driver first*/
 
                        status = winreg_del_driver(p->mem_ctx,
-                                                  p->server_info,
+                                                  get_server_info_system(),
                                                   p->msg_ctx,
                                                   info_win2k, 3);
                        talloc_free(info_win2k);
@@ -1896,7 +2088,9 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
                }
        }
 
-       status = winreg_del_driver(p->mem_ctx, p->server_info, p->msg_ctx,
+       status = winreg_del_driver(p->mem_ctx,
+                                  get_server_info_system(),
+                                  p->msg_ctx,
                                   info, version);
 
 done:
@@ -1917,13 +2111,12 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
        int                             version;
        bool                            delete_files;
        WERROR                          status;
-       SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
 
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
 
        if ( (p->server_info->utok.uid != sec_initial_uid())
-               && !user_has_privileges(p->server_info->ptok, &se_printop )
+               && !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR)
                && !token_contains_name_in_list(
                        uidtoname(p->server_info->utok.uid),
                        p->server_info->info3->base.domain.string,
@@ -1942,9 +2135,13 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
        if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
                version = r->in.version;
 
-       status = winreg_get_driver(p->mem_ctx, p->server_info,
-                                  p->msg_ctx, r->in.architecture,
-                                  r->in.driver, version, &info);
+       status = winreg_get_driver(p->mem_ctx,
+                                  get_server_info_system(),
+                                  p->msg_ctx,
+                                  r->in.architecture,
+                                  r->in.driver,
+                                  version,
+                                  &info);
        if (!W_ERROR_IS_OK(status)) {
                status = WERR_UNKNOWN_PRINTER_DRIVER;
 
@@ -1960,7 +2157,9 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
                /* try for Win2k driver if "Windows NT x86" */
 
                version = 3;
-               status = winreg_get_driver(info, p->server_info, p->msg_ctx,
+               status = winreg_get_driver(info,
+                                          get_server_info_system(),
+                                          p->msg_ctx,
                                           r->in.architecture,
                                           r->in.driver,
                                           version, &info);
@@ -1970,7 +2169,10 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
                }
        }
 
-       if (printer_driver_in_use(info, p->server_info, p->msg_ctx, info)) {
+       if (printer_driver_in_use(info,
+                                 get_server_info_system(),
+                                 p->msg_ctx,
+                                 info)) {
                status = WERR_PRINTER_DRIVER_IN_USE;
                goto done;
        }
@@ -1993,7 +2195,9 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
 
        if (delete_files &&
            (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
-           printer_driver_files_in_use(info, p->server_info, p->msg_ctx,
+           printer_driver_files_in_use(info,
+                                       get_server_info_system(),
+                                       p->msg_ctx,
                                        info)) {
                /* no idea of the correct error here */
                status = WERR_ACCESS_DENIED;
@@ -2004,14 +2208,17 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
        /* 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, p->server_info, p->msg_ctx,
+               status = winreg_get_driver(info,
+                                          get_server_info_system(),
+                                          p->msg_ctx,
                                           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, p->server_info,
+                           printer_driver_files_in_use(info,
+                                                       get_server_info_system(),
                                                        p->msg_ctx,
                                                        info_win2k)) {
                                /* no idea of the correct error here */
@@ -2023,8 +2230,11 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
                        /* if we get to here, we now have 2 driver info structures to remove */
                        /* remove the Win2k driver first*/
 
-                       status = winreg_del_driver(info, p->server_info,
-                                                  p->msg_ctx, info_win2k, 3);
+                       status = winreg_del_driver(info,
+                                                  get_server_info_system(),
+                                                  p->msg_ctx,
+                                                  info_win2k,
+                                                  3);
 
                        /* this should not have failed---if it did, report to client */
 
@@ -2038,13 +2248,16 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
                         * because the driver doesn not exist any more
                         */
                        if (delete_files) {
-                               delete_driver_files(p->server_info,
+                               delete_driver_files(get_server_info_system(),
                                                    info_win2k);
                        }
                }
        }
 
-       status = winreg_del_driver(info, p->server_info, p->msg_ctx, info,
+       status = winreg_del_driver(info,
+                                  get_server_info_system(),
+                                  p->msg_ctx,
+                                  info,
                                   version);
        if (!W_ERROR_IS_OK(status)) {
                goto done;
@@ -2056,7 +2269,7 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
         * because the driver doesn not exist any more
         */
        if (delete_files) {
-               delete_driver_files(p->server_info, info);
+               delete_driver_files(get_server_info_system(), info);
        }
 
 done:
@@ -2299,25 +2512,46 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
 ****************************************************************************/
 
 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
-                                       uint32_t localprinter, uint32_t type,
+                                       uint32_t localprinter,
+                                       enum winreg_Type type,
                                        struct policy_handle *handle,
+                                       struct notify_back_channel **_chan,
                                        struct sockaddr_storage *client_ss,
                                        struct messaging_context *msg_ctx)
 {
        WERROR result;
        NTSTATUS status;
+       struct notify_back_channel *chan;
+
+       for (chan = back_channels; chan; chan = chan->next) {
+               if (memcmp(&chan->client_address, client_ss,
+                          sizeof(struct sockaddr_storage)) == 0) {
+                       break;
+               }
+       }
 
        /*
         * If it's the first connection, contact the client
         * and connect to the IPC$ share anonymously
         */
-       if (smb_connections==0) {
+       if (!chan) {
                fstring unix_printer;
 
-               fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
+               /* the +2 is to strip the leading 2 backslashs */
+               fstrcpy(unix_printer, printer + 2);
+
+               chan = talloc_zero(back_channels, struct notify_back_channel);
+               if (!chan) {
+                       return false;
+               }
+               chan->client_address = *client_ss;
 
-               if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
+               if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
+                       TALLOC_FREE(chan);
                        return false;
+               }
+
+               DLIST_ADD(back_channels, chan);
 
                messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
                                   receive_notify2_message_list);
@@ -2332,12 +2566,12 @@ static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
         * by registering our PID.
         */
 
-       if (!print_notify_register_pid(snum))
-               DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
-
-       smb_connections++;
+       if (!print_notify_register_pid(snum)) {
+               DEBUG(0, ("Failed to register our pid for printer %s\n",
+                         printer));
+       }
 
-       status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
+       status = rpccli_spoolss_ReplyOpenPrinter(chan->cli_pipe, talloc_tos(),
                                                 printer,
                                                 localprinter,
                                                 type,
@@ -2345,9 +2579,12 @@ static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
                                                 NULL,
                                                 handle,
                                                 &result);
-       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
-               DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
-                       win_errstr(result)));
+       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
+               DEBUG(5, ("Client RPC returned [%s]\n", win_errstr(result)));
+       }
+
+       chan->active_connections++;
+       *_chan = chan;
 
        return (W_ERROR_IS_OK(result));
 }
@@ -2422,7 +2659,7 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
 
        /* store the notify value in the printer struct */
 
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
@@ -2450,20 +2687,20 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
                return WERR_BADFID;
 
        DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
-               "client_address is %s\n", p->client_address));
+               "client_address is %s\n", p->client_id->addr));
 
-       if (!interpret_string_addr(&client_ss, p->client_address,
+       if (!interpret_string_addr(&client_ss, p->client_id->addr,
                                   AI_NUMERICHOST)) {
                return WERR_SERVER_UNAVAILABLE;
        }
 
        if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
-                                       Printer->notify.printerlocal, 1,
-                                       &Printer->notify.client_hnd,
-                                       &client_ss, p->msg_ctx))
+                                       Printer->notify.printerlocal, REG_SZ,
+                                       &Printer->notify.cli_hnd,
+                                       &Printer->notify.cli_chan,
+                                       &client_ss, p->msg_ctx)) {
                return WERR_SERVER_UNAVAILABLE;
-
-       Printer->notify.client_connected = true;
+       }
 
        return WERR_OK;
 }
@@ -2472,7 +2709,8 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
  * fill a notify_info_data with the servername
  ********************************************************************/
 
-static void spoolss_notify_server_name(int snum,
+static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
+                                      int snum,
                                       struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       struct spoolss_PrinterInfo2 *pinfo2,
@@ -2485,7 +2723,8 @@ static void spoolss_notify_server_name(int snum,
  * fill a notify_info_data with the printername (not including the servername).
  ********************************************************************/
 
-static void spoolss_notify_printer_name(int snum,
+static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
+                                       int snum,
                                        struct spoolss_Notify *data,
                                        print_queue_struct *queue,
                                        struct spoolss_PrinterInfo2 *pinfo2,
@@ -2507,7 +2746,8 @@ static void spoolss_notify_printer_name(int snum,
  * fill a notify_info_data with the servicename
  ********************************************************************/
 
-static void spoolss_notify_share_name(int snum,
+static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
+                                     int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      struct spoolss_PrinterInfo2 *pinfo2,
@@ -2520,7 +2760,8 @@ static void spoolss_notify_share_name(int snum,
  * fill a notify_info_data with the port name
  ********************************************************************/
 
-static void spoolss_notify_port_name(int snum,
+static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
+                                    int snum,
                                     struct spoolss_Notify *data,
                                     print_queue_struct *queue,
                                     struct spoolss_PrinterInfo2 *pinfo2,
@@ -2534,7 +2775,8 @@ static void spoolss_notify_port_name(int snum,
  * but it doesn't exist, have to see what to do
  ********************************************************************/
 
-static void spoolss_notify_driver_name(int snum,
+static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
+                                      int snum,
                                       struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       struct spoolss_PrinterInfo2 *pinfo2,
@@ -2547,7 +2789,8 @@ static void spoolss_notify_driver_name(int snum,
  * fill a notify_info_data with the comment
  ********************************************************************/
 
-static void spoolss_notify_comment(int snum,
+static void spoolss_notify_comment(struct messaging_context *msg_ctx,
+                                  int snum,
                                   struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   struct spoolss_PrinterInfo2 *pinfo2,
@@ -2569,7 +2812,8 @@ static void spoolss_notify_comment(int snum,
  * location = "Room 1, floor 2, building 3"
  ********************************************************************/
 
-static void spoolss_notify_location(int snum,
+static void spoolss_notify_location(struct messaging_context *msg_ctx,
+                                   int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    struct spoolss_PrinterInfo2 *pinfo2,
@@ -2583,7 +2827,8 @@ static void spoolss_notify_location(int snum,
  * jfm:xxxx don't to it for know but that's a real problem !!!
  ********************************************************************/
 
-static void spoolss_notify_devmode(int snum,
+static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
+                                  int snum,
                                   struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   struct spoolss_PrinterInfo2 *pinfo2,
@@ -2597,7 +2842,8 @@ static void spoolss_notify_devmode(int snum,
  * fill a notify_info_data with the separator file name
  ********************************************************************/
 
-static void spoolss_notify_sepfile(int snum,
+static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
+                                  int snum,
                                   struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   struct spoolss_PrinterInfo2 *pinfo2,
@@ -2611,7 +2857,8 @@ static void spoolss_notify_sepfile(int snum,
  * jfm:xxxx return always winprint to indicate we don't do anything to it
  ********************************************************************/
 
-static void spoolss_notify_print_processor(int snum,
+static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
+                                          int snum,
                                           struct spoolss_Notify *data,
                                           print_queue_struct *queue,
                                           struct spoolss_PrinterInfo2 *pinfo2,
@@ -2625,7 +2872,8 @@ static void spoolss_notify_print_processor(int snum,
  * jfm:xxxx send an empty string
  ********************************************************************/
 
-static void spoolss_notify_parameters(int snum,
+static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
+                                     int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      struct spoolss_PrinterInfo2 *pinfo2,
@@ -2639,7 +2887,8 @@ static void spoolss_notify_parameters(int snum,
  * jfm:xxxx always send RAW as data type
  ********************************************************************/
 
-static void spoolss_notify_datatype(int snum,
+static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
+                                   int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    struct spoolss_PrinterInfo2 *pinfo2,
@@ -2654,7 +2903,8 @@ static void spoolss_notify_datatype(int snum,
  * have to implement security before !
  ********************************************************************/
 
-static void spoolss_notify_security_desc(int snum,
+static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
+                                        int snum,
                                         struct spoolss_Notify *data,
                                         print_queue_struct *queue,
                                         struct spoolss_PrinterInfo2 *pinfo2,
@@ -2668,7 +2918,8 @@ static void spoolss_notify_security_desc(int snum,
  * jfm:xxxx a samba printer is always shared
  ********************************************************************/
 
-static void spoolss_notify_attributes(int snum,
+static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
+                                     int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      struct spoolss_PrinterInfo2 *pinfo2,
@@ -2681,7 +2932,8 @@ static void spoolss_notify_attributes(int snum,
  * fill a notify_info_data with the priority
  ********************************************************************/
 
-static void spoolss_notify_priority(int snum,
+static void spoolss_notify_priority(struct messaging_context *msg_ctx,
+                                   int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    struct spoolss_PrinterInfo2 *pinfo2,
@@ -2694,7 +2946,8 @@ static void spoolss_notify_priority(int snum,
  * fill a notify_info_data with the default priority
  ********************************************************************/
 
-static void spoolss_notify_default_priority(int snum,
+static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
+                                           int snum,
                                            struct spoolss_Notify *data,
                                            print_queue_struct *queue,
                                            struct spoolss_PrinterInfo2 *pinfo2,
@@ -2707,7 +2960,8 @@ static void spoolss_notify_default_priority(int snum,
  * fill a notify_info_data with the start time
  ********************************************************************/
 
-static void spoolss_notify_start_time(int snum,
+static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
+                                     int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      struct spoolss_PrinterInfo2 *pinfo2,
@@ -2720,7 +2974,8 @@ static void spoolss_notify_start_time(int snum,
  * fill a notify_info_data with the until time
  ********************************************************************/
 
-static void spoolss_notify_until_time(int snum,
+static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
+                                     int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      struct spoolss_PrinterInfo2 *pinfo2,
@@ -2733,7 +2988,8 @@ static void spoolss_notify_until_time(int snum,
  * fill a notify_info_data with the status
  ********************************************************************/
 
-static void spoolss_notify_status(int snum,
+static void spoolss_notify_status(struct messaging_context *msg_ctx,
+                                 int snum,
                                  struct spoolss_Notify *data,
                                  print_queue_struct *queue,
                                  struct spoolss_PrinterInfo2 *pinfo2,
@@ -2741,7 +2997,7 @@ static void spoolss_notify_status(int snum,
 {
        print_status_struct status;
 
-       print_queue_length(snum, &status);
+       print_queue_length(msg_ctx, snum, &status);
        SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
 }
 
@@ -2749,20 +3005,23 @@ static void spoolss_notify_status(int snum,
  * fill a notify_info_data with the number of jobs queued
  ********************************************************************/
 
-static void spoolss_notify_cjobs(int snum,
+static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
+                                int snum,
                                 struct spoolss_Notify *data,
                                 print_queue_struct *queue,
                                 struct spoolss_PrinterInfo2 *pinfo2,
                                 TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
+               data, print_queue_length(msg_ctx, snum, NULL));
 }
 
 /*******************************************************************
  * fill a notify_info_data with the average ppm
  ********************************************************************/
 
-static void spoolss_notify_average_ppm(int snum,
+static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
+                                      int snum,
                                       struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       struct spoolss_PrinterInfo2 *pinfo2,
@@ -2777,7 +3036,8 @@ static void spoolss_notify_average_ppm(int snum,
  * fill a notify_info_data with username
  ********************************************************************/
 
-static void spoolss_notify_username(int snum,
+static void spoolss_notify_username(struct messaging_context *msg_ctx,
+                                   int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    struct spoolss_PrinterInfo2 *pinfo2,
@@ -2790,7 +3050,8 @@ static void spoolss_notify_username(int snum,
  * fill a notify_info_data with job status
  ********************************************************************/
 
-static void spoolss_notify_job_status(int snum,
+static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
+                                     int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      struct spoolss_PrinterInfo2 *pinfo2,
@@ -2803,7 +3064,8 @@ static void spoolss_notify_job_status(int snum,
  * fill a notify_info_data with job name
  ********************************************************************/
 
-static void spoolss_notify_job_name(int snum,
+static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
+                                   int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    struct spoolss_PrinterInfo2 *pinfo2,
@@ -2816,7 +3078,8 @@ static void spoolss_notify_job_name(int snum,
  * fill a notify_info_data with job status
  ********************************************************************/
 
-static void spoolss_notify_job_status_string(int snum,
+static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
+                                            int snum,
                                             struct spoolss_Notify *data,
                                             print_queue_struct *queue,
                                             struct spoolss_PrinterInfo2 *pinfo2,
@@ -2854,7 +3117,8 @@ static void spoolss_notify_job_status_string(int snum,
  * fill a notify_info_data with job time
  ********************************************************************/
 
-static void spoolss_notify_job_time(int snum,
+static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
+                                   int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    struct spoolss_PrinterInfo2 *pinfo2,
@@ -2867,7 +3131,8 @@ static void spoolss_notify_job_time(int snum,
  * fill a notify_info_data with job size
  ********************************************************************/
 
-static void spoolss_notify_job_size(int snum,
+static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
+                                   int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    struct spoolss_PrinterInfo2 *pinfo2,
@@ -2879,7 +3144,8 @@ static void spoolss_notify_job_size(int snum,
 /*******************************************************************
  * fill a notify_info_data with page info
  ********************************************************************/
-static void spoolss_notify_total_pages(int snum,
+static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
+                                      int snum,
                                struct spoolss_Notify *data,
                                print_queue_struct *queue,
                                struct spoolss_PrinterInfo2 *pinfo2,
@@ -2891,7 +3157,8 @@ static void spoolss_notify_total_pages(int snum,
 /*******************************************************************
  * fill a notify_info_data with pages printed info.
  ********************************************************************/
-static void spoolss_notify_pages_printed(int snum,
+static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
+                                        int snum,
                                struct spoolss_Notify *data,
                                print_queue_struct *queue,
                                struct spoolss_PrinterInfo2 *pinfo2,
@@ -2905,7 +3172,8 @@ static void spoolss_notify_pages_printed(int snum,
  Fill a notify_info_data with job position.
  ********************************************************************/
 
-static void spoolss_notify_job_position(int snum,
+static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
+                                       int snum,
                                        struct spoolss_Notify *data,
                                        print_queue_struct *queue,
                                        struct spoolss_PrinterInfo2 *pinfo2,
@@ -2918,7 +3186,8 @@ static void spoolss_notify_job_position(int snum,
  Fill a notify_info_data with submitted time.
  ********************************************************************/
 
-static void spoolss_notify_submitted_time(int snum,
+static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
+                                         int snum,
                                          struct spoolss_Notify *data,
                                          print_queue_struct *queue,
                                          struct spoolss_PrinterInfo2 *pinfo2,
@@ -2939,7 +3208,8 @@ struct s_notify_info_data_table
        uint16_t field;
        const char *name;
        enum spoolss_NotifyTable variable_type;
-       void (*fn) (int snum, struct spoolss_Notify *data,
+       void (*fn) (struct messaging_context *msg_ctx,
+                   int snum, struct spoolss_Notify *data,
                    print_queue_struct *queue,
                    struct spoolss_PrinterInfo2 *pinfo2,
                    TALLOC_CTX *mem_ctx);
@@ -3006,8 +3276,8 @@ static const struct s_notify_info_data_table notify_info_data_table[] =
  Return the variable_type of info_data structure.
 ********************************************************************/
 
-static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
-                                                 uint16_t field)
+static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
+                                                                 uint16_t field)
 {
        int i=0;
 
@@ -3020,7 +3290,7 @@ static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
 
        DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
 
-       return 0;
+       return (enum spoolss_NotifyTable) 0;
 }
 
 /****************************************************************************
@@ -3063,7 +3333,8 @@ static void construct_info_data(struct spoolss_Notify *info_data,
  *
  ********************************************************************/
 
-static bool construct_notify_printer_info(Printer_entry *print_hnd,
+static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
+                                         struct printer_handle *print_hnd,
                                          struct spoolss_NotifyInfo *info,
                                          struct spoolss_PrinterInfo2 *pinfo2,
                                          int snum,
@@ -3109,8 +3380,8 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
                           notify_info_data_table[j].name, snum,
                           pinfo2->printername));
 
-               notify_info_data_table[j].fn(snum, current_data, queue,
-                                            pinfo2, mem_ctx);
+               notify_info_data_table[j].fn(msg_ctx, snum, current_data,
+                                            queue, pinfo2, mem_ctx);
 
                info->count++;
        }
@@ -3124,7 +3395,8 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
  *
  ********************************************************************/
 
-static bool construct_notify_jobs_info(print_queue_struct *queue,
+static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
+                                      print_queue_struct *queue,
                                       struct spoolss_NotifyInfo *info,
                                       struct spoolss_PrinterInfo2 *pinfo2,
                                       int snum,
@@ -3162,8 +3434,8 @@ static bool construct_notify_jobs_info(print_queue_struct *queue,
                current_data=&(info->notifies[info->count]);
 
                construct_info_data(current_data, type, field, id);
-               notify_info_data_table[j].fn(snum, current_data, queue,
-                                            pinfo2, mem_ctx);
+               notify_info_data_table[j].fn(msg_ctx, snum, current_data,
+                                            queue, pinfo2, mem_ctx);
                info->count++;
        }
 
@@ -3206,7 +3478,7 @@ static WERROR printserver_notify_info(struct pipes_struct *p,
                                      TALLOC_CTX *mem_ctx)
 {
        int snum;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
        int n_services=lp_numservices();
        int i;
        struct spoolss_NotifyOption *option;
@@ -3245,9 +3517,9 @@ static WERROR printserver_notify_info(struct pipes_struct *p,
                        }
 
                        /* Maybe we should use the SYSTEM server_info here... */
-                       result = winreg_get_printer(mem_ctx, p->server_info,
+                       result = winreg_get_printer(mem_ctx,
+                                                   get_server_info_system(),
                                                    p->msg_ctx,
-                                                   Printer->servername,
                                                    lp_servicename(snum),
                                                    &pinfo2);
                        if (!W_ERROR_IS_OK(result)) {
@@ -3258,7 +3530,8 @@ static WERROR printserver_notify_info(struct pipes_struct *p,
                        }
 
 
-                       construct_notify_printer_info(Printer, info,
+                       construct_notify_printer_info(p->msg_ctx,
+                                                     Printer, info,
                                                      pinfo2, snum,
                                                      &option_type, snum,
                                                      mem_ctx);
@@ -3298,7 +3571,7 @@ static WERROR printer_notify_info(struct pipes_struct *p,
                                  TALLOC_CTX *mem_ctx)
 {
        int snum;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
        int i;
        uint32_t id;
        struct spoolss_NotifyOption *option;
@@ -3330,8 +3603,9 @@ static WERROR printer_notify_info(struct pipes_struct *p,
        get_printer_snum(p, hnd, &snum, NULL);
 
        /* Maybe we should use the SYSTEM server_info here... */
-       result = winreg_get_printer(mem_ctx, p->server_info, p->msg_ctx,
-                                   Printer->servername,
+       result = winreg_get_printer(mem_ctx,
+                                   get_server_info_system(),
+                                   p->msg_ctx,
                                    lp_servicename(snum), &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
                return WERR_BADFID;
@@ -3342,7 +3616,8 @@ static WERROR printer_notify_info(struct pipes_struct *p,
 
                switch (option_type.type) {
                case PRINTER_NOTIFY_TYPE:
-                       if (construct_notify_printer_info(Printer, info,
+                       if (construct_notify_printer_info(p->msg_ctx,
+                                                         Printer, info,
                                                          pinfo2, snum,
                                                          &option_type, id,
                                                          mem_ctx)) {
@@ -3352,10 +3627,12 @@ static WERROR printer_notify_info(struct pipes_struct *p,
 
                case JOB_NOTIFY_TYPE:
 
-                       count = print_queue_status(snum, &queue, &status);
+                       count = print_queue_status(p->msg_ctx, snum, &queue,
+                                                  &status);
 
                        for (j=0; j<count; j++) {
-                               construct_notify_jobs_info(&queue[j], info,
+                               construct_notify_jobs_info(p->msg_ctx,
+                                                          &queue[j], info,
                                                           pinfo2, snum,
                                                           &option_type,
                                                           queue[j].job,
@@ -3395,7 +3672,7 @@ WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
 {
        struct spoolss_NotifyInfo *info;
 
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        WERROR result = WERR_BADFID;
 
        /* we always have a spoolss_NotifyInfo struct */
@@ -3428,7 +3705,8 @@ WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
 
        Printer->notify.fnpcn = true;
 
-       if (Printer->notify.client_connected) {
+       if (Printer->notify.cli_chan != NULL &&
+           Printer->notify.cli_chan->active_connections > 0) {
                DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
                        "Saving change value in request [%x]\n",
                        r->in.change_low));
@@ -3455,30 +3733,78 @@ done:
        return result;
 }
 
+/********************************************************************
+ ********************************************************************/
+
+static WERROR create_printername(TALLOC_CTX *mem_ctx,
+                                const char *servername,
+                                const char *printername,
+                                const char **printername_p)
+{
+       /* FIXME: add lp_force_printername() */
+
+       if (servername == NULL) {
+               *printername_p = talloc_strdup(mem_ctx, printername);
+               W_ERROR_HAVE_NO_MEMORY(*printername_p);
+               return WERR_OK;
+       }
+
+       if (servername[0] == '\\' && servername[1] == '\\') {
+               servername += 2;
+       }
+
+       *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
+       W_ERROR_HAVE_NO_MEMORY(*printername_p);
+
+       return WERR_OK;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
+                                         const char *printername)
+{
+       if (dm == NULL) {
+               return;
+       }
+
+       dm->devicename = talloc_strndup(dm, printername,
+                                       MIN(strlen(printername), 31));
+}
+
 /********************************************************************
  * construct_printer_info_0
  * fill a printer_info_0 struct
  ********************************************************************/
 
 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
-                                     struct auth_serversupplied_info *server_info,
+                                     const struct auth_serversupplied_info *server_info,
                                      struct messaging_context *msg_ctx,
                                      struct spoolss_PrinterInfo2 *info2,
+                                     const char *servername,
                                      struct spoolss_PrinterInfo0 *r,
                                      int snum)
 {
        int count;
-       counter_printer_0 *session_counter;
+       struct printer_session_counter *session_counter;
        struct timeval setuptime;
        print_status_struct status;
+       WERROR result;
 
-       r->printername          = talloc_strdup(mem_ctx, info2->printername);
-       W_ERROR_HAVE_NO_MEMORY(r->printername);
+       result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
 
-       r->servername           = talloc_strdup(mem_ctx, info2->servername);
-       W_ERROR_HAVE_NO_MEMORY(r->servername);
+       if (servername) {
+               r->servername = talloc_strdup(mem_ctx, servername);
+               W_ERROR_HAVE_NO_MEMORY(r->servername);
+       } else {
+               r->servername = NULL;
+       }
 
-       count = print_queue_length(snum, &status);
+       count = print_queue_length(msg_ctx, snum, &status);
 
        /* check if we already have a counter for this printer */
        for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
@@ -3488,9 +3814,8 @@ static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
 
        /* it's the first time, add it to the list */
        if (session_counter == NULL) {
-               session_counter = SMB_MALLOC_P(counter_printer_0);
+               session_counter = talloc_zero(counter_list, struct printer_session_counter);
                W_ERROR_HAVE_NO_MEMORY(session_counter);
-               ZERO_STRUCTP(session_counter);
                session_counter->snum           = snum;
                session_counter->counter        = 0;
                DLIST_ADD(counter_list, session_counter);
@@ -3534,7 +3859,7 @@ static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
        r->status                       = nt_printq_status(status.status);
        r->enumerate_network_printers   = 0x0;
        r->c_setprinter                 = 0x0;
-       r->processor_architecture       = 0x0;
+       r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
        r->processor_level              = 0x6;          /* 6  ???*/
        r->ref_ic                       = 0;
        r->reserved2                    = 0;
@@ -3552,16 +3877,13 @@ static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
                                      const struct spoolss_PrinterInfo2 *info2,
                                      uint32_t flags,
+                                     const char *servername,
                                      struct spoolss_PrinterInfo1 *r,
                                      int snum)
 {
-       r->flags                = flags;
+       WERROR result;
 
-       r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
-                                                 info2->printername,
-                                                 info2->drivername,
-                                                 info2->location);
-       W_ERROR_HAVE_NO_MEMORY(r->description);
+       r->flags                = flags;
 
        if (info2->comment == NULL || info2->comment[0] == '\0') {
                r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
@@ -3570,8 +3892,16 @@ static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
        }
        W_ERROR_HAVE_NO_MEMORY(r->comment);
 
-       r->name                 = talloc_strdup(mem_ctx, info2->printername);
-       W_ERROR_HAVE_NO_MEMORY(r->name);
+       result = create_printername(mem_ctx, servername, info2->printername, &r->name);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
+       r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
+                                                 r->name,
+                                                 info2->drivername,
+                                                 r->comment);
+       W_ERROR_HAVE_NO_MEMORY(r->description);
 
        return WERR_OK;
 }
@@ -3582,19 +3912,30 @@ static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
 ********************************************************************/
 
 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
+                                     struct messaging_context *msg_ctx,
                                      const struct spoolss_PrinterInfo2 *info2,
+                                     const char *servername,
                                      struct spoolss_PrinterInfo2 *r,
                                      int snum)
 {
        int count;
        print_status_struct status;
+       WERROR result;
+
+       count = print_queue_length(msg_ctx, snum, &status);
 
-       count = print_queue_length(snum, &status);
+       if (servername) {
+               r->servername           = talloc_strdup(mem_ctx, servername);
+               W_ERROR_HAVE_NO_MEMORY(r->servername);
+       } else {
+               r->servername           = NULL;
+       }
+
+       result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
 
-       r->servername           = talloc_strdup(mem_ctx, info2->servername);
-       W_ERROR_HAVE_NO_MEMORY(r->servername);
-       r->printername          = talloc_strdup(mem_ctx, info2->printername);
-       W_ERROR_HAVE_NO_MEMORY(r->printername);
        r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
        W_ERROR_HAVE_NO_MEMORY(r->sharename);
        r->portname             = talloc_strdup(mem_ctx, info2->portname);
@@ -3635,6 +3976,8 @@ static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
                DEBUG(8,("Returning NULL Devicemode!\n"));
        }
 
+       compose_devicemode_devicename(r->devmode, r->printername);
+
        r->secdesc = NULL;
 
        if (info2->secdesc != NULL) {
@@ -3654,6 +3997,7 @@ static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
 
 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
                                      const struct spoolss_PrinterInfo2 *info2,
+                                     const char *servername,
                                      struct spoolss_PrinterInfo3 *r,
                                      int snum)
 {
@@ -3677,13 +4021,23 @@ static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
 
 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
                                      const struct spoolss_PrinterInfo2 *info2,
+                                     const char *servername,
                                      struct spoolss_PrinterInfo4 *r,
                                      int snum)
 {
-       r->printername  = talloc_strdup(mem_ctx, info2->printername);
-       W_ERROR_HAVE_NO_MEMORY(r->printername);
-       r->servername   = talloc_strdup(mem_ctx, info2->servername);
-       W_ERROR_HAVE_NO_MEMORY(r->servername);
+       WERROR result;
+
+       result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
+       if (servername) {
+               r->servername   = talloc_strdup(mem_ctx, servername);
+               W_ERROR_HAVE_NO_MEMORY(r->servername);
+       } else {
+               r->servername = NULL;
+       }
 
        r->attributes   = info2->attributes;
 
@@ -3697,11 +4051,17 @@ static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
 
 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
                                      const struct spoolss_PrinterInfo2 *info2,
+                                     const char *servername,
                                      struct spoolss_PrinterInfo5 *r,
                                      int snum)
 {
-       r->printername  = talloc_strdup(mem_ctx, info2->printername);
-       W_ERROR_HAVE_NO_MEMORY(r->printername);
+       WERROR result;
+
+       result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
        r->portname     = talloc_strdup(mem_ctx, info2->portname);
        W_ERROR_HAVE_NO_MEMORY(r->portname);
 
@@ -3720,14 +4080,16 @@ static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
+                                     struct messaging_context *msg_ctx,
                                      const struct spoolss_PrinterInfo2 *info2,
+                                     const char *servername,
                                      struct spoolss_PrinterInfo6 *r,
                                      int snum)
 {
        int count;
        print_status_struct status;
 
-       count = print_queue_length(snum, &status);
+       count = print_queue_length(msg_ctx, snum, &status);
 
        r->status = nt_printq_status(status.status);
 
@@ -3741,7 +4103,7 @@ static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
 
 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
                                      struct messaging_context *msg_ctx,
-                                     Printer_entry *print_hnd,
+                                     const char *servername,
                                      struct spoolss_PrinterInfo7 *r,
                                      int snum)
 {
@@ -3757,7 +4119,7 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
        }
 
        if (is_printer_published(mem_ctx, server_info, msg_ctx,
-                                print_hnd->servername,
+                                servername,
                                 lp_servicename(snum), &guid, NULL)) {
                r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
                r->action = DSPRINT_PUBLISH;
@@ -3778,14 +4140,25 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
 
 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
                                      const struct spoolss_PrinterInfo2 *info2,
+                                     const char *servername,
                                      struct spoolss_DeviceModeInfo *r,
                                      int snum)
 {
+       WERROR result;
+       const char *printername;
+
+       result = create_printername(mem_ctx, servername, info2->printername, &printername);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
        copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
        if (!r->devmode) {
                DEBUG(8,("Returning NULL Devicemode!\n"));
        }
 
+       compose_devicemode_devicename(r->devmode, printername);
+
        return WERR_OK;
 }
 
@@ -3803,8 +4176,9 @@ static bool snum_is_shared_printer(int snum)
 ********************************************************************/
 
 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
-                                          struct auth_serversupplied_info *server_info,
+                                          const struct auth_serversupplied_info *server_info,
                                           struct messaging_context *msg_ctx,
+                                          const char *servername,
                                           uint32_t level,
                                           uint32_t flags,
                                           union spoolss_PrinterInfo **info_p,
@@ -3836,7 +4210,6 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                result = winreg_create_printer(mem_ctx,
                                               server_info,
                                               msg_ctx,
-                                              NULL,
                                               printer);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
@@ -3851,7 +4224,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                }
 
                result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
-                                           NULL, printer, &info2);
+                                           printer, &info2);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
                }
@@ -3860,22 +4233,27 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                case 0:
                        result = construct_printer_info0(info, server_info,
                                                         msg_ctx, info2,
+                                                        servername,
                                                         &info[count].info0, snum);
                        break;
                case 1:
                        result = construct_printer_info1(info, info2, flags,
+                                                        servername,
                                                         &info[count].info1, snum);
                        break;
                case 2:
-                       result = construct_printer_info2(info, info2,
+                       result = construct_printer_info2(info, msg_ctx, info2,
+                                                        servername,
                                                         &info[count].info2, snum);
                        break;
                case 4:
                        result = construct_printer_info4(info, info2,
+                                                        servername,
                                                         &info[count].info4, snum);
                        break;
                case 5:
                        result = construct_printer_info5(info, info2,
+                                                        servername,
                                                         &info[count].info5, snum);
                        break;
 
@@ -3910,7 +4288,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
-                                 struct auth_serversupplied_info *server_info,
+                                 const struct auth_serversupplied_info *server_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
                                  const char *servername,
@@ -3920,7 +4298,7 @@ static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
        DEBUG(4,("enum_all_printers_info_0\n"));
 
        return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
-                                           0, flags, info, count);
+                                           servername, 0, flags, info, count);
 }
 
 
@@ -3928,8 +4306,9 @@ static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
 ********************************************************************/
 
 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
-                                      struct auth_serversupplied_info *server_info,
+                                      const struct auth_serversupplied_info *server_info,
                                       struct messaging_context *msg_ctx,
+                                      const char *servername,
                                       uint32_t flags,
                                       union spoolss_PrinterInfo **info,
                                       uint32_t *count)
@@ -3937,7 +4316,7 @@ static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
        DEBUG(4,("enum_all_printers_info_1\n"));
 
        return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
-                                           1, flags, info, count);
+                                           servername, 1, flags, info, count);
 }
 
 /********************************************************************
@@ -3945,15 +4324,16 @@ static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
 *********************************************************************/
 
 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
-                                            struct auth_serversupplied_info *server_info,
+                                            const struct auth_serversupplied_info *server_info,
                                             struct messaging_context *msg_ctx,
+                                            const char *servername,
                                             union spoolss_PrinterInfo **info,
                                             uint32_t *count)
 {
        DEBUG(4,("enum_all_printers_info_1_local\n"));
 
        return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
-                                       PRINTER_ENUM_ICON8, info, count);
+                                       servername, PRINTER_ENUM_ICON8, info, count);
 }
 
 /********************************************************************
@@ -3961,18 +4341,18 @@ static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
 *********************************************************************/
 
 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
-                                           struct auth_serversupplied_info *server_info,
+                                           const struct auth_serversupplied_info *server_info,
                                            struct messaging_context *msg_ctx,
-                                           const char *name,
+                                           const char *servername,
                                            union spoolss_PrinterInfo **info,
                                            uint32_t *count)
 {
-       const char *s = name;
+       const char *s = servername;
 
        DEBUG(4,("enum_all_printers_info_1_name\n"));
 
-       if ((name[0] == '\\') && (name[1] == '\\')) {
-               s = name + 2;
+       if ((servername[0] == '\\') && (servername[1] == '\\')) {
+               s = servername + 2;
        }
 
        if (!is_myname_or_ipaddr(s)) {
@@ -3980,7 +4360,7 @@ static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
        }
 
        return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
-                                       PRINTER_ENUM_ICON8, info, count);
+                                       servername, PRINTER_ENUM_ICON8, info, count);
 }
 
 /********************************************************************
@@ -3988,13 +4368,13 @@ static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
 *********************************************************************/
 
 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
-                                              struct auth_serversupplied_info *server_info,
+                                              const struct auth_serversupplied_info *server_info,
                                               struct messaging_context *msg_ctx,
-                                              const char *name,
+                                              const char *servername,
                                               union spoolss_PrinterInfo **info,
                                               uint32_t *count)
 {
-       const char *s = name;
+       const char *s = servername;
 
        DEBUG(4,("enum_all_printers_info_1_network\n"));
 
@@ -4006,8 +4386,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 (name[0] == '\\' && name[1] == '\\') {
-                s = name + 2;
+       if (servername[0] == '\\' && servername[1] == '\\') {
+                s = servername + 2;
        }
 
        if (is_myname_or_ipaddr(s)) {
@@ -4015,7 +4395,7 @@ static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
        }
 
        return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
-                                       PRINTER_ENUM_NAME, info, count);
+                                       servername, PRINTER_ENUM_NAME, info, count);
 }
 
 /********************************************************************
@@ -4025,15 +4405,16 @@ static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
-                                      struct auth_serversupplied_info *server_info,
+                                      const struct auth_serversupplied_info *server_info,
                                       struct messaging_context *msg_ctx,
+                                      const char *servername,
                                       union spoolss_PrinterInfo **info,
                                       uint32_t *count)
 {
        DEBUG(4,("enum_all_printers_info_2\n"));
 
        return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
-                                           2, 0, info, count);
+                                           servername, 2, 0, info, count);
 }
 
 /********************************************************************
@@ -4041,10 +4422,10 @@ static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
-                                 struct auth_serversupplied_info *server_info,
+                                 const struct auth_serversupplied_info *server_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
-                                 const char *name,
+                                 const char *servername,
                                  union spoolss_PrinterInfo **info,
                                  uint32_t *count)
 {
@@ -4052,18 +4433,18 @@ static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
 
        if (flags & PRINTER_ENUM_LOCAL) {
                return enum_all_printers_info_1_local(mem_ctx, server_info,
-                                                     msg_ctx, info, count);
+                                                     msg_ctx, servername, info, count);
        }
 
        if (flags & PRINTER_ENUM_NAME) {
                return enum_all_printers_info_1_name(mem_ctx, server_info,
-                                                    msg_ctx, name, info,
+                                                    msg_ctx, servername, info,
                                                     count);
        }
 
        if (flags & PRINTER_ENUM_NETWORK) {
                return enum_all_printers_info_1_network(mem_ctx, server_info,
-                                                       msg_ctx, name, info,
+                                                       msg_ctx, servername, info,
                                                        count);
        }
 
@@ -4075,7 +4456,7 @@ static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
-                                 struct auth_serversupplied_info *server_info,
+                                 const struct auth_serversupplied_info *server_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
                                  const char *servername,
@@ -4083,16 +4464,19 @@ static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
                                  uint32_t *count)
 {
        if (flags & PRINTER_ENUM_LOCAL) {
+
                return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
+                                               servername,
                                                info, count);
        }
 
        if (flags & PRINTER_ENUM_NAME) {
-               if (!is_myname_or_ipaddr(canon_servername(servername))) {
+               if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
                        return WERR_INVALID_NAME;
                }
 
                return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
+                                               servername,
                                                info, count);
        }
 
@@ -4108,7 +4492,7 @@ static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
-                                 struct auth_serversupplied_info *server_info,
+                                 const struct auth_serversupplied_info *server_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
                                  const char *servername,
@@ -4118,7 +4502,7 @@ static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
        DEBUG(4,("enum_all_printers_info_4\n"));
 
        return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
-                                           4, flags, info, count);
+                                           servername, 4, flags, info, count);
 }
 
 
@@ -4127,7 +4511,7 @@ static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
-                                 struct auth_serversupplied_info *server_info,
+                                 const struct auth_serversupplied_info *server_info,
                                  struct messaging_context *msg_ctx,
                                  uint32_t flags,
                                  const char *servername,
@@ -4137,7 +4521,7 @@ static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
        DEBUG(4,("enum_all_printers_info_5\n"));
 
        return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
-                                           5, flags, info, count);
+                                           servername, 5, flags, info, count);
 }
 
 /****************************************************************
@@ -4147,7 +4531,7 @@ static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
                             struct spoolss_EnumPrinters *r)
 {
-       const char *name = NULL;
+       const struct auth_serversupplied_info *server_info = get_server_info_system();
        WERROR result;
 
        /* that's an [in out] buffer */
@@ -4175,35 +4559,39 @@ WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
         * Level 5: same as Level 2
         */
 
-       if (r->in.server) {
-               name = talloc_strdup_upper(p->mem_ctx, r->in.server);
-               W_ERROR_HAVE_NO_MEMORY(name);
+       if (r->in.server && r->in.server[0] == '\0') {
+               r->in.server = NULL;
        }
 
        switch (r->in.level) {
        case 0:
-               result = enumprinters_level0(p->mem_ctx, p->server_info,
-                                            p->msg_ctx, r->in.flags, name,
+               result = enumprinters_level0(p->mem_ctx, server_info,
+                                            p->msg_ctx, r->in.flags,
+                                            r->in.server,
                                             r->out.info, r->out.count);
                break;
        case 1:
-               result = enumprinters_level1(p->mem_ctx, p->server_info,
-                                            p->msg_ctx, r->in.flags, name,
+               result = enumprinters_level1(p->mem_ctx, server_info,
+                                            p->msg_ctx, r->in.flags,
+                                            r->in.server,
                                             r->out.info, r->out.count);
                break;
        case 2:
-               result = enumprinters_level2(p->mem_ctx, p->server_info,
-                                            p->msg_ctx, r->in.flags, name,
+               result = enumprinters_level2(p->mem_ctx, server_info,
+                                            p->msg_ctx, r->in.flags,
+                                            r->in.server,
                                             r->out.info, r->out.count);
                break;
        case 4:
-               result = enumprinters_level4(p->mem_ctx, p->server_info,
-                                            p->msg_ctx, r->in.flags, name,
+               result = enumprinters_level4(p->mem_ctx, server_info,
+                                            p->msg_ctx, r->in.flags,
+                                            r->in.server,
                                             r->out.info, r->out.count);
                break;
        case 5:
-               result = enumprinters_level5(p->mem_ctx, p->server_info,
-                                            p->msg_ctx, r->in.flags, name,
+               result = enumprinters_level5(p->mem_ctx, server_info,
+                                            p->msg_ctx, r->in.flags,
+                                            r->in.server,
                                             r->out.info, r->out.count);
                break;
        default:
@@ -4231,10 +4619,9 @@ WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
                           struct spoolss_GetPrinter *r)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        struct spoolss_PrinterInfo2 *info2 = NULL;
        WERROR result = WERR_OK;
-       const char *servername = NULL;
        int snum;
 
        /* that's an [in out] buffer */
@@ -4245,62 +4632,72 @@ WERROR _spoolss_GetPrinter(struct pipes_struct *p,
 
        *r->out.needed = 0;
 
-       if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
+       if (Printer == NULL) {
                return WERR_BADFID;
        }
 
-       if (Printer != NULL || Printer->servername != NULL) {
-               servername = Printer->servername;
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
+               return WERR_BADFID;
        }
 
        result = winreg_get_printer(p->mem_ctx,
-                                   p->server_info,
+                                   get_server_info_system(),
                                    p->msg_ctx,
-                                   servername,
                                    lp_const_servicename(snum),
                                    &info2);
        if (!W_ERROR_IS_OK(result)) {
-               return result;
+               goto out;
        }
 
        switch (r->in.level) {
        case 0:
-               result = construct_printer_info0(p->mem_ctx, p->server_info,
-                                                p->msg_ctx, info2,
-                                                &r->out.info->info0, snum);
+               result = construct_printer_info0(p->mem_ctx,
+                                                get_server_info_system(),
+                                                p->msg_ctx,
+                                                info2,
+                                                Printer->servername,
+                                                &r->out.info->info0,
+                                                snum);
                break;
        case 1:
                result = construct_printer_info1(p->mem_ctx, info2,
                                                 PRINTER_ENUM_ICON8,
+                                                Printer->servername,
                                                 &r->out.info->info1, snum);
                break;
        case 2:
-               result = construct_printer_info2(p->mem_ctx, info2,
+               result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
+                                                Printer->servername,
                                                 &r->out.info->info2, snum);
                break;
        case 3:
                result = construct_printer_info3(p->mem_ctx, info2,
+                                                Printer->servername,
                                                 &r->out.info->info3, snum);
                break;
        case 4:
                result = construct_printer_info4(p->mem_ctx, info2,
+                                                Printer->servername,
                                                 &r->out.info->info4, snum);
                break;
        case 5:
                result = construct_printer_info5(p->mem_ctx, info2,
+                                                Printer->servername,
                                                 &r->out.info->info5, snum);
                break;
        case 6:
-               result = construct_printer_info6(p->mem_ctx, info2,
+               result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
+                                                Printer->servername,
                                                 &r->out.info->info6, snum);
                break;
        case 7:
                result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
-                                                Printer,
+                                                Printer->servername,
                                                 &r->out.info->info7, snum);
                break;
        case 8:
                result = construct_printer_info8(p->mem_ctx, info2,
+                                                Printer->servername,
                                                 &r->out.info->info8, snum);
                break;
        default:
@@ -4308,6 +4705,7 @@ WERROR _spoolss_GetPrinter(struct pipes_struct *p,
                break;
        }
 
+ out:
        if (!W_ERROR_IS_OK(result)) {
                DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
                          r->in.level, win_errstr(result)));
@@ -5003,7 +5401,7 @@ static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
-                                                 struct auth_serversupplied_info *server_info,
+                                                 const struct auth_serversupplied_info *server_info,
                                                  struct messaging_context *msg_ctx,
                                                  uint32_t level,
                                                  union spoolss_DriverInfo *r,
@@ -5016,10 +5414,13 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
        struct spoolss_DriverInfo8 *driver;
        WERROR result;
 
+       if (level == 101) {
+               return WERR_UNKNOWN_LEVEL;
+       }
+
        result = winreg_get_printer(mem_ctx,
                                    server_info,
                                    msg_ctx,
-                                   servername,
                                    lp_const_servicename(snum),
                                    &pinfo2);
 
@@ -5106,7 +5507,7 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
                                  struct spoolss_GetPrinterDriver2 *r)
 {
-       Printer_entry *printer;
+       struct printer_handle *printer;
        WERROR result;
 
        int snum;
@@ -5133,7 +5534,7 @@ WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
        }
 
        result = construct_printer_driver_info_level(p->mem_ctx,
-                                                    p->server_info,
+                                                    get_server_info_system(),
                                                     p->msg_ctx,
                                                     r->in.level, r->out.info,
                                                     snum, printer->servername,
@@ -5159,7 +5560,7 @@ WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
                                 struct spoolss_StartPagePrinter *r)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(3,("_spoolss_StartPagePrinter: "
@@ -5180,7 +5581,7 @@ WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
 {
        int snum;
 
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
@@ -5192,7 +5593,7 @@ WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
                return WERR_BADFID;
 
        Printer->page_started = false;
-       print_job_endpage(snum, Printer->jobid);
+       print_job_endpage(p->msg_ctx, snum, Printer->jobid);
 
        return WERR_OK;
 }
@@ -5206,7 +5607,7 @@ WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
 {
        struct spoolss_DocumentInfo1 *info_1;
        int snum;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        WERROR werr;
 
        if (!Printer) {
@@ -5249,9 +5650,14 @@ WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
-       werr = print_job_start(p->server_info, snum,
-                               info_1->document_name, info_1->output_file,
-                               Printer->devmode, &Printer->jobid);
+       werr = print_job_start(p->server_info,
+                              p->msg_ctx,
+                              p->client_id->name,
+                              snum,
+                              info_1->document_name,
+                              info_1->output_file,
+                              Printer->devmode,
+                              &Printer->jobid);
 
        /* An error occured in print_job_start() so return an appropriate
           NT error code. */
@@ -5273,7 +5679,7 @@ WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
                              struct spoolss_EndDocPrinter *r)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        NTSTATUS status;
        int snum;
 
@@ -5288,7 +5694,7 @@ WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
        }
 
        Printer->document_started = false;
-       status = print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
+       status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(2, ("_spoolss_EndDocPrinter: "
                          "print_job_end failed [%s]\n",
@@ -5308,7 +5714,7 @@ WERROR _spoolss_WritePrinter(struct pipes_struct *p,
 {
        ssize_t buffer_written;
        int snum;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
@@ -5321,9 +5727,9 @@ WERROR _spoolss_WritePrinter(struct pipes_struct *p,
                return WERR_BADFID;
 
        /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
-       buffer_written = print_job_write(snum, Printer->jobid,
+       buffer_written = print_job_write(server_event_context(),p->msg_ctx,
+                                                  snum, Printer->jobid,
                                                   (const char *)r->in.data.data,
-                                                  (SMB_OFF_T)-1,
                                                   (size_t)r->in._data_size);
        if (buffer_written == (ssize_t)-1) {
                *r->out.num_written = 0;
@@ -5347,9 +5753,10 @@ WERROR _spoolss_WritePrinter(struct pipes_struct *p,
 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
                              struct pipes_struct *p)
 {
+       const struct auth_serversupplied_info *server_info = p->server_info;
        int snum;
        WERROR errcode = WERR_BADFUNC;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
 
        if (!Printer) {
                DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
@@ -5362,14 +5769,14 @@ static WERROR control_printer(struct policy_handle *handle, uint32_t command,
 
        switch (command) {
        case SPOOLSS_PRINTER_CONTROL_PAUSE:
-               errcode = print_queue_pause(p->server_info, snum);
+               errcode = print_queue_pause(server_info, p->msg_ctx, snum);
                break;
        case SPOOLSS_PRINTER_CONTROL_RESUME:
        case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
-               errcode = print_queue_resume(p->server_info, snum);
+               errcode = print_queue_resume(server_info, p->msg_ctx, snum);
                break;
        case SPOOLSS_PRINTER_CONTROL_PURGE:
-               errcode = print_queue_purge(p->server_info, snum);
+               errcode = print_queue_purge(server_info, p->msg_ctx, snum);
                break;
        default:
                return WERR_UNKNOWN_LEVEL;
@@ -5388,7 +5795,7 @@ static WERROR control_printer(struct policy_handle *handle, uint32_t command,
 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
                             struct spoolss_AbortPrinter *r)
 {
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int             snum;
        WERROR          errcode = WERR_OK;
 
@@ -5405,7 +5812,10 @@ WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
                return WERR_SPL_NO_STARTDOC;
        }
 
-       errcode = print_job_delete(p->server_info, snum, Printer->jobid);
+       errcode = print_job_delete(p->server_info,
+                                  p->msg_ctx,
+                                  snum,
+                                  Printer->jobid);
 
        return errcode;
 }
@@ -5425,7 +5835,7 @@ static WERROR update_printer_sec(struct policy_handle *handle,
        WERROR result;
        int snum;
 
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
 
        if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
                DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
@@ -5456,7 +5866,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,
-                                           p->server_info,
+                                           get_server_info_system(),
                                            p->msg_ctx,
                                            printer,
                                            &old_secdesc);
@@ -5508,7 +5918,7 @@ static WERROR update_printer_sec(struct policy_handle *handle,
        }
 
        result = winreg_set_printer_secdesc(p->mem_ctx,
-                                           p->server_info,
+                                           get_server_info_system(),
                                            p->msg_ctx,
                                            printer,
                                            new_secdesc);
@@ -5573,12 +5983,11 @@ static bool check_printer_ok(TALLOC_CTX *mem_ctx,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
+static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
 {
        char *cmd = lp_addport_cmd();
        char *command = NULL;
        int ret;
-       SE_PRIV se_printop = SE_PRINT_OPERATOR;
        bool is_print_op = false;
 
        if ( !*cmd ) {
@@ -5592,7 +6001,7 @@ static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *p
        }
 
        if ( token )
-               is_print_op = user_has_privileges( token, &se_printop );
+               is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
 
        DEBUG(10,("Running [%s]\n", command));
 
@@ -5622,7 +6031,7 @@ static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *p
 /****************************************************************************
 ****************************************************************************/
 
-static bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
+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)
@@ -5633,7 +6042,6 @@ static bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
        int numlines;
        int ret;
        int fd;
-       SE_PRIV se_printop = SE_PRINT_OPERATOR;
        bool is_print_op = false;
 
        if (!remote_machine) {
@@ -5650,7 +6058,7 @@ static bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
        }
 
        if ( token )
-               is_print_op = user_has_privileges( token, &se_printop );
+               is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
 
        DEBUG(10,("Running [%s]\n", command));
 
@@ -5681,7 +6089,7 @@ static bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
 
        /* reload our services immediately */
        become_root();
-       reload_services(false);
+       reload_services(msg_ctx, -1, false);
        unbecome_root();
 
        numlines = 0;
@@ -5704,7 +6112,7 @@ static bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
 }
 
 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
-                              struct auth_serversupplied_info *server_info,
+                              const struct auth_serversupplied_info *server_info,
                               struct messaging_context *msg_ctx,
                               int snum,
                               struct spoolss_SetPrinterInfo2 *printer,
@@ -5734,7 +6142,9 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                        DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
                                printer->drivername));
 
-                       notify_printer_driver(snum, printer->drivername);
+                       notify_printer_driver(server_event_context(), msg_ctx,
+                                             snum, printer->drivername ?
+                                             printer->drivername : "");
                }
        }
 
@@ -5751,7 +6161,9 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                          buffer.length);
 
                if (!force_update) {
-                       notify_printer_comment(snum, printer->comment);
+                       notify_printer_comment(server_event_context(), msg_ctx,
+                                              snum, printer->comment ?
+                                              printer->comment : "");
                }
        }
 
@@ -5768,7 +6180,10 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                          buffer.length);
 
                if (!force_update) {
-                       notify_printer_sharename(snum, printer->sharename);
+                       notify_printer_sharename(server_event_context(),
+                                                msg_ctx,
+                                                snum, printer->sharename ?
+                                                printer->sharename : "");
                }
        }
 
@@ -5794,7 +6209,8 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                          buffer.length);
 
                if (!force_update) {
-                       notify_printer_printername(snum, p);
+                       notify_printer_printername(server_event_context(),
+                                                  msg_ctx, snum, p ? p : "");
                }
        }
 
@@ -5811,7 +6227,9 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                          buffer.length);
 
                if (!force_update) {
-                       notify_printer_port(snum, printer->portname);
+                       notify_printer_port(server_event_context(),
+                                           msg_ctx, snum, printer->portname ?
+                                           printer->portname : "");
                }
        }
 
@@ -5828,7 +6246,10 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                          buffer.length);
 
                if (!force_update) {
-                       notify_printer_location(snum, printer->location);
+                       notify_printer_location(server_event_context(),
+                                               msg_ctx, snum,
+                                               printer->location ?
+                                               printer->location : "");
                }
        }
 
@@ -5845,7 +6266,10 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                          buffer.length);
 
                if (!force_update) {
-                       notify_printer_location(snum, printer->location);
+                       notify_printer_sepfile(server_event_context(),
+                                              msg_ctx, snum,
+                                              printer->sepfile ?
+                                              printer->sepfile : "");
                }
        }
 
@@ -5993,8 +6417,7 @@ static WERROR update_printer(struct pipes_struct *p,
        uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
        struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
        struct spoolss_PrinterInfo2 *old_printer;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
-       const char *servername = NULL;
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
        int snum;
        WERROR result = WERR_OK;
        TALLOC_CTX *tmp_ctx;
@@ -6016,14 +6439,9 @@ static WERROR update_printer(struct pipes_struct *p,
                goto done;
        }
 
-       if (Printer != NULL || Printer->servername != NULL) {
-               servername = Printer->servername;
-       }
-
        result = winreg_get_printer(tmp_ctx,
-                                   p->server_info,
+                                   get_server_info_system(),
                                    p->msg_ctx,
-                                   servername,
                                    lp_const_servicename(snum),
                                    &old_printer);
        if (!W_ERROR_IS_OK(result)) {
@@ -6058,7 +6476,7 @@ static WERROR update_printer(struct pipes_struct *p,
        {
                /* add_printer_hook() will call reload_services() */
                if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
-                                     printer, p->client_address,
+                                     printer, p->client_id->addr,
                                      p->msg_ctx)) {
                        result = WERR_ACCESS_DENIED;
                        goto done;
@@ -6066,7 +6484,7 @@ static WERROR update_printer(struct pipes_struct *p,
        }
 
        update_dsspooler(tmp_ctx,
-                        p->server_info,
+                        get_server_info_system(),
                         p->msg_ctx,
                         snum,
                         printer,
@@ -6078,7 +6496,7 @@ static WERROR update_printer(struct pipes_struct *p,
                printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
        }
        result = winreg_update_printer(tmp_ctx,
-                                      p->server_info,
+                                      get_server_info_system(),
                                       p->msg_ctx,
                                       printer->sharename,
                                       printer_mask,
@@ -6102,7 +6520,7 @@ static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
        struct spoolss_PrinterInfo2 *pinfo2 = NULL;
        WERROR result;
        int snum;
-       Printer_entry *Printer;
+       struct printer_handle *Printer;
 
        if ( lp_security() != SEC_ADS ) {
                return WERR_UNKNOWN_LEVEL;
@@ -6118,14 +6536,19 @@ static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
        if (!get_printer_snum(p, handle, &snum, NULL))
                return WERR_BADFID;
 
-       result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
-                                   Printer->servername,
-                                   lp_servicename(snum), &pinfo2);
+       result = winreg_get_printer(p->mem_ctx,
+                                   get_server_info_system(),
+                                   p->msg_ctx,
+                                   lp_servicename(snum),
+                                   &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
                return WERR_BADFID;
        }
 
-       nt_printer_publish(pinfo2, p->server_info, p->msg_ctx, pinfo2,
+       nt_printer_publish(pinfo2,
+                          get_server_info_system(),
+                          p->msg_ctx,
+                          pinfo2,
                           info7->action);
 
        TALLOC_FREE(pinfo2);
@@ -6143,7 +6566,7 @@ static WERROR update_printer_devmode(struct pipes_struct *p,
                                     struct spoolss_DeviceMode *devmode)
 {
        int snum;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
        uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
 
        DEBUG(8,("update_printer_devmode\n"));
@@ -6163,7 +6586,7 @@ static WERROR update_printer_devmode(struct pipes_struct *p,
        }
 
        return winreg_update_printer(p->mem_ctx,
-                                    p->server_info,
+                                    get_server_info_system(),
                                     p->msg_ctx,
                                     lp_const_servicename(snum),
                                     info2_mask,
@@ -6182,7 +6605,7 @@ WERROR _spoolss_SetPrinter(struct pipes_struct *p,
 {
        WERROR result;
 
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
@@ -6225,7 +6648,7 @@ WERROR _spoolss_SetPrinter(struct pipes_struct *p,
 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
                                       struct spoolss_FindClosePrinterNotify *r)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_FindClosePrinterNotify: "
@@ -6233,17 +6656,17 @@ WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
-       if (Printer->notify.client_connected == true) {
+       if (Printer->notify.cli_chan != NULL &&
+           Printer->notify.cli_chan->active_connections > 0) {
                int snum = -1;
 
-               if ( Printer->printer_type == SPLHND_SERVER)
-                       snum = -1;
-               else if ( (Printer->printer_type == SPLHND_PRINTER) &&
-                               !get_printer_snum(p, r->in.handle, &snum, NULL) )
-                       return WERR_BADFID;
+               if (Printer->printer_type == SPLHND_PRINTER) {
+                       if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
+                               return WERR_BADFID;
+                       }
+               }
 
-               srv_spoolss_replycloseprinter(
-                       snum, &Printer->notify.client_hnd, p->msg_ctx);
+               srv_spoolss_replycloseprinter(snum, Printer);
        }
 
        Printer->notify.flags=0;
@@ -6251,7 +6674,6 @@ WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
        Printer->notify.localmachine[0]='\0';
        Printer->notify.printerlocal=0;
        TALLOC_FREE(Printer->notify.option);
-       Printer->notify.client_connected = false;
 
        return WERR_OK;
 }
@@ -6577,13 +6999,16 @@ WERROR _spoolss_EnumJobs(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
-       result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
-                                   NULL, lp_servicename(snum), &pinfo2);
+       result = winreg_get_printer(p->mem_ctx,
+                                   get_server_info_system(),
+                                   p->msg_ctx,
+                                   lp_const_servicename(snum),
+                                   &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
                return result;
        }
 
-       count = print_queue_status(snum, &queue, &prt_status);
+       count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
        DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
                count, prt_status.status, prt_status.message));
 
@@ -6642,6 +7067,7 @@ WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
 ****************************************************************/
 
 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
+                              struct messaging_context *msg_ctx,
                               const char *printer_name,
                               uint32_t job_id,
                               struct spoolss_SetJobInfo1 *r)
@@ -6656,7 +7082,8 @@ static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
                return WERR_OK;
        }
 
-       if (!print_job_set_name(printer_name, job_id, r->document_name)) {
+       if (!print_job_set_name(server_event_context(), msg_ctx,
+                               printer_name, job_id, r->document_name)) {
                return WERR_BADFID;
        }
 
@@ -6670,6 +7097,7 @@ static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
 WERROR _spoolss_SetJob(struct pipes_struct *p,
                       struct spoolss_SetJob *r)
 {
+       const struct auth_serversupplied_info *server_info = p->server_info;
        int snum;
        WERROR errcode = WERR_BADFUNC;
 
@@ -6684,20 +7112,22 @@ WERROR _spoolss_SetJob(struct pipes_struct *p,
        switch (r->in.command) {
        case SPOOLSS_JOB_CONTROL_CANCEL:
        case SPOOLSS_JOB_CONTROL_DELETE:
-               errcode = print_job_delete(p->server_info,
+               errcode = print_job_delete(server_info, p->msg_ctx,
                                           snum, r->in.job_id);
                if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
                        errcode = WERR_OK;
                }
                break;
        case SPOOLSS_JOB_CONTROL_PAUSE:
-               if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
+               if (print_job_pause(server_info, p->msg_ctx,
+                                   snum, r->in.job_id, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
        case SPOOLSS_JOB_CONTROL_RESTART:
        case SPOOLSS_JOB_CONTROL_RESUME:
-               if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
+               if (print_job_resume(server_info, p->msg_ctx,
+                                    snum, r->in.job_id, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
@@ -6718,7 +7148,8 @@ WERROR _spoolss_SetJob(struct pipes_struct *p,
 
        switch (r->in.ctr->level) {
        case 1:
-               errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
+               errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
+                                          lp_const_servicename(snum),
                                           r->in.job_id,
                                           r->in.ctr->info.info1);
                break;
@@ -6737,7 +7168,7 @@ WERROR _spoolss_SetJob(struct pipes_struct *p,
 ****************************************************************************/
 
 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
-                                                      struct auth_serversupplied_info *server_info,
+                                                      const struct auth_serversupplied_info *server_info,
                                                       struct messaging_context *msg_ctx,
                                                       const char *servername,
                                                       const char *architecture,
@@ -6855,7 +7286,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
 ****************************************************************************/
 
 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
-                                      struct auth_serversupplied_info *server_info,
+                                      const struct auth_serversupplied_info *server_info,
                                       struct messaging_context *msg_ctx,
                                       const char *servername,
                                       const char *architecture,
@@ -6933,7 +7364,7 @@ WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
        }
 
        result = enumprinterdrivers_level(p->mem_ctx,
-                                         p->server_info,
+                                         get_server_info_system(),
                                          p->msg_ctx,
                                          cservername,
                                          r->in.environment,
@@ -6980,7 +7411,7 @@ WERROR _spoolss_EnumForms(struct pipes_struct *p,
        switch (r->in.level) {
        case 1:
                result = winreg_printer_enumforms1(p->mem_ctx,
-                                                  p->server_info,
+                                                  get_server_info_system(),
                                                   p->msg_ctx,
                                                   r->out.count,
                                                   r->out.info);
@@ -7030,7 +7461,7 @@ WERROR _spoolss_GetForm(struct pipes_struct *p,
        switch (r->in.level) {
        case 1:
                result = winreg_printer_getform1(p->mem_ctx,
-                                                p->server_info,
+                                                get_server_info_system(),
                                                 p->msg_ctx,
                                                 r->in.form_name,
                                                 &r->out.info->info1);
@@ -7362,7 +7793,7 @@ static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
 
        if (*lp_addprinter_cmd() ) {
                if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
-                                      info2, p->client_address,
+                                      info2, p->client_id->addr,
                                       p->msg_ctx) ) {
                        return WERR_ACCESS_DENIED;
                }
@@ -7378,7 +7809,9 @@ 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->server_info, p->msg_ctx, snum,
+       if (!print_access_check(p->server_info,
+                               p->msg_ctx,
+                               snum,
                                PRINTER_ACCESS_ADMINISTER)) {
                return WERR_ACCESS_DENIED;
        }
@@ -7396,14 +7829,14 @@ static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
        }
 
        update_dsspooler(p->mem_ctx,
-                        p->server_info,
+                        get_server_info_system(),
                         p->msg_ctx,
                         0,
                         info2,
                         NULL);
 
        err = winreg_update_printer(p->mem_ctx,
-                                   p->server_info,
+                                   get_server_info_system(),
                                    p->msg_ctx,
                                    info2->sharename,
                                    info2_mask,
@@ -7528,8 +7961,12 @@ WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
                goto done;
        }
 
-       err = winreg_add_driver(p->mem_ctx, p->server_info, p->msg_ctx,
-                                r->in.info_ctr, &driver_name, &version);
+       err = winreg_add_driver(p->mem_ctx,
+                               get_server_info_system(),
+                               p->msg_ctx,
+                               r->in.info_ctr,
+                               &driver_name,
+                               &version);
        if (!W_ERROR_IS_OK(err)) {
                goto done;
        }
@@ -7880,7 +8317,7 @@ WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
                             struct spoolss_ResetPrinter *r)
 {
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int             snum;
 
        DEBUG(5,("_spoolss_ResetPrinter\n"));
@@ -7931,9 +8368,8 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
        struct spoolss_AddFormInfo1 *form = r->in.info.info1;
        int snum = -1;
        WERROR status = WERR_OK;
-       SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        DEBUG(5,("_spoolss_AddForm\n"));
 
@@ -7947,8 +8383,8 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
           and not a printer admin, then fail */
 
        if ((p->server_info->utok.uid != sec_initial_uid()) &&
-            !user_has_privileges(p->server_info->ptok, &se_printop) &&
-            !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
+           !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
+           !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
                                          p->server_info->info3->base.domain.string,
                                          NULL,
                                          p->server_info->ptok,
@@ -7966,8 +8402,10 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
                return WERR_INVALID_PARAM;
        }
 
-       status = winreg_printer_addform1(p->mem_ctx, p->server_info,
-                                        p->msg_ctx, form);
+       status = winreg_printer_addform1(p->mem_ctx,
+                                        get_server_info_system(),
+                                        p->msg_ctx,
+                                        form);
        if (!W_ERROR_IS_OK(status)) {
                return status;
        }
@@ -7981,7 +8419,7 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
                }
 
                status = winreg_printer_update_changeid(p->mem_ctx,
-                                                       p->server_info,
+                                                       get_server_info_system(),
                                                        p->msg_ctx,
                                                        lp_const_servicename(snum));
                if (!W_ERROR_IS_OK(status)) {
@@ -8000,10 +8438,9 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
                           struct spoolss_DeleteForm *r)
 {
        const char *form_name = r->in.form_name;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int snum = -1;
        WERROR status = WERR_OK;
-       SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
        DEBUG(5,("_spoolss_DeleteForm\n"));
 
@@ -8014,8 +8451,8 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
        }
 
        if ((p->server_info->utok.uid != sec_initial_uid()) &&
-            !user_has_privileges(p->server_info->ptok, &se_printop) &&
-            !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
+           !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
+           !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
                                          p->server_info->info3->base.domain.string,
                                          NULL,
                                          p->server_info->ptok,
@@ -8025,7 +8462,7 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
        }
 
        status = winreg_printer_deleteform1(p->mem_ctx,
-                                           p->server_info,
+                                           get_server_info_system(),
                                            p->msg_ctx,
                                            form_name);
        if (!W_ERROR_IS_OK(status)) {
@@ -8041,7 +8478,7 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
                }
 
                status = winreg_printer_update_changeid(p->mem_ctx,
-                                                       p->server_info,
+                                                       get_server_info_system(),
                                                        p->msg_ctx,
                                                        lp_const_servicename(snum));
                if (!W_ERROR_IS_OK(status)) {
@@ -8063,9 +8500,8 @@ WERROR _spoolss_SetForm(struct pipes_struct *p,
        const char *form_name = r->in.form_name;
        int snum = -1;
        WERROR status = WERR_OK;
-       SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        DEBUG(5,("_spoolss_SetForm\n"));
 
@@ -8079,7 +8515,7 @@ WERROR _spoolss_SetForm(struct pipes_struct *p,
           and not a printer admin, then fail */
 
        if ((p->server_info->utok.uid != sec_initial_uid()) &&
-            !user_has_privileges(p->server_info->ptok, &se_printop) &&
+            !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
             !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
                                          p->server_info->info3->base.domain.string,
                                          NULL,
@@ -8090,7 +8526,7 @@ WERROR _spoolss_SetForm(struct pipes_struct *p,
        }
 
        status = winreg_printer_setform1(p->mem_ctx,
-                                        p->server_info,
+                                        get_server_info_system(),
                                         p->msg_ctx,
                                         form_name,
                                         form);
@@ -8107,7 +8543,7 @@ WERROR _spoolss_SetForm(struct pipes_struct *p,
                }
 
                status = winreg_printer_update_changeid(p->mem_ctx,
-                                                       p->server_info,
+                                                       get_server_info_system(),
                                                        p->msg_ctx,
                                                        lp_const_servicename(snum));
                if (!W_ERROR_IS_OK(status)) {
@@ -8193,6 +8629,10 @@ WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
        *r->out.needed = 0;
        *r->out.info = NULL;
 
+       if (!get_short_archi(r->in.environment)) {
+               return WERR_INVALID_ENVIRONMENT;
+       }
+
        switch (r->in.level) {
        case 1:
                result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
@@ -8284,6 +8724,11 @@ WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
        *r->out.needed = 0;
        *r->out.info = NULL;
 
+       if (r->in.print_processor_name == NULL ||
+           !strequal(r->in.print_processor_name, "winprint")) {
+               return WERR_UNKNOWN_PRINTPROCESSOR;
+       }
+
        switch (r->in.level) {
        case 1:
                result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
@@ -8591,13 +9036,16 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
-       result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
-                                   NULL, lp_servicename(snum), &pinfo2);
+       result = winreg_get_printer(p->mem_ctx,
+                                   get_server_info_system(),
+                                   p->msg_ctx,
+                                   lp_const_servicename(snum),
+                                   &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
                return result;
        }
 
-       count = print_queue_status(snum, &queue, &prt_status);
+       count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
 
        DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
                     count, prt_status.status, prt_status.message));
@@ -8641,7 +9089,7 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                                 struct spoolss_GetPrinterDataEx *r)
 {
 
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        const char *printer;
        int                     snum = 0;
        WERROR result = WERR_OK;
@@ -8716,7 +9164,7 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                        uint32_t changeid = 0;
 
                        result = winreg_printer_get_changeid(p->mem_ctx,
-                                                            p->server_info,
+                                                            get_server_info_system(),
                                                             p->msg_ctx,
                                                             printer,
                                                             &changeid);
@@ -8731,7 +9179,7 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
        }
 
        result = winreg_get_printer_dataex(p->mem_ctx,
-                                          p->server_info,
+                                          get_server_info_system(),
                                           p->msg_ctx,
                                           printer,
                                           r->in.key_name,
@@ -8767,7 +9215,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
        struct spoolss_PrinterInfo2 *pinfo2 = NULL;
        int                     snum = 0;
        WERROR                  result = WERR_OK;
-       Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        char                    *oid_string;
 
        DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
@@ -8805,8 +9253,9 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       result = winreg_get_printer(Printer, p->server_info, p->msg_ctx,
-                                   Printer->servername,
+       result = winreg_get_printer(Printer,
+                                   get_server_info_system(),
+                                   p->msg_ctx,
                                    lp_servicename(snum),
                                    &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
@@ -8824,7 +9273,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
        /* save the registry data */
 
        result = winreg_set_printer_dataex(p->mem_ctx,
-                                          p->server_info,
+                                          get_server_info_system(),
                                           p->msg_ctx,
                                           pinfo2->sharename,
                                           r->in.key_name,
@@ -8850,7 +9299,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
                         * this is right.    --jerry
                         */
                        winreg_set_printer_dataex(p->mem_ctx,
-                                                 p->server_info,
+                                                 get_server_info_system(),
                                                  p->msg_ctx,
                                                  pinfo2->sharename,
                                                  str,
@@ -8861,7 +9310,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
                }
 
                result = winreg_printer_update_changeid(p->mem_ctx,
-                                                       p->server_info,
+                                                       get_server_info_system(),
                                                        p->msg_ctx,
                                                        lp_const_servicename(snum));
 
@@ -8882,7 +9331,7 @@ WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
        const char *printer;
        int             snum=0;
        WERROR          status = WERR_OK;
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
 
@@ -8909,14 +9358,14 @@ WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
        printer = lp_const_servicename(snum);
 
        status = winreg_delete_printer_dataex(p->mem_ctx,
-                                             p->server_info,
+                                             get_server_info_system(),
                                              p->msg_ctx,
                                              printer,
                                              r->in.key_name,
                                              r->in.value_name);
        if (W_ERROR_IS_OK(status)) {
                status = winreg_printer_update_changeid(p->mem_ctx,
-                                                       p->server_info,
+                                                       get_server_info_system(),
                                                        p->msg_ctx,
                                                        printer);
        }
@@ -8932,7 +9381,7 @@ WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
                               struct spoolss_EnumPrinterKey *r)
 {
        uint32_t        num_keys;
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int             snum = 0;
        WERROR          result = WERR_BADFILE;
        const char **array = NULL;
@@ -8951,7 +9400,7 @@ WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
        }
 
        result = winreg_enum_printer_key(p->mem_ctx,
-                                        p->server_info,
+                                        get_server_info_system(),
                                         p->msg_ctx,
                                         lp_const_servicename(snum),
                                         r->in.key_name,
@@ -8994,7 +9443,7 @@ WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
                                 struct spoolss_DeletePrinterKey *r)
 {
-       Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int                     snum=0;
        WERROR                  status;
        const char *printer;
@@ -9025,13 +9474,13 @@ WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
 
        /* delete the key and all subkeys */
        status = winreg_delete_printer_key(p->mem_ctx,
-                                          p->server_info,
+                                          get_server_info_system(),
                                           p->msg_ctx,
                                           printer,
                                           r->in.key_name);
        if (W_ERROR_IS_OK(status)) {
                status = winreg_printer_update_changeid(p->mem_ctx,
-                                                       p->server_info,
+                                                       get_server_info_system(),
                                                        p->msg_ctx,
                                                        printer);
        }
@@ -9048,7 +9497,7 @@ WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
 {
        uint32_t        count = 0;
        struct spoolss_PrinterEnumValues *info = NULL;
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int             snum;
        WERROR          result;
 
@@ -9082,7 +9531,7 @@ WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
 
        /* now look for a match on the key name */
        result = winreg_enum_printer_dataex(p->mem_ctx,
-                                           p->server_info,
+                                           get_server_info_system(),
                                            p->msg_ctx,
                                            lp_const_servicename(snum),
                                            r->in.key_name,
@@ -9157,6 +9606,9 @@ WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
                                           struct spoolss_GetPrintProcessorDirectory *r)
 {
        WERROR result;
+       fstring prnproc_share;
+       bool prnproc_share_exists = false;
+       int snum;
 
        /* that's an [in out] buffer */
 
@@ -9173,10 +9625,17 @@ WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
 
        /* We always should reply with a local print processor directory so that
         * users are not forced to have a [prnproc$] share on the Samba spoolss
-        * server - Guenther */
+        * server, if users decide to do so, lets announce it though - Guenther */
+
+       fstrcpy(prnproc_share, "prnproc$");
+
+       snum = find_service(prnproc_share);
+       if (snum != -1) {
+               prnproc_share_exists = true;
+       }
 
        result = getprintprocessordirectory_level_1(p->mem_ctx,
-                                                   NULL, /* r->in.server */
+                                                   prnproc_share_exists ? r->in.server : NULL,
                                                    r->in.environment,
                                                    &r->out.info->info1);
        if (!W_ERROR_IS_OK(result)) {
@@ -9215,7 +9674,7 @@ static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
 *******************************************************************/
 
 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
-                              NT_USER_TOKEN *token, DATA_BLOB *in,
+                              struct security_token *token, DATA_BLOB *in,
                               DATA_BLOB *out, uint32_t *needed)
 {
        const char *dllname = "tcpmonui.dll";
@@ -9270,7 +9729,7 @@ static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
 *******************************************************************/
 
 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
-                            NT_USER_TOKEN *token, DATA_BLOB *in,
+                            struct security_token *token, DATA_BLOB *in,
                             DATA_BLOB *out, uint32_t *needed)
 {
        struct spoolss_PortData1 port1;
@@ -9362,7 +9821,7 @@ struct xcv_api_table xcvtcp_cmds[] = {
 };
 
 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
-                                    NT_USER_TOKEN *token, const char *command,
+                                    struct security_token *token, const char *command,
                                     DATA_BLOB *inbuf,
                                     DATA_BLOB *outbuf,
                                     uint32_t *needed )
@@ -9384,7 +9843,7 @@ static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
 #if 0  /* don't support management using the "Local Port" monitor */
 
 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
-                                NT_USER_TOKEN *token, DATA_BLOB *in,
+                                struct security_token *token, DATA_BLOB *in,
                                 DATA_BLOB *out, uint32_t *needed)
 {
        const char *dllname = "localui.dll";
@@ -9421,7 +9880,7 @@ struct xcv_api_table xcvlocal_cmds[] = {
 *******************************************************************/
 
 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
-                                      NT_USER_TOKEN *token, const char *command,
+                                      struct security_token *token, const char *command,
                                       DATA_BLOB *inbuf, DATA_BLOB *outbuf,
                                       uint32_t *needed)
 {
@@ -9443,7 +9902,7 @@ static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
 WERROR _spoolss_XcvData(struct pipes_struct *p,
                        struct spoolss_XcvData *r)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        DATA_BLOB out_data = data_blob_null;
        WERROR werror;
 
@@ -9845,11 +10304,11 @@ WERROR _spoolss_44(struct pipes_struct *p,
 }
 
 /****************************************************************
- _spoolss_47
+ _spoolss_SetPort
 ****************************************************************/
 
-WERROR _spoolss_47(struct pipes_struct *p,
-                  struct spoolss_47 *r)
+WERROR _spoolss_SetPort(struct pipes_struct *p,
+                       struct spoolss_SetPort *r)
 {
        p->rng_fault_state = true;
        return WERR_NOT_SUPPORTED;