r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need
[vlendec/samba-autobuild/.git] / source3 / rpc_server / srv_spoolss_nt.c
index 126c2cc140e966ace648036e1779b30b44317a3c..3dbad208cc8ad0e4c8054c19e9843feeba2e883a 100644 (file)
@@ -40,23 +40,6 @@ extern userdom_struct current_user_info;
 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
 
-
-/* Table to map the driver version */
-/* to OS */
-static const char * drv_ver_to_os[] = {
-       "WIN9X",   /* driver version/cversion 0 */
-       "",        /* unused ? */
-       "WINNT",   /* driver version/cversion 2 */
-       "WIN2K",   /* driver version/cversion 3 */
-};
-
-static const char *get_drv_ver_to_os(int ver)
-{
-       if (ver < 0 || ver > 3)
-               return "";
-       return drv_ver_to_os[ver];
-}
-
 struct table_node {
        const char    *long_archi;
        const char    *short_archi;
@@ -91,7 +74,7 @@ extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
 
 struct xcv_api_table {
        const char *name;
-       WERROR(*fn) (RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
+       WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
 };
 
 
@@ -348,7 +331,7 @@ WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
        /* go ahead and re-read the services immediately */
        reload_services( False );
        
-       if ( lp_servicenumber( sharename )  < 0 )
+       if ( !share_defined( sharename ) )
                return WERR_ACCESS_DENIED;
                
        return WERR_OK;
@@ -723,14 +706,21 @@ static void notify_system_time(struct spoolss_notify_msg *msg,
 
        if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
                DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
+               prs_mem_free(&ps);
                return;
        }
 
-       if (!spoolss_io_system_time("", &ps, 0, &systime))
+       if (!spoolss_io_system_time("", &ps, 0, &systime)) {
+               prs_mem_free(&ps);
                return;
+       }
 
        data->notify_data.data.length = prs_offset(&ps);
        data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
+       if (!data->notify_data.data.string) {
+               prs_mem_free(&ps);
+               return;
+       }
 
        prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
 
@@ -977,6 +967,10 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
                /* allocate the max entries possible */
                
                data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
+               if (!data) {
+                       return;
+               }
+
                ZERO_STRUCTP(data);
                
                /* build the array of change notifications */
@@ -1393,6 +1387,9 @@ static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
        len = unistrlen(devmode->devicename.buffer);
        if (len != -1) {
                d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
+               if (!d->devicename.buffer) {
+                       return NULL;
+               }
                if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
                        return NULL;
        }
@@ -1401,12 +1398,17 @@ static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
        len = unistrlen(devmode->formname.buffer);
        if (len != -1) {
                d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
+               if (!d->devicename.buffer) {
+                       return NULL;
+               }
                if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
                        return NULL;
        }
 
        d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
-       
+       if (!d->dev_private) {
+               return NULL;
+       }       
        return d;
 }
 
@@ -1507,7 +1509,6 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
 
        fstring name;
        int snum;
-       struct current_user user;
        Printer_entry *Printer=NULL;
 
        if ( !q_u->printername )
@@ -1531,8 +1532,6 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                return WERR_INVALID_PRINTER_NAME;
        }
 
-       get_current_user(&user, p);
-
        /*
         * First case: the user is opening the print server:
         *
@@ -1597,12 +1596,12 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
                           and not a printer admin, then fail */
                        
-                       if ((user.ut.uid != 0) &&
-                           !user_has_privileges(user.nt_user_token,
+                       if ((p->pipe_user.ut.uid != 0) &&
+                           !user_has_privileges(p->pipe_user.nt_user_token,
                                                 &se_printop ) &&
                            !token_contains_name_in_list(
-                                   uidtoname(user.ut.uid), NULL,
-                                   user.nt_user_token,
+                                   uidtoname(p->pipe_user.ut.uid), NULL,
+                                   p->pipe_user.nt_user_token,
                                    lp_printer_admin(snum))) {
                                close_printer_handle(p, handle);
                                return WERR_ACCESS_DENIED;
@@ -1655,9 +1654,9 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                        return WERR_ACCESS_DENIED;
                }
 
-               if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
-                                  snum) ||
-                   !print_access_check(&user, snum,
+               if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
+                                  p->pipe_user.nt_user_token, snum) ||
+                   !print_access_check(&p->pipe_user, snum,
                                        printer_default->access_required)) {
                        DEBUG(3, ("access DENIED for printer open\n"));
                        close_printer_handle(p, handle);
@@ -1951,20 +1950,17 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
        NT_PRINTER_DRIVER_INFO_LEVEL    info;
        NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
        int                             version;
-       struct current_user             user;
        WERROR                          status;
        WERROR                          status_win2k = WERR_ACCESS_DENIED;
        SE_PRIV                         se_printop = SE_PRINT_OPERATOR; 
        
-       get_current_user(&user, p);
-        
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
                        
-       if ( (user.ut.uid != 0) 
-               && !user_has_privileges(user.nt_user_token, &se_printop ) 
-               && !token_contains_name_in_list( uidtoname(user.ut.uid), 
-                   NULL, user.nt_user_token, lp_printer_admin(-1)) ) 
+       if ( (p->pipe_user.ut.uid != 0) 
+               && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) 
+               && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid), 
+                   NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) ) 
        {
                return WERR_ACCESS_DENIED;
        }
