s3-printing: safe a ton of roundtrips by reusing existing winreg binding_handles.
[sfrench/samba-autobuild/.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
index 828d06aa1ef5592f243617305ba95cf7f8727e65..0bf678780b7254378b331c2b1bc77d2c56610668 100644 (file)
    up, all the errors returned are DOS errors, not NT status codes. */
 
 #include "includes.h"
+#include "ntdomain.h"
 #include "nt_printing.h"
 #include "srv_spoolss_util.h"
 #include "../librpc/gen_ndr/srv_spoolss.h"
 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
 #include "rpc_client/init_spoolss.h"
 #include "rpc_client/cli_pipe.h"
-#include "librpc/gen_ndr/messaging.h"
 #include "../libcli/security/security.h"
 #include "librpc/gen_ndr/ndr_security.h"
 #include "registry.h"
 #include "../librpc/gen_ndr/netlogon.h"
 #include "rpc_misc.h"
 #include "printing/notify.h"
+#include "serverid.h"
+#include "../libcli/registry/util_reg.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "auth.h"
+#include "messages.h"
+#include "rpc_server/spoolss/srv_spoolss_nt.h"
+#include "util_tdb.h"
+#include "libsmb/libsmb.h"
+#include "printing/printer_list.h"
+#include "../lib/tsocket/tsocket.h"
+#include "rpc_client/cli_winreg_spoolss.h"
 
 /* macros stolen from s4 spoolss server */
 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
@@ -454,7 +466,7 @@ 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,
+       result = winreg_delete_printer_key_internal(p->mem_ctx,
                                           get_session_info_system(),
                                           p->msg_ctx,
                                           Printer->sharename,
@@ -569,7 +581,7 @@ static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
        DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
                (unsigned long)strlen(handlename)));
 
-       aprinter = CONST_DISCARD(char *, handlename);
+       aprinter = discard_const_p(char, handlename);
        if ( *handlename == '\\' ) {
                servername = canon_servername(handlename);
                if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
@@ -676,7 +688,7 @@ static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
                        continue;
                }
 
-               result = winreg_get_printer(mem_ctx,
+               result = winreg_get_printer_internal(mem_ctx,
                                            session_info,
                                            msg_ctx,
                                            sname,
@@ -721,7 +733,7 @@ static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
 
        DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
 
-       fstrcpy(Printer->sharename, sname);
+       strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
 
        return WERR_OK;
 }
@@ -1084,7 +1096,7 @@ static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MS
        if ( i == ctr->num_groups ) {
                ctr->num_groups++;
 
-               if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
+               if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
                        DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
                        return 0;
                }
@@ -1102,7 +1114,7 @@ static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MS
 
        msg_grp->num_msgs++;
 
-       if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
+       if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
                DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
                return 0;
        }
@@ -1115,7 +1127,7 @@ static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MS
 
        if ( msg->len != 0 )
                msg_grp->msgs[new_slot].notify.data = (char *)
-                       TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
+                       talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
 
        return ctr->num_groups;
 }
@@ -1495,7 +1507,7 @@ static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
 
        messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
                           MSG_PRINTER_DRVUPGRADE,
-                          (uint8_t *)drivername, len+1);
+                          (const uint8_t *)drivername, len+1);
 
        return true;
 }
@@ -1531,6 +1543,7 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
        const char *drivername;
        int snum;
        int n_services = lp_numservices();
+       struct dcerpc_binding_handle *b = NULL;
 
        tmp_ctx = talloc_new(NULL);
        if (!tmp_ctx) return;
@@ -1563,7 +1576,17 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
                        continue;
                }
 
