r11860: BUG 3156: don't use find_service() when explicitly looking for a printer...
[samba.git] / source3 / rpc_server / srv_spoolss_nt.c
index 0329471d49ac59aaf2a5b1d298b307eedb5e9797..f0ba863b4d706676d1e6e973c67348675dba8127 100644 (file)
@@ -75,7 +75,7 @@ typedef struct _counter_printer_0 {
 
 static counter_printer_0 *counter_list;
 
-static struct cli_state notify_cli; /* print notify back-channel */
+static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
 static uint32 smb_connections=0;
 
 
@@ -166,7 +166,7 @@ static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
                return;
        }
 
-       result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
+       result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
        
        if (!W_ERROR_IS_OK(result))
                DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
@@ -174,9 +174,10 @@ static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
 
        /* if it's the last connection, deconnect the IPC$ share */
        if (smb_connections==1) {
-               cli_nt_session_close(&notify_cli);
-               cli_ulogoff(&notify_cli);
-               cli_shutdown(&notify_cli);
+
+               cli_shutdown( notify_cli_pipe->cli );
+               notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
+
                message_deregister(MSG_PRINTER_NOTIFY2);
 
                /* Tell the connections db we're no longer interested in
@@ -274,59 +275,6 @@ static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd
        return find_printer;
 }
 
-/****************************************************************************
- look for a printer object cached on an open printer handle
-****************************************************************************/
-
-WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2, 
-                                        const char *servername, const char *printername )
-{
-       Printer_entry *p;
-       
-       DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n", 
-               servername, printername));
-
-       for ( p=printers_list; p; p=p->next )
-       {
-               if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER 
-                       && p->printer_info
-                       && strequal( p->sharename, printername )
-                       && strequal( p->servername, servername ) )
-               {
-                       DEBUG(10,("Found printer\n"));
-                       *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
-                       if ( *info2 )
-                               return WERR_OK;
-               }
-       }
-
-       return WERR_INVALID_PRINTER_NAME;
-}
-
-/****************************************************************************
-  destroy any cached printer_info_2 structures on open handles
-****************************************************************************/
-
-void invalidate_printer_hnd_cache( char *printername )
-{
-       Printer_entry *p;
-       
-       DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
-
-       for ( p=printers_list; p; p=p->next )
-       {
-               if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER 
-                       && p->printer_info
-                       && StrCaseCmp(p->sharename, printername)==0)
-               {
-                       DEBUG(10,("invalidating printer_info cache for handl:\n"));
-                       free_a_printer( &p->printer_info, 2 );
-                       p->printer_info = NULL;
-               }
-       }
-
-       return;
-}
 /****************************************************************************
  Close printer index by handle.
 ****************************************************************************/
@@ -345,6 +293,58 @@ static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
        return True;
 }      
 
+/****************************************************************************
+ Delete a printer given a handle.
+****************************************************************************/
+WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
+{
+       char *cmd = lp_deleteprinter_cmd();
+       pstring command;
+       int ret;
+       SE_PRIV se_printop = SE_PRINT_OPERATOR;
+       BOOL is_print_op = False;
+               
+       /* can't fail if we don't try */
+       
+       if ( !*cmd )
+               return WERR_OK;
+               
+       pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
+
+       if ( token )
+               is_print_op = user_has_privileges( token, &se_printop );
+       
+       DEBUG(10,("Running [%s]\n", command));
+
+       /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
+       
+       if ( is_print_op )
+               become_root();
+               
+       if ( (ret = smbrun(command, NULL)) == 0 ) {
+               /* Tell everyone we updated smb.conf. */
+               message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
+       }
+               
+       if ( is_print_op )
+               unbecome_root();
+
+       /********** END SePrintOperatorPrivlege BLOCK **********/
+       
+       DEBUGADD(10,("returned [%d]\n", ret));
+
+       if (ret != 0) 
+               return WERR_BADFID; /* What to return here? */
+
+       /* go ahead and re-read the services immediately */
+       reload_services( False );
+       
+       if ( lp_servicenumber( sharename )  < 0 )
+               return WERR_ACCESS_DENIED;
+               
+       return WERR_OK;
+}
+
 /****************************************************************************
  Delete a printer given a handle.
 ****************************************************************************/
@@ -369,18 +369,6 @@ static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
                DEBUG(3, ("delete_printer_handle: denied by handle\n"));
                return WERR_ACCESS_DENIED;
        }