@@ -2011,7 +2007,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
                        /* if we get to here, we now have 2 driver info structures to remove */
                        /* remove the Win2k driver first*/
                
-                       status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
+                       status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
                        free_a_printer_driver( info_win2k, 3 );
                
                        /* this should not have failed---if it did, report to client */
@@ -2023,7 +2019,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
                }
        }
        
-       status = delete_printer_driver(info.info_3, &user, version, False);
+       status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
        
        /* if at least one of the deletes succeeded return OK */
        
@@ -2049,20 +2045,17 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
        int                             version;
        uint32                          flags = q_u->delete_flags;
        BOOL                            delete_files;
-       struct current_user             user;
        WERROR                          status;
        WERROR                          status_win2k = WERR_ACCESS_DENIED;
        SE_PRIV                         se_printop = SE_PRINT_OPERATOR; 
        
-       get_current_user(&user, p);
-       
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
                        
-       if ( (user.ut.uid != 0) 
-               && !user_has_privileges(user.nt_user_token, &se_printop ) 
-               && !token_contains_name_in_list( uidtoname(user.ut.uid), 
-                   NULL, user.nt_user_token, lp_printer_admin(-1)) ) 
+       if ( (p->pipe_user.ut.uid != 0) 
+               && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) 
+               && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid), 
+                   NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) ) 
        {
                return WERR_ACCESS_DENIED;
        }
@@ -2148,7 +2141,7 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
                        /* if we get to here, we now have 2 driver info structures to remove */
                        /* remove the Win2k driver first*/
                
-                       status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
+                       status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
                        free_a_printer_driver( info_win2k, 3 );
                                
                        /* this should not have failed---if it did, report to client */
@@ -2158,7 +2151,7 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
                }
        }
 
-       status = delete_printer_driver(info.info_3, &user, version, delete_files);
+       status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
 
        if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
                status = WERR_OK;