-               result = winreg_get_printer(tmp_ctx, session_info, msg,
+               if (b == NULL) {
+                       result = winreg_printer_binding_handle(tmp_ctx,
+                                                              session_info,
+                                                              msg,
+                                                              &b);
+                       if (!W_ERROR_IS_OK(result)) {
+                               break;
+                       }
+               }
+
+               result = winreg_get_printer(tmp_ctx, b,
                                            lp_const_servicename(snum),
                                            &pinfo2);
 
@@ -1582,9 +1605,7 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
                DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
 
                /* all we care about currently is the change_id */
-               result = winreg_printer_update_changeid(tmp_ctx,
-                                                       session_info,
-                                                       msg,
+               result = winreg_printer_update_changeid(tmp_ctx, b,
                                                        pinfo2->printername);
 
                if (!W_ERROR_IS_OK(result)) {
@@ -1701,14 +1722,17 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
                              struct spoolss_OpenPrinterEx *r)
 {
        int snum;
+       char *raddr;
+       char *rhost;
        struct printer_handle *Printer=NULL;
        WERROR result;
+       int rc;
 
        if (!r->in.printername) {
                return WERR_INVALID_PARAM;
        }
 
-       if (r->in.level < 0 || r->in.level > 3) {
+       if (r->in.level > 3) {
                return WERR_INVALID_PARAM;
        }
        if ((r->in.level == 1 && !r->in.userlevel.level1) ||
@@ -1867,9 +1891,24 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
                }
 
                /* check smb.conf parameters and the the sec_desc */
+               raddr = tsocket_address_inet_addr_string(p->remote_address,
+                                                        p->mem_ctx);
+               if (raddr == NULL) {
+                       return WERR_NOMEM;
+               }
+
+               rc = get_remote_hostname(p->remote_address,
+                                        &rhost,
+                                        p->mem_ctx);
+               if (rc < 0) {
+                       return WERR_NOMEM;
+               }
+               if (strequal(rhost, "UNKNOWN")) {
+                       rhost = raddr;
+               }
 
                if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
-                                 p->client_id->name, p->client_id->addr)) {
+                                 rhost, raddr)) {
                        DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
                        ZERO_STRUCTP(r->out.handle);
                        return WERR_ACCESS_DENIED;
@@ -1902,7 +1941,7 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
                DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
                        ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
 
-               winreg_create_printer(p->mem_ctx,
+               winreg_create_printer_internal(p->mem_ctx,
                                      get_session_info_system(),
                                      p->msg_ctx,
                                      lp_const_servicename(snum));
@@ -1993,7 +2032,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,
+               winreg_delete_printer_key_internal(p->mem_ctx,
                                          get_session_info_system(),
                                          p->msg_ctx,
                                          lp_const_servicename(snum),
@@ -2047,6 +2086,7 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
        struct spoolss_DriverInfo8 *info_win2k = NULL;
        int                             version;
        WERROR                          status;
+       struct dcerpc_binding_handle *b;
 
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
@@ -2068,9 +2108,15 @@ 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,
-                                  get_session_info_system(),
-                                  p->msg_ctx,
+       status = winreg_printer_binding_handle(p->mem_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(status)) {
+               return status;
+       }
+
+       status = winreg_get_driver(p->mem_ctx, b,
                                   r->in.architecture, r->in.driver,
                                   version, &info);
        if (!W_ERROR_IS_OK(status)) {
@@ -2079,9 +2125,7 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
                if ( version == 2 ) {
                        version = 3;
 
-                       status = winreg_get_driver(p->mem_ctx,
-                                                  get_session_info_system(),
-                                                  p->msg_ctx,
+                       status = winreg_get_driver(p->mem_ctx, b,
                                                   r->in.architecture,
                                                   r->in.driver,
                                                   version, &info);
@@ -2107,18 +2151,14 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
        }
 
        if (version == 2) {
-               status = winreg_get_driver(p->mem_ctx,
-                                          get_session_info_system(),
-                                          p->msg_ctx,
+               status = winreg_get_driver(p->mem_ctx, b,
                                           r->in.architecture,
                                           r->in.driver, 3, &info_win2k);
                if (W_ERROR_IS_OK(status)) {
                        /* if we get to here, we now have 2 driver info structures to remove */
                        /* remove the Win2k driver first*/
 
-                       status = winreg_del_driver(p->mem_ctx,
-                                                  get_session_info_system(),
-                                                  p->msg_ctx,
+                       status = winreg_del_driver(p->mem_ctx, b,
                                                   info_win2k, 3);
                        talloc_free(info_win2k);
 
@@ -2129,9 +2169,7 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
                }
        }
 
-       status = winreg_del_driver(p->mem_ctx,
-                                  get_session_info_system(),
-                                  p->msg_ctx,
+       status = winreg_del_driver(p->mem_ctx, b,
                                   info, version);
 
 done:
@@ -2152,6 +2190,7 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
        int                             version;
        bool                            delete_files;
        WERROR                          status;
+       struct dcerpc_binding_handle *b;
 
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
@@ -2176,9 +2215,15 @@ 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,
-                                  get_session_info_system(),
-                                  p->msg_ctx,
+       status = winreg_printer_binding_handle(p->mem_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(status)) {
+               return status;
+       }
+
+       status = winreg_get_driver(p->mem_ctx, b,
                                   r->in.architecture,
                                   r->in.driver,
                                   version,
@@ -2198,9 +2243,7 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
                /* try for Win2k driver if "Windows NT x86" */
 
                version = 3;
-               status = winreg_get_driver(info,
-                                          get_session_info_system(),
-                                          p->msg_ctx,
+               status = winreg_get_driver(info, b,
                                           r->in.architecture,
                                           r->in.driver,
                                           version, &info);
@@ -2249,9 +2292,7 @@ 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,
-                                          get_session_info_system(),
-                                          p->msg_ctx,
+               status = winreg_get_driver(info, b,
                                           r->in.architecture,
                                           r->in.driver, 3, &info_win2k);
                if (W_ERROR_IS_OK(status)) {
@@ -2271,9 +2312,7 @@ 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,
-                                                  get_session_info_system(),
-                                                  p->msg_ctx,
+                       status = winreg_del_driver(info, b,
                                                   info_win2k,
                                                   3);
 
@@ -2295,9 +2334,7 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
                }
        }
 
-       status = winreg_del_driver(info,
-                                  get_session_info_system(),
-                                  p->msg_ctx,
+       status = winreg_del_driver(info, b,
                                   info,
                                   version);
        if (!W_ERROR_IS_OK(status)) {
@@ -2330,32 +2367,32 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
 {
        DEBUG(8,("getprinterdata_printer_server:%s\n", value));
 
-       if (!StrCaseCmp(value, "W3SvcInstalled")) {
+       if (!strcasecmp_m(value, "W3SvcInstalled")) {
                *type = REG_DWORD;
                data->value = 0x00;
                return WERR_OK;
        }
 
-       if (!StrCaseCmp(value, "BeepEnabled")) {
+       if (!strcasecmp_m(value, "BeepEnabled")) {
                *type = REG_DWORD;
                data->value = 0x00;
                return WERR_OK;
        }
 
-       if (!StrCaseCmp(value, "EventLog")) {
+       if (!strcasecmp_m(value, "EventLog")) {
                *type = REG_DWORD;
                /* formally was 0x1b */
                data->value = 0x00;
                return WERR_OK;
        }
 
-       if (!StrCaseCmp(value, "NetPopup")) {
+       if (!strcasecmp_m(value, "NetPopup")) {
                *type = REG_DWORD;
                data->value = 0x00;
                return WERR_OK;
        }
 
-       if (!StrCaseCmp(value, "MajorVersion")) {
+       if (!strcasecmp_m(value, "MajorVersion")) {
                *type = REG_DWORD;
 
                /* Windows NT 4.0 seems to not allow uploading of drivers
@@ -2372,7 +2409,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
                return WERR_OK;
        }
 
-       if (!StrCaseCmp(value, "MinorVersion")) {
+       if (!strcasecmp_m(value, "MinorVersion")) {
                *type = REG_DWORD;
                data->value = 0x00;
                return WERR_OK;
@@ -2385,7 +2422,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
         *  uint32_t build       = [2195|2600]
         *  extra unicode string = e.g. "Service Pack 3"
         */
-       if (!StrCaseCmp(value, "OSVersion")) {
+       if (!strcasecmp_m(value, "OSVersion")) {
                DATA_BLOB blob;
                enum ndr_err_code ndr_err;
                struct spoolss_OSVersion os;
@@ -2408,7 +2445,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
        }
 
 
-       if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
+       if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
                *type = REG_SZ;
 
                data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
@@ -2417,7 +2454,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
                return WERR_OK;
        }
 
-       if (!StrCaseCmp(value, "Architecture")) {
+       if (!strcasecmp_m(value, "Architecture")) {
                *type = REG_SZ;
                data->string = talloc_strdup(mem_ctx,
                        lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
@@ -2426,7 +2463,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
                return WERR_OK;
        }
 
-       if (!StrCaseCmp(value, "DsPresent")) {
+       if (!strcasecmp_m(value, "DsPresent")) {
                *type = REG_DWORD;
 
                /* only show the publish check box if we are a
@@ -2440,7 +2477,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
                return WERR_OK;
        }
 
-       if (!StrCaseCmp(value, "DNSMachineName")) {
+       if (!strcasecmp_m(value, "DNSMachineName")) {
                const char *hostname = get_mydnsfullname();
 
                if (!hostname) {
@@ -2513,7 +2550,7 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
        }
 
        /* setup the connection */
-       ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
+       ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
                &rm_addr, 0, "IPC$", "IPC",
                "", /* username */
                "", /* domain */
@@ -2702,6 +2739,7 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
        int snum = -1;
        struct spoolss_NotifyOption *option = r->in.notify_options;
        struct sockaddr_storage client_ss;
+       socklen_t client_len;
 
        /* store the notify value in the printer struct */
 
@@ -2733,13 +2771,22 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
                return WERR_BADFID;
 
        DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
-               "client_address is %s\n", p->client_id->addr));
+                 "remote_address is %s\n",
+                 tsocket_address_string(p->remote_address, p->mem_ctx)));
 
-       if (!interpret_string_addr(&client_ss, p->client_id->addr,
-                                  AI_NUMERICHOST)) {
+       if (!lp_print_notify_backchannel(snum)) {
+               DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
+                       "backchannel disabled\n"));
                return WERR_SERVER_UNAVAILABLE;
        }
 
+       client_len = tsocket_address_bsd_sockaddr(p->remote_address,
+                                                 (struct sockaddr *) &client_ss,
+                                                 sizeof(struct sockaddr_storage));
+       if (client_len < 0) {
+               return WERR_NOMEM;
+       }
+
        if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
                                        Printer->notify.printerlocal, REG_SZ,
                                        &Printer->notify.cli_hnd,
@@ -2865,7 +2912,21 @@ static void spoolss_notify_location(struct messaging_context *msg_ctx,
                                    struct spoolss_PrinterInfo2 *pinfo2,
                                    TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
+       const char *loc = pinfo2->location;
+       NTSTATUS status;
+
+       status = printer_list_get_printer(mem_ctx,
+                                         pinfo2->sharename,
+                                         NULL,
+                                         &loc,
+                                         NULL);
+       if (NT_STATUS_IS_OK(status)) {
+               if (loc == NULL) {
+                       loc = pinfo2->location;
+               }
+       }
+
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
 }
 
 /*******************************************************************
@@ -3393,7 +3454,6 @@ static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
        uint16_t field;
 
        struct spoolss_Notify *current_data;
-       print_queue_struct *queue=NULL;
 
        type = option_type->type;
 
@@ -3409,7 +3469,7 @@ static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
                if (!search_notify(type, field, &j) )
                        continue;
 
-               info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
+               info->notifies = talloc_realloc(info, info->notifies,
                                                      struct spoolss_Notify,
                                                      info->count + 1);
                if (info->notifies == NULL) {
@@ -3427,7 +3487,7 @@ static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
                           pinfo2->printername));
 
                notify_info_data_table[j].fn(msg_ctx, snum, current_data,
-                                            queue, pinfo2, mem_ctx);
+                                            NULL, pinfo2, mem_ctx);
 
                info->count++;
        }
@@ -3469,7 +3529,7 @@ static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
                if (!search_notify(type, field, &j) )
                        continue;
 
-               info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
+               info->notifies = talloc_realloc(info, info->notifies,
                                                      struct spoolss_Notify,
                                                      info->count + 1);
                if (info->notifies == NULL) {
@@ -3563,7 +3623,7 @@ static WERROR printserver_notify_info(struct pipes_struct *p,
                        }
 
                        /* Maybe we should use the SYSTEM session_info here... */
-                       result = winreg_get_printer(mem_ctx,
+                       result = winreg_get_printer_internal(mem_ctx,
                                                    get_session_info_system(),
                                                    p->msg_ctx,
                                                    lp_servicename(snum),
@@ -3646,10 +3706,12 @@ static WERROR printer_notify_info(struct pipes_struct *p,
        if ( !option )
                return WERR_BADFID;
 
-       get_printer_snum(p, hnd, &snum, NULL);
+       if (!get_printer_snum(p, hnd, &snum, NULL)) {
+               return WERR_BADFID;
+       }
 
        /* Maybe we should use the SYSTEM session_info here... */
-       result = winreg_get_printer(mem_ctx,
+       result = winreg_get_printer_internal(mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
                                    lp_servicename(snum), &pinfo2);
@@ -3898,7 +3960,7 @@ static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
        r->high_part_total_bytes        = 0x0;
 
        /* ChangeID in milliseconds*/
-       winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
+       winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
                                    info2->sharename, &r->change_id);
 
        r->last_error                   = WERR_OK;
@@ -3996,8 +4058,24 @@ static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
        }
        W_ERROR_HAVE_NO_MEMORY(r->comment);
 
-       r->location             = talloc_strdup(mem_ctx, info2->location);
+       r->location     = talloc_strdup(mem_ctx, info2->location);
+       if (info2->location[0] == '\0') {
+               const char *loc = NULL;
+               NTSTATUS nt_status;
+
+               nt_status = printer_list_get_printer(mem_ctx,
+                                                    info2->sharename,
+                                                    NULL,
+                                                    &loc,
+                                                    NULL);
+               if (NT_STATUS_IS_OK(nt_status)) {
+                       if (loc != NULL) {
+                               r->location = talloc_strdup(mem_ctx, loc);
+                       }
+               }
+       }
        W_ERROR_HAVE_NO_MEMORY(r->location);
+
        r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
        W_ERROR_HAVE_NO_MEMORY(r->sepfile);
        r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
@@ -4132,10 +4210,9 @@ static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
                                      struct spoolss_PrinterInfo6 *r,
                                      int snum)
 {
-       int count;
        print_status_struct status;
 
-       count = print_queue_length(msg_ctx, snum, &status);
+       print_queue_length(msg_ctx, snum, &status);
 
        r->status = nt_printq_status(status.status);
 
@@ -4235,6 +4312,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
        union spoolss_PrinterInfo *info = NULL;
        uint32_t count = 0;
        WERROR result = WERR_OK;
+       struct dcerpc_binding_handle *b = NULL;
 
        *count_p = 0;
        *info_p = NULL;
@@ -4253,15 +4331,23 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
                        printer, snum));
 
-               result = winreg_create_printer(mem_ctx,
-                                              session_info,
-                                              msg_ctx,
+               if (b == NULL) {
+                       result = winreg_printer_binding_handle(mem_ctx,
+                                                              session_info,
+                                                              msg_ctx,
+                                                              &b);
+                       if (!W_ERROR_IS_OK(result)) {
+                               goto out;
+                       }
+               }
+
+               result = winreg_create_printer(mem_ctx, b,
                                               printer);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
                }
 
-               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+               info = talloc_realloc(mem_ctx, info,
                                            union spoolss_PrinterInfo,
                                            count + 1);
                if (!info) {
@@ -4269,7 +4355,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
                        goto out;
                }
 
-               result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
+               result = winreg_get_printer(mem_ctx, b,
                                            printer, &info2);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
@@ -4686,7 +4772,7 @@ WERROR _spoolss_GetPrinter(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
-       result = winreg_get_printer(p->mem_ctx,
+       result = winreg_get_printer_internal(p->mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
                                    lp_const_servicename(snum),
@@ -5301,7 +5387,7 @@ static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
        *count_p = 0;
 
        if (strlen(driver->driver_path)) {
-               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+               info = talloc_realloc(mem_ctx, info,
                                            struct spoolss_DriverFileInfo,
                                            count + 1);
                W_ERROR_HAVE_NO_MEMORY(info);
@@ -5316,7 +5402,7 @@ static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
        }
 
        if (strlen(driver->config_file)) {
-               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+               info = talloc_realloc(mem_ctx, info,
                                            struct spoolss_DriverFileInfo,
                                            count + 1);
                W_ERROR_HAVE_NO_MEMORY(info);
@@ -5331,7 +5417,7 @@ static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
        }
 
        if (strlen(driver->data_file)) {
-               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+               info = talloc_realloc(mem_ctx, info,
                                            struct spoolss_DriverFileInfo,
                                            count + 1);
                W_ERROR_HAVE_NO_MEMORY(info);
@@ -5346,7 +5432,7 @@ static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
        }
 
        if (strlen(driver->help_file)) {
-               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+               info = talloc_realloc(mem_ctx, info,
                                            struct spoolss_DriverFileInfo,
                                            count + 1);
                W_ERROR_HAVE_NO_MEMORY(info);
@@ -5361,7 +5447,7 @@ static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
        }
 
        for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
-               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+               info = talloc_realloc(mem_ctx, info,
                                            struct spoolss_DriverFileInfo,
                                            count + 1);
                W_ERROR_HAVE_NO_MEMORY(info);
@@ -5459,14 +5545,21 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
        struct spoolss_PrinterInfo2 *pinfo2 = NULL;
        struct spoolss_DriverInfo8 *driver;
        WERROR result;
+       struct dcerpc_binding_handle *b;
 
        if (level == 101) {
                return WERR_UNKNOWN_LEVEL;
        }
 
-       result = winreg_get_printer(mem_ctx,
-                                   session_info,
-                                   msg_ctx,
+       result = winreg_printer_binding_handle(mem_ctx,
+                                              session_info,
+                                              msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
+       result = winreg_get_printer(mem_ctx, b,
                                    lp_const_servicename(snum),
                                    &pinfo2);
 
@@ -5477,7 +5570,7 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
                return WERR_INVALID_PRINTER_NAME;
        }
 
-       result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
+       result = winreg_get_driver(mem_ctx, b,
                                   architecture,
                                   pinfo2->drivername, version, &driver);
 
@@ -5496,7 +5589,7 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
 
                /* Yes - try again with a WinNT driver. */
                version = 2;
-               result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
+               result = winreg_get_driver(mem_ctx, b,
                                           architecture,
                                           pinfo2->drivername,
                                           version, &driver);
@@ -5655,6 +5748,8 @@ WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
        int snum;
        struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        WERROR werr;
+       char *rhost;
+       int rc;
 
        if (!Printer) {
                DEBUG(2,("_spoolss_StartDocPrinter: "
@@ -5696,9 +5791,23 @@ WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
+       rc = get_remote_hostname(p->remote_address,
+                                &rhost,
+                                p->mem_ctx);
+       if (rc < 0) {
+               return WERR_NOMEM;
+       }
+       if (strequal(rhost,"UNKNOWN")) {
+               rhost = tsocket_address_inet_addr_string(p->remote_address,
+                                                        p->mem_ctx);
+               if (rhost == NULL) {
+                       return WERR_NOMEM;
+               }
+       }
+
        werr = print_job_start(p->session_info,
                               p->msg_ctx,
-                              p->client_id->name,
+                              rhost,
                               snum,
                               info_1->document_name,
                               info_1->output_file,
@@ -5880,8 +5989,8 @@ static WERROR update_printer_sec(struct policy_handle *handle,
        const char *printer;
        WERROR result;
        int snum;
-
        struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
+       struct dcerpc_binding_handle *b;
 
        if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
                DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
@@ -5909,15 +6018,21 @@ static WERROR update_printer_sec(struct policy_handle *handle,
                goto done;
        }
 
+       result = winreg_printer_binding_handle(p->mem_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
        /* NT seems to like setting the security descriptor even though
           nothing may have actually changed. */
-       result = winreg_get_printer_secdesc(p->mem_ctx,
-                                           get_session_info_system(),
-                                           p->msg_ctx,
+       result = winreg_get_printer_secdesc(p->mem_ctx, b,
                                            printer,
                                            &old_secdesc);
        if (!W_ERROR_IS_OK(result)) {
-               DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
+               DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
                result = WERR_BADFID;
                goto done;
        }
@@ -5963,9 +6078,7 @@ static WERROR update_printer_sec(struct policy_handle *handle,
                goto done;
        }
 
-       result = winreg_set_printer_secdesc(p->mem_ctx,
-                                           get_session_info_system(),
-                                           p->msg_ctx,
+       result = winreg_set_printer_secdesc(p->mem_ctx, b,
                                            printer,
                                            new_secdesc);
 
@@ -5991,7 +6104,7 @@ static bool check_printer_ok(TALLOC_CTX *mem_ctx,
                info2->location));
 
        /* we force some elements to "correct" values */
-       info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
+       info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
        if (info2->servername == NULL) {
                return false;
        }
@@ -6003,7 +6116,7 @@ static bool check_printer_ok(TALLOC_CTX *mem_ctx,
        /* check to see if we allow printername != sharename */
        if (lp_force_printername(snum)) {
                info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
-                                       global_myname(), info2->sharename);
+                                       lp_netbios_name(), info2->sharename);
        } else {
                /* make sure printername is in \\server\printername format */
                fstrcpy(printername, info2->printername);
@@ -6014,7 +6127,7 @@ static bool check_printer_ok(TALLOC_CTX *mem_ctx,
                }
 
                info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
-                                       global_myname(), p);
+                                       lp_netbios_name(), p);
        }
        if (info2->printername == NULL) {
                return false;
@@ -6171,12 +6284,19 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
        const char *spooling;
        DATA_BLOB buffer;
        WERROR result = WERR_OK;
+       struct dcerpc_binding_handle *b;
+
+       result = winreg_printer_binding_handle(mem_ctx,
+                                              session_info,
+                                              msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
 
        if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
                push_reg_sz(mem_ctx, &buffer, printer->drivername);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_DRIVERNAME,
@@ -6196,9 +6316,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
 
        if (force_update || !strequal(printer->comment, old_printer->comment)) {
                push_reg_sz(mem_ctx, &buffer, printer->comment);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_DESCRIPTION,
@@ -6215,9 +6333,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
 
        if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
                push_reg_sz(mem_ctx, &buffer, printer->sharename);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTSHARENAME,
@@ -6244,9 +6360,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                }
 
                push_reg_sz(mem_ctx, &buffer, p);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTERNAME,
@@ -6262,9 +6376,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
 
        if (force_update || !strequal(printer->portname, old_printer->portname)) {
                push_reg_sz(mem_ctx, &buffer, printer->portname);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PORTNAME,
@@ -6281,9 +6393,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
 
        if (force_update || !strequal(printer->location, old_printer->location)) {
                push_reg_sz(mem_ctx, &buffer, printer->location);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_LOCATION,
@@ -6301,9 +6411,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
 
        if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
                push_reg_sz(mem_ctx, &buffer, printer->sepfile);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTSEPARATORFILE,
@@ -6322,9 +6430,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
        if (force_update || printer->starttime != old_printer->starttime) {
                buffer = data_blob_talloc(mem_ctx, NULL, 4);
                SIVAL(buffer.data, 0, printer->starttime);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTSTARTTIME,
@@ -6336,9 +6442,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
        if (force_update || printer->untiltime != old_printer->untiltime) {
                buffer = data_blob_talloc(mem_ctx, NULL, 4);
                SIVAL(buffer.data, 0, printer->untiltime);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTENDTIME,
@@ -6350,9 +6454,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
        if (force_update || printer->priority != old_printer->priority) {
                buffer = data_blob_talloc(mem_ctx, NULL, 4);
                SIVAL(buffer.data, 0, printer->priority);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRIORITY,
@@ -6365,9 +6467,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                buffer = data_blob_talloc(mem_ctx, NULL, 4);
                SIVAL(buffer.data, 0, (printer->attributes &
                                       PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTKEEPPRINTEDJOBS,
@@ -6389,9 +6489,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                spooling = "unknown";
                }
                push_reg_sz(mem_ctx, &buffer, spooling);
-               winreg_set_printer_dataex(mem_ctx,
-                                         session_info,
-                                         msg_ctx,
+               winreg_set_printer_dataex(mem_ctx, b,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
                                          SPOOL_REG_PRINTSPOOLING,
@@ -6400,10 +6498,8 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                          buffer.length);
        }
 
-       push_reg_sz(mem_ctx, &buffer, global_myname());
-       winreg_set_printer_dataex(mem_ctx,
-                                 session_info,
-                                 msg_ctx,
+       push_reg_sz(mem_ctx, &buffer, lp_netbios_name());
+       winreg_set_printer_dataex(mem_ctx, b,
                                  printer->sharename,
                                  SPOOL_DSSPOOLER_KEY,
                                  SPOOL_REG_SHORTSERVERNAME,
@@ -6415,7 +6511,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
        if (dnsdomname != NULL && dnsdomname[0] != '\0') {
                longname = talloc_strdup(mem_ctx, dnsdomname);
        } else {
-               longname = talloc_strdup(mem_ctx, global_myname());
+               longname = talloc_strdup(mem_ctx, lp_netbios_name());
        }
        if (longname == NULL) {
                result = WERR_NOMEM;
@@ -6423,9 +6519,7 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
        }
 
        push_reg_sz(mem_ctx, &buffer, longname);
-       winreg_set_printer_dataex(mem_ctx,
-                                 session_info,
-                                 msg_ctx,
+       winreg_set_printer_dataex(mem_ctx, b,
                                  printer->sharename,
                                  SPOOL_DSSPOOLER_KEY,
                                  SPOOL_REG_SERVERNAME,
@@ -6434,11 +6528,9 @@ static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
                                  buffer.length);
 
        uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
-                                 global_myname(), printer->sharename);
+                                 lp_netbios_name(), printer->sharename);
        push_reg_sz(mem_ctx, &buffer, uncname);
-       winreg_set_printer_dataex(mem_ctx,
-                                 session_info,
-                                 msg_ctx,
+       winreg_set_printer_dataex(mem_ctx, b,
                                  printer->sharename,
                                  SPOOL_DSSPOOLER_KEY,
                                  SPOOL_REG_UNCNAME,
@@ -6467,6 +6559,7 @@ static WERROR update_printer(struct pipes_struct *p,
        int snum;
        WERROR result = WERR_OK;
        TALLOC_CTX *tmp_ctx;
+       struct dcerpc_binding_handle *b;
 
        DEBUG(8,("update_printer\n"));
 
@@ -6485,9 +6578,15 @@ static WERROR update_printer(struct pipes_struct *p,
                goto done;
        }
 
-       result = winreg_get_printer(tmp_ctx,
-                                   get_session_info_system(),
-                                   p->msg_ctx,
+       result = winreg_printer_binding_handle(tmp_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       result = winreg_get_printer(tmp_ctx, b,
                                    lp_const_servicename(snum),
                                    &old_printer);
        if (!W_ERROR_IS_OK(result)) {
@@ -6520,9 +6619,17 @@ static WERROR update_printer(struct pipes_struct *p,
                         !strequal(printer->portname, old_printer->portname) ||
                         !strequal(printer->location, old_printer->location)) )
        {
+               char *raddr;
+
+               raddr = tsocket_address_inet_addr_string(p->remote_address,
+                                                        p->mem_ctx);
+               if (raddr == NULL) {
+                       return WERR_NOMEM;
+               }
+
                /* add_printer_hook() will call reload_services() */
                if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
-                                     printer, p->client_id->addr,
+                                     printer, raddr,
                                      p->msg_ctx)) {
                        result = WERR_ACCESS_DENIED;
                        goto done;
@@ -6541,9 +6648,7 @@ static WERROR update_printer(struct pipes_struct *p,
        if (devmode == NULL) {
                printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
        }
-       result = winreg_update_printer(tmp_ctx,
-                                      get_session_info_system(),
-                                      p->msg_ctx,
+       result = winreg_update_printer(tmp_ctx, b,
                                       printer->sharename,
                                       printer_mask,
                                       printer,
@@ -6582,7 +6687,7 @@ 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,
+       result = winreg_get_printer_internal(p->mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
                                    lp_servicename(snum),
@@ -6631,7 +6736,7 @@ static WERROR update_printer_devmode(struct pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       return winreg_update_printer(p->mem_ctx,
+       return winreg_update_printer_internal(p->mem_ctx,
                                     get_session_info_system(),
                                     p->msg_ctx,
                                     lp_const_servicename(snum),
@@ -6878,7 +6983,7 @@ static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
        int i;
        WERROR result = WERR_OK;
 
-       info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
+       info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
        W_ERROR_HAVE_NO_MEMORY(info);
 
        *count = num_queues;
@@ -6922,7 +7027,7 @@ static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
        int i;
        WERROR result = WERR_OK;
 
-       info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
+       info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
        W_ERROR_HAVE_NO_MEMORY(info);
 
        *count = num_queues;
@@ -6977,7 +7082,7 @@ static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
        int i;
        WERROR result = WERR_OK;
 
-       info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
+       info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
        W_ERROR_HAVE_NO_MEMORY(info);
 
        *count = num_queues;
@@ -7045,7 +7150,7 @@ WERROR _spoolss_EnumJobs(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
-       result = winreg_get_printer(p->mem_ctx,
+       result = winreg_get_printer_internal(p->mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
                                    lp_const_servicename(snum),
@@ -7230,12 +7335,21 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
        WERROR result = WERR_OK;
        uint32_t num_drivers;
        const char **drivers;
+       struct dcerpc_binding_handle *b;
 
        *count_p = 0;
        *info_p = NULL;
 
+       result = winreg_printer_binding_handle(mem_ctx,
+                                              session_info,
+                                              msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(result)) {
+               goto out;
+       }
+
        for (version=0; version<DRIVER_MAX_VERSION; version++) {
-               result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
+               result = winreg_get_driver_list(mem_ctx, b,
                                                architecture, version,
                                                &num_drivers, &drivers);
                if (!W_ERROR_IS_OK(result)) {
@@ -7246,7 +7360,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                          num_drivers, architecture, version));
 
                if (num_drivers != 0) {
-                       info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+                       info = talloc_realloc(mem_ctx, info,
                                                    union spoolss_DriverInfo,
                                                    count + num_drivers);
                        if (!info) {
@@ -7260,8 +7374,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                for (i = 0; i < num_drivers; i++) {
                        DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
 
-                       result = winreg_get_driver(mem_ctx, session_info,
-                                                  msg_ctx,
+                       result = winreg_get_driver(mem_ctx, b,
                                                   architecture, drivers[i],
                                                   version, &driver);
                        if (!W_ERROR_IS_OK(result)) {
@@ -7456,7 +7569,7 @@ WERROR _spoolss_EnumForms(struct pipes_struct *p,
 
        switch (r->in.level) {
        case 1:
-               result = winreg_printer_enumforms1(p->mem_ctx,
+               result = winreg_printer_enumforms1_internal(p->mem_ctx,
                                                   get_session_info_system(),
                                                   p->msg_ctx,
                                                   r->out.count,
@@ -7506,7 +7619,7 @@ WERROR _spoolss_GetForm(struct pipes_struct *p,
 
        switch (r->in.level) {
        case 1:
-               result = winreg_printer_getform1(p->mem_ctx,
+               result = winreg_printer_getform1_internal(p->mem_ctx,
                                                 get_session_info_system(),
                                                 p->msg_ctx,
                                                 r->in.form_name,
@@ -7586,7 +7699,7 @@ static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
        /* if no hook then just fill in the default port */
 
        if ( !*cmd ) {
-               if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
+               if (!(qlines = talloc_array( NULL, char*, 2 ))) {
                        return WERR_NOMEM;
                }
                if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
@@ -7647,7 +7760,7 @@ static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
        }
 
        if (numlines) {
-               info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
+               info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
                if (!info) {
                        DEBUG(10,("Returning WERR_NOMEM\n"));
                        result = WERR_NOMEM;
@@ -7699,7 +7812,7 @@ static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
        }
 
        if (numlines) {
-               info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
+               info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
                if (!info) {
                        DEBUG(10,("Returning WERR_NOMEM\n"));
                        result = WERR_NOMEM;
@@ -7838,14 +7951,22 @@ static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
           trying to add a printer like this  --jerry */
 
        if (*lp_addprinter_cmd() ) {
+               char *raddr;
+
+               raddr = tsocket_address_inet_addr_string(p->remote_address,
+                                                        p->mem_ctx);
+               if (raddr == NULL) {
+                       return WERR_NOMEM;
+               }
+
                if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
-                                      info2, p->client_id->addr,
+                                      info2, raddr,
                                       p->msg_ctx) ) {
                        return WERR_ACCESS_DENIED;
                }
        } else {
-               DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
-                       "smb.conf parameter \"addprinter command\" is defined. This"
+               DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
+                       "smb.conf parameter \"addprinter command\" is defined. This "
                        "parameter must exist for this call to succeed\n",
                        info2->sharename ));
        }
@@ -7881,7 +8002,7 @@ static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
                         info2,
                         NULL);
 
-       err = winreg_update_printer(p->mem_ctx,
+       err = winreg_update_printer_internal(p->mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
                                    info2->sharename,
@@ -7998,17 +8119,17 @@ WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
        }
 
        DEBUG(5,("Cleaning driver's information\n"));
-       err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
+       err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
        if (!W_ERROR_IS_OK(err))
                goto done;
 
        DEBUG(5,("Moving driver to final destination\n"));
-       if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
-                                                             &err)) ) {
+       err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
+       if (!W_ERROR_IS_OK(err)) {
                goto done;
        }
 
-       err = winreg_add_driver(p->mem_ctx,
+       err = winreg_add_driver_internal(p->mem_ctx,
                                get_session_info_system(),
                                p->msg_ctx,
                                r->in.info_ctr,
@@ -8415,8 +8536,8 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
        struct spoolss_AddFormInfo1 *form = r->in.info.info1;
        int snum = -1;
        WERROR status = WERR_OK;
-
        struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       struct dcerpc_binding_handle *b;
 
        DEBUG(5,("_spoolss_AddForm\n"));
 
@@ -8449,9 +8570,15 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
                return WERR_INVALID_PARAM;
        }
 
-       status = winreg_printer_addform1(p->mem_ctx,
-                                        get_session_info_system(),
-                                        p->msg_ctx,
+       status = winreg_printer_binding_handle(p->mem_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(status)) {
+               return status;
+       }
+
+       status = winreg_printer_addform1(p->mem_ctx, b,
                                         form);
        if (!W_ERROR_IS_OK(status)) {
                return status;
@@ -8465,9 +8592,7 @@ WERROR _spoolss_AddForm(struct pipes_struct *p,
                        return WERR_BADFID;
                }
 
-               status = winreg_printer_update_changeid(p->mem_ctx,
-                                                       get_session_info_system(),
-                                                       p->msg_ctx,
+               status = winreg_printer_update_changeid(p->mem_ctx, b,
                                                        lp_const_servicename(snum));
                if (!W_ERROR_IS_OK(status)) {
                        return status;
@@ -8488,6 +8613,7 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
        struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int snum = -1;
        WERROR status = WERR_OK;
+       struct dcerpc_binding_handle *b;
 
        DEBUG(5,("_spoolss_DeleteForm\n"));
 
@@ -8508,9 +8634,15 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       status = winreg_printer_deleteform1(p->mem_ctx,
-                                           get_session_info_system(),
-                                           p->msg_ctx,
+       status = winreg_printer_binding_handle(p->mem_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(status)) {
+               return status;
+       }
+
+       status = winreg_printer_deleteform1(p->mem_ctx, b,
                                            form_name);
        if (!W_ERROR_IS_OK(status)) {
                return status;
@@ -8524,9 +8656,7 @@ WERROR _spoolss_DeleteForm(struct pipes_struct *p,
                        return WERR_BADFID;
                }
 
-               status = winreg_printer_update_changeid(p->mem_ctx,
-                                                       get_session_info_system(),
-                                                       p->msg_ctx,
+               status = winreg_printer_update_changeid(p->mem_ctx, b,
                                                        lp_const_servicename(snum));
                if (!W_ERROR_IS_OK(status)) {
                        return status;
@@ -8547,6 +8677,7 @@ WERROR _spoolss_SetForm(struct pipes_struct *p,
        const char *form_name = r->in.form_name;
        int snum = -1;
        WERROR status = WERR_OK;
+       struct dcerpc_binding_handle *b;
 
        struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
@@ -8572,9 +8703,15 @@ WERROR _spoolss_SetForm(struct pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       status = winreg_printer_setform1(p->mem_ctx,
-                                        get_session_info_system(),
-                                        p->msg_ctx,
+       status = winreg_printer_binding_handle(p->mem_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(status)) {
+               return status;
+       }
+
+       status = winreg_printer_setform1(p->mem_ctx, b,
                                         form_name,
                                         form);
        if (!W_ERROR_IS_OK(status)) {
@@ -8589,9 +8726,7 @@ WERROR _spoolss_SetForm(struct pipes_struct *p,
                        return WERR_BADFID;
                }
 
-               status = winreg_printer_update_changeid(p->mem_ctx,
-                                                       get_session_info_system(),
-                                                       p->msg_ctx,
+               status = winreg_printer_update_changeid(p->mem_ctx, b,
                                                        lp_const_servicename(snum));
                if (!W_ERROR_IS_OK(status)) {
                        return status;
@@ -8626,7 +8761,7 @@ static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
        union spoolss_PrintProcessorInfo *info;
        WERROR result;
 
-       info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
+       info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
        W_ERROR_HAVE_NO_MEMORY(info);
 
        *count = 1;
@@ -8728,7 +8863,7 @@ static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
        WERROR result;
        union spoolss_PrintProcDataTypesInfo *info;
 
-       info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
+       info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
        W_ERROR_HAVE_NO_MEMORY(info);
 
        *count = 1;
@@ -8785,6 +8920,10 @@ WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
                return WERR_UNKNOWN_LEVEL;
        }
 
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
        *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
                                                     spoolss_EnumPrintProcDataTypes,
                                                     *r->out.info, r->in.level,
@@ -8840,7 +8979,7 @@ static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
        union spoolss_MonitorInfo *info;
        WERROR result = WERR_OK;
 
-       info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
+       info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
        W_ERROR_HAVE_NO_MEMORY(info);
 
        *count = 2;
@@ -8880,7 +9019,7 @@ static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
        union spoolss_MonitorInfo *info;
        WERROR result = WERR_OK;
 
-       info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
+       info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
        W_ERROR_HAVE_NO_MEMORY(info);
 
        *count = 2;
@@ -9083,7 +9222,7 @@ WERROR _spoolss_GetJob(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
-       result = winreg_get_printer(p->mem_ctx,
+       result = winreg_get_printer_internal(p->mem_ctx,
                                    get_session_info_system(),
                                    p->msg_ctx,
                                    lp_const_servicename(snum),
@@ -9141,10 +9280,10 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
        int                     snum = 0;
        WERROR result = WERR_OK;
        DATA_BLOB blob;
-       enum winreg_Type val_type;
-       uint8_t *val_data;
-       uint32_t val_size;
-
+       enum winreg_Type val_type = REG_NONE;
+       uint8_t *val_data = NULL;
+       uint32_t val_size = 0;
+       struct dcerpc_binding_handle *b;
 
        DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
 
@@ -9202,6 +9341,14 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                return WERR_INVALID_PARAM;
        }
 
+       result = winreg_printer_binding_handle(p->mem_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
        /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
        if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
            strequal(r->in.value_name, "ChangeId")) {
@@ -9210,9 +9357,7 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                if (r->in.offered >= *r->out.needed) {
                        uint32_t changeid = 0;
 
-                       result = winreg_printer_get_changeid(p->mem_ctx,
-                                                            get_session_info_system(),
-                                                            p->msg_ctx,
+                       result = winreg_printer_get_changeid(p->mem_ctx, b,
                                                             printer,
                                                             &changeid);
                        if (!W_ERROR_IS_OK(result)) {
@@ -9225,9 +9370,7 @@ WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
                goto done;
        }
 
-       result = winreg_get_printer_dataex(p->mem_ctx,
-                                          get_session_info_system(),
-                                          p->msg_ctx,
+       result = winreg_get_printer_dataex(p->mem_ctx, b,
                                           printer,
                                           r->in.key_name,
                                           r->in.value_name,
@@ -9264,6 +9407,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
        WERROR                  result = WERR_OK;
        struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
        char                    *oid_string;
+       struct dcerpc_binding_handle *b;
 
        DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
 
@@ -9300,9 +9444,15 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       result = winreg_get_printer(Printer,
-                                   get_session_info_system(),
-                                   p->msg_ctx,
+       result = winreg_printer_binding_handle(p->mem_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
+       result = winreg_get_printer(Printer, b,
                                    lp_servicename(snum),
                                    &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
@@ -9319,9 +9469,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
 
        /* save the registry data */
 
-       result = winreg_set_printer_dataex(p->mem_ctx,
-                                          get_session_info_system(),
-                                          p->msg_ctx,
+       result = winreg_set_printer_dataex(p->mem_ctx, b,
                                           pinfo2->sharename,
                                           r->in.key_name,
                                           r->in.value_name,
@@ -9345,9 +9493,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
                         * previous set_printer_dataex() call.  I have no idea if
                         * this is right.    --jerry
                         */
-                       winreg_set_printer_dataex(p->mem_ctx,
-                                                 get_session_info_system(),
-                                                 p->msg_ctx,
+                       winreg_set_printer_dataex(p->mem_ctx, b,
                                                  pinfo2->sharename,
                                                  str,
                                                  r->in.value_name,
@@ -9356,9 +9502,7 @@ WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
                                                  strlen(oid_string) + 1);
                }
 
-               result = winreg_printer_update_changeid(p->mem_ctx,
-                                                       get_session_info_system(),
-                                                       p->msg_ctx,
+               result = winreg_printer_update_changeid(p->mem_ctx, b,
                                                        lp_const_servicename(snum));
 
        }
@@ -9404,14 +9548,14 @@ WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
        }
        printer = lp_const_servicename(snum);
 
-       status = winreg_delete_printer_dataex(p->mem_ctx,
+       status = winreg_delete_printer_dataex_internal(p->mem_ctx,
                                              get_session_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,
+               status = winreg_printer_update_changeid_internal(p->mem_ctx,
                                                        get_session_info_system(),
                                                        p->msg_ctx,
                                                        printer);
@@ -9446,7 +9590,7 @@ WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
                return WERR_BADFID;
        }
 
-       result = winreg_enum_printer_key(p->mem_ctx,
+       result = winreg_enum_printer_key_internal(p->mem_ctx,
                                         get_session_info_system(),
                                         p->msg_ctx,
                                         lp_const_servicename(snum),
@@ -9494,6 +9638,7 @@ WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
        int                     snum=0;
        WERROR                  status;
        const char *printer;
+       struct dcerpc_binding_handle *b;
 
        DEBUG(5,("_spoolss_DeletePrinterKey\n"));
 
@@ -9519,16 +9664,20 @@ WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
 
        printer = lp_const_servicename(snum);
 
+       status = winreg_printer_binding_handle(p->mem_ctx,
+                                              get_session_info_system(),
+                                              p->msg_ctx,
+                                              &b);
+       if (!W_ERROR_IS_OK(status)) {
+               return status;
+       }
+
        /* delete the key and all subkeys */
-       status = winreg_delete_printer_key(p->mem_ctx,
-                                          get_session_info_system(),
-                                          p->msg_ctx,
+       status = winreg_delete_printer_key(p->mem_ctx, b,
                                           printer,
                                           r->in.key_name);
        if (W_ERROR_IS_OK(status)) {
-               status = winreg_printer_update_changeid(p->mem_ctx,
-                                                       get_session_info_system(),
-                                                       p->msg_ctx,
+               status = winreg_printer_update_changeid(p->mem_ctx, b,
                                                        printer);
        }
 
@@ -9577,7 +9726,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,
+       result = winreg_enum_printer_dataex_internal(p->mem_ctx,
                                            get_session_info_system(),
                                            p->msg_ctx,
                                            lp_const_servicename(snum),