-
-#if 0
-       /* Check calling user has permission to delete printer.  Note that
-          since we set the snum parameter to -1 only administrators can
-          delete the printer.  This stops people with the Full Control
-          permission from deleting the printer. */
-
-       if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
-               DEBUG(3, ("printer delete denied by security descriptor\n"));
-               return WERR_ACCESS_DENIED;
-       }
-#endif
        
        /* this does not need a become root since the access check has been 
           done on the handle already */
@@ -390,50 +378,7 @@ static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
                return WERR_BADFID;
        }
 
-       /* the delete printer script shoudl be run as root if the user has perms */
-       
-       if (*lp_deleteprinter_cmd()) {
-
-               char *cmd = lp_deleteprinter_cmd();
-               pstring command;
-               int ret;
-               SE_PRIV se_printop = SE_PRINT_OPERATOR;
-               BOOL is_print_op;
-               
-               pstr_sprintf(command, "%s \"%s\"", cmd, Printer->sharename);
-
-               is_print_op = user_has_privileges( p->pipe_user.nt_user_token, &se_printop );
-       
-               DEBUG(10,("Running [%s]\n", command));
-
-               /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
-       
-               if ( is_print_op )
-                       become_root();
-               
-               if ( (ret = smbrun(command, NULL)) == 0 ) {
-                       /* Tell everyone we updated smb.conf. */
-                       message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
-               }
-               
-               if ( is_print_op )
-                       unbecome_root();
-
-               /********** END SePrintOperatorPrivlege BLOCK **********/
-
-               DEBUGADD(10,("returned [%d]\n", ret));
-
-               if (ret != 0) 
-                       return WERR_BADFID; /* What to return here? */
-
-               /* go ahead and re-read the services immediately */
-               reload_services( False );
-
-               if ( lp_servicenumber( Printer->sharename )  < 0 )
-                       return WERR_ACCESS_DENIED;
-       }
-
-       return WERR_OK;
+       return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
 }
 
 /****************************************************************************
@@ -534,29 +479,30 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
        DEBUGADD(5, ("searching for [%s]\n", aprinter ));
 
        /* Search all sharenames first as this is easier than pulling 
-          the printer_info_2 off of disk */
-       
-       snum = find_service(aprinter);
+          the printer_info_2 off of disk. Don't use find_service() since
+          that calls out to map_username() */
        
-       if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
-               found = True;
-               fstrcpy( sname, aprinter );
-       }
-
        /* do another loop to look for printernames */
        
        for (snum=0; !found && snum<n_services; snum++) {
 
-               /* no point in checking if this is not a printer or 
-                  we aren't allowing printername != sharename */
+               /* no point going on if this is not a printer */
 
-               if ( !(lp_snum_ok(snum) 
-                       && lp_print_ok(snum) 
-                       && !lp_force_printername(snum)) ) 
-               {
+               if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
                        continue;
+
+               fstrcpy(sname, lp_servicename(snum));
+               if ( strequal( aprinter, sname ) ) {
+                       found = True;
+                       break;
                }
+
+               /* no point looking up the printer object if
+                  we aren't allowing printername != sharename */
                
+               if ( lp_force_printername(snum) )
+                       continue;
+
                fstrcpy(sname, lp_servicename(snum));
 
                printer = NULL;
@@ -579,6 +525,7 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
                
                if ( strequal(printername, aprinter) ) {
                        found = True;
+                       break;
                }
                
                DEBUGADD(10, ("printername: %s\n", printername));
@@ -744,7 +691,7 @@ static void notify_system_time(struct spoolss_notify_msg *msg,
                return;
        }
 
-       if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
+       if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
                DEBUG(5, ("notify_system_time: prs_init() failed\n"));
                return;
        }
@@ -1077,7 +1024,7 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
                }
 
                if ( sending_msg_count ) {
-                       cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd, 
+                       rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd, 
                                        data_len, data, p->notify.change, 0 );
                }
        }
@@ -1131,7 +1078,8 @@ static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, voi
  Receive a notify2 message list
  ********************************************************************/
 
-static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
+static void receive_notify2_message_list(int msg_type, struct process_id src,
+                                        void *msg, size_t len)
 {
        size_t                  msg_count, i;
        char                    *buf = (char *)msg;
@@ -1216,22 +1164,6 @@ static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, siz
        return;
 }
 
