s3-spoolss: add pull_spoolss_PrinterData().
[jra/samba/.git] / source3 / rpc_server / srv_spoolss_nt.c
index 925b15eba9b5aa22c944c7886d126c1c96fc210f..8ce0b28db04aad39a678943403ddd480854a115d 100644 (file)
@@ -2461,6 +2461,22 @@ WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, cons
        return add_printer_data( printer->info_2, key, value, type, data, real_len );
 }
 
+/*******************************************************************
+ ********************************************************************/
+
+static WERROR push_spoolss_PrinterData(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
+                                      enum winreg_Type type,
+                                      union spoolss_PrinterData *data)
+{
+       enum ndr_err_code ndr_err;
+       ndr_err = ndr_push_union_blob(blob, mem_ctx, NULL, data, type,
+                       (ndr_push_flags_fn_t)ndr_push_spoolss_PrinterData);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return WERR_GENERAL_FAILURE;
+       }
+       return WERR_OK;
+}
+
 /********************************************************************
  GetPrinterData on a printer server Handle.
 ********************************************************************/
@@ -3924,149 +3940,81 @@ done:
  * fill a printer_info_0 struct
  ********************************************************************/
 
-static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
+static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
+                                     const NT_PRINTER_INFO_LEVEL *ntprinter,
+                                     struct spoolss_PrinterInfo0 *r,
+                                     int snum)
 {
-       char *chaine = NULL;
        int count;
-       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
        counter_printer_0 *session_counter;
-       uint32 global_counter;
-       struct tm *t;
        time_t setuptime;
        print_status_struct status;
-       TALLOC_CTX *ctx = talloc_tos();
 
-       if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
-               return False;
-
-       init_unistr(&printer->printername, ntprinter->info_2->printername);
+       r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
+       W_ERROR_HAVE_NO_MEMORY(r->printername);
 
-       chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
-       if (!chaine) {
-               free_a_printer(&ntprinter,2);
-               return false;
-       }
+       r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
+       W_ERROR_HAVE_NO_MEMORY(r->servername);
 
        count = print_queue_length(snum, &status);
 
        /* check if we already have a counter for this printer */
-       for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
+       for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
                if (session_counter->snum == snum)
                        break;
        }
 
-       init_unistr(&printer->servername, chaine);
-
        /* it's the first time, add it to the list */
-       if (session_counter==NULL) {
-               if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
-                       free_a_printer(&ntprinter, 2);
-                       return False;
-               }
+       if (session_counter == NULL) {
+               session_counter = SMB_MALLOC_P(counter_printer_0);
+               W_ERROR_HAVE_NO_MEMORY(session_counter);
                ZERO_STRUCTP(session_counter);
-               session_counter->snum=snum;
-               session_counter->counter=0;
+               session_counter->snum           = snum;
+               session_counter->counter        = 0;
                DLIST_ADD(counter_list, session_counter);
        }
 
        /* increment it */
        session_counter->counter++;
 
-       /* JFM:
-        * the global_counter should be stored in a TDB as it's common to all the clients
-        * and should be zeroed on samba startup
-        */
-       global_counter=session_counter->counter;
-       printer->cjobs = count;
-       printer->total_jobs = 0;
-       printer->total_bytes = 0;
+       r->cjobs                        = count;
+       r->total_jobs                   = 0;
+       r->total_bytes                  = 0;
 
        setuptime = (time_t)ntprinter->info_2->setuptime;
-       t=gmtime(&setuptime);
 
-       printer->year = t->tm_year+1900;
-       printer->month = t->tm_mon+1;
-       printer->dayofweek = t->tm_wday;
-       printer->day = t->tm_mday;
-       printer->hour = t->tm_hour;
-       printer->minute = t->tm_min;
-       printer->second = t->tm_sec;
-       printer->milliseconds = 0;
-
-       printer->global_counter = global_counter;
-       printer->total_pages = 0;
+       init_systemtime(&r->time, gmtime(&setuptime));
 