@@ -3441,25 +3434,22 @@ static uint32 size_of_notify_info_data(uint16 type, uint16 field)
 {
        int i=0;
 
-       for (i = 0; i < sizeof(notify_info_data_table); i++) 
-       {
+       for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
                if ( (notify_info_data_table[i].type == type)
-                       && (notify_info_data_table[i].field == field) ) 
-               {
-                       switch(notify_info_data_table[i].size) 
-                       {
-                       case NOTIFY_ONE_VALUE:
-                       case NOTIFY_TWO_VALUE:
-                               return 1;
-                       case NOTIFY_STRING:
-                               return 2;
-
-                       /* The only pointer notify data I have seen on
-                          the wire is the submitted time and this has
-                          the notify size set to 4. -tpot */
-
-                       case NOTIFY_POINTER:
-                               return 4;
+                       && (notify_info_data_table[i].field == field) ) {
+                       switch(notify_info_data_table[i].size) {
+                               case NOTIFY_ONE_VALUE:
+                               case NOTIFY_TWO_VALUE:
+                                       return 1;
+                               case NOTIFY_STRING:
+                                       return 2;
+
+                               /* The only pointer notify data I have seen on
+                                  the wire is the submitted time and this has
+                                  the notify size set to 4. -tpot */
+
+                               case NOTIFY_POINTER:
+                                       return 4;
                                        
                                case NOTIFY_SECDESC:
                                        return 5;
@@ -3476,23 +3466,23 @@ static uint32 size_of_notify_info_data(uint16 type, uint16 field)
  Return the type of notify_info_data.
 ********************************************************************/
 
-static int type_of_notify_info_data(uint16 type, uint16 field)
+static uint32 type_of_notify_info_data(uint16 type, uint16 field)
 {
-       int i=0;
+       uint32 i=0;
 
-       for (i = 0; i < sizeof(notify_info_data_table); i++) {
+       for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
                if (notify_info_data_table[i].type == type &&
                    notify_info_data_table[i].field == field)
                        return notify_info_data_table[i].size;
        }
 
-       return False;
+       return 0;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static int search_notify(uint16 type, uint16 field, int *value)
+static BOOL search_notify(uint16 type, uint16 field, int *value)
 {      
        int i;
 
@@ -3521,10 +3511,8 @@ void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16
        info_data->enc_type = type_of_notify_info_data(type, field);
 
        info_data->id = id;
-
 }
 
-
 /*******************************************************************
  *
  * fill a notify_info struct with info asked
@@ -3540,7 +3528,7 @@ static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY
        uint16 type;
        uint16 field;
 
-       SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
+       SPOOL_NOTIFY_INFO_DATA *current_data;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
        print_queue_struct *queue=NULL;
 
@@ -3561,11 +3549,10 @@ static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY
                if (!search_notify(type, field, &j) )
                        continue;
 
-               if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
+               if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
                        DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
                        return False;
-               } else 
-                       info->data = tid;
+               }
 
                current_data = &info->data[info->count];
 
@@ -3601,7 +3588,7 @@ static BOOL construct_notify_jobs_info(print_queue_struct *queue,
        uint16 type;
        uint16 field;
 
-       SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
+       SPOOL_NOTIFY_INFO_DATA *current_data;
        
        DEBUG(4,("construct_notify_jobs_info\n"));
        
@@ -3617,11 +3604,10 @@ static BOOL construct_notify_jobs_info(print_queue_struct *queue,
                if (!search_notify(type, field, &j) )
                        continue;
 
-               if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
+               if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
                        DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
                        return False;
                }
-               else info->data = tid;
 
                current_data=&(info->data[info->count]);
 
@@ -4078,7 +4064,7 @@ static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode
  Create a DEVMODE struct. Returns malloced memory.
 ****************************************************************************/
 
-DEVICEMODE *construct_dev_mode(int snum)
+DEVICEMODE *construct_dev_mode(const char *servicename)
 {
        NT_PRINTER_INFO_LEVEL   *printer = NULL;
        DEVICEMODE              *devmode = NULL;
@@ -4087,7 +4073,7 @@ DEVICEMODE *construct_dev_mode(int snum)
        
        DEBUGADD(8,("getting printer characteristics\n"));
 
-       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum)))) 
+       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
                return NULL;
 
        if ( !printer->info_2->devmode ) {
@@ -4159,7 +4145,7 @@ 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)) )
+       if ( !(printer->devmode = construct_dev_mode(lp_const_servicename(snum))) )
                DEBUG(8, ("Returning NULL Devicemode!\n"));
 
        printer->secdesc = NULL;
@@ -4296,7 +4282,7 @@ static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32
        int snum;
        int i;
        int n_services=lp_numservices();
-       PRINTER_INFO_1 *tp, *printers=NULL;
+       PRINTER_INFO_1 *printers=NULL;
        PRINTER_INFO_1 current_prt;
        WERROR result = WERR_OK;
        
@@ -4307,13 +4293,11 @@ static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32
                        DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
 
                        if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
-                               if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
+                               if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
                                        DEBUG(2,("enum_all_printers_info_1: 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_1\n", *returned));             
 
                                memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
@@ -4484,26 +4468,25 @@ static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint3
        int snum;
        int i;
        int n_services=lp_numservices();
-       PRINTER_INFO_2 *tp, *printers=NULL;
+       PRINTER_INFO_2 *printers=NULL;
        PRINTER_INFO_2 current_prt;
        WERROR result = WERR_OK;
 
+       *returned = 0;
+
        for (snum=0; snum<n_services; snum++) {
                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)) ) {
+                       if (construct_printer_info_2(NULL, &current_prt, snum)) {
+                               if ( !(printers=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;
                                }
 
-                               DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
+                               DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));         
 
-                               printers = tp;
                                memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
 
                                (*returned)++;
@@ -4631,11 +4614,13 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_
        
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(4,("_spoolss_enumprinters\n"));
 
        *needed=0;
@@ -4826,8 +4811,10 @@ static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER
        if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
                return WERR_NOMEM;
 
-       if (!construct_printer_info_4(print_hnd, printer, snum))
+       if (!construct_printer_info_4(print_hnd, printer, snum)) {
+               SAFE_FREE(printer);
                return WERR_NOMEM;
+       }
        
        /* check the required size. */  
        *needed += spoolss_size_printer_info_4(printer);
@@ -4863,8 +4850,10 @@ static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER
        if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
                return WERR_NOMEM;
 
-       if (!construct_printer_info_5(print_hnd, printer, snum))
+       if (!construct_printer_info_5(print_hnd, printer, snum)) {
+               free_printer_info_5(printer);
                return WERR_NOMEM;
+       }
        
        /* check the required size. */  
        *needed += spoolss_size_printer_info_5(printer);
@@ -4940,11 +4929,13 @@ WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GET
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        *needed=0;
 
        if (!get_printer_snum(p, handle, &snum))
@@ -5074,7 +5065,6 @@ static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const c
        int j=0;
        const char *v;
        pstring line;
-       uint16 *tuary;
 
        DEBUG(6,("init_unistr_array\n"));
        *uni_array=NULL;
@@ -5102,12 +5092,11 @@ static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const c
 
                /* add one extra unit16 for the second terminating NULL */
                
-               if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
+               if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
                        DEBUG(2,("init_unistr_array: Realloc error\n" ));
                        return 0;
-               } else
-                       *uni_array = tuary;
-                       
+               }
+
                if ( !strlen(v) ) 
                        break;
                