-/********************************************************************
- callback to MSG_PRINTER_CHANGED.  When a printer is changed by 
- one smbd, all of processes must clear their printer cache immediately.
- ********************************************************************/
-
-void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
-{
-       fstring printername;
-       
-       fstrcpy( printername, buf );
-       
-       DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
-       
-       invalidate_printer_hnd_cache( printername );
-}
-
 /********************************************************************
  Send a message to ourself about new driver being installed
  so we can upgrade the information for each printer bound to this
@@ -1248,7 +1180,8 @@ static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
        DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
                drivername));
                
-       message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
+       message_send_pid(pid_to_procid(sys_getpid()),
+                        MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
 
        return True;
 }
@@ -1258,7 +1191,7 @@ static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
  over all printers, upgrading ones as necessary 
  **********************************************************************/
  
-void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
+void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
 {
        fstring drivername;
        int snum;
@@ -1344,7 +1277,8 @@ static BOOL srv_spoolss_reset_printerdata(char* drivername)
        DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
                drivername));
                
-       message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
+       message_send_pid(pid_to_procid(sys_getpid()),
+                        MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
 
        return True;
 }
@@ -1354,7 +1288,8 @@ static BOOL srv_spoolss_reset_printerdata(char* drivername)
  over all printers, resetting printer data as neessary 
  **********************************************************************/
  
-void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
+void reset_all_printerdata(int msg_type, struct process_id src,
+                          void *buf, size_t len)
 {
        fstring drivername;
        int snum;
@@ -1486,19 +1421,23 @@ static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRIN
  * SPOOL_Q_OPEN_PRINTER_EX structure
  ********************************************************************/
 
-static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
+static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
 {
        if (!q_u_ex || !q_u)
-               return;
+               return WERR_OK;
 
        DEBUG(8,("convert_to_openprinterex\n"));
                                
        if ( q_u->printername ) {
-               q_u_ex->printername = TALLOC_P( ctx, UNISTR2 );
+               q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
+               if (q_u_ex->printername == NULL)
+                       return WERR_NOMEM;
                copy_unistr2(q_u_ex->printername, q_u->printername);
        }
        
        copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
+
+       return WERR_OK;
 }
 
 /********************************************************************
@@ -1520,7 +1459,9 @@ WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R
        
        /* convert the OpenPrinter() call to OpenPrinterEx() */
        
-       convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
+       r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
+       if (!W_ERROR_IS_OK(r_u_ex.status))
+               return r_u_ex.status;
        
        r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
        
@@ -1660,7 +1601,7 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
 
                if (printer_default->access_required &
                    ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
-                       DEBUG(3, ("access DENIED for non-printserver bits"));
+                       DEBUG(3, ("access DENIED for non-printserver bits\n"));
                        close_printer_handle(p, handle);
                        return WERR_ACCESS_DENIED;
                }
@@ -1792,17 +1733,29 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
                                NT_PRINTER_INFO_LEVEL *printer, uint32 level)
 {
-       BOOL ret = True;
+       BOOL ret;
 
        switch (level) {
                case 2:
-                       ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
-                       break;
-               default:
-                       break;
+                       /* allocate memory if needed.  Messy because 
+                          convert_printer_info is used to update an existing 
+                          printer or build a new one */
+
+                       if ( !printer->info_2 ) {
+                               printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
+                               if ( !printer->info_2 ) {
+                                       DEBUG(0,("convert_printer_info: talloc() failed!\n"));
+                                       return False;
+                               }
+                       }
+
+                       ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
+                       printer->info_2->setuptime = time(NULL);
+
+                       return ret;
        }
 
-       return ret;
+       return False;
 }
 
 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
@@ -2064,7 +2017,10 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
                
                        /* this should not have failed---if it did, report to client */
                        if ( !W_ERROR_IS_OK(status_win2k) )
+                       {
+                               status = status_win2k;
                                goto done;
+                       }
                }
        }
        
@@ -2264,8 +2220,8 @@ static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char
 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value, 
                                   uint32 type, uint8 *data, int real_len  )
 {
-       delete_printer_data( printer->info_2, key, value );
-       
+       /* the registry objects enforce uniqueness based on value name */
+
        return add_printer_data( printer->info_2, key, value, type, data, real_len );
 }
 