+       /* JFM:
+        * the global_counter should be stored in a TDB as it's common to all the clients
+        * and should be zeroed on samba startup
+        */
+       r->global_counter               = session_counter->counter;
+       r->total_pages                  = 0;
        /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
-       printer->major_version = 0x0005;        /* NT 5 */
-       printer->build_version = 0x0893;        /* build 2195 */
-
-       printer->unknown7 = 0x1;
-       printer->unknown8 = 0x0;
-       printer->unknown9 = 0x0;
-       printer->session_counter = session_counter->counter;
-       printer->unknown11 = 0x0;
-       printer->printer_errors = 0x0;          /* number of print failure */
-       printer->unknown13 = 0x0;
-       printer->unknown14 = 0x1;
-       printer->unknown15 = 0x024a;            /* 586 Pentium ? */
-       printer->unknown16 =  0x0;
-       printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
-       printer->unknown18 =  0x0;
-       printer->status = nt_printq_status(status.status);
-       printer->unknown20 =  0x0;
-       printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
-       printer->unknown22 = 0x0;
-       printer->unknown23 = 0x6;               /* 6  ???*/
-       printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
-       printer->unknown25 = 0;
-       printer->unknown26 = 0;
-       printer->unknown27 = 0;
-       printer->unknown28 = 0;
-       printer->unknown29 = 0;
-
-       free_a_printer(&ntprinter,2);
-       return (True);
-}
-
-/********************************************************************
- * construct_printer_info_1
- * fill a printer_info_1 struct
- ********************************************************************/
-static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
-{
-       char *chaine = NULL;
-       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
-       TALLOC_CTX *ctx = talloc_tos();
-
-       if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
-               return false;
-
-       printer->flags=flags;
+       r->version                      = 0x0005;       /* NT 5 */
+       r->free_build                   = 0x0893;       /* build 2195 */
+       r->spooling                     = 0;
+       r->max_spooling                 = 0;
+       r->session_counter              = session_counter->counter;
+       r->num_error_out_of_paper       = 0x0;
+       r->num_error_not_ready          = 0x0;          /* number of print failure */
+       r->job_error                    = 0x0;
+       r->number_of_processors         = 0x1;
+       r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
+       r->high_part_total_bytes        = 0x0;
+       r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
+       r->last_error                   = WERR_OK;
+       r->status                       = nt_printq_status(status.status);
+       r->enumerate_network_printers   = 0x0;
+       r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
+       r->processor_architecture       = 0x0;
+       r->processor_level              = 0x6;          /* 6  ???*/
+       r->ref_ic                       = 0;
+       r->reserved2                    = 0;
+       r->reserved3                    = 0;
 
-       if (*ntprinter->info_2->comment == '\0') {
-               init_unistr(&printer->comment, lp_comment(snum));
-               chaine = talloc_asprintf(ctx,
-                               "%s,%s,%s", ntprinter->info_2->printername,
-                               ntprinter->info_2->drivername, lp_comment(snum));
-       }
-       else {
-               init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
-               chaine = talloc_asprintf(ctx,
-                               "%s,%s,%s", ntprinter->info_2->printername,
-                               ntprinter->info_2->drivername, ntprinter->info_2->comment);
-       }
-
-       if (!chaine) {
-               free_a_printer(&ntprinter,2);
-               return false;
-       }
-
-       init_unistr(&printer->description, chaine);
-       init_unistr(&printer->name, ntprinter->info_2->printername);
-
-       free_a_printer(&ntprinter,2);
-
-       return True;
+       return WERR_OK;
 }
 
 /****************************************************************************
@@ -4280,205 +4228,116 @@ done:
 }
 
 /********************************************************************
- * construct_printer_info_2
- * fill a printer_info_2 struct
- ********************************************************************/
-
-static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
-{
-       int count;
-       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
-
-       print_status_struct status;
-
-       if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
-               return False;
-
-       count = print_queue_length(snum, &status);
-
-       init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
-       init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
-       init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
-       init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
-       init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
-
-       if (*ntprinter->info_2->comment == '\0')
-               init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
-       else
-               init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
-
-       init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
-       init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
-       init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
-       init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
-       init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
-
-       printer->attributes = ntprinter->info_2->attributes;
-
-       printer->priority = ntprinter->info_2->priority;                                /* priority */
-       printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
-       printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
-       printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
-       printer->status = nt_printq_status(status.status);                      /* status */
-       printer->cjobs = count;                                                 /* jobs */
-       printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
-
-       if ( !(printer->devmode = construct_dev_mode(
-                      lp_const_servicename(snum))) )
-               DEBUG(8, ("Returning NULL Devicemode!\n"));
-
-       printer->secdesc = NULL;
-
-       if ( ntprinter->info_2->secdesc_buf
-               && ntprinter->info_2->secdesc_buf->sd_size != 0 )
-       {
-               /* don't use talloc_steal() here unless you do a deep steal of all
-                  the SEC_DESC members */
-
-               printer->secdesc = dup_sec_desc( talloc_tos(),
-                       ntprinter->info_2->secdesc_buf->sd );
-       }
-
-       free_a_printer(&ntprinter, 2);
-
-       return True;
-}
-
-/********************************************************************
- * construct_printer_info_3
- * fill a printer_info_3 struct
+ * construct_printer_info3
+ * fill a spoolss_PrinterInfo3 struct
  ********************************************************************/
 