@@ -5539,11 +5528,13 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(4,("_spoolss_getprinterdriver2\n"));
 
        if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
@@ -5640,15 +5631,12 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S
        pstring jobname;
        fstring datatype;
        Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
-       struct current_user user;
 
        if (!Printer) {
                DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
 
-       get_current_user(&user, p);
-
        /*
         * a nice thing with NT is it doesn't listen to what you tell it.
         * when asked to send _only_ RAW datas, it tries to send datas
@@ -5672,7 +5660,7 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S
 
        unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
        
-       Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
+       Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
 
        /* An error occured in print_job_start() so return an appropriate
           NT error code. */
@@ -5745,13 +5733,10 @@ WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R
 static WERROR control_printer(POLICY_HND *handle, uint32 command,
                              pipes_struct *p)
 {
-       struct current_user user;
        int snum;
        WERROR errcode = WERR_BADFUNC;
        Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
 
-       get_current_user(&user, p);
-
        if (!Printer) {
                DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
@@ -5762,18 +5747,18 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command,
 
        switch (command) {
        case PRINTER_CONTROL_PAUSE:
-               if (print_queue_pause(&user, snum, &errcode)) {
+               if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
        case PRINTER_CONTROL_RESUME:
        case PRINTER_CONTROL_UNPAUSE:
-               if (print_queue_resume(&user, snum, &errcode)) {
+               if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
        case PRINTER_CONTROL_PURGE:
-               if (print_queue_purge(&user, snum, &errcode)) {
+               if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
@@ -5795,7 +5780,6 @@ WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R
        POLICY_HND      *handle = &q_u->handle;
        Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
        int             snum;
-       struct          current_user user;
        WERROR          errcode = WERR_OK;
        
        if (!Printer) {
@@ -5806,9 +5790,7 @@ WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R
        if (!get_printer_snum(p, handle, &snum))
                return WERR_BADFID;
        
-       get_current_user( &user, p );   
-       
-       print_job_delete( &user, snum, Printer->jobid, &errcode );      
+       print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );      
        
        return errcode;
 }
@@ -5889,6 +5871,10 @@ static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
        }
 
        new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
+       if (!new_secdesc_ctr) {
+               result = WERR_NOMEM;
+               goto done;
+       }
 
        if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
                result = WERR_OK;
@@ -5956,6 +5942,52 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
 /****************************************************************************
 ****************************************************************************/
 
+WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
+{
+       char *cmd = lp_addport_cmd();
+       pstring command;
+       int ret;
+       int fd;
+       SE_PRIV se_printop = SE_PRINT_OPERATOR;
+       BOOL is_print_op = False;
+
+       if ( !*cmd ) {
+               return WERR_ACCESS_DENIED;
+       }
+               
+       slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
+
+       if ( token )
+               is_print_op = user_has_privileges( token, &se_printop );
+
+       DEBUG(10,("Running [%s]\n", command));
+
+       /********* BEGIN SePrintOperatorPrivilege **********/
+
+       if ( is_print_op )
+               become_root();
+       
+       ret = smbrun(command, &fd);
+
+       if ( is_print_op )
+               unbecome_root();
+
+       /********* END SePrintOperatorPrivilege **********/
+
+       DEBUGADD(10,("returned [%d]\n", ret));
+
+       if ( ret != 0 ) {
+               if (fd != -1)
+                       close(fd);
+               return WERR_ACCESS_DENIED;
+       }
+       
+       return WERR_OK;
+}
+
+/****************************************************************************
+****************************************************************************/
+
 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
 {
        char *cmd = lp_addprinter_cmd();
@@ -5968,7 +6000,9 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
        SE_PRIV se_printop = SE_PRINT_OPERATOR;
        BOOL is_print_op = False;
 
-       standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
+       standard_sub_basic(current_user_info.smb_name,
+                          current_user_info.domain,
+                          remote_machine,sizeof(remote_machine));
        
        slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
                        cmd, printer->info_2->printername, printer->info_2->sharename,
@@ -6025,6 +6059,7 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
        return True;
 }
 
+
 /********************************************************************
  * Called by spoolss_api_setprinter
  * when updating a printer description.
@@ -6228,7 +6263,13 @@ static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
 #ifdef HAVE_ADS
        SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
        int snum;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer;
+
+       if ( lp_security() != SEC_ADS ) {
+               return WERR_UNKNOWN_LEVEL;
+       }
+
+       Printer = find_printer_index_by_hnd(p, handle);
 
        DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
 
@@ -6329,8 +6370,11 @@ WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u
 {
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) 
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
+       if (!q_u->buffer && (q_u->offered!=0)) {
+               return WERR_INVALID_PARAM;
+       }
+
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
 
        r_u->needed = 0;
        return WERR_INVALID_PARAM; /* this is what a NT server
@@ -6484,7 +6528,7 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
                
        /* this should not be a failure condition if the devmode is NULL */
        
-       devmode = construct_dev_mode(snum);
+       devmode = construct_dev_mode(lp_const_servicename(snum));
 
        for (i=0; i<*returned; i++)
                fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
@@ -6541,11 +6585,13 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(4,("_spoolss_enumjobs\n"));
 
        *needed=0;
@@ -6602,7 +6648,6 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u
        uint32 jobid = q_u->jobid;
        uint32 command = q_u->command;
 
-       struct current_user user;
        int snum;
        WERROR errcode = WERR_BADFUNC;
                
@@ -6614,23 +6659,21 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u
                return WERR_INVALID_PRINTER_NAME;
        }
 
-       get_current_user(&user, p);     
-
        switch (command) {
        case JOB_CONTROL_CANCEL:
        case JOB_CONTROL_DELETE:
-               if (print_job_delete(&user, snum, jobid, &errcode)) {
+               if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
        case JOB_CONTROL_PAUSE:
-               if (print_job_pause(&user, snum, jobid, &errcode)) {
+               if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
                        errcode = WERR_OK;
                }               
                break;
        case JOB_CONTROL_RESTART:
        case JOB_CONTROL_RESUME:
-               if (print_job_resume(&user, snum, jobid, &errcode)) {
+               if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
@@ -6652,7 +6695,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
        uint32 version;
        fstring *list = NULL;
        NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
+       DRIVER_INFO_1 *driver_info_1=NULL;
        WERROR result = WERR_OK;
 
        *returned=0;
@@ -6662,17 +6705,17 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
                ndrivers=get_ntdrivers(&list, architecture, version);
                DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
 
-               if(ndrivers == -1)
+               if(ndrivers == -1) {
+                       SAFE_FREE(driver_info_1);
                        return WERR_NOMEM;
+               }
 
                if(ndrivers != 0) {
-                       if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
+                       if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
                                DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
-                               SAFE_FREE(driver_info_1);
                                SAFE_FREE(list);
                                return WERR_NOMEM;
                        }
-                       else driver_info_1 = tdi1;
                }
 
                for (i=0; i<ndrivers; i++) {
@@ -6683,6 +6726,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
                                                      architecture, version);
                        if (!W_ERROR_IS_OK(status)) {
                                SAFE_FREE(list);
+                               SAFE_FREE(driver_info_1);
                                return status;
                        }
                        fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
@@ -6735,7 +6779,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
        uint32 version;
        fstring *list = NULL;
        NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
+       DRIVER_INFO_2 *driver_info_2=NULL;
        WERROR result = WERR_OK;
 
        *returned=0;
@@ -6745,17 +6789,17 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
                ndrivers=get_ntdrivers(&list, architecture, version);
                DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
 
-               if(ndrivers == -1)
+               if(ndrivers == -1) {
+                       SAFE_FREE(driver_info_2);
                        return WERR_NOMEM;
+               }
 
                if(ndrivers != 0) {
-                       if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
+                       if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
                                DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
-                               SAFE_FREE(driver_info_2);
                                SAFE_FREE(list);
                                return WERR_NOMEM;
                        }
-                       else driver_info_2 = tdi2;
                }
                
                for (i=0; i<ndrivers; i++) {
@@ -6767,6 +6811,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
                                                      architecture, version);
                        if (!W_ERROR_IS_OK(status)) {
                                SAFE_FREE(list);
+                               SAFE_FREE(driver_info_2);
                                return status;
                        }
                        fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
@@ -6818,8 +6863,8 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
        int ndrivers;
        uint32 version;
        fstring *list = NULL;
+       DRIVER_INFO_3 *driver_info_3=NULL;
        NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
        WERROR result = WERR_OK;
 
        *returned=0;
@@ -6829,17 +6874,17 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
                ndrivers=get_ntdrivers(&list, architecture, version);
                DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
 
-               if(ndrivers == -1)
+               if(ndrivers == -1) {
+                       SAFE_FREE(driver_info_3);
                        return WERR_NOMEM;
+               }
 
                if(ndrivers != 0) {
-                       if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
+                       if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
                                DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
-                               SAFE_FREE(driver_info_3);
                                SAFE_FREE(list);
                                return WERR_NOMEM;
                        }
-                       else driver_info_3 = tdi3;
                }
 
                for (i=0; i<ndrivers; i++) {
@@ -6851,6 +6896,7 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
                                                      architecture, version);
                        if (!W_ERROR_IS_OK(status)) {
                                SAFE_FREE(list);
+                               SAFE_FREE(driver_info_3);
                                return status;
                        }
                        fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
@@ -6884,8 +6930,9 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
        }
 
 out:
-       for (i=0; i<*returned; i++)
+       for (i=0; i<*returned; i++) {
                SAFE_FREE(driver_info_3[i].dependentfiles);
+       }
 
        SAFE_FREE(driver_info_3);
        
@@ -6912,11 +6959,13 @@ WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(4,("_spoolss_enumprinterdrivers\n"));
        
        *needed   = 0;
@@ -6975,11 +7024,13 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0) ) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(4,("_spoolss_enumforms\n"));
        DEBUGADD(5,("Offered buffer size [%d]\n", offered));
        DEBUGADD(5,("Info level [%d]\n",          level));
@@ -6990,12 +7041,17 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
        DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
        *numofforms += numbuiltinforms;
 
-       if (*numofforms == 0) 
+       if (*numofforms == 0) {
+               SAFE_FREE(builtinlist);
+               SAFE_FREE(list);
                return WERR_NO_MORE_ITEMS;
+       }
 
        switch (level) {
        case 1:
                if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
+                       SAFE_FREE(builtinlist);
+                       SAFE_FREE(list);
                        *numofforms=0;
                        return WERR_NOMEM;
                }
@@ -7058,7 +7114,6 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
                SAFE_FREE(builtinlist);
                return WERR_UNKNOWN_LEVEL;
        }