@@ -2281,7 +2237,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
                
        if (!StrCaseCmp(value, "W3SvcInstalled")) {
                *type = REG_DWORD;
-               if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
+               if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
                        return WERR_NOMEM;
                *needed = 0x4;
                return WERR_OK;
@@ -2289,7 +2245,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
 
        if (!StrCaseCmp(value, "BeepEnabled")) {
                *type = REG_DWORD;
-               if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
+               if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
                        return WERR_NOMEM;
                SIVAL(*data, 0, 0x00);
                *needed = 0x4;                  
@@ -2298,7 +2254,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
 
        if (!StrCaseCmp(value, "EventLog")) {
                *type = REG_DWORD;
-               if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
+               if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
                        return WERR_NOMEM;
                /* formally was 0x1b */
                SIVAL(*data, 0, 0x0);
@@ -2308,7 +2264,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
 
        if (!StrCaseCmp(value, "NetPopup")) {
                *type = REG_DWORD;
-               if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
+               if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
                        return WERR_NOMEM;
                SIVAL(*data, 0, 0x00);
                *needed = 0x4;
@@ -2317,7 +2273,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
 
        if (!StrCaseCmp(value, "MajorVersion")) {
                *type = REG_DWORD;
-               if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
+               if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
                        return WERR_NOMEM;
 
                /* Windows NT 4.0 seems to not allow uploading of drivers
@@ -2336,7 +2292,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
 
        if (!StrCaseCmp(value, "MinorVersion")) {
                *type = REG_DWORD;
-               if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
+               if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
                        return WERR_NOMEM;
                SIVAL(*data, 0, 0);
                *needed = 0x4;
@@ -2354,7 +2310,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
                *type = REG_BINARY;
                *needed = 0x114;
 
-               if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, *needed)) )
+               if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
                        return WERR_NOMEM;
 
                SIVAL(*data, 0, *needed);       /* size */
@@ -2400,7 +2356,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
 
        if (!StrCaseCmp(value, "DsPresent")) {
                *type = REG_DWORD;
-               if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
+               if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
                        return WERR_NOMEM;
 
                /* only show the publish check box if we are a 
@@ -2542,98 +2498,66 @@ done:
  Connect to the client machine.
 **********************************************************/
 
-static BOOL spoolss_connect_to_client(struct cli_state *the_cli, 
+static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
                        struct in_addr *client_ip, const char *remote_machine)
 {
-       ZERO_STRUCTP(the_cli);
-       
-       if(cli_initialise(the_cli) == NULL) {
-               DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
-               return False;
-       }
-       
+       NTSTATUS ret;
+       struct cli_state *the_cli;
+       struct in_addr rm_addr;
+
        if ( is_zero_ip(*client_ip) ) {
-               if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
-                       DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
-                       cli_shutdown(the_cli);
-               return False;
+               if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
+                       DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
+                       return False;
                }
 
-               if (ismyip(the_cli->dest_ip)) {
+               if ( ismyip( rm_addr )) {
                        DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
-                       cli_shutdown(the_cli);
                        return False;
                }
-       }
-       else {
-               the_cli->dest_ip.s_addr = client_ip->s_addr;
+       } else {
+               rm_addr.s_addr = client_ip->s_addr;
                DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
                        inet_ntoa(*client_ip) ));
        }
 
-       if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
-               DEBUG(0,("spoolss_connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
-               cli_shutdown(the_cli);
-               return False;
-       }
-  
-       if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
-               DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n", 
-                       remote_machine));
-               cli_shutdown(the_cli);
-               return False;
-       }
+       /* setup the connection */
 
-       the_cli->protocol = PROTOCOL_NT1;
-       cli_setup_signing_state(the_cli, lp_client_signing());
-  
-       if (!cli_negprot(the_cli)) {
-               DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
-               cli_shutdown(the_cli);
-               return False;
-       }
+       ret = cli_full_connection( &the_cli, global_myname(), remote_machine, 
+               &rm_addr, 0, "IPC$", "IPC",
+               "", /* username */
+               "", /* domain */
+               "", /* password */
+               0, lp_client_signing(), NULL );
 
-       if (the_cli->protocol != PROTOCOL_NT1) {
-               DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
-               cli_shutdown(the_cli);
+       if ( !NT_STATUS_IS_OK( ret ) ) {
+               DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n", 
+                       remote_machine ));
                return False;
-       }
-    
-       /*
-        * Do an anonymous session setup.
-        */
-    
-       if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
-               DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
-               cli_shutdown(the_cli);
-               return False;
-       }
-    
-       if (!(the_cli->sec_mode & 1)) {
-               DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
+       }       
+               
+       if ( the_cli->protocol != PROTOCOL_NT1 ) {
+               DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
                cli_shutdown(the_cli);
                return False;
        }
     
-       if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
-               DEBUG(0,("spoolss_connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
-               cli_shutdown(the_cli);
-               return False;
-       }
-
        /*
         * Ok - we have an anonymous connection to the IPC$ share.
         * Now start the NT Domain stuff :-).
         */
 
-       if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
-               DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
-               cli_nt_session_close(the_cli);
-               cli_ulogoff(the_cli);
+       if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
+               DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
+                       remote_machine, nt_errstr(ret)));
                cli_shutdown(the_cli);
                return False;
        } 
 