-static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
+static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
+                                     const NT_PRINTER_INFO_LEVEL *ntprinter,
+                                     struct spoolss_PrinterInfo3 *r,
+                                     int snum)
 {
-       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
-       PRINTER_INFO_3 *printer = NULL;
-
-       if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
-               return False;
-
-       *pp_printer = NULL;
-       if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
-               DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
-               free_a_printer(&ntprinter, 2);
-               return False;
-       }
-
-       ZERO_STRUCTP(printer);
-
        /* These are the components of the SD we are returning. */
 
        if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
                /* don't use talloc_steal() here unless you do a deep steal of all
                   the SEC_DESC members */
 
-               printer->secdesc = dup_sec_desc( talloc_tos(),
-                       ntprinter->info_2->secdesc_buf->sd );
+               r->secdesc = dup_sec_desc(mem_ctx,
+                                         ntprinter->info_2->secdesc_buf->sd);
+               W_ERROR_HAVE_NO_MEMORY(r->secdesc);
        }
 
-       free_a_printer(&ntprinter, 2);
-
-       *pp_printer = printer;
-       return True;
+       return WERR_OK;
 }
 
 /********************************************************************
- * construct_printer_info_4
- * fill a printer_info_4 struct
+ * construct_printer_info4
+ * fill a spoolss_PrinterInfo4 struct
  ********************************************************************/
 
-static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
+static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
+                                     const NT_PRINTER_INFO_LEVEL *ntprinter,
+                                     struct spoolss_PrinterInfo4 *r,
+                                     int snum)
 {
-       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
-
-       if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
-               return False;
+       r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
+       W_ERROR_HAVE_NO_MEMORY(r->printername);
+       r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
+       W_ERROR_HAVE_NO_MEMORY(r->servername);
 
-       init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
-       init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
-       printer->attributes = ntprinter->info_2->attributes;
+       r->attributes   = ntprinter->info_2->attributes;
 
-       free_a_printer(&ntprinter, 2);
-       return True;
+       return WERR_OK;
 }
 
 /********************************************************************
- * construct_printer_info_5
- * fill a printer_info_5 struct
+ * construct_printer_info5
+ * fill a spoolss_PrinterInfo5 struct
  ********************************************************************/
 