-
 }
 
 /****************************************************************************
@@ -7082,11 +7137,13 @@ WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
 
        DEBUG(4,("_spoolss_getform\n"));
@@ -7183,6 +7240,8 @@ WERROR enumports_hook( int *count, char ***lines )
        int ret;
        int fd;
 
+       *count = 0;
+       *lines = NULL;
 
        /* if no hook then just fill in the default port */
        
@@ -7201,9 +7260,9 @@ WERROR enumports_hook( int *count, char ***lines )
                ret = smbrun(command, &fd);
                DEBUG(10,("Returned [%d]\n", ret));
                if (ret != 0) {
-                       if (fd != -1)
+                       if (fd != -1) {
                                close(fd);
-                       
+                       }
                        return WERR_ACCESS_DENIED;
                }
 
@@ -7228,11 +7287,14 @@ static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *need
        PORT_INFO_1 *ports=NULL;
        int i=0;
        WERROR result = WERR_OK;
-       char **qlines;
-       int numlines;
+       char **qlines = NULL;
+       int numlines = 0;
 
-       if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) ) 
+       result = enumports_hook( &numlines, &qlines );
+       if (!W_ERROR_IS_OK(result)) {
+               file_lines_free(qlines);
                return result;
+       }
        
        if(numlines) {
                if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
@@ -7246,9 +7308,8 @@ static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *need
                        DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
                        fill_port_1(&ports[i], qlines[i]);
                }
-
-               file_lines_free(qlines);
        }
+       file_lines_free(qlines);
 
        *returned = numlines;
 
@@ -7292,12 +7353,14 @@ static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *need
        PORT_INFO_2 *ports=NULL;
        int i=0;
        WERROR result = WERR_OK;
-       char **qlines;
-       int numlines;
+       char **qlines = NULL;
+       int numlines = 0;
 
-       if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) ) 
+       result = enumports_hook( &numlines, &qlines );
+       if ( !W_ERROR_IS_OK(result)) {
+               file_lines_free(qlines);
                return result;
-       
+       }
        
        if(numlines) {
                if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
@@ -7309,10 +7372,10 @@ static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *need
                        DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
                        fill_port_2(&(ports[i]), qlines[i]);
                }
-
-               file_lines_free(qlines);
        }
 
+       file_lines_free(qlines);
+
        *returned = numlines;
 
        /* check the required size. */
@@ -7360,11 +7423,13 @@ WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUM
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(4,("_spoolss_enumports\n"));
        
        *returned=0;
@@ -7534,26 +7599,23 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
        SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
        WERROR err = WERR_OK;
        NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       struct current_user user;
        fstring driver_name;
        uint32 version;
 
        ZERO_STRUCT(driver);
 
-       get_current_user(&user, p);
-       
        if (!convert_printer_driver_info(info, &driver, level)) {
                err = WERR_NOMEM;
                goto done;
        }
 
        DEBUG(5,("Cleaning driver's information\n"));
-       err = clean_up_driver_struct(driver, level, &user);
+       err = clean_up_driver_struct(driver, level, &p->pipe_user);
        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(driver, level, &user, &err)) ) {
+       if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
                goto done;
        }
 
@@ -7562,21 +7624,6 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
                goto done;
        }
 
-       /* BEGIN_ADMIN_LOG */
-        switch(level) {
-           case 3:
-               fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
-               sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
-                       driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
-               break;
-           case 6:   
-               fstrcpy(driver_name, driver.info_6->name ?  driver.info_6->name : "");
-               sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
-                       driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
-               break;
-        }
-       /* END_ADMIN_LOG */
-
        /* 
         * I think this is where he DrvUpgradePrinter() hook would be
         * be called in a driver's interface DLL on a Windows NT 4.0/2k
@@ -7768,11 +7815,13 @@ WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRI
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
 
        *needed=0;
@@ -7939,7 +7988,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
                        goto done;
                }
        
-               *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
+               *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
 
                /* type */
                
@@ -8378,11 +8427,13 @@ WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(5,("spoolss_enumprintprocessors\n"));
 
        /*
@@ -8455,11 +8506,13 @@ WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDAT
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
        
        *returned=0;
@@ -8581,11 +8634,13 @@ WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(5,("spoolss_enumprintmonitors\n"));
 
        /*
@@ -8700,7 +8755,7 @@ static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
         */
         
        if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
-               devmode = construct_dev_mode(snum);
+               devmode = construct_dev_mode(lp_const_servicename(snum));
        else {
                if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
                        ZERO_STRUCTP( devmode );
@@ -8755,11 +8810,13 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(5,("spoolss_getjob\n"));
        
        *needed = 0;
@@ -9375,11 +9432,13 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
 
        /* that's an [in out] buffer */
 
-       if ( q_u->buffer ) {
-               rpcbuf_move(q_u->buffer, &r_u->buffer);
-               buffer = r_u->buffer;
+       if (!q_u->buffer && (offered!=0)) {
+               return WERR_INVALID_PARAM;
        }
 
+       rpcbuf_move(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
        DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
        
        *needed=0;
@@ -9400,7 +9459,8 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
  Streams the monitor UI DLL name in UNICODE
 *******************************************************************/
 
-static WERROR xcvtcp_monitorui( RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed )
+static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in, 
+                                RPC_BUFFER *out, uint32 *needed )
 {
        const char *dllname = "tcpmonui.dll";
        
@@ -9417,16 +9477,54 @@ static WERROR xcvtcp_monitorui( RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed
        return WERR_OK;
 }
 
+/*******************************************************************
+ Create a new TCP/IP port
+*******************************************************************/
+
+static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in, 
+                              RPC_BUFFER *out, uint32 *needed )
+{
+       NT_PORT_DATA_1 port1;
+       pstring device_uri;
+
+       ZERO_STRUCT( port1 );
+
+       /* convert to our internal port data structure */
+
+       if ( !convert_port_data_1( &port1, in ) ) {
+               return WERR_NOMEM;
+       }
+
+       /* create the device URI and call the add_port_hook() */
+
+       switch ( port1.protocol ) {
+       case PORT_PROTOCOL_DIRECT:
+               pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
+               break;
+
+       case PORT_PROTOCOL_LPR:
+               pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
+               break;
+       
+       default:
+               return WERR_UNKNOWN_PORT;
+       }
+
+       return add_port_hook( token, port1.name, device_uri );
+}
+
 /*******************************************************************
 *******************************************************************/
 
 struct xcv_api_table xcvtcp_cmds[] = {
        { "MonitorUI",  xcvtcp_monitorui },
+       { "AddPort",    xcvtcp_addport},
        { NULL,         NULL }
 };
 
-static WERROR process_xcvtcp_command( const char *command, RPC_BUFFER *inbuf,
-                                        RPC_BUFFER *outbuf, uint32 *needed )
+static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command, 
+                                      RPC_BUFFER *inbuf, RPC_BUFFER *outbuf, 
+                                      uint32 *needed )
 {
        int i;
        
@@ -9434,7 +9532,7 @@ static WERROR process_xcvtcp_command( const char *command, RPC_BUFFER *inbuf,
        
        for ( i=0; xcvtcp_cmds[i].name; i++ ) {
                if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
-                       return xcvtcp_cmds[i].fn( inbuf, outbuf, needed );
+                       return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
        }
        
        return WERR_BADFUNC;
@@ -9442,8 +9540,10 @@ static WERROR process_xcvtcp_command( const char *command, RPC_BUFFER *inbuf,
 
 /*******************************************************************
 *******************************************************************/
+#if 0  /* don't support management using the "Local Port" monitor */
 
-static WERROR xcvlocal_monitorui( RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed )
+static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in, 
+                                  RPC_BUFFER *out, uint32 *needed )
 {
        const char *dllname = "localui.dll";
        
@@ -9467,22 +9567,28 @@ struct xcv_api_table xcvlocal_cmds[] = {
        { "MonitorUI",  xcvlocal_monitorui },
        { NULL,         NULL }
 };
+#else
+struct xcv_api_table xcvlocal_cmds[] = {
+       { NULL,         NULL }
+};
+#endif
+
 
 
 /*******************************************************************
 *******************************************************************/
 
-static WERROR process_xcvlocal_command( const char *command, RPC_BUFFER *inbuf, 
-                                        RPC_BUFFER *outbuf, uint32 *needed )
+static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command, 
+                                        RPC_BUFFER *inbuf, RPC_BUFFER *outbuf, 
+                                       uint32 *needed )
 {
        int i;
        
        DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
-       
 
        for ( i=0; xcvlocal_cmds[i].name; i++ ) {
                if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
-                       return xcvlocal_cmds[i].fn( inbuf, outbuf , needed );
+                       return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
        }
        return WERR_BADFUNC;
 }
@@ -9526,9 +9632,11 @@ WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_X
        
        switch ( Printer->printer_type ) {
        case SPLHND_PORTMON_TCP:
-               return process_xcvtcp_command( command, &q_u->indata, &r_u->outdata, &r_u->needed );
+               return process_xcvtcp_command( p->pipe_user.nt_user_token, command, 
+                       &q_u->indata, &r_u->outdata, &r_u->needed );
        case SPLHND_PORTMON_LOCAL:
-               return process_xcvlocal_command( command, &q_u->indata, &r_u->outdata, &r_u->needed );
+               return process_xcvlocal_command( p->pipe_user.nt_user_token, command, 
+                       &q_u->indata, &r_u->outdata, &r_u->needed );
        }
 
        return WERR_INVALID_PRINT_MONITOR;