Round and round we go....
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
index 2a412ccc98b1f80a77c7e4889656699e188e41b1..adc954653058339b60857b75b10317243390a035 100644 (file)
@@ -5,7 +5,9 @@
  *  Copyright (C) Andrew Tridgell              1992-2000,
  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
  *  Copyright (C) Jean François Micouleau      1998-2000.
- *  Copyright (C) Jeremy Allison                                       2001.
+ *  Copyright (C) Jeremy Allison                   2001.
+ *  Copyright (C) Gerald Carter                       2000-2001.
+ *  Copyright (C) Tim Potter                       2001.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -27,9 +29,6 @@
 
 #include "includes.h"
 
-extern int DEBUGLEVEL;
-extern pstring global_myname;
-
 #ifndef MAX_OPEN_PRINTER_EXS
 #define MAX_OPEN_PRINTER_EXS 50
 #endif
@@ -141,17 +140,11 @@ static int nt_printq_status(int v)
 
 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
 {
-       SPOOL_NOTIFY_OPTION *sp = *pp;
-
-       *pp = NULL;
-
-       if (!sp)
+       if (*pp == NULL)
                return;
 
-       if (sp->ctr.type)
-               safe_free(sp->ctr.type);
-
-       free(sp);
+       SAFE_FREE((*pp)->ctr.type);
+       SAFE_FREE(*pp);
 }
 
 /***************************************************************************
@@ -201,7 +194,7 @@ static void free_printer_entry(void *ptr)
        Printer->notify.option=NULL;
        Printer->notify.client_connected=False;
 
-       safe_free(Printer);
+       SAFE_FREE(Printer);
 }
 
 /****************************************************************************
@@ -225,7 +218,7 @@ SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
                new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
 
                if (!new_sp->ctr.type) {
-                       safe_free(new_sp);
+                       SAFE_FREE(new_sp);
                        return NULL;
                }
        }
@@ -541,7 +534,7 @@ static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
        new_printer->notify.option=NULL;
                                
        if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
-               safe_free(new_printer);
+               SAFE_FREE(new_printer);
                return False;
        }
 
@@ -695,7 +688,7 @@ static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
        /*srv_spoolss_receive_message(printer);*/
        DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
 
-       message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
+       broadcast_printer_notify(printer);
 
        return True;
 }      
@@ -810,6 +803,7 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                /* map an empty access mask to the minimum access mask */
                if (printer_default->access_required == 0x0)
                        printer_default->access_required = PRINTER_ACCESS_USE;
+               
 
                /*
                 * If we are not serving the printer driver for this printer,
@@ -913,15 +907,17 @@ 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;
+
        switch (level) {
                case 2:
-                       uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
+                       ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
                        break;
                default:
                        break;
        }
 
-       return True;
+       return ret;
 }
 
 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
@@ -1005,7 +1001,7 @@ BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
         */
 
        if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
-               safe_free(nt_devmode->private);
+               SAFE_FREE(nt_devmode->private);
                nt_devmode->driverextra=devmode->driverextra;
                if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
                        return False;
@@ -1137,6 +1133,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
        
        /* check that we have a valid driver name first */
        if ((version=get_version_id(arch)) == -1) {
+               /* this is what NT returns */
                return WERR_INVALID_ENVIRONMENT;
        }
                
@@ -1284,7 +1281,7 @@ static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND
        
        DEBUG(5,("getprinterdata_printer:copy done\n"));
                        
-       safe_free(idata);
+       SAFE_FREE(idata);
        
        return True;
 }      
@@ -1323,7 +1320,7 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO
        DEBUG(4,("_spoolss_getprinterdata\n"));
        
        if (!Printer) {
-               if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
+               if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
                        return WERR_NOMEM;
                DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
@@ -1351,9 +1348,8 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO
        
        if (*needed > *out_size)
                return WERR_STATUS_MORE_ENTRIES;
-       else {
+       else 
                return WERR_OK;
-    }
 }
 
 /***************************************************************************
@@ -1449,11 +1445,11 @@ static void spoolss_notify_server_name(int snum,
        pstring temp_name, temp;
        uint32 len;
 
-       slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
+       slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
 
-       len = rpcstr_push(temp, temp_name, sizeof(temp)-2, 0);
+       len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
 
        if (!data->notify_data.data.string) {
@@ -1485,8 +1481,8 @@ static void spoolss_notify_printer_name(int snum,
                p++;
        }
 
-       len = rpcstr_push(temp, p, sizeof(temp)-2, 0);
-       data->notify_data.data.length = len / 2 - 1;
+       len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1509,9 +1505,9 @@ static void spoolss_notify_share_name(int snum,
        pstring temp;
        uint32 len;
 
-       len = rpcstr_push(temp, lp_servicename(snum),  sizeof(temp) - 2, 0);
+       len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1536,9 +1532,9 @@ static void spoolss_notify_port_name(int snum,
 
        /* even if it's strange, that's consistant in all the code */
 