+       /* make sure to save the cli_state pointer.  Keep its own talloc_ctx */
+
+       (*pp_pipe)->cli = the_cli;
+
        return True;
 }
 
@@ -2656,9 +2580,7 @@ static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
 
                fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
 
-               ZERO_STRUCT(notify_cli);
-
-               if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
+               if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
                        return False;
                        
                message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
@@ -2677,7 +2599,7 @@ static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
 
        smb_connections++;
 
-       result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter, 
+       result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter, 
                        type, handle);
                        
        if (!W_ERROR_IS_OK(result))
@@ -4226,22 +4148,23 @@ static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *p
        printer->cjobs = count;                                                 /* jobs */
        printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
                        
-       if((printer->devmode = construct_dev_mode(snum)) == NULL) {
+       if ( !(printer->devmode = construct_dev_mode(snum)) )
                DEBUG(8, ("Returning NULL Devicemode!\n"));
-       }
 
-       if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
-               /* steal the printer info sec_desc structure.  [badly done]. */
-               printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
-               ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
-               ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
-               ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
-       }
-       else {
-               printer->secdesc = NULL;
+       printer->secdesc = NULL;
+
+       if ( ntprinter->info_2->secdesc_buf 
+               && ntprinter->info_2->secdesc_buf->len != 0 ) 
+       {
+               /* don't use talloc_steal() here unless you do a deep steal of all 
+                  the SEC_DESC members */
+
+               printer->secdesc = dup_sec_desc( get_talloc_ctx(), 
+                       ntprinter->info_2->secdesc_buf->sec );
        }
 
        free_a_printer(&ntprinter, 2);
+
        return True;
 }
 
@@ -4266,32 +4189,16 @@ static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **
 
        ZERO_STRUCTP(printer);
        
-       printer->flags = 4; /* These are the components of the SD we are returning. */
-       if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
-               /* steal the printer info sec_desc structure.  [badly done]. */
-               printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
-
-#if 0
-               /*
-                * Set the flags for the components we are returning.
-                */
+       /* These are the components of the SD we are returning. */
 
-               if (printer->secdesc->owner_sid)
-                       printer->flags |= OWNER_SECURITY_INFORMATION;
+       printer->flags = 0x4; 
 
-               if (printer->secdesc->grp_sid)
-                       printer->flags |= GROUP_SECURITY_INFORMATION;
-
-               if (printer->secdesc->dacl)
-                       printer->flags |= DACL_SECURITY_INFORMATION;
-
-               if (printer->secdesc->sacl)
-                       printer->flags |= SACL_SECURITY_INFORMATION;
-#endif
+       if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
+               /* don't use talloc_steal() here unless you do a deep steal of all 
+                  the SEC_DESC members */
 
-               ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
-               ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
-               ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
+               printer->secdesc = dup_sec_desc( get_talloc_ctx(), 
+                       ntprinter->info_2->secdesc_buf->sec );
        }
 
        free_a_printer(&ntprinter, 2);
@@ -4574,16 +4481,20 @@ static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint3
                if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
                        DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
                                
-                       if (construct_printer_info_2(NULL, &current_prt, snum)) {
-                               if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
+                       if (construct_printer_info_2(NULL, &current_prt, snum)) 
+                       {
+                               if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
                                        DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
                                        SAFE_FREE(printers);
                                        *returned = 0;
                                        return WERR_NOMEM;
                                }
-                               else printers = tp;
+
                                DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
+
+                               printers = tp;
                                memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
+
                                (*returned)++;
                        }
                }
@@ -4609,9 +4520,10 @@ static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint3
        
 out:
        /* clear memory */
-       for (i=0; i<*returned; i++) {
+
+       for (i=0; i<*returned; i++) 
                free_devmode(printers[i].devmode);
-       }
+
        SAFE_FREE(printers);
 
        if ( !W_ERROR_IS_OK(result) )
@@ -6033,7 +5945,7 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
 /****************************************************************************
 ****************************************************************************/
 