-static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
+static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
+                                     const NT_PRINTER_INFO_LEVEL *ntprinter,
+                                     struct spoolss_PrinterInfo5 *r,
+                                     int snum)
 {
-       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
-
-       if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
-               return False;
+       r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
+       W_ERROR_HAVE_NO_MEMORY(r->printername);
+       r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
+       W_ERROR_HAVE_NO_MEMORY(r->portname);
 
-       init_unistr(&printer->printername, ntprinter->info_2->printername);
-       init_unistr(&printer->portname, ntprinter->info_2->portname);
-       printer->attributes = ntprinter->info_2->attributes;
+       r->attributes   = ntprinter->info_2->attributes;
 
        /* these two are not used by NT+ according to MSDN */
 
-       printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
-       printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
+       r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
+       r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
 
-       free_a_printer(&ntprinter, 2);
-
-       return True;
+       return WERR_OK;
 }
 
 /********************************************************************
  * construct_printer_info_6
- * fill a printer_info_6 struct
+ * fill a spoolss_PrinterInfo6 struct
  ********************************************************************/
 
-static bool construct_printer_info_6(Printer_entry *print_hnd,
-                                    PRINTER_INFO_6 *printer,
-                                    int snum)
+static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
+                                     const NT_PRINTER_INFO_LEVEL *ntprinter,
+                                     struct spoolss_PrinterInfo6 *r,
+                                     int snum)
 {
-       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
        int count;
        print_status_struct status;
 
-       if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
-                                        lp_const_servicename(snum))))
-               return False;
-
        count = print_queue_length(snum, &status);
 
-       printer->status = nt_printq_status(status.status);
-
-       free_a_printer(&ntprinter, 2);
+       r->status = nt_printq_status(status.status);
 
-       return True;
+       return WERR_OK;
 }
 
 /********************************************************************
- * construct_printer_info_7
- * fill a printer_info_7 struct
+ * construct_printer_info7
+ * fill a spoolss_PrinterInfo7 struct
  ********************************************************************/
 
-static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
+static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
+                                     Printer_entry *print_hnd,
+                                     struct spoolss_PrinterInfo7 *r,
+                                     int snum)
 {
-       char *guid_str = NULL;
        struct GUID guid;
 
        if (is_printer_published(print_hnd, snum, &guid)) {
-               if (asprintf(&guid_str, "{%s}",
-                            GUID_string(talloc_tos(), &guid)) == -1) {
-                       return false;
-               }
-               strupper_m(guid_str);
-               init_unistr(&printer->guid, guid_str);
-               SAFE_FREE(guid_str);
-               printer->action = DSPRINT_PUBLISH;
+               r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
+               r->action = DSPRINT_PUBLISH;
        } else {
-               init_unistr(&printer->guid, "");
-               printer->action = DSPRINT_UNPUBLISH;
+               r->guid = talloc_strdup(mem_ctx, "");
+               r->action = DSPRINT_UNPUBLISH;
        }
+       W_ERROR_HAVE_NO_MEMORY(r->guid);
 
-       return True;
+       return WERR_OK;
 }
 
 /********************************************************************
@@ -4589,6 +4448,14 @@ static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
+/********************************************************************
+********************************************************************/
+
+static bool snum_is_shared_printer(int snum)
+{
+       return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
+}
+
 /********************************************************************
  Spoolss_enumprinters.
 ********************************************************************/
@@ -4608,38 +4475,40 @@ static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
        *count = 0;
 
        for (snum=0; snum<n_services; snum++) {
-               if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
-
-                       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
-                       struct spoolss_PrinterInfo1 info1;
 
-                       DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
+               NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
+               struct spoolss_PrinterInfo1 info1;
 
-                       result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
-                       if (!W_ERROR_IS_OK(result)) {
-                               continue;
-                       }
+               if (!snum_is_shared_printer(snum)) {
+                       continue;
+               }
 
-                       result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
-                       free_a_printer(&ntprinter,2);
-                       if (!W_ERROR_IS_OK(result)) {
-                               continue;
-                       }
+               DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
 
-                       info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
-                                                   union spoolss_PrinterInfo,
-                                                   *count + 1);
-                       if (!info) {
-                               DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
-                               result = WERR_NOMEM;
-                               goto out;
-                       }
+               result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
+               if (!W_ERROR_IS_OK(result)) {
+                       continue;
+               }
 
-                       DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
+               result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
+               free_a_printer(&ntprinter,2);
+               if (!W_ERROR_IS_OK(result)) {
+                       continue;
+               }
 
-                       info[*count].info1 = info1;
-                       (*count)++;
+               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+                                           union spoolss_PrinterInfo,
+                                           *count + 1);
+               if (!info) {
+                       DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
+                       result = WERR_NOMEM;
+                       goto out;
                }
+
+               DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
+
+               info[*count].info1 = info1;
+               (*count)++;
        }
 
  out:
@@ -4805,39 +4674,41 @@ static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
        *count = 0;
 
        for (snum=0; snum<n_services; snum++) {
-               if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum)) {
 
-                       struct spoolss_PrinterInfo2 info2;
-                       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
+               struct spoolss_PrinterInfo2 info2;
+               NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
 
-                       DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
+               if (!snum_is_shared_printer(snum)) {
+                       continue;
+               }
 
-                       result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
-                       if (!W_ERROR_IS_OK(result)) {
-                               continue;
-                       }
+               DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
 
-                       result = construct_printer_info2(info, ntprinter, &info2, snum);
-                       free_a_printer(&ntprinter, 2);
-                       if (!W_ERROR_IS_OK(result)) {
-                               continue;
-                       }
+               result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
+               if (!W_ERROR_IS_OK(result)) {
+                       continue;
+               }
 
-                       info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
-                                                   union spoolss_PrinterInfo,
-                                                   *count + 1);
-                       if (!info) {
-                               DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
-                               result = WERR_NOMEM;
-                               goto out;
-                       }
+               result = construct_printer_info2(info, ntprinter, &info2, snum);
+               free_a_printer(&ntprinter, 2);
+               if (!W_ERROR_IS_OK(result)) {
+                       continue;
+               }
 
-                       DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
+               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+                                           union spoolss_PrinterInfo,
+                                           *count + 1);
+               if (!info) {
+                       DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
+                       result = WERR_NOMEM;
+                       goto out;
+               }
 
-                       info[*count].info2 = info2;
+               DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
 
-                       (*count)++;
-               }
+               info[*count].info2 = info2;
+
+               (*count)++;
        }
 
  out:
@@ -5001,356 +4872,88 @@ WERROR _spoolss_EnumPrinters(pipes_struct *p,
        return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
 }
 
-/****************************************************************************
-****************************************************************************/
-
-static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
-{
-       PRINTER_INFO_0 *printer=NULL;
-       WERROR result = WERR_OK;
-
-       if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
-               return WERR_NOMEM;
-
-       construct_printer_info_0(print_hnd, printer, snum);
-
-       /* check the required size. */
-       *needed += spoolss_size_printer_info_0(printer);
-
-       if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_NOMEM;
-               goto out;
-       }
-
-       /* fill the buffer with the structures */
-       smb_io_printer_info_0("", buffer, printer, 0);
-
-out:
-       /* clear memory */
-
-       SAFE_FREE(printer);
-
-       return result;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
-{
-       PRINTER_INFO_1 *printer=NULL;
-       WERROR result = WERR_OK;
-
-       if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
-               return WERR_NOMEM;
-
-       construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
-
-       /* check the required size. */
-       *needed += spoolss_size_printer_info_1(printer);
-
-       if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_NOMEM;
-               goto out;
-       }
-
-       /* fill the buffer with the structures */
-       smb_io_printer_info_1("", buffer, printer, 0);
-
-out:
-       /* clear memory */
-       SAFE_FREE(printer);
-
-       return result;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
-{
-       PRINTER_INFO_2 *printer=NULL;
-       WERROR result = WERR_OK;
-
-       if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
-               return WERR_NOMEM;
-
-       construct_printer_info_2(print_hnd, printer, snum);
-
-       /* check the required size. */
-       *needed += spoolss_size_printer_info_2(printer);
-
-       if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_NOMEM;
-               goto out;
-       }
-
-       /* fill the buffer with the structures */
-       if (!smb_io_printer_info_2("", buffer, printer, 0))
-               result = WERR_NOMEM;
-
-out:
-       /* clear memory */
-       free_printer_info_2(printer);
-
-       return result;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
-{
-       PRINTER_INFO_3 *printer=NULL;
-       WERROR result = WERR_OK;
-
-       if (!construct_printer_info_3(print_hnd, &printer, snum))
-               return WERR_NOMEM;
-
-       /* check the required size. */
-       *needed += spoolss_size_printer_info_3(printer);
-
-       if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_NOMEM;
-               goto out;
-       }
-
-       /* fill the buffer with the structures */
-       smb_io_printer_info_3("", buffer, printer, 0);
-
-out:
-       /* clear memory */
-       free_printer_info_3(printer);
-
-       return result;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
-{
-       PRINTER_INFO_4 *printer=NULL;
-       WERROR result = WERR_OK;
-
-       if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
-               return WERR_NOMEM;
-
-       if (!construct_printer_info_4(print_hnd, printer, snum)) {
-               SAFE_FREE(printer);
-               return WERR_NOMEM;
-       }
-
-       /* check the required size. */
-       *needed += spoolss_size_printer_info_4(printer);
-
-       if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_NOMEM;
-               goto out;
-       }
-
-       /* fill the buffer with the structures */
-       smb_io_printer_info_4("", buffer, printer, 0);
-
-out:
-       /* clear memory */
-       free_printer_info_4(printer);
-
-       return result;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
-{
-       PRINTER_INFO_5 *printer=NULL;
-       WERROR result = WERR_OK;
-
-       if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
-               return WERR_NOMEM;
-
-       if (!construct_printer_info_5(print_hnd, printer, snum)) {
-               free_printer_info_5(printer);
-               return WERR_NOMEM;
-       }
-
-       /* check the required size. */
-       *needed += spoolss_size_printer_info_5(printer);
-
-       if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_NOMEM;
-               goto out;
-       }
-
-       /* fill the buffer with the structures */
-       smb_io_printer_info_5("", buffer, printer, 0);
-
-out:
-       /* clear memory */
-       free_printer_info_5(printer);
-
-       return result;
-}
-
-static WERROR getprinter_level_6(Printer_entry *print_hnd,
-                                int snum,
-                                RPC_BUFFER *buffer, uint32 offered,
-                                uint32 *needed)
-{
-       PRINTER_INFO_6 *printer;
-       WERROR result = WERR_OK;
-
-       if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
-               return WERR_NOMEM;
-       }
-
-       if (!construct_printer_info_6(print_hnd, printer, snum)) {
-               free_printer_info_6(printer);
-               return WERR_NOMEM;
-       }
-
-       /* check the required size. */
-       *needed += spoolss_size_printer_info_6(printer);
-
-       if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_NOMEM;
-               goto out;
-       }
-
-       /* fill the buffer with the structures */
-       smb_io_printer_info_6("", buffer, printer, 0);
-
-out:
-       /* clear memory */
-       free_printer_info_6(printer);
-
-       return result;
-}
+/****************************************************************
+ _spoolss_GetPrinter
+****************************************************************/
 
-static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
+WERROR _spoolss_GetPrinter(pipes_struct *p,
+                          struct spoolss_GetPrinter *r)
 {
-       PRINTER_INFO_7 *printer=NULL;
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
        WERROR result = WERR_OK;
 
-       if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
-               return WERR_NOMEM;
-
-       if (!construct_printer_info_7(print_hnd, printer, snum)) {
-               result = WERR_NOMEM;
-               goto out;
-       }
-
-       /* check the required size. */
-       *needed += spoolss_size_printer_info_7(printer);
-
-       if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_NOMEM;
-               goto out;
-
-       }
-
-       /* fill the buffer with the structures */
-       smb_io_printer_info_7("", buffer, printer, 0);
-
-out:
-       /* clear memory */
-       free_printer_info_7(printer);
-
-       return result;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
-{
-       POLICY_HND *handle = &q_u->handle;
-       uint32 level = q_u->level;
-       RPC_BUFFER *buffer = NULL;
-       uint32 offered = q_u->offered;
-       uint32 *needed = &r_u->needed;
-       Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
-
        int snum;
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer && (offered!=0)) {
-               return WERR_INVALID_PARAM;
-       }
-
-       if (offered > MAX_RPC_DATA_SIZE) {
+       if (!r->in.buffer && (r->in.offered != 0)) {
                return WERR_INVALID_PARAM;
        }
 
-       rpcbuf_move(q_u->buffer, &r_u->buffer);
-       buffer = r_u->buffer;
-
-       *needed=0;
+       *r->out.needed = 0;
 
-       if (!get_printer_snum(p, handle, &snum, NULL))
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
                return WERR_BADFID;
+       }
 
-       switch (level) {
+       result = get_a_printer(Printer, &ntprinter, 2,
+                              lp_const_servicename(snum));
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
+       switch (r->in.level) {
        case 0:
-               return getprinter_level_0(Printer, snum, buffer, offered, needed);
+               result = construct_printer_info0(p->mem_ctx, ntprinter,
+                                                &r->out.info->info0, snum);
+               break;
        case 1:
-               return getprinter_level_1(Printer, snum, buffer, offered, needed);
+               result = construct_printer_info1(p->mem_ctx, ntprinter,
+                                                PRINTER_ENUM_ICON8,
+                                                &r->out.info->info1, snum);
+               break;
        case 2:
-               return getprinter_level_2(Printer, snum, buffer, offered, needed);
+               result = construct_printer_info2(p->mem_ctx, ntprinter,
+                                                &r->out.info->info2, snum);
+               break;
        case 3:
-               return getprinter_level_3(Printer, snum, buffer, offered, needed);
+               result = construct_printer_info3(p->mem_ctx, ntprinter,
+                                                &r->out.info->info3, snum);
+               break;
        case 4:
-               return getprinter_level_4(Printer, snum, buffer, offered, needed);
+               result = construct_printer_info4(p->mem_ctx, ntprinter,
+                                                &r->out.info->info4, snum);
+               break;
        case 5:
-               return getprinter_level_5(Printer, snum, buffer, offered, needed);
+               result = construct_printer_info5(p->mem_ctx, ntprinter,
+                                                &r->out.info->info5, snum);
+               break;
        case 6:
-               return getprinter_level_6(Printer, snum, buffer, offered, needed);
+               result = construct_printer_info6(p->mem_ctx, ntprinter,
+                                                &r->out.info->info6, snum);
+               break;
        case 7:
-               return getprinter_level_7(Printer, snum, buffer, offered, needed);
+               result = construct_printer_info7(p->mem_ctx, Printer,
+                                                &r->out.info->info7, snum);
+               break;
+       default:
+               result = WERR_UNKNOWN_LEVEL;
+               break;
        }
-       return WERR_UNKNOWN_LEVEL;
+
+       free_a_printer(&ntprinter, 2);
+
+       if (!W_ERROR_IS_OK(result)) {
+               TALLOC_FREE(r->out.info);
+               return result;
+       }
+
+       *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
+                                              r->out.info, r->in.level);
+       r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+
+       return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
 }
 
 /********************************************************************
@@ -10365,17 +9968,6 @@ WERROR _spoolss_AddPrinter(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_GetPrinter
-****************************************************************/
-
-WERROR _spoolss_GetPrinter(pipes_struct *p,
-                          struct spoolss_GetPrinter *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_GetPrinterDriver
 ****************************************************************/