-       len = rpcstr_push(temp, printer->info_2->portname,  sizeof(temp) - 2, 0);
+       len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1563,8 +1559,8 @@ static void spoolss_notify_driver_name(int snum,
        pstring temp;
        uint32 len;
 
-       len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp) - 2, 0);
-       data->notify_data.data.length = len / 2 - 1;
+       len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1588,12 +1584,12 @@ static void spoolss_notify_comment(int snum,
        uint32 len;
 
        if (*printer->info_2->comment == '\0')
-               len = rpcstr_push(temp, lp_comment(snum), sizeof(temp) - 2, 0);
+               len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
 
        else
-               len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp) - 2, 0);
+               len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1618,9 +1614,9 @@ static void spoolss_notify_location(int snum,
        pstring temp;
        uint32 len;
 
-       len = rpcstr_push(temp, printer->info_2->location,sizeof(temp) - 2, 0);
+       len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1657,9 +1653,9 @@ static void spoolss_notify_sepfile(int snum,
        pstring temp;
        uint32 len;
 
-       len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp) - 2, 0);
+       len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1683,9 +1679,9 @@ static void spoolss_notify_print_processor(int snum,
        pstring temp;
        uint32 len;
 
-       len = rpcstr_push(temp,  printer->info_2->printprocessor, sizeof(temp) - 2, 0);
+       len = rpcstr_push(temp,  printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1709,10 +1705,9 @@ static void spoolss_notify_parameters(int snum,
        pstring temp;
        uint32 len;
 
-       len = rpcstr_push(temp,  printer->info_2->parameters, sizeof(temp) -
-                        2, 0);
+       len = rpcstr_push(temp,  printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1736,9 +1731,9 @@ static void spoolss_notify_datatype(int snum,
        pstring temp;
        uint32 len;
 
-       len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, 0);
+       len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1775,6 +1770,7 @@ static void spoolss_notify_attributes(int snum,
                                      TALLOC_CTX *mem_ctx)
 {
        data->notify_data.value[0] = printer->info_2->attributes;
+       data->notify_data.value[1] = 0;
 }
 
 /*******************************************************************
@@ -1787,6 +1783,7 @@ static void spoolss_notify_priority(int snum,
                                    TALLOC_CTX *mem_ctx)
 {
        data->notify_data.value[0] = printer->info_2->priority;
+       data->notify_data.value[1] = 0;
 }
 
 /*******************************************************************
@@ -1799,6 +1796,7 @@ static void spoolss_notify_default_priority(int snum,
                                            TALLOC_CTX *mem_ctx)
 {
        data->notify_data.value[0] = printer->info_2->default_priority;
+       data->notify_data.value[1] = 0;
 }
 
 /*******************************************************************
@@ -1811,6 +1809,7 @@ static void spoolss_notify_start_time(int snum,
                                      TALLOC_CTX *mem_ctx)
 {
        data->notify_data.value[0] = printer->info_2->starttime;
+       data->notify_data.value[1] = 0;
 }
 
 /*******************************************************************
@@ -1823,6 +1822,7 @@ static void spoolss_notify_until_time(int snum,
                                      TALLOC_CTX *mem_ctx)
 {
        data->notify_data.value[0] = printer->info_2->untiltime;
+       data->notify_data.value[1] = 0;
 }
 
 /*******************************************************************
@@ -1834,13 +1834,11 @@ static void spoolss_notify_status(int snum,
                                  NT_PRINTER_INFO_LEVEL *printer,
                                  TALLOC_CTX *mem_ctx)
 {
-       print_queue_struct *q=NULL;
        print_status_struct status;
 
-       memset(&status, 0, sizeof(status));
-       print_queue_status(snum, &q, &status);
+       print_queue_length(snum, &status);
        data->notify_data.value[0]=(uint32) status.status;
-       safe_free(q);
+       data->notify_data.value[1] = 0;
 }
 
 /*******************************************************************
@@ -1852,12 +1850,8 @@ static void spoolss_notify_cjobs(int snum,
                                 NT_PRINTER_INFO_LEVEL *printer, 
                                 TALLOC_CTX *mem_ctx)
 {
-       print_queue_struct *q=NULL;
-       print_status_struct status;
-
-       memset(&status, 0, sizeof(status));
-       data->notify_data.value[0] = print_queue_status(snum, &q, &status);
-       safe_free(q);
+       data->notify_data.value[0] = print_queue_length(snum, NULL);
+       data->notify_data.value[1] = 0;
 }
 
 /*******************************************************************
@@ -1872,6 +1866,7 @@ static void spoolss_notify_average_ppm(int snum,
        /* always respond 8 pages per minutes */
        /* a little hard ! */
        data->notify_data.value[0] = printer->info_2->averageppm;
+       data->notify_data.value[1] = 0;
 }
 
 /*******************************************************************
@@ -1886,10 +1881,10 @@ static void spoolss_notify_username(int snum,
        pstring temp;
        uint32 len;
 
-       len = rpcstr_push(temp, queue->user, sizeof(temp) - 2, 0);
+       len = rpcstr_push(temp, queue->user, sizeof(temp)-2, STR_TERMINATE);
 
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1910,6 +1905,7 @@ static void spoolss_notify_job_status(int snum,
                                      TALLOC_CTX *mem_ctx)
 {
        data->notify_data.value[0]=nt_printj_status(queue->status);
+       data->notify_data.value[1] = 0;
 }
 
 /*******************************************************************
@@ -1924,9 +1920,9 @@ static void spoolss_notify_job_name(int snum,
        pstring temp;
        uint32 len;
 
-       len = rpcstr_push(temp, queue->file, sizeof(temp) - 2, 0);
+       len = rpcstr_push(temp, queue->file, sizeof(temp)-2, STR_TERMINATE);
        
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1973,9 +1969,9 @@ static void spoolss_notify_job_status_string(int snum,
        }
 #endif /* NO LONGER NEEDED. */
 
-       len = rpcstr_push(temp, p, sizeof(temp) - 2, 0);
+       len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
 
-       data->notify_data.data.length = len / 2 - 1;
+       data->notify_data.data.length = len / 2;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
        
        if (!data->notify_data.data.string) {
@@ -1996,6 +1992,7 @@ static void spoolss_notify_job_time(int snum,
                                    TALLOC_CTX *mem_ctx)
 {
        data->notify_data.value[0]=0x0;
+       data->notify_data.value[1]=0;
 }
 
 /*******************************************************************
@@ -2008,6 +2005,7 @@ static void spoolss_notify_job_size(int snum,
                                    TALLOC_CTX *mem_ctx)
 {
        data->notify_data.value[0]=queue->size;
+       data->notify_data.value[1]=0;
 }
 
 /*******************************************************************
@@ -2020,6 +2018,7 @@ static void spoolss_notify_job_position(int snum,
                                        TALLOC_CTX *mem_ctx)
 {
        data->notify_data.value[0]=queue->job;
+       data->notify_data.value[1]=0;
 }
 
 /*******************************************************************
@@ -2039,7 +2038,7 @@ static void spoolss_notify_submitted_time(int snum,
 
        len = sizeof(SYSTEMTIME);
 
-       data->notify_data.data.length = len/2 - 1;
+       data->notify_data.data.length = len;
        data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
 
        if (!data->notify_data.data.string) {
@@ -2231,13 +2230,13 @@ static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
 
                if (!search_notify(type, field, &j) )
                        continue;
-               
+
                if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
                        DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
                        return False;
                }
                else info->data = tid;
-               
+
                current_data=&info->data[info->count];
 
                construct_info_data(current_data, type, field, id);             
@@ -2427,7 +2426,6 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY
                case JOB_NOTIFY_TYPE: {
                        NT_PRINTER_INFO_LEVEL *printer = NULL;
 
-                       memset(&status, 0, sizeof(status));     
                        count = print_queue_status(snum, &queue, &status);
 
                        if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, 
@@ -2445,7 +2443,7 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY
                        free_a_printer(&printer, 2);
                        
                done:
-                       safe_free(queue);
+                       SAFE_FREE(queue);
                        break;
                }
                }
@@ -2533,16 +2531,12 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
        uint32 global_counter;
        struct tm *t;
        time_t setuptime;
-
-       print_queue_struct *queue=NULL;
        print_status_struct status;
        
-       memset(&status, 0, sizeof(status));     
-
        if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
                return False;
 
-       count = print_queue_status(snum, &queue, &status);
+       count = print_queue_length(snum, &status);
 
        /* check if we already have a counter for this printer */       
        session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
@@ -2577,7 +2571,7 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
 
        init_unistr(&printer->printername, chaine);
        
-       slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
+       slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
        init_unistr(&printer->servername, chaine);
        
        printer->cjobs = count;
@@ -2624,7 +2618,6 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
        printer->unknown28 = 0;
        printer->unknown29 = 0;
        
-       safe_free(queue);
        free_a_printer(&ntprinter,2);
        return (True);  
 }
@@ -2646,12 +2639,12 @@ static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int
 
        if (*ntprinter->info_2->comment == '\0') {
                init_unistr(&printer->comment, lp_comment(snum));
-               slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
+               slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
                        ntprinter->info_2->drivername, lp_comment(snum));
        }
        else {
                init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
-               slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
+               slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",get_called_name(), ntprinter->info_2->printername,
                        ntprinter->info_2->drivername, ntprinter->info_2->comment);
        }
                
@@ -2674,10 +2667,8 @@ static void free_dev_mode(DEVICEMODE *dev)
        if (dev == NULL)
                return;
 
-       if (dev->private)
-               safe_free(dev->private);
-
-       safe_free(dev); 
+       SAFE_FREE(dev->private);
+       SAFE_FREE(dev); 
 }
 
 /****************************************************************************
@@ -2775,15 +2766,12 @@ static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
        int count;
        NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
 
-       print_queue_struct *queue=NULL;
        print_status_struct status;
-       memset(&status, 0, sizeof(status));     
 
        if (!W_ERROR_IS_OK(get_a_printer(&ntprinter, 2, lp_servicename(snum))))
                return False;
                
-       memset(&status, 0, sizeof(status));             
-       count = print_queue_status(snum, &queue, &status);
+       count = print_queue_length(snum, &status);
 
        init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
        init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
@@ -2828,7 +2816,6 @@ static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
        }
 
        free_a_printer(&ntprinter, 2);
-       safe_free(queue);
        return True;
 }
 
@@ -2906,7 +2893,7 @@ static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32
                        if (construct_printer_info_1(flags, &current_prt, snum)) {
                                if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
                                        DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
-                                       safe_free(printers);
+                                       SAFE_FREE(printers);
                                        *returned=0;
                                        return WERR_NOMEM;
                                }
@@ -2930,7 +2917,7 @@ static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32
                smb_io_printer_info_1("", buffer, &printers[i], 0);     
 
        /* clear memory */