-static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
+BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
 {
        char *cmd = lp_addprinter_cmd();
        char **qlines;
@@ -6043,7 +5955,7 @@ static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printe
        int fd;
        fstring remote_machine = "%m";
        SE_PRIV se_printop = SE_PRINT_OPERATOR;
-       BOOL is_print_op;
+       BOOL is_print_op = False;
 
        standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
        
@@ -6052,7 +5964,8 @@ static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printe
                        printer->info_2->portname, printer->info_2->drivername,
                        printer->info_2->location, printer->info_2->comment, remote_machine);
 
-       is_print_op = user_has_privileges( token, &se_printop );
+       if ( token )
+               is_print_op = user_has_privileges( token, &se_printop );
 
        DEBUG(10,("Running [%s]\n", command));
 
@@ -6189,17 +6102,12 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
                        || !strequal(printer->info_2->portname, old_printer->info_2->portname)
                        || !strequal(printer->info_2->location, old_printer->info_2->location)) )
        {
+               /* add_printer_hook() will call reload_services() */
+
                if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
                        result = WERR_ACCESS_DENIED;
                        goto done;
                }
-
-               /* 
-                * make sure we actually reload the services after 
-                * this as smb.conf could have a new section in it 
-                * .... shouldn't .... but could
-                */
-               reload_services(False); 
        }
        
        /*
@@ -7473,13 +7381,11 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
        int     snum;
        WERROR err = WERR_OK;
 
-       if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
+       if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
                DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
                return WERR_NOMEM;
        }
 
-       ZERO_STRUCTP(printer);
-
        /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
        if (!convert_printer_info(info, printer, 2)) {
                free_a_printer(&printer, 2);
@@ -7489,7 +7395,7 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
        /* check to see if the printer already exists */
 
        if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
-               DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n", 
+               DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n", 
                        printer->info_2->sharename));
                free_a_printer(&printer, 2);
                return WERR_PRINTER_ALREADY_EXISTS;
@@ -7502,7 +7408,12 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
                if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
                        free_a_printer(&printer,2);
                        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"
+                       "parameter must exist for this call to succeed\n",
+                       printer->info_2->sharename ));
        }
 
        /* use our primary netbios name since get_a_printer() will convert 
@@ -7891,8 +7802,6 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
        int             i, key_index, num_values;
        int             name_length;
        
-       ZERO_STRUCT( printer );
-       
        *out_type = 0;
 
        *out_max_data_len = 0;
@@ -7913,7 +7822,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
        if (!W_ERROR_IS_OK(result))
                return result;
                
-       p_data = &printer->info_2->data;        
+       p_data = printer->info_2->data; 
        key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
 
        result = WERR_OK;
@@ -7931,11 +7840,11 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
                biggest_valuesize = 0;
                biggest_datasize  = 0;
                                
-               num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
-               
+               num_values = regval_ctr_numvals( p_data->keys[key_index].values );
+       
                for ( i=0; i<num_values; i++ )
                {
-                       val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
+                       val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
                        
                        name_length = strlen(val->valuename);
                        if ( strlen(val->valuename) > biggest_valuesize ) 
@@ -7965,7 +7874,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
         */
        
        if ( key_index != -1 )
-               val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
+               val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
 
        if ( !val ) 
        {
@@ -8026,13 +7935,14 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
                /* data - counted in bytes */
 
                *out_max_data_len = in_data_len;
-               if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) 
+               if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) 
                {
                        result = WERR_NOMEM;
                        goto done;
                }
                data_len = regval_size(val);
-               memcpy( *data_out, regval_data_p(val), data_len );
+               if ( *data_out )
+                       memcpy( *data_out, regval_data_p(val), data_len );
                *out_data_len = data_len;
        }
 
@@ -8922,7 +8832,7 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u,
                goto done;
        }
        
-       if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
+       if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
                DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
                free_a_printer( &printer, 2 );
                status = WERR_BADFILE;
@@ -9143,7 +9053,7 @@ WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPO
        /* get the list of subkey names */
        
        unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
-       data = &printer->info_2->data;
+       data = printer->info_2->data;
 
        num_keys = get_printer_subkeys( data, key, &keynames );
 
@@ -9286,7 +9196,7 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
        
        /* now look for a match on the key name */
        
-       p_data = &printer->info_2->data;
+       p_data = printer->info_2->data;
        
        unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
        if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
@@ -9301,7 +9211,7 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
        
        /* allocate the memory for the array of pointers -- if necessary */
        
-       num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
+       num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
        if ( num_entries )
        {
                if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
@@ -9324,7 +9234,7 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
        {
                /* lookup the registry value */
                
-               val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
+               val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
                DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
 
                /* copy the data */