r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need
[vlendec/samba-autobuild/.git] / source3 / rpc_server / srv_spoolss_nt.c
index dd706b68edd5cf0f405c347962a10647c7e6879d..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;
@@ -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
@@ -4076,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;
@@ -4085,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 ) {
@@ -4157,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;
@@ -4626,7 +4614,7 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_
        
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -4941,7 +4929,7 @@ WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GET
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -5540,7 +5528,7 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -5643,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
@@ -5675,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. */
@@ -5748,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;
@@ -5765,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;
@@ -5798,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) {
@@ -5809,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;
 }
@@ -5892,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;
@@ -6017,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,
@@ -6278,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));
 
@@ -6379,7 +6370,7 @@ 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) {
+       if (!q_u->buffer && (q_u->offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -6537,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);
@@ -6594,7 +6585,7 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -6657,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;
                
@@ -6669,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;
@@ -6717,8 +6705,10 @@ 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((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
@@ -6799,8 +6789,10 @@ 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((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
@@ -6871,8 +6863,8 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
        int ndrivers;
        uint32 version;
        fstring *list = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
        DRIVER_INFO_3 *driver_info_3=NULL;
+       NT_PRINTER_DRIVER_INFO_LEVEL driver;
        WERROR result = WERR_OK;
 
        *returned=0;
@@ -6882,8 +6874,10 @@ 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((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
@@ -6936,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);
        
@@ -6964,7 +6959,7 @@ WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -7029,7 +7024,7 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0) ) {
                return WERR_INVALID_PARAM;
        }
 
@@ -7142,7 +7137,7 @@ WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -7428,7 +7423,7 @@ WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUM
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -7604,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;
        }
 
@@ -7632,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
@@ -7838,7 +7815,7 @@ WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRI
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer ) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -8011,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 */
                
@@ -8450,7 +8427,7 @@ WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -8529,7 +8506,7 @@ WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDAT
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -8657,7 +8634,7 @@ WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -8778,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 );
@@ -8833,7 +8810,7 @@ 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) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }
 
@@ -9455,7 +9432,7 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer) {
+       if (!q_u->buffer && (offered!=0)) {
                return WERR_INVALID_PARAM;
        }