-       safe_free(printers);
+       SAFE_FREE(printers);
 
        if (*needed > offered) {
                *returned=0;
@@ -2955,13 +2942,14 @@ static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered,
 *********************************************************************/
 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
 {
-       fstring temp;
+       char *s = name;
+       
        DEBUG(4,("enum_all_printers_info_1_name\n"));   
        
-       fstrcpy(temp, "\\\\");
-       fstrcat(temp, global_myname);
+       if ((name[0] == '\\') && (name[1] == '\\'))
+               s = name + 2;
 
-       if (strequal(name, temp)) {
+       if (is_myname_or_ipaddr(s)) {
                return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
        }
        else
@@ -2991,8 +2979,8 @@ static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer,
 
        *returned=1;
        
-       slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);               
-       slprintf(desc, sizeof(desc)-1,"%s", global_myname);
+       slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());           
+       slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
        slprintf(comment, sizeof(comment)-1, "Logged on Domain");
 
        init_unistr(&printer->description, desc);
@@ -3004,7 +2992,7 @@ static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer,
        *needed += spoolss_size_printer_info_1(printer);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(printer);
+               SAFE_FREE(printer);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -3012,7 +3000,7 @@ static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer,
        smb_io_printer_info_1("", buffer, printer, 0);  
 
        /* clear memory */
-       safe_free(printer);
+       SAFE_FREE(printer);
 
        if (*needed > offered) {
                *returned=0;
@@ -3054,7 +3042,7 @@ static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint3
                        if (construct_printer_info_2(&current_prt, snum)) {
                                if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
                                        DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
-                                       safe_free(printers);
+                                       SAFE_FREE(printers);
                                        *returned = 0;
                                        return WERR_NOMEM;
                                }
@@ -3074,7 +3062,7 @@ static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint3
                for (i=0; i<*returned; i++) {
                        free_devmode(printers[i].devmode);
                }
-               safe_free(printers);
+               SAFE_FREE(printers);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -3086,7 +3074,7 @@ static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint3
        for (i=0; i<*returned; i++) {
                free_devmode(printers[i].devmode);
        }
-       safe_free(printers);
+       SAFE_FREE(printers);
 
        if (*needed > offered) {
                *returned=0;
@@ -3127,20 +3115,16 @@ static WERROR enumprinters_level2( uint32 flags, fstring servername,
                                 NEW_BUFFER *buffer, uint32 offered,
                                 uint32 *needed, uint32 *returned)
 {
-       fstring temp;
-       
-       fstrcpy(temp, "\\\\");
-       fstrcat(temp, global_myname);
+       char *s = servername;
 
        if (flags & PRINTER_ENUM_LOCAL) {
-               if (strequal(servername, temp))
-                       return enum_all_printers_info_2(buffer, offered, needed, returned);
-               else
                        return enum_all_printers_info_2(buffer, offered, needed, returned);
        }
 
        if (flags & PRINTER_ENUM_NAME) {
-               if (strequal(servername, temp))
+               if ((servername[0] == '\\') && (servername[1] == '\\'))
+                       s = servername + 2;
+               if (is_myname_or_ipaddr(s))
                        return enum_all_printers_info_2(buffer, offered, needed, returned);
                else
                        return WERR_INVALID_NAME;
@@ -3178,6 +3162,7 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_
        uint32 offered = q_u->offered;
        uint32 *needed = &r_u->needed;
        uint32 *returned = &r_u->returned;
+
        fstring name;
        
        /* that's an [in out] buffer */
@@ -3234,7 +3219,7 @@ static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, u
        *needed += spoolss_size_printer_info_0(printer);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(printer);
+               SAFE_FREE(printer);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -3242,7 +3227,7 @@ static WERROR getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, u
        smb_io_printer_info_0("", buffer, printer, 0);  
        
        /* clear memory */
-       safe_free(printer);
+       SAFE_FREE(printer);
 
        if (*needed > offered) {
                return WERR_INSUFFICIENT_BUFFER;
@@ -3266,7 +3251,7 @@ static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, u
        *needed += spoolss_size_printer_info_1(printer);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(printer);
+               SAFE_FREE(printer);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -3274,7 +3259,7 @@ static WERROR getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, u
        smb_io_printer_info_1("", buffer, printer, 0);  
        
        /* clear memory */
-       safe_free(printer);
+       SAFE_FREE(printer);
 
        if (*needed > offered) {
                return WERR_INSUFFICIENT_BUFFER;
@@ -3704,7 +3689,7 @@ static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fst
 
 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
 {
-       safe_free(info->dependentfiles);
+       SAFE_FREE(info->dependentfiles);
 }
 
 /****************************************************************************
@@ -3712,7 +3697,7 @@ static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
 
 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
 {
-       safe_free(info->dependentfiles);
+       SAFE_FREE(info->dependentfiles);
        
 }
 
@@ -3728,7 +3713,7 @@ static WERROR getprinterdriver2_level1(fstring servername, fstring architecture,
        
        status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
        if (!W_ERROR_IS_OK(status)) {
-               safe_free(info);
+               SAFE_FREE(info);
                return status;
        }
 
@@ -3736,7 +3721,7 @@ static WERROR getprinterdriver2_level1(fstring servername, fstring architecture,
        *needed += spoolss_size_printer_driver_info_1(info);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(info);
+               SAFE_FREE(info);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -3744,7 +3729,7 @@ static WERROR getprinterdriver2_level1(fstring servername, fstring architecture,
        smb_io_printer_driver_info_1("", buffer, info, 0);      
 
        /* clear memory */
-       safe_free(info);
+       SAFE_FREE(info);
 
        if (*needed > offered)
                return WERR_INSUFFICIENT_BUFFER;
@@ -3764,7 +3749,7 @@ static WERROR getprinterdriver2_level2(fstring servername, fstring architecture,
        
        status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
        if (!W_ERROR_IS_OK(status)) {
-               safe_free(info);
+               SAFE_FREE(info);
                return status;
        }
 
@@ -3772,7 +3757,7 @@ static WERROR getprinterdriver2_level2(fstring servername, fstring architecture,
        *needed += spoolss_size_printer_driver_info_2(info);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(info);
+               SAFE_FREE(info);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -3780,7 +3765,7 @@ static WERROR getprinterdriver2_level2(fstring servername, fstring architecture,
        smb_io_printer_driver_info_2("", buffer, info, 0);      
 
        /* clear memory */
-       safe_free(info);
+       SAFE_FREE(info);
 
        if (*needed > offered)
                return WERR_INSUFFICIENT_BUFFER;
@@ -3884,7 +3869,7 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_
        *servermajorversion=0;
        *serverminorversion=0;
 
-       pstrcpy(servername, global_myname);
+       pstrcpy(servername, get_called_name());
        unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
 
        if (!get_printer_snum(p, handle, &snum))
@@ -3900,6 +3885,7 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_
        case 6:
                return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
        }
+
        return WERR_UNKNOWN_LEVEL;
 }
 
@@ -4147,7 +4133,7 @@ static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
                for (i = 0; i < the_acl->num_aces; i++) {
                        fstring sid_str;
 
-                       sid_to_string(sid_str, &the_acl->ace[i].sid);
+                       sid_to_string(sid_str, &the_acl->ace[i].trustee);
 
                        DEBUG(10, ("%s 0x%08x\n", sid_str, 
                                  the_acl->ace[i].info.mask));
@@ -4162,7 +4148,7 @@ static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
                        for (i = 0; i < the_acl->num_aces; i++) {
                                fstring sid_str;
                                
-                               sid_to_string(sid_str, &the_acl->ace[i].sid);
+                               sid_to_string(sid_str, &the_acl->ace[i].trustee);
                                
                                DEBUG(10, ("%s 0x%08x\n", sid_str, 
                                           the_acl->ace[i].info.mask));
@@ -4212,9 +4198,9 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
                 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
 
        /* we force some elements to "correct" values */
-       slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
+       slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
        slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
-                global_myname, lp_servicename(snum));
+                get_called_name(), lp_servicename(snum));
        fstrcpy(info->sharename, lp_servicename(snum));
        info->attributes = PRINTER_ATTRIBUTE_SHARED   \
                | PRINTER_ATTRIBUTE_LOCAL  \
@@ -4238,7 +4224,7 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
 
        /* build driver path... only 9X architecture is needed for legacy reasons */
        slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
-                       global_myname);
+                       get_called_name());
        /* change \ to \\ for the shell */
        all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
 
@@ -4566,7 +4552,10 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
         * just read from the tdb in the pointer 'printer'.
         */
 
-       convert_printer_info(info, printer, level);
+       if (!convert_printer_info(info, printer, level)) {
+               result =  WERR_NOMEM;
+               goto done;
+       }
 
        if (info->info_2->devmode_ptr != 0) {
                /* we have a valid devmode
@@ -4698,9 +4687,9 @@ WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u
 
        r_u->needed = 0;
        return WERR_INVALID_PARAM; /* this is what a NT server
-                                     returns for AddJob. AddJob
-                                     must fail on non-local
-                                     printers */
+                                           returns for AddJob. AddJob
+                                           must fail on non-local
+                                           printers */
 }
 
 /****************************************************************************
@@ -4713,7 +4702,7 @@ static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
        struct tm *t;
        
        t=gmtime(&queue->time);
-       slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
+       slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
 
        job_info->jobid=queue->job;     
        init_unistr(&job_info->printername, lp_servicename(snum));
@@ -4742,11 +4731,11 @@ static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
        struct tm *t;
 
        t=gmtime(&queue->time);
-       slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
+       slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
 
        job_info->jobid=queue->job;
        
-       slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
+       slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", get_called_name(), ntprinter->info_2->printername);
 
        init_unistr(&job_info->printername, chaine);
        
@@ -4792,7 +4781,7 @@ static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
        
        info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
        if (info==NULL) {
-               safe_free(queue);
+               SAFE_FREE(queue);
                *returned=0;
                return WERR_NOMEM;
        }
@@ -4800,14 +4789,14 @@ static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
        for (i=0; i<*returned; i++)
                fill_job_info_1(&info[i], &queue[i], i, snum);
 
-       safe_free(queue);
+       SAFE_FREE(queue);
 
        /* check the required size. */  
        for (i=0; i<*returned; i++)
                (*needed) += spoolss_size_job_info_1(&info[i]);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(info);
+               SAFE_FREE(info);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -4816,7 +4805,7 @@ static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
                smb_io_job_info_1("", buffer, &info[i], 0);     
 
        /* clear memory */
-       safe_free(info);
+       SAFE_FREE(info);
 
        if (*needed > offered) {
                *returned=0;
@@ -4854,14 +4843,14 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
                fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
 
        free_a_printer(&ntprinter, 2);
-       safe_free(queue);
+       SAFE_FREE(queue);
 
        /* check the required size. */  
        for (i=0; i<*returned; i++)
                (*needed) += spoolss_size_job_info_2(&info[i]);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(info);
+               SAFE_FREE(info);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -4873,7 +4862,7 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
        for (i = 0; i < *returned; i++)
                free_job_info_2(&info[i]);
 
-       free(info);
+       SAFE_FREE(info);
 
        if (*needed > offered) {
                *returned=0;
@@ -4899,8 +4888,8 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO
        uint32 *returned = &r_u->returned;
 
        int snum;
-       print_queue_struct *queue=NULL;
        print_status_struct prt_status;
+       print_queue_struct *queue=NULL;
 
        /* that's an [in out] buffer */
        spoolss_move_buffer(q_u->buffer, &r_u->buffer);
@@ -4908,8 +4897,6 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO
 
        DEBUG(4,("_spoolss_enumjobs\n"));
 
-       ZERO_STRUCT(prt_status);
-
        *needed=0;
        *returned=0;
 
@@ -4920,7 +4907,7 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO
        DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
 
        if (*returned == 0) {
-               safe_free(queue);
+               SAFE_FREE(queue);
                return WERR_OK;
        }
 
@@ -4930,7 +4917,7 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO
        case 2:
                return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
        default:
-               safe_free(queue);
+               SAFE_FREE(queue);
                *returned=0;
                return WERR_UNKNOWN_LEVEL;
        }
@@ -4956,12 +4943,9 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u
        uint32 command = q_u->command;
 
        struct current_user user;
-       print_status_struct prt_status;
        int snum;
        WERROR errcode = WERR_BADFUNC;
                
-       memset(&prt_status, 0, sizeof(prt_status));
-
        if (!get_printer_snum(p, handle, &snum)) {
                return WERR_BADFID;
        }
@@ -5006,6 +4990,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
        int ndrivers;
        uint32 version;
        fstring *list = NULL;
+
        NT_PRINTER_DRIVER_INFO_LEVEL driver;
        DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
 
@@ -5024,8 +5009,8 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
                if(ndrivers != 0) {
                        if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
                                DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
-                               safe_free(driver_info_1);
-                               safe_free(list);
+                               SAFE_FREE(driver_info_1);
+                               SAFE_FREE(list);
                                return WERR_NOMEM;
                        }
                        else driver_info_1 = tdi1;
@@ -5038,7 +5023,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
                        status = get_a_printer_driver(&driver, 3, list[i], 
                                                      architecture, version);
                        if (!W_ERROR_IS_OK(status)) {
-                               safe_free(list);
+                               SAFE_FREE(list);
                                return status;
                        }
                        fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
@@ -5046,7 +5031,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
                }       
 
                *returned+=ndrivers;
-               safe_free(list);
+               SAFE_FREE(list);
        }
        
        /* check the required size. */
@@ -5056,7 +5041,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
        }
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(driver_info_1);
+               SAFE_FREE(driver_info_1);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -5066,7 +5051,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
                smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
        }
 
-       safe_free(driver_info_1);
+       SAFE_FREE(driver_info_1);
 
        if (*needed > offered) {
                *returned=0;
@@ -5085,6 +5070,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
        int ndrivers;
        uint32 version;
        fstring *list = NULL;
+
        NT_PRINTER_DRIVER_INFO_LEVEL driver;
        DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
 
@@ -5103,8 +5089,8 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
                if(ndrivers != 0) {
                        if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
                                DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
-                               safe_free(driver_info_2);
-                               safe_free(list);
+                               SAFE_FREE(driver_info_2);
+                               SAFE_FREE(list);
                                return WERR_NOMEM;
                        }
                        else driver_info_2 = tdi2;
@@ -5118,7 +5104,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
                        status = get_a_printer_driver(&driver, 3, list[i], 
                                                      architecture, version);
                        if (!W_ERROR_IS_OK(status)) {
-                               safe_free(list);
+                               SAFE_FREE(list);
                                return status;
                        }
                        fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
@@ -5126,7 +5112,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
                }       
 
                *returned+=ndrivers;
-               safe_free(list);
+               SAFE_FREE(list);
        }
        
        /* check the required size. */
@@ -5136,7 +5122,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
        }
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(driver_info_2);
+               SAFE_FREE(driver_info_2);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -5146,7 +5132,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
                smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
        }
 
-       safe_free(driver_info_2);
+       SAFE_FREE(driver_info_2);
 
        if (*needed > offered) {
                *returned=0;
@@ -5165,6 +5151,7 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
        int ndrivers;
        uint32 version;
        fstring *list = NULL;
+
        NT_PRINTER_DRIVER_INFO_LEVEL driver;
        DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
 
@@ -5183,8 +5170,8 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
                if(ndrivers != 0) {
                        if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
                                DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
-                               safe_free(driver_info_3);
-                               safe_free(list);
+                               SAFE_FREE(driver_info_3);
+                               SAFE_FREE(list);
                                return WERR_NOMEM;
                        }
                        else driver_info_3 = tdi3;
@@ -5198,7 +5185,7 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
                        status = get_a_printer_driver(&driver, 3, list[i], 
                                                      architecture, version);
                        if (!W_ERROR_IS_OK(status)) {
-                               safe_free(list);
+                               SAFE_FREE(list);
                                return status;
                        }
                        fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
@@ -5206,7 +5193,7 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
                }       
 
                *returned+=ndrivers;
-               safe_free(list);
+               SAFE_FREE(list);
        }
 
        /* check the required size. */
@@ -5216,7 +5203,7 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
        }
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(driver_info_3);
+               SAFE_FREE(driver_info_3);
                return WERR_INSUFFICIENT_BUFFER;
        }
        
@@ -5227,9 +5214,9 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
        }
 
        for (i=0; i<*returned; i++)
-               safe_free(driver_info_3[i].dependentfiles);
+               SAFE_FREE(driver_info_3[i].dependentfiles);
        
-       safe_free(driver_info_3);
+       SAFE_FREE(driver_info_3);
        
        if (*needed > offered) {
                *returned=0;
@@ -5262,7 +5249,7 @@ WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS
        buffer = r_u->buffer;
 
        DEBUG(4,("_spoolss_enumprinterdrivers\n"));
-       fstrcpy(servername, global_myname);
+       fstrcpy(servername, get_called_name());
        *needed=0;
        *returned=0;
 
@@ -5277,7 +5264,7 @@ WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS
                return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
        default:
                *returned=0;
-               safe_free(list);
+               SAFE_FREE(list);
                return WERR_UNKNOWN_LEVEL;
        }
 }
@@ -5345,14 +5332,14 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
                        fill_form_1(&forms_1[i], &builtinlist[i]);
                }
                
-               safe_free(builtinlist);
+               SAFE_FREE(builtinlist);
 
                for (; i<*numofforms; i++) {
                        DEBUGADD(6,("Filling form number [%d]\n",i));
                        fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
                }
                
-               safe_free(list);
+               SAFE_FREE(list);
 
                /* check the required size. */
                for (i=0; i<numbuiltinforms; i++) {
@@ -5367,7 +5354,7 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
                *needed=buffer_size;            
                
                if (!alloc_buffer_size(buffer, buffer_size)){
-                       safe_free(forms_1);
+                       SAFE_FREE(forms_1);
                        return WERR_INSUFFICIENT_BUFFER;
                }
 
@@ -5381,7 +5368,7 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
                        smb_io_form_1("", buffer, &forms_1[i], 0);
                }
 
-               safe_free(forms_1);
+               SAFE_FREE(forms_1);
 
                if (*needed > offered) {
                        *numofforms=0;
@@ -5391,8 +5378,8 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
                        return WERR_OK;
                        
        default:
-               safe_free(list);
-               safe_free(builtinlist);
+               SAFE_FREE(list);
+               SAFE_FREE(builtinlist);
                return WERR_UNKNOWN_LEVEL;
        }
 
@@ -5455,7 +5442,7 @@ WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *
                                }
                        }
                        
-                       safe_free(list);
+                       SAFE_FREE(list);
                        if (i == numofforms) {
                                return WERR_BADFID;
                        }
@@ -5479,7 +5466,7 @@ WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *
                return WERR_OK;
                        
        default:
-               safe_free(list);
+               SAFE_FREE(list);
                return WERR_UNKNOWN_LEVEL;
        }
 }
@@ -5572,7 +5559,7 @@ static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *need
        }
                
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(ports);
+               SAFE_FREE(ports);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -5582,7 +5569,7 @@ static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *need
                smb_io_port_1("", buffer, &ports[i], 0);
        }
 
-       safe_free(ports);
+       SAFE_FREE(ports);
 
        if (*needed > offered) {
                *returned=0;
@@ -5670,7 +5657,7 @@ static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *need
        }
                
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(ports);
+               SAFE_FREE(ports);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -5680,7 +5667,7 @@ static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *need
                smb_io_port_2("", buffer, &ports[i], 0);
        }
 
-       safe_free(ports);
+       SAFE_FREE(ports);
 
        if (*needed > offered) {
                *returned=0;
@@ -5731,9 +5718,9 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
                                POLICY_HND *handle)
 {
        NT_PRINTER_INFO_LEVEL *printer = NULL;
-       WERROR err;
-       fstring name;
-       int snum;
+       fstring name;
+       int     snum;
+       WERROR err = WERR_OK;
 
        if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
                DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
@@ -5743,7 +5730,19 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
        ZERO_STRUCTP(printer);
 
        /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
-       convert_printer_info(info, printer, 2);
+       if (!convert_printer_info(info, printer, 2)) {
+               free_a_printer(&printer, 2);
+               return WERR_NOMEM;
+       }
+
+       /* 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", 
+                       printer->info_2->sharename));
+               free_a_printer(&printer, 2);
+               return WERR_PRINTER_ALREADY_EXISTS;
+       }
 
        if (*lp_addprinter_cmd() )
                if ( !add_printer_hook(printer) ) {
@@ -5751,7 +5750,7 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
                        return WERR_ACCESS_DENIED;
        }
 
-       slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
+       slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
              printer->info_2->sharename);
 
        if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
@@ -5774,13 +5773,13 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
                return WERR_INVALID_PARAM;
        }
 
-       /*
+    /*
         * When a printer is created, the drivername bound to the printer is used
-        * to lookup previously saved driver initialization info, which is then
+        * to lookup previously saved driver initialization info, which is then 
         * bound to the new printer, simulating what happens in the Windows arch.
         */
        set_driver_init(printer, 2);
-
+       
        /* write the ASCII on disk */
        err = add_a_printer(*printer, 2);
        if (!W_ERROR_IS_OK(err)) {
@@ -5893,13 +5892,13 @@ static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environmen
 
        unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
 
-       if (get_short_archi(short_archi, long_archi)==FALSE)
+       if (get_short_archi(short_archi, long_archi)==False)
                return WERR_INVALID_ENVIRONMENT;
 
        if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
                return WERR_NOMEM;
 
-       slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
+       slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
 
        DEBUG(4,("printer driver directory: [%s]\n", path));
 
@@ -5908,13 +5907,13 @@ static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environmen
        *needed += spoolss_size_driverdir_info_1(info);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(info);
+               SAFE_FREE(info);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
        smb_io_driverdir_1("", buffer, info, 0);
 
-       safe_free(info);
+       SAFE_FREE(info);
        
        if (*needed > offered)
                return WERR_INSUFFICIENT_BUFFER;
@@ -5983,10 +5982,6 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
 
        ZERO_STRUCT(printer);
        
-       *out_max_value_len=0;
-       *out_value=NULL;
-       *out_value_len=0;
-
        *out_type=0;
 
        *out_max_data_len=0;
@@ -6026,14 +6021,13 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
                 */
 
                if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
-                       safe_free(data);
+                       SAFE_FREE(data);
                        free_a_printer(&printer, 2);
                        return WERR_NO_MORE_ITEMS;
                }
 #endif
 
-               safe_free(data);
-               data = NULL;
+               SAFE_FREE(data);
 
                param_index=0;
                biggest_valuesize=0;
@@ -6045,23 +6039,10 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
 
                        DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
 
-                       safe_free(data);
-                       data = NULL;
+                       SAFE_FREE(data);
                        param_index++;
                }
 
-               /*
-                * I think this is correct, it doesn't break APW and
-                * allows Gerald's Win32 test programs to work correctly,
-                * but may need altering.... JRA.
-                */
-
-               if (param_index == 0) {
-                       /* No parameters found. */
-                       free_a_printer(&printer, 2);
-                       return WERR_NO_MORE_ITEMS;
-               }
-
                /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
                *out_value_len=2*(1+biggest_valuesize);
                *out_data_len=biggest_datasize;
@@ -6078,8 +6059,28 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
         */
 
        if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
-               safe_free(data);
+
+               SAFE_FREE(data);
                free_a_printer(&printer, 2);
+
+               /* out_value should default to "" or else NT4 has
+                  problems unmarshalling the response */
+
+               *out_max_value_len=(in_value_len/sizeof(uint16));
+               if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL)
+                       return WERR_NOMEM;
+
+               ZERO_STRUCTP(*out_value);
+               *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
+
+               /* the data is counted in bytes */
+               *out_max_data_len = in_data_len;
+               *out_data_len = in_data_len;
+               if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL)
+                       return WERR_NOMEM;
+
+               memset(*data_out,'\0',in_data_len);
+
                return WERR_NO_MORE_ITEMS;
        }
 
@@ -6096,7 +6097,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
        
        *out_max_value_len=(in_value_len/sizeof(uint16));
        if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
-               safe_free(data);
+               SAFE_FREE(data);
                return WERR_NOMEM;
        }
        
@@ -6107,14 +6108,14 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
        /* the data is 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) {
-               safe_free(data);
+               SAFE_FREE(data);
                return WERR_NOMEM;
        }
        
        memcpy(*data_out, data, (size_t)data_len);
        *out_data_len=data_len;
 
-       safe_free(data);
+       SAFE_FREE(data);
        
        return WERR_OK;
 }
@@ -6148,12 +6149,6 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
        if (!get_printer_snum(p,handle, &snum))
                return WERR_BADFID;
 
-       status = get_a_printer(&printer, 2, lp_servicename(snum));
-       if (!W_ERROR_IS_OK(status))
-               return status;
-
-       convert_specific_param(&param, value , type, data, real_len);
-
        ZERO_STRUCT(old_param);
 
        /* 
@@ -6167,16 +6162,22 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
        if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
                DEBUG(3, ("security descriptor change denied by existing "
                          "security descriptor\n"));
-               status = ERROR_ACCESS_DENIED;
+               status = WERR_ACCESS_DENIED;
                goto done;
        }
 
-
        /* Check if we are making any changes or not.  Return true if
           nothing is actually changing.  This is not needed anymore but
           has been left in as an optimization to keep from from
           writing to disk as often  --jerry  */
 
+       status = get_a_printer(&printer, 2, lp_servicename(snum));
+       if (!W_ERROR_IS_OK(status))
+               return status;
+
+       convert_specific_param(&param, value , type, data, real_len);
+
+#if 0
        if (get_specific_param(*printer, 2, param->value, &old_param.data,
                               &old_param.type, (uint32 *)&old_param.data_len)) {
 
@@ -6190,9 +6191,10 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
                        goto done;
                }
        }
+#endif
 
        unlink_specific_param_if_exist(printer->info_2, param);
-
+       
        /*
         * When client side code sets a magic printer data key, detect it and save
         * the current printer data and the magic key's data (its the DEVMODE) for
@@ -6208,12 +6210,12 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
                add_a_specific_param(printer->info_2, &param);
                status = mod_a_printer(*printer, 2);
        }
-       
+
  done:
        free_a_printer(&printer, 2);
        if (param)
                free_nt_printer_param(&param);
-       safe_free(old_param.data);
+       SAFE_FREE(old_param.data);
 
        return status;
 }
@@ -6285,6 +6287,11 @@ WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM
                return WERR_BADFID;
        }
 
+       /* 
+        * FIXME!!  Feels like there should be an access check here, but haven't
+        * had time to verify.  --jerry
+        */
+
        /* can't add if builtin */
        if (get_a_builtin_ntform(&form->name,&tmpForm)) {
                return WERR_INVALID_PARAM;
@@ -6295,7 +6302,7 @@ WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM
                return WERR_NOMEM;
        write_ntforms(&list, count);
 
-       safe_free(list);
+       SAFE_FREE(list);
 
        return WERR_OK;
 }
@@ -6326,10 +6333,10 @@ WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DE
        }
 
        count = get_ntforms(&list);
-       if (!delete_a_form(&list, form_name, &count, &ret))
+       if(!delete_a_form(&list, form_name, &count, &ret))
                return WERR_INVALID_PARAM;
 
-       safe_free(list);
+       SAFE_FREE(list);
 
        return ret;
 }
@@ -6364,7 +6371,7 @@ WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *
        update_a_form(&list, form, count);
        write_ntforms(&list, count);
 
-       safe_free(list);
+       SAFE_FREE(list);
 
        return WERR_OK;
 }
@@ -6390,7 +6397,7 @@ static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, ui
 
        smb_io_printprocessor_info_1("", buffer, info_1, 0);
 
-       safe_free(info_1);
+       SAFE_FREE(info_1);
 
        if (*needed > offered) {
                *returned=0;
@@ -6408,9 +6415,9 @@ WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS
 /*     UNISTR2 *name = &q_u->name; - notused. */
 /*     UNISTR2 *environment = &q_u->environment; - notused. */
        uint32 level = q_u->level;
-       NEW_BUFFER *buffer = NULL;
+    NEW_BUFFER *buffer = NULL;
        uint32 offered = q_u->offered;
-       uint32 *needed = &r_u->needed;
+    uint32 *needed = &r_u->needed;
        uint32 *returned = &r_u->returned;
 
        /* that's an [in out] buffer */
@@ -6458,7 +6465,7 @@ static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered,
 
        smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
 
-       safe_free(info_1);
+       SAFE_FREE(info_1);
 
        if (*needed > offered) {
                *returned=0;
@@ -6520,7 +6527,7 @@ static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint
 
        smb_io_printmonitor_info_1("", buffer, info_1, 0);
 
-       safe_free(info_1);
+       SAFE_FREE(info_1);
 
        if (*needed > offered) {
                *returned=0;
@@ -6553,7 +6560,7 @@ static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint
 
        smb_io_printmonitor_info_2("", buffer, info_2, 0);
 
-       safe_free(info_2);
+       SAFE_FREE(info_2);
 
        if (*needed > offered) {
                *returned=0;
@@ -6570,9 +6577,9 @@ WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_
 {
 /*     UNISTR2 *name = &q_u->name; - notused. */
        uint32 level = q_u->level;
-       NEW_BUFFER *buffer = NULL;
+    NEW_BUFFER *buffer = NULL;
        uint32 offered = q_u->offered;
-       uint32 *needed = &r_u->needed;
+    uint32 *needed = &r_u->needed;
        uint32 *returned = &r_u->returned;
 
        /* that's an [in out] buffer */
@@ -6612,7 +6619,7 @@ static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uin
        info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
 
        if (info_1 == NULL) {
-               safe_free(queue);
+               SAFE_FREE(queue);
                return WERR_NOMEM;
        }
                
@@ -6622,26 +6629,26 @@ static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uin
        }
        
        if (found==False) {
-               safe_free(queue);
-               safe_free(info_1);
-               /* I shoud reply something else ... I can't find the good one */
-               return WERR_OK;
+               SAFE_FREE(queue);
+               SAFE_FREE(info_1);
+               /* NT treats not found as bad param... yet another bad choice */
+               return WERR_INVALID_PARAM;
        }
        
        fill_job_info_1(info_1, &(queue[i-1]), i, snum);
        
-       safe_free(queue);
+       SAFE_FREE(queue);
        
        *needed += spoolss_size_job_info_1(info_1);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(info_1);
+               SAFE_FREE(info_1);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
        smb_io_job_info_1("", buffer, info_1, 0);
 
-       safe_free(info_1);
+       SAFE_FREE(info_1);
 
        if (*needed > offered)
                return WERR_INSUFFICIENT_BUFFER;
@@ -6665,7 +6672,7 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin
        ZERO_STRUCTP(info_2);
 
        if (info_2 == NULL) {
-               safe_free(queue);
+               SAFE_FREE(queue);
                return WERR_NOMEM;
        }
 
@@ -6675,34 +6682,34 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin
        }
        
        if (found==False) {
-               safe_free(queue);
-               safe_free(info_2);
-               /* I shoud reply something else ... I can't find the good one */
-               return WERR_OK;
+               SAFE_FREE(queue);
+               SAFE_FREE(info_2);
+               /* NT treats not found as bad param... yet another bad choice */
+               return WERR_INVALID_PARAM;
        }
        
        ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
        if (!W_ERROR_IS_OK(ret)) {
-               safe_free(queue);
+               SAFE_FREE(queue);
                return ret;
        }
 
        fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
        
        free_a_printer(&ntprinter, 2);
-       safe_free(queue);
+       SAFE_FREE(queue);
        
        *needed += spoolss_size_job_info_2(info_2);
 
        if (!alloc_buffer_size(buffer, *needed)) {
-               safe_free(info_2);
+               SAFE_FREE(info_2);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
        smb_io_job_info_2("", buffer, info_2, 0);
 
        free_job_info_2(info_2);
-       free(info_2);
+       SAFE_FREE(info_2);
 
        if (*needed > offered)
                return WERR_INSUFFICIENT_BUFFER;
@@ -6733,8 +6740,6 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_
 
        DEBUG(5,("spoolss_getjob\n"));
        
-       memset(&prt_status, 0, sizeof(prt_status));
-
        *needed=0;
        
        if (!get_printer_snum(p, handle, &snum))
@@ -6751,7 +6756,415 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_
        case 2:
                return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
        default:
-               safe_free(queue);
+               SAFE_FREE(queue);
                return WERR_UNKNOWN_LEVEL;
        }
 }
+
+/********************************************************************
+ * spoolss_getprinterdataex
+ ********************************************************************/
+
+WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
+{
+       POLICY_HND      *handle = &q_u->handle;
+       uint32          in_size = q_u->size;
+       uint32          *type = &r_u->type;
+       uint32          *out_size = &r_u->size;
+       uint8           **data = &r_u->data;
+       uint32          *needed = &r_u->needed;
+
+       fstring         key, value;
+       Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
+       BOOL            found = False;
+
+       DEBUG(4,("_spoolss_getprinterdataex\n"));
+
+        unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
+        unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
+
+       /* in case of problem, return some default values */
+       *needed=0;
+       *type=0;
+       *out_size=0;
+
+               
+       if (!Printer) {
+               if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
+                       return WERR_NOMEM;
+               DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
+               return WERR_BADFID;
+       }
+
+               
+       /* Is the handle to a printer or to the server? */
+
+       if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
+       {
+               DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
+               return WERR_INVALID_PARAM;
+       }
+       else
+       {
+               /* 
+                * From MSDN documentation of GetPrinterDataEx: pass request
+                * to GetPrinterData if key is "PrinterDriverData". This is 
+                * the only key we really support. Other keys to implement:
+                * (a) DsDriver
+                * (b) DsSpooler
+                * (c) PnPData
+                */
+          
+               if (strcmp(key, "PrinterDriverData") != 0)
+                       return WERR_INVALID_PARAM;
+
+               DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
+               found = getprinterdata_printer(p, p->mem_ctx, handle, value, 
+                       type, data, needed, in_size);
+               
+       }
+        
+       if (!found) {
+               DEBUG(5, ("value not found, allocating %d\n", *out_size));
+               
+               /* reply this param doesn't exist */
+               if (*out_size) {
+                       if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
+                               return WERR_NOMEM;
+               } else {
+                       *data = NULL;
+               }
+
+               return WERR_INVALID_PARAM;
+       }
+       
+       if (*needed > *out_size)
+               return WERR_MORE_DATA;
+       else
+               return WERR_OK;
+}
+
+/********************************************************************
+ * spoolss_setprinterdata
+ ********************************************************************/
+
+WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
+{
+       SPOOL_Q_SETPRINTERDATA q_u_local;
+       SPOOL_R_SETPRINTERDATA r_u_local;
+        fstring key;
+
+       DEBUG(4,("_spoolss_setprinterdataex\n"));
+
+        /* From MSDN documentation of SetPrinterDataEx: pass request to
+           SetPrinterData if key is "PrinterDriverData" */
+
+        unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
+
+        if (strcmp(key, "PrinterDriverData") == 0)
+               return WERR_INVALID_PARAM;
+               
+       ZERO_STRUCT(q_u_local); 
+       ZERO_STRUCT(r_u_local); 
+       
+       /* make a copy to call _spoolss_setprinterdata() */
+
+       memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
+       copy_unistr2(&q_u_local.value, &q_u->value);
+       q_u_local.type = q_u->type;
+       q_u_local.max_len = q_u->max_len;
+       q_u_local.data = q_u->data;
+       q_u_local.real_len = q_u->real_len;
+       q_u_local.numeric_data = q_u->numeric_data;
+               
+       return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
+}
+
+/********************************************************************
+ * spoolss_enumprinterkey
+ ********************************************************************/
+
+/* constants for EnumPrinterKey() */
+#define ENUMERATED_KEY_SIZE    19
+
+WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
+{
+       fstring key;
+       uint16  enumkeys[ENUMERATED_KEY_SIZE+1];
+       char*   ptr = NULL;
+       int     i;
+       char    *PrinterKey = "PrinterDriverData";
+
+       DEBUG(4,("_spoolss_enumprinterkey\n"));
+
+       unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
+
+       /* 
+        * we only support enumating all keys (key == "")
+        * Of course, the only key we support is the "PrinterDriverData" 
+        * key
+        */     
+       if (strlen(key) == 0)
+       {
+               r_u->needed = ENUMERATED_KEY_SIZE *2;
+               if (q_u->size < r_u->needed)
+                       return WERR_MORE_DATA;
+       
+               ptr = PrinterKey;
+               for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
+               {
+                       enumkeys[i] = (uint16)(*ptr);
+                       ptr++;
+               }
+
+               /* tag of with 2 '\0's */
+               enumkeys[i++] = '\0';
+               enumkeys[i] = '\0';
+       
+               if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
+                       return WERR_BADFILE;
+                       
+               return WERR_OK;
+       }
+       
+       /* The "PrinterDriverData" key should have no subkeys */
+       if (strcmp(key, PrinterKey) == 0)
+       {
+               r_u-> needed = 2;
+               if (q_u->size < r_u->needed)
+                       return WERR_MORE_DATA;
+               enumkeys[0] = 0x0;
+               if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
+                       return WERR_BADFILE;
+                       
+               return WERR_OK;
+       }
+       
+
+       /* The return value for an unknown key is documented in MSDN
+          EnumPrinterKey description */
+        return WERR_BADFILE;
+}
+
+/********************************************************************
+ * spoolss_enumprinterdataex
+ ********************************************************************/
+
+WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
+{
+       POLICY_HND      *handle = &q_u->handle; 
+       uint32          in_size = q_u->size;
+       uint32          num_entries, 
+                       needed;
+       NT_PRINTER_INFO_LEVEL   *printer = NULL;
+       PRINTER_ENUM_VALUES     *enum_values = NULL;
+       fstring         key, value;
+       Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
+       int             snum;
+       uint32          param_index, 
+                       data_len,
+                       type;
+       WERROR          result;
+       uint8           *data=NULL;
+       
+
+       DEBUG(4,("_spoolss_enumprinterdataex\n"));
+
+       if (!Printer) {
+               DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
+               return WERR_BADFID;
+       }
+
+               
+        /* 
+        * The only key we support is "PrinterDriverData". This should return 
+        > an array of all the key/value pairs returned by EnumPrinterDataSee 
+        * _spoolss_getprinterdataex() for details    --jerry
+        */
+   
+       unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
+       if (strcmp(key, "PrinterDriverData") != 0)
+       {
+               DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
+               return WERR_INVALID_PARAM;
+       }
+
+
+       if (!get_printer_snum(p,handle, &snum))
+               return WERR_BADFID;
+       
+       ZERO_STRUCT(printer);
+       result = get_a_printer(&printer, 2, lp_servicename(snum));
+       if (!W_ERROR_IS_OK(result))
+               return result;
+
+       
+       /* 
+        * loop through all params and build the array to pass 
+        * back to the  client 
+        */
+       result = WERR_OK;
+       param_index             = 0;
+       needed                  = 0;
+       num_entries             = 0;
+       
+       while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) 
+       {
+               PRINTER_ENUM_VALUES     *ptr;
+               uint32                  add_len = 0;
+
+               DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
+
+               if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
+               {
+                       DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
+                       result = WERR_NOMEM;
+                       goto done;
+               }
+               enum_values = ptr;
+
+               /* copy the data */
+               init_unistr(&enum_values[num_entries].valuename, value);
+               enum_values[num_entries].value_len = (strlen(value)+1) * 2;
+               enum_values[num_entries].type      = type;
+               
+               /* 
+                * NULL terminate REG_SZ
+                * FIXME!!!  We should not be correctly problems in the way
+                * we store PrinterData here.  Need to investogate 
+                * SetPrinterData[Ex]   --jerry
+                */
+               
+               if (type == REG_SZ) {
+                       /* fix alignment if the string was stored 
+                          in a bizarre fashion */
+                       if ((data_len % 2) == 0)
+                               add_len = 2;
+                       else
+                               add_len = data_len % 2;
+               }
+               
+               if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
+                       DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
+                       result = WERR_NOMEM;
+                       goto done;
+               }
+               memcpy(enum_values[num_entries].data, data, data_len);
+               enum_values[num_entries].data_len = data_len + add_len;
+
+               /* keep track of the size of the array in bytes */
+               
+               needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
+               
+               num_entries++;
+               param_index++;
+       }
+       
+       r_u->needed             = needed;
+       r_u->returned           = num_entries;
+
+       if (needed > in_size) {
+               result = WERR_MORE_DATA;
+               goto done;
+       }
+               
+       /* copy data into the reply */
+       
+       r_u->ctr.size           = r_u->needed;
+       r_u->ctr.size_of_array  = r_u->returned;
+       r_u->ctr.values         = enum_values;
+       
+       
+               
+done:  
+       free_a_printer(&printer, 2);
+
+       return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+/* Disabled because it doesn't fix the bug I am looking at but it would be
+   a shame to throw away the code. -tpot */
+
+#if 0
+
+static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
+{
+       init_unistr(&info->name, name);
+}
+
+static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, 
+                                                UNISTR2 *environment, 
+                                                NEW_BUFFER *buffer, 
+                                                uint32 offered, 
+                                                uint32 *needed)
+{
+       pstring path;
+       pstring long_archi;
+       pstring short_archi;
+       PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
+
+       unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
+
+       if (get_short_archi(short_archi, long_archi)==False)
+               return WERR_INVALID_ENVIRONMENT;
+
+       if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
+               return WERR_NOMEM;
+
+       /* Not sure what to return here - are UNC names valid here?.
+          Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
+          which is pretty bogus for a RPC. */
+
+       slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
+
+       DEBUG(4,("print processor directory: [%s]\n", path));
+
+       fill_printprocessordirectory_1(info, path);
+       
+       *needed += spoolss_size_printprocessordirectory_info_1(info);
+
+       if (!alloc_buffer_size(buffer, *needed)) {
+               safe_free(info);
+               return WERR_INSUFFICIENT_BUFFER;
+       }
+
+       smb_io_printprocessordirectory_1("", buffer, info, 0);
+
+       safe_free(info);
+       
+       if (*needed > offered)
+               return WERR_INSUFFICIENT_BUFFER;
+       else
+               return WERR_OK;
+}
+
+WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
+{
+       uint32 level = q_u->level;
+       NEW_BUFFER *buffer = NULL;
+       uint32 offered = q_u->offered;
+       uint32 *needed = &r_u->needed;
+
+       /* that's an [in out] buffer */
+       spoolss_move_buffer(q_u->buffer, &r_u->buffer);
+       buffer = r_u->buffer;
+
+       DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
+       
+       *needed=0;
+
+       switch(level) {
+       case 1:
+               return getprintprocessordirectory_level_1
+                 (&q_u->name, &q_u->environment, buffer, offered, needed);
+       default:
+               return WERR_UNKNOWN_LEVEL;
+       }
+
+       return WERR_ACCESS_DENIED;
+}
+
+#endif