s3-spoolss: cleanup _spoolss_EnumPrinterDrivers().
[kai/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
index 83522b46e50b883e3ed9c22216c7d10fc4455252..9abed16ed98401e6ed2418cf11d419bb7ca8d512 100644 (file)
@@ -7,6 +7,7 @@
  *  Copyright (C) Jeremy Allison               2001-2002,
  *  Copyright (C) Gerald Carter                       2000-2004,
  *  Copyright (C) Tim Potter                   2001-2002.
+ *  Copyright (C) Guenther Deschner                 2009.
  *
  *  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
@@ -26,6 +27,8 @@
    up, all the errors returned are DOS errors, not NT status codes. */
 
 #include "includes.h"
+#include "../librpc/gen_ndr/srv_spoolss.h"
+#include "../librpc/gen_ndr/cli_spoolss.h"
 
 /* macros stolen from s4 spoolss server */
 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
@@ -52,12 +55,6 @@ extern userdom_struct current_user_info;
 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
 
-struct table_node {
-       const char    *long_archi;
-       const char    *short_archi;
-       int     version;
-};
-
 static Printer_entry *printers_list;
 
 typedef struct _counter_printer_0 {
@@ -65,13 +62,13 @@ typedef struct _counter_printer_0 {
        struct _counter_printer_0 *prev;
 
        int snum;
-       uint32 counter;
+       uint32_t counter;
 } counter_printer_0;
 
 static counter_printer_0 *counter_list;
 
 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
-static uint32 smb_connections=0;
+static uint32_t smb_connections = 0;
 
 
 /* in printing/nt_printing.c */
@@ -147,7 +144,7 @@ static int nt_printq_status(int v)
  Disconnect from the client
 ****************************************************************************/
 
-static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
+static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
 {
        WERROR result;
        NTSTATUS status;
@@ -185,7 +182,7 @@ static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
                /* Tell the connections db we're no longer interested in
                 * printer notify messages. */
 
-               register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
+               register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
        }
 
        smb_connections--;
@@ -197,7 +194,7 @@ static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
 
 static int printer_entry_destructor(Printer_entry *Printer)
 {
-       if (Printer->notify.client_connected==True) {
+       if (Printer->notify.client_connected == true) {
                int snum = -1;
 
                if ( Printer->printer_type == SPLHND_SERVER) {
@@ -216,7 +213,7 @@ static int printer_entry_destructor(Printer_entry *Printer)
        Printer->notify.localmachine[0]='\0';
        Printer->notify.printerlocal=0;
        TALLOC_FREE(Printer->notify.option);
-       Printer->notify.client_connected=False;
+       Printer->notify.client_connected = false;
 
        free_nt_devicemode( &Printer->nt_devmode );
        free_a_printer( &Printer->printer_info, 2 );
@@ -230,7 +227,8 @@ static int printer_entry_destructor(Printer_entry *Printer)
   find printer index by handle
 ****************************************************************************/
 
-static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
+static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
+                                               struct policy_handle *hnd)
 {
        Printer_entry *find_printer = NULL;
 
@@ -246,31 +244,32 @@ static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd
  Close printer index by handle.
 ****************************************************************************/
 
-static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
+static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
 {
        Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
 
        if (!Printer) {
-               DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
-               return False;
+               DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
+                       OUR_HANDLE(hnd)));
+               return false;
        }
 
        close_policy_hnd(p, hnd);
 
-       return True;
+       return true;
 }
 
 /****************************************************************************
  Delete a printer given a handle.
 ****************************************************************************/
 
-WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
+static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
 {
        char *cmd = lp_deleteprinter_cmd();
        char *command = NULL;
        int ret;
        SE_PRIV se_printop = SE_PRINT_OPERATOR;
-       bool is_print_op = False;
+       bool is_print_op = false;
 
        /* can't fail if we don't try */
 
@@ -312,7 +311,9 @@ WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sh
                return WERR_BADFID; /* What to return here? */
 
        /* go ahead and re-read the services immediately */
-       reload_services( False );
+       become_root();
+       reload_services(false);
+       unbecome_root();
 
        if ( lp_servicenumber( sharename )  < 0 )
                return WERR_ACCESS_DENIED;
@@ -324,12 +325,13 @@ WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sh
  Delete a printer given a handle.
 ****************************************************************************/
 
-static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
+static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
 {
        Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
 
        if (!Printer) {
-               DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
+               DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
+                       OUR_HANDLE(hnd)));
                return WERR_BADFID;
        }
 
@@ -361,14 +363,15 @@ static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
  Return the snum of a printer corresponding to an handle.
 ****************************************************************************/
 
-static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
-                            struct share_params **params)
+static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
+                            int *number, struct share_params **params)
 {
        Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
 
        if (!Printer) {
-               DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
-               return False;
+               DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
+                       OUR_HANDLE(hnd)));
+               return false;
        }
 
        switch (Printer->printer_type) {
@@ -377,9 +380,9 @@ static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
                        *number = print_queue_snum(Printer->sharename);
                        return (*number != -1);
                case SPLHND_SERVER:
-                       return False;
+                       return false;
                default:
-                       return False;
+                       return false;
        }
 }
 
@@ -388,13 +391,13 @@ static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
  Check if it's \\server or \\server\printer
 ****************************************************************************/
 
-static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
+static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
 {
        DEBUG(3,("Setting printer type=%s\n", handlename));
 
        if ( strlen(handlename) < 3 ) {
                DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
-               return False;
+               return false;
        }
 
        /* it's a print server */
@@ -408,7 +411,7 @@ static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename
                Printer->printer_type = SPLHND_PRINTER;
        }
 
-       return True;
+       return true;
 }
 
 /****************************************************************************
@@ -418,20 +421,21 @@ static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename
  XcvDataPort() interface.
 ****************************************************************************/
 
-static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
+static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
 {
        int snum;
        int n_services=lp_numservices();
        char *aprinter, *printername;
        const char *servername;
        fstring sname;
-       bool found=False;
+       bool found = false;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
        WERROR result;
 
-       DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
+       DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
+               (unsigned long)strlen(handlename)));
 
-       aprinter = handlename;
+       aprinter = CONST_DISCARD(char *, handlename);
        if ( *handlename == '\\' ) {
                servername = canon_servername(handlename);
                if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
@@ -439,21 +443,21 @@ static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
                        aprinter++;
                }
        } else {
-               servername = "";
+               servername = global_myname();
        }
 
        /* save the servername to fill in replies on this handle */
 
        if ( !is_myname_or_ipaddr( servername ) )
-               return False;
+               return false;
 
        fstrcpy( Printer->servername, servername );
 
        if ( Printer->printer_type == SPLHND_SERVER )
-               return True;
+               return true;
 
        if ( Printer->printer_type != SPLHND_PRINTER )
-               return False;
+               return false;
 
        DEBUGADD(5, ("searching for [%s]\n", aprinter ));
 
@@ -462,12 +466,12 @@ static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
        if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
                Printer->printer_type = SPLHND_PORTMON_TCP;
                fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
-               found = True;
+               found = true;
        }
        else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
                Printer->printer_type = SPLHND_PORTMON_LOCAL;
                fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
-               found = True;
+               found = true;
        }
 
        /* Search all sharenames first as this is easier than pulling
@@ -485,7 +489,7 @@ static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
 
                fstrcpy(sname, lp_servicename(snum));
                if ( strequal( aprinter, sname ) ) {
-                       found = True;
+                       found = true;
                        break;
                }
 
@@ -523,7 +527,7 @@ static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
 
                if ( strequal(printername, aprinter) ) {
                        free_a_printer( &printer, 2);
-                       found = True;
+                       found = true;
                        break;
                }
 
@@ -536,21 +540,22 @@ static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
 
        if ( !found ) {
                DEBUGADD(4,("Printer not found\n"));
-               return False;
+               return false;
        }
 
        DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
 
        fstrcpy(Printer->sharename, sname);
 
-       return True;
+       return true;
 }
 
 /****************************************************************************
  Find first available printer slot. creates a printer handle for you.
  ****************************************************************************/
 
-static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
+static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
+                            const char *name, uint32_t access_granted)
 {
        Printer_entry *new_printer;
 
@@ -564,7 +569,7 @@ static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint3
 
        if (!create_policy_hnd(p, hnd, new_printer)) {
                TALLOC_FREE(new_printer);
-               return False;
+               return false;
        }
 
        /* Add to the internal list. */
@@ -574,19 +579,20 @@ static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint3
 
        if (!set_printer_hnd_printertype(new_printer, name)) {
                close_printer_handle(p, hnd);
-               return False;
+               return false;
        }
 
        if (!set_printer_hnd_name(new_printer, name)) {
                close_printer_handle(p, hnd);
-               return False;
+               return false;
        }
 
        new_printer->access_granted = access_granted;
 
-       DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
+       DEBUG(5, ("%d printer handles active\n",
+                 (int)num_pipe_handles(p->pipe_handles)));
 
-       return True;
+       return true;
 }
 
 /***************************************************************************
@@ -594,17 +600,17 @@ static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint3
  given by (notify_type, notify_field).
  **************************************************************************/
 
-static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
-                                     uint16 notify_field)
+static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
+                                     uint16_t notify_field)
 {
-       return True;
+       return true;
 }
 
-static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
-                               uint16 notify_field)
+static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
+                               uint16_t notify_field)
 {
        struct spoolss_NotifyOption *option = p->notify.option;
-       uint32 i, j;
+       uint32_t i, j;
 
        /*
         * Flags should always be zero when the change notify
@@ -614,7 +620,7 @@ static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
         */
 
        if (!option) {
-               return False;
+               return false;
        }
 
        if (p->notify.flags)
@@ -632,7 +638,7 @@ static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
 
                for (j = 0; j < option->types[i].count; j++) {
                        if (option->types[i].fields[j].field == notify_field) {
-                               return True;
+                               return true;
                        }
                }
        }
@@ -640,7 +646,7 @@ static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
        DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
                   p->servername, p->sharename, notify_type, notify_field));
 
-       return False;
+       return false;
 }
 
 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
@@ -749,52 +755,52 @@ struct notify2_message_table {
 };
 
 static struct notify2_message_table printer_notify_table[] = {
-       /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
-       /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
-       /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
-       /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
-       /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
-       /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
-       /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
-       /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
-       /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
-       /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
-       /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
-       /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
-       /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
-       /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
-       /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
-       /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
-       /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
-       /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
-       /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
+       /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
+       /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
+       /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
+       /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
+       /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
+       /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
+       /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
+       /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
+       /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
+       /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
+       /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
+       /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
+       /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
+       /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
+       /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
+       /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
+       /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
+       /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
+       /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
 };
 
 static struct notify2_message_table job_notify_table[] = {
-       /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
-       /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
-       /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
-       /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
-       /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
-       /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
-       /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
-       /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
-       /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
-       /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
-       /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
-       /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
-       /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
-       /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
-       /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
-       /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
-       /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
-       /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
-       /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
-       /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
-       /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
-       /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
-       /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
-       /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
+       /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
+       /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
+       /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
+       /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
+       /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
+       /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
+       /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
+       /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
+       /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
+       /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
+       /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
+       /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
+       /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
+       /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
+       /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
+       /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
+       /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
+       /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
+       /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
+       /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
+       /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
+       /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
+       /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
+       /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
 };
 
 
@@ -843,7 +849,7 @@ static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
 /***********************************************************************
  **********************************************************************/
 
-static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
+static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
 {
        if ( !ctr || !ctr->msg_groups )
                return NULL;
@@ -934,7 +940,7 @@ static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MS
  back registered
  **********************************************************************/
 
-static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
+static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
 {
        Printer_entry            *p;
        TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
@@ -1107,23 +1113,23 @@ done:
 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
 {
 
-       uint32 tv_sec, tv_usec;
+       uint32_t tv_sec, tv_usec;
        size_t offset = 0;
 
        /* Unpack message */
 
-       offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
+       offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
                             msg->printer);
 
-       offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
+       offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
                                &tv_sec, &tv_usec,
                                &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
 
        if (msg->len == 0)
-               tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
+               tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
                           &msg->notify.value[0], &msg->notify.value[1]);
        else
-               tdb_unpack((uint8 *)buf + offset, len - offset, "B",
+               tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
                           &msg->len, &msg->notify.data);
 
        DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
@@ -1136,9 +1142,9 @@ static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, voi
                DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
                          msg->notify.value[1]));
        else
-               dump_data(3, (uint8 *)msg->notify.data, msg->len);
+               dump_data(3, (uint8_t *)msg->notify.data, msg->len);
 
-       return True;
+       return true;
 }
 
 /********************************************************************
@@ -1227,7 +1233,8 @@ static void receive_notify2_message_list(struct messaging_context *msg,
 
        /* cleanup */
 
-       DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
+       DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
+               (uint32_t)msg_count ));
 
        notify_msg_ctr_destroy( &messages );
 
@@ -1240,21 +1247,21 @@ static void receive_notify2_message_list(struct messaging_context *msg,
  driver
  ********************************************************************/
 
-static bool srv_spoolss_drv_upgrade_printer(char* drivername)
+static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
 {
        int len = strlen(drivername);
 
        if (!len)
-               return False;
+               return false;
 
        DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
                drivername));
 
        messaging_send_buf(smbd_messaging_context(), procid_self(),
                           MSG_PRINTER_DRVUPGRADE,
-                          (uint8 *)drivername, len+1);
+                          (uint8_t *)drivername, len+1);
 
-       return True;
+       return true;
 }
 
 /**********************************************************************
@@ -1322,7 +1329,7 @@ void update_monitored_printq_cache( void )
        int snum;
 
        /* loop through all printers and update the cache where
-          client_connected == True */
+          client_connected == true */
        while ( printer )
        {
                if ( (printer->printer_type == SPLHND_PRINTER)
@@ -1348,16 +1355,16 @@ static bool srv_spoolss_reset_printerdata(char* drivername)
        int len = strlen(drivername);
 
        if (!len)
-               return False;
+               return false;
 
        DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
                drivername));
 
        messaging_send_buf(smbd_messaging_context(), procid_self(),
                           MSG_PRINTERDATA_INIT_RESET,
-                          (uint8 *)drivername, len+1);
+                          (uint8_t *)drivername, len+1);
 
-       return True;
+       return true;
 }
 
 /**********************************************************************
@@ -1477,8 +1484,11 @@ bool convert_devicemode(const char *printername,
                        return false;
        }
 
-       rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
-       rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
+       fstrcpy(nt_devmode->devicename, devmode->devicename);
+       fstrcpy(nt_devmode->formname, devmode->formname);
+
+       nt_devmode->devicename[31] = '\0';
+       nt_devmode->formname[31] = '\0';
 
        nt_devmode->specversion         = devmode->specversion;
        nt_devmode->driverversion       = devmode->driverversion;
@@ -1521,7 +1531,7 @@ bool convert_devicemode(const char *printername,
        if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
                SAFE_FREE(nt_devmode->nt_dev_private);
                nt_devmode->driverextra = devmode->__driverextra_length;
-               if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
+               if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
                        return false;
                memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
        }
@@ -1538,30 +1548,28 @@ bool convert_devicemode(const char *printername,
 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
                              struct spoolss_OpenPrinterEx *r)
 {
-       POLICY_HND              *handle = r->out.handle;
-       char *name = CONST_DISCARD(char *, r->in.printername);
        int snum;
        Printer_entry *Printer=NULL;
 
-       if (!name) {
+       if (!r->in.printername) {
                return WERR_INVALID_PARAM;
        }
 
        /* some sanity check because you can open a printer or a print server */
        /* aka: \\server\printer or \\server */
 
-       DEBUGADD(3,("checking name: %s\n",name));
+       DEBUGADD(3,("checking name: %s\n", r->in.printername));
 
-       if (!open_printer_hnd(p, handle, name, 0)) {
+       if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
                ZERO_STRUCTP(r->out.handle);
                return WERR_INVALID_PARAM;
        }
 
-       Printer=find_printer_index_by_hnd(p, handle);
+       Printer = find_printer_index_by_hnd(p, r->out.handle);
        if ( !Printer ) {
                DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
-                       "handle we created for printer %s\n", name ));
-               close_printer_handle(p,handle);
+                       "handle we created for printer %s\n", r->in.printername));
+               close_printer_handle(p, r->out.handle);
                ZERO_STRUCTP(r->out.handle);
                return WERR_INVALID_PARAM;
        }
@@ -1612,7 +1620,7 @@ WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
                if (r->in.access_mask &
                    ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
                        DEBUG(3, ("access DENIED for non-printserver bits\n"));
-                       close_printer_handle(p, handle);
+                       close_printer_handle(p, r->out.handle);
                        ZERO_STRUCTP(r->out.handle);
                        return WERR_ACCESS_DENIED;
                }
@@ -1624,7 +1632,7 @@ WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
                        SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
                        if (!lp_ms_add_printer_wizard()) {
-                               close_printer_handle(p, handle);
+                               close_printer_handle(p, r->out.handle);
                                ZERO_STRUCTP(r->out.handle);
                                return WERR_ACCESS_DENIED;
                        }
@@ -1632,7 +1640,7 @@ WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
                        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
                           and not a printer admin, then fail */
 
-                       if ((p->server_info->utok.uid != 0) &&
+                       if ((p->server_info->utok.uid != sec_initial_uid()) &&
                            !user_has_privileges(p->server_info->ptok,
                                                 &se_printop ) &&
                            !token_contains_name_in_list(
@@ -1640,7 +1648,7 @@ WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
                                    NULL, NULL,
                                    p->server_info->ptok,
                                    lp_printer_admin(snum))) {
-                               close_printer_handle(p, handle);
+                               close_printer_handle(p, r->out.handle);
                                ZERO_STRUCTP(r->out.handle);
                                return WERR_ACCESS_DENIED;
                        }
@@ -1662,12 +1670,16 @@ WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
                /* NT doesn't let us connect to a printer if the connecting user
                   doesn't have print permission.  */
 
-               if (!get_printer_snum(p, handle, &snum, NULL)) {
-                       close_printer_handle(p, handle);
+               if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
+                       close_printer_handle(p, r->out.handle);
                        ZERO_STRUCTP(r->out.handle);
                        return WERR_BADFID;
                }
 
+               if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
+                       r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
+               }
+
                se_map_standard(&r->in.access_mask, &printer_std_mapping);
 
                /* map an empty access mask to the minimum access mask */
@@ -1699,14 +1711,14 @@ WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
                    !print_access_check(p->server_info, snum,
                                        r->in.access_mask)) {
                        DEBUG(3, ("access DENIED for printer open\n"));
-                       close_printer_handle(p, handle);
+                       close_printer_handle(p, r->out.handle);
                        ZERO_STRUCTP(r->out.handle);
                        return WERR_ACCESS_DENIED;
                }
 
                if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
                        DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
-                       close_printer_handle(p, handle);
+                       close_printer_handle(p, r->out.handle);
                        ZERO_STRUCTP(r->out.handle);
                        return WERR_ACCESS_DENIED;
                }
@@ -1823,201 +1835,6 @@ static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
        return false;
 }
 
-/*******************************************************************
-********************************************************************/
-
-static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
-{
-       int i;
-
-       if (!sarray) {
-               *farray = NULL;
-               return true;
-       }
-
-       *farray = SMB_MALLOC_ARRAY(fstring, 1);
-       if (!*farray) {
-               return false;
-       }
-
-       for (i=0; sarray[i] != NULL; i++) {
-               *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
-               if (!*farray) {
-                       return false;
-               }
-               fstrcpy((*farray)[i], sarray[i]);
-       }
-
-       fstrcpy((*farray)[i], "");
-
-       return true;
-}
-
-/*******************************************************************
-********************************************************************/
-
-static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
-                                           NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
-{
-       NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
-
-       DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
-
-       if (*p == NULL) {
-               *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
-               if (*p == NULL) {
-                       return false;
-               }
-               ZERO_STRUCTP(*p);
-       }
-
-       d = *p;
-
-       d->cversion =                   r->version;
-
-       fstrcpy(d->name,                r->driver_name);
-       fstrcpy(d->environment,         r->architecture);
-       fstrcpy(d->driverpath,          r->driver_path);
-       fstrcpy(d->datafile,            r->data_file);
-       fstrcpy(d->configfile,          r->config_file);
-       fstrcpy(d->helpfile,            r->help_file);
-       fstrcpy(d->monitorname,         r->monitor_name);
-       fstrcpy(d->defaultdatatype,     r->default_datatype);
-
-       DEBUGADD(8,( "version:         %d\n", d->cversion));
-       DEBUGADD(8,( "name:            %s\n", d->name));
-       DEBUGADD(8,( "environment:     %s\n", d->environment));
-       DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
-       DEBUGADD(8,( "datafile:        %s\n", d->datafile));
-       DEBUGADD(8,( "configfile:      %s\n", d->configfile));
-       DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
-       DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
-       DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
-
-       if (r->dependent_files) {
-               if (!string_array_to_fstring_array(r->dependent_files->string,
-                                                  &d->dependentfiles)) {
-                       SAFE_FREE(*p);
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-/*******************************************************************
-********************************************************************/
-
-static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
-                                           NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
-{
-       NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
-
-       DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
-
-       if (*p == NULL) {
-               *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
-               if (*p == NULL) {
-                       return false;
-               }
-               ZERO_STRUCTP(*p);
-       }
-
-       d = *p;
-
-       d->version =                    r->version;
-
-       fstrcpy(d->name,                r->driver_name);
-       fstrcpy(d->environment,         r->architecture);
-       fstrcpy(d->driverpath,          r->driver_path);
-       fstrcpy(d->datafile,            r->data_file);
-       fstrcpy(d->configfile,          r->config_file);
-       fstrcpy(d->helpfile,            r->help_file);
-       fstrcpy(d->monitorname,         r->monitor_name);
-       fstrcpy(d->defaultdatatype,     r->default_datatype);
-
-       DEBUGADD(8,( "version:         %d\n", d->version));
-       DEBUGADD(8,( "name:            %s\n", d->name));
-       DEBUGADD(8,( "environment:     %s\n", d->environment));
-       DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
-       DEBUGADD(8,( "datafile:        %s\n", d->datafile));
-       DEBUGADD(8,( "configfile:      %s\n", d->configfile));
-       DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
-       DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
-       DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
-
-       if (r->dependent_files) {
-               if (!string_array_to_fstring_array(r->dependent_files->string,
-                                                  &d->dependentfiles)) {
-                       goto error;
-               }
-       }
-
-       if (r->previous_names) {
-               if (!string_array_to_fstring_array(r->previous_names->string,
-                                                  &d->previousnames)) {
-                       goto error;
-               }
-       }
-
-       return true;
-
- error:
-       SAFE_FREE(*p);
-       return false;
-}
-
-/********************************************************************
- ********************************************************************/
-
-static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
-                                       NT_PRINTER_DRIVER_INFO_LEVEL *printer,
-                                       uint32_t level)
-{
-       switch (level) {
-       case 3:
-               printer->info_3 = NULL;
-               if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
-                       return false;
-               }
-               break;
-       case 6:
-               printer->info_6 = NULL;
-               if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
-                       return false;
-               }
-               break;
-       default:
-               return false;
-       }
-
-       return true;
-}
-
-/********************************************************************
- * _spoolss_enddocprinter_internal.
- ********************************************************************/
-
-static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
-{
-       Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
-       int snum;
-
-       if (!Printer) {
-               DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
-               return WERR_BADFID;
-       }
-
-       if (!get_printer_snum(p, handle, &snum, NULL))
-               return WERR_BADFID;
-
-       Printer->document_started=False;
-       print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
-       /* error codes unhandled so far ... */
-
-       return WERR_OK;
-}
-
 /****************************************************************
  _spoolss_ClosePrinter
 ****************************************************************/
@@ -2025,14 +1842,17 @@ static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handl
 WERROR _spoolss_ClosePrinter(pipes_struct *p,
                             struct spoolss_ClosePrinter *r)
 {
-       POLICY_HND *handle = r->in.handle;
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
-       Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+       if (Printer && Printer->document_started) {
+               struct spoolss_EndDocPrinter e;
 
-       if (Printer && Printer->document_started)
-               _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
+               e.in.handle = r->in.handle;
+
+               _spoolss_EndDocPrinter(p, &e);
+       }
 
-       if (!close_printer_handle(p, handle))
+       if (!close_printer_handle(p, r->in.handle))
                return WERR_BADFID;
 
        /* clear the returned printer handle.  Observed behavior
@@ -2052,16 +1872,20 @@ WERROR _spoolss_ClosePrinter(pipes_struct *p,
 WERROR _spoolss_DeletePrinter(pipes_struct *p,
                              struct spoolss_DeletePrinter *r)
 {
-       POLICY_HND *handle = r->in.handle;
-       Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
        WERROR result;
 
-       if (Printer && Printer->document_started)
-               _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
+       if (Printer && Printer->document_started) {
+               struct spoolss_EndDocPrinter e;
+
+               e.in.handle = r->in.handle;
+
+               _spoolss_EndDocPrinter(p, &e);
+       }
 
-       result = delete_printer_handle(p, handle);
+       result = delete_printer_handle(p, r->in.handle);
 
-       update_c_setprinter(False);
+       update_c_setprinter(false);
 
        return result;
 }
@@ -2071,20 +1895,21 @@ WERROR _spoolss_DeletePrinter(pipes_struct *p,
  * long architecture string
  ******************************************************************/
 
-static int get_version_id (char * arch)
+static const struct print_architecture_table_node archi_table[]= {
+
+       {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
+       {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
+       {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
+       {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
+       {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
+       {"Windows IA64",         SPL_ARCH_IA64,         3 },
+       {"Windows x64",          SPL_ARCH_X64,          3 },
+       {NULL,                   "",            -1 }
+};
+
+static int get_version_id(const char *arch)
 {
        int i;
-       struct table_node archi_table[]= {
-
-               {"Windows 4.0",          "WIN40",       0 },
-               {"Windows NT x86",       "W32X86",      2 },
-               {"Windows NT R4000",     "W32MIPS",     2 },
-               {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
-               {"Windows NT PowerPC",   "W32PPC",      2 },
-               {"Windows IA64",         "IA64",        3 },
-               {"Windows x64",          "x64",         3 },
-               {NULL,                   "",            -1 }
-       };
 
        for (i=0; archi_table[i].long_archi != NULL; i++)
        {
@@ -2102,10 +1927,9 @@ static int get_version_id (char * arch)
 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
                                    struct spoolss_DeletePrinterDriver *r)
 {
-       char *driver;
-       char *arch;
-       NT_PRINTER_DRIVER_INFO_LEVEL    info;
-       NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
+
+       struct spoolss_DriverInfo8 *info = NULL;
+       struct spoolss_DriverInfo8 *info_win2k = NULL;
        int                             version;
        WERROR                          status;
        WERROR                          status_win2k = WERR_ACCESS_DENIED;
@@ -2114,7 +1938,7 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
 
-       if ( (p->server_info->utok.uid != 0)
+       if ( (p->server_info->utok.uid != sec_initial_uid())
                && !user_has_privileges(p->server_info->ptok, &se_printop )
                && !token_contains_name_in_list(
                        uidtoname(p->server_info->utok.uid), NULL,
@@ -2124,24 +1948,24 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       driver = CONST_DISCARD(char *, r->in.driver);
-       arch   = CONST_DISCARD(char *, r->in.architecture);
-
        /* check that we have a valid driver name first */
 
-       if ((version=get_version_id(arch)) == -1)
+       if ((version = get_version_id(r->in.architecture)) == -1)
                return WERR_INVALID_ENVIRONMENT;
 
-       ZERO_STRUCT(info);
-       ZERO_STRUCT(info_win2k);
-
-       if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
+       if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
+                                               r->in.architecture,
+                                               version)))
        {
                /* try for Win2k driver if "Windows NT x86" */
 
                if ( version == 2 ) {
                        version = 3;
-                       if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
+                       if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
+                                                               &info,
+                                                               r->in.driver,
+                                                               r->in.architecture,
+                                                               version))) {
                                status = WERR_UNKNOWN_PRINTER_DRIVER;
                                goto done;
                        }
@@ -2154,21 +1978,24 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
 
        }
 
-       if (printer_driver_in_use(info.info_3)) {
+       if (printer_driver_in_use(info)) {
                status = WERR_PRINTER_DRIVER_IN_USE;
                goto done;
        }
 
        if ( version == 2 )
        {
-               if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
+               if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
+                                                      &info_win2k,
+                                                      r->in.driver,
+                                                      r->in.architecture, 3)))
                {
                        /* if we get to here, we now have 2 driver info structures to remove */
                        /* remove the Win2k driver first*/
 
                        status_win2k = delete_printer_driver(
-                               p, info_win2k.info_3, 3, False );
-                       free_a_printer_driver( info_win2k, 3 );
+                               p, info_win2k, 3, false);
+                       free_a_printer_driver(info_win2k);
 
                        /* this should not have failed---if it did, report to client */
                        if ( !W_ERROR_IS_OK(status_win2k) )
@@ -2179,7 +2006,7 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
                }
        }
 
-       status = delete_printer_driver(p, info.info_3, version, False);
+       status = delete_printer_driver(p, info, version, false);
 
        /* if at least one of the deletes succeeded return OK */
 
@@ -2187,7 +2014,7 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
                status = WERR_OK;
 
 done:
-       free_a_printer_driver( info, 3 );
+       free_a_printer_driver(info);
 
        return status;
 }
@@ -2199,12 +2026,9 @@ done:
 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
                                      struct spoolss_DeletePrinterDriverEx *r)
 {
-       char *driver;
-       char *arch;
-       NT_PRINTER_DRIVER_INFO_LEVEL    info;
-       NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
+       struct spoolss_DriverInfo8      *info = NULL;
+       struct spoolss_DriverInfo8      *info_win2k = NULL;
        int                             version;
-       uint32_t                        flags = r->in.delete_flags;
        bool                            delete_files;
        WERROR                          status;
        WERROR                          status_win2k = WERR_ACCESS_DENIED;
@@ -2213,7 +2037,7 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
           and not a printer admin, then fail */
 
-       if ( (p->server_info->utok.uid != 0)
+       if ( (p->server_info->utok.uid != sec_initial_uid())
                && !user_has_privileges(p->server_info->ptok, &se_printop )
                && !token_contains_name_in_list(
                        uidtoname(p->server_info->utok.uid), NULL, NULL,
@@ -2222,22 +2046,17 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       driver = CONST_DISCARD(char *, r->in.driver);
-       arch   = CONST_DISCARD(char *, r->in.architecture);
-
        /* check that we have a valid driver name first */
-       if ((version=get_version_id(arch)) == -1) {
+       if ((version = get_version_id(r->in.architecture)) == -1) {
                /* this is what NT returns */
                return WERR_INVALID_ENVIRONMENT;
        }
 
-       if ( flags & DPD_DELETE_SPECIFIC_VERSION )
+       if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
                version = r->in.version;
 
-       ZERO_STRUCT(info);
-       ZERO_STRUCT(info_win2k);
-
-       status = get_a_printer_driver(&info, 3, driver, arch, version);
+       status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
+                                     r->in.architecture, version);
 
        if ( !W_ERROR_IS_OK(status) )
        {
@@ -2247,19 +2066,21 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
                 * then we've failed
                 */
 
-               if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
+               if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
                        goto done;
 
                /* try for Win2k driver if "Windows NT x86" */
 
                version = 3;
-               if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
+               if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
+                                                       r->in.architecture,
+                                                       version))) {
                        status = WERR_UNKNOWN_PRINTER_DRIVER;
                        goto done;
                }
        }
 
-       if ( printer_driver_in_use(info.info_3) ) {
+       if (printer_driver_in_use(info)) {
                status = WERR_PRINTER_DRIVER_IN_USE;
                goto done;
        }
@@ -2276,11 +2097,11 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
         * Refer to MSDN docs on DeletePrinterDriverEx() for details.
         */
 
-       delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
+       delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
 
        /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
 
-       if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
+       if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
                /* no idea of the correct error here */
                status = WERR_ACCESS_DENIED;
                goto done;
@@ -2289,13 +2110,15 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
 
        /* also check for W32X86/3 if necessary; maybe we already have? */
 
-       if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
-               if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
+       if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
+               if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
+                                                      r->in.driver,
+                                                      r->in.architecture, 3)))
                {
 
-                       if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
+                       if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
                                /* no idea of the correct error here */
-                               free_a_printer_driver( info_win2k, 3 );
+                               free_a_printer_driver(info_win2k);
                                status = WERR_ACCESS_DENIED;
                                goto done;
                        }
@@ -2304,8 +2127,8 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
                        /* remove the Win2k driver first*/
 
                        status_win2k = delete_printer_driver(
-                               p, info_win2k.info_3, 3, delete_files);
-                       free_a_printer_driver( info_win2k, 3 );
+                               p, info_win2k, 3, delete_files);
+                       free_a_printer_driver(info_win2k);
 
                        /* this should not have failed---if it did, report to client */
 
@@ -2314,12 +2137,12 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
                }
        }
 
-       status = delete_printer_driver(p, info.info_3, version, delete_files);
+       status = delete_printer_driver(p, info, version, delete_files);
 
        if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
                status = WERR_OK;
 done:
-       free_a_printer_driver( info, 3 );
+       free_a_printer_driver(info);
 
        return status;
 }
@@ -2338,8 +2161,9 @@ static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char
  Internal routine for storing printerdata
  ***************************************************************************/
 
-WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
-                                  uint32 type, uint8 *data, int real_len  )
+WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
+                         const char *key, const char *value,
+                         uint32_t type, uint8_t *data, int real_len)
 {
        /* the registry objects enforce uniqueness based on value name */
 
@@ -2406,10 +2230,10 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
        }
 
        /* REG_BINARY
-        *  uint32 size          = 0x114
-        *  uint32 major         = 5
-        *  uint32 minor         = [0|1]
-        *  uint32 build         = [2195|2600]
+        *  uint32_t size        = 0x114
+        *  uint32_t major       = 5
+        *  uint32_t minor       = [0|1]
+        *  uint32_t build       = [2195|2600]
         *  extra unicode string = e.g. "Service Pack 3"
         */
        if (!StrCaseCmp(value, "OSVersion")) {
@@ -2481,7 +2305,9 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
                return WERR_OK;
        }
 
-       return WERR_BADFILE;
+       *type = REG_NONE;
+
+       return WERR_INVALID_PARAM;
 }
 
 /****************************************************************
@@ -2491,92 +2317,17 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
 WERROR _spoolss_GetPrinterData(pipes_struct *p,
                               struct spoolss_GetPrinterData *r)
 {
-       WERROR result;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
-       int snum = 0;
-
-       /*
-        * Reminder: when it's a string, the length is in BYTES
-        * even if UNICODE is negociated.
-        *
-        * JFM, 4/19/1999
-        */
-
-       /* in case of problem, return some default values */
-
-       *r->out.needed  = 0;
-       *r->out.type    = 0;
-
-       DEBUG(4,("_spoolss_GetPrinterData\n"));
-
-       if (!Printer) {
-               DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
-                       OUR_HANDLE(r->in.handle)));
-               result = WERR_BADFID;
-               goto done;
-       }
-
-       if (Printer->printer_type == SPLHND_SERVER) {
-               result = getprinterdata_printer_server(p->mem_ctx,
-                                                      r->in.value_name,
-                                                      r->out.type,
-                                                      r->out.data);
-       } else {
-               if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-                       result = WERR_BADFID;
-                       goto done;
-               }
-
-               result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
-               if (!W_ERROR_IS_OK(result)) {
-                       goto done;
-               }
-
-               /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
-
-               if (strequal(r->in.value_name, "ChangeId")) {
-                       *r->out.type = REG_DWORD;
-                       r->out.data->value = printer->info_2->changeid;
-                       result = WERR_OK;
-               } else {
-                       REGISTRY_VALUE *v;
-                       DATA_BLOB blob;
-
-                       v = get_printer_data(printer->info_2,
-                                            SPOOL_PRINTERDATA_KEY,
-                                            r->in.value_name);
-                       if (!v) {
-                               result = WERR_BADFILE;
-                               goto done;
-                       }
-
-                       *r->out.type = v->type;
-
-                       blob = data_blob_const(v->data_p, v->size);
-
-                       result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
-                                                         r->out.data,
-                                                         *r->out.type);
-               }
-       }
-
- done:
-       /* cleanup & exit */
-
-       if (printer) {
-               free_a_printer(&printer, 2);
-       }
-
-       if (!W_ERROR_IS_OK(result)) {
-               return result;
-       }
+       struct spoolss_GetPrinterDataEx r2;
 
-       *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
-       *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
-       r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
+       r2.in.handle            = r->in.handle;
+       r2.in.key_name          = "PrinterDriverData";
+       r2.in.value_name        = r->in.value_name;
+       r2.in.offered           = r->in.offered;
+       r2.out.type             = r->out.type;
+       r2.out.data             = r->out.data;
+       r2.out.needed           = r->out.needed;
 
-       return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
+       return _spoolss_GetPrinterDataEx(p, &r2);
 }
 
 /*********************************************************
@@ -2591,14 +2342,14 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
        struct sockaddr_storage rm_addr;
 
        if ( is_zero_addr((struct sockaddr *)client_ss) ) {
-               if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
+               if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
                        DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
-                       return False;
+                       return false;
                }
 
                if (ismyaddr((struct sockaddr *)&rm_addr)) {
                        DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
-                       return False;
+                       return false;
                }
        } else {
                char addr[INET6_ADDRSTRLEN];
@@ -2620,13 +2371,13 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
        if ( !NT_STATUS_IS_OK( ret ) ) {
                DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
                        remote_machine ));
-               return False;
+               return false;
        }
 
        if ( the_cli->protocol != PROTOCOL_NT1 ) {
                DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
                cli_shutdown(the_cli);
-               return False;
+               return false;
        }
 
        /*
@@ -2639,10 +2390,10 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
                DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
                        remote_machine, nt_errstr(ret)));
                cli_shutdown(the_cli);
-               return False;
+               return false;
        }
 
-       return True;
+       return true;
 }
 
 /***************************************************************************
@@ -2650,8 +2401,9 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
 ****************************************************************************/
 
 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
-                                       uint32 localprinter, uint32 type,
-                                       POLICY_HND *handle, struct sockaddr_storage *client_ss)
+                                       uint32_t localprinter, uint32_t type,
+                                       struct policy_handle *handle,
+                                       struct sockaddr_storage *client_ss)
 {
        WERROR result;
        NTSTATUS status;
@@ -2666,14 +2418,14 @@ static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
                fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
 
                if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
-                       return False;
+                       return false;
 
                messaging_register(smbd_messaging_context(), NULL,
                                   MSG_PRINTER_NOTIFY2,
                                   receive_notify2_message_list);
                /* Tell the connections db we're now interested in printer
                 * notify messages. */
-               register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
+               register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
        }
 
        /*
@@ -2765,18 +2517,18 @@ static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx
 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
                                                     struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
 {
-       POLICY_HND *handle = r->in.handle;
        int snum = -1;
        struct spoolss_NotifyOption *option = r->in.notify_options;
        struct sockaddr_storage client_ss;
 
        /* store the notify value in the printer struct */
 
-       Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
-                       "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+                       "Invalid handle (%s:%u:%u).\n",
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
@@ -2794,7 +2546,7 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
        if ( Printer->printer_type == SPLHND_SERVER)
                snum = -1;
        else if ( (Printer->printer_type == SPLHND_PRINTER) &&
-                       !get_printer_snum(p, handle, &snum, NULL) )
+                       !get_printer_snum(p, r->in.handle, &snum, NULL) )
                return WERR_BADFID;
 
        if (!interpret_string_addr(&client_ss, p->client_address,
@@ -2807,7 +2559,7 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
                                        &Printer->notify.client_hnd, &client_ss))
                return WERR_SERVER_UNAVAILABLE;
 
-       Printer->notify.client_connected=True;
+       Printer->notify.client_connected = true;
 
        return WERR_OK;
 }
@@ -3292,59 +3044,59 @@ struct s_notify_info_data_table
 
 /* A table describing the various print notification constants and
    whether the notification data is a pointer to a variable sized
-   buffer, a one value uint32 or a two value uint32. */
+   buffer, a one value uint32_t or a two value uint32_t. */
 
 static const struct s_notify_info_data_table notify_info_data_table[] =
 {
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
 };
 
 /*******************************************************************
@@ -3382,11 +3134,11 @@ static bool search_notify(enum spoolss_NotifyType type,
                    notify_info_data_table[i].field == field &&
                    notify_info_data_table[i].fn != NULL) {
                        *value = i;
-                       return True;
+                       return true;
                }
        }
 
-       return False;
+       return false;
 }
 
 /****************************************************************************
@@ -3431,7 +3183,7 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
                option_type->count, lp_servicename(snum)));
 
        if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
-               return False;
+               return false;
 
        for(field_num=0; field_num < option_type->count; field_num++) {
                field = option_type->fields[field_num].field;
@@ -3447,7 +3199,7 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
                if (info->notifies == NULL) {
                        DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
                        free_a_printer(&printer, 2);
-                       return False;
+                       return false;
                }
 
                current_data = &info->notifies[info->count];
@@ -3464,7 +3216,7 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
        }
 
        free_a_printer(&printer, 2);
-       return True;
+       return true;
 }
 
 /*******************************************************************
@@ -3505,7 +3257,7 @@ static bool construct_notify_jobs_info(print_queue_struct *queue,
                                                      info->count + 1);
                if (info->notifies == NULL) {
                        DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
-                       return False;
+                       return false;
                }
 
                current_data=&(info->notifies[info->count]);
@@ -3516,7 +3268,7 @@ static bool construct_notify_jobs_info(print_queue_struct *queue,
                info->count++;
        }
 
-       return True;
+       return true;
 }
 
 /*
@@ -3549,12 +3301,13 @@ static bool construct_notify_jobs_info(print_queue_struct *queue,
  *
  ********************************************************************/
 
-static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
+static WERROR printserver_notify_info(pipes_struct *p,
+                                     struct policy_handle *hnd,
                                      struct spoolss_NotifyInfo *info,
                                      TALLOC_CTX *mem_ctx)
 {
        int snum;
-       Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
        int n_services=lp_numservices();
        int i;
        struct spoolss_NotifyOption *option;
@@ -3615,13 +3368,14 @@ static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
  *
  ********************************************************************/
 
-static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
+static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
+                                 struct spoolss_NotifyInfo *info,
                                  TALLOC_CTX *mem_ctx)
 {
        int snum;
-       Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
        int i;
-       uint32 id;
+       uint32_t id;
        struct spoolss_NotifyOption *option;
        struct spoolss_NotifyOptionType option_type;
        int count,j;
@@ -3708,10 +3462,9 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spool
 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
                                                 struct spoolss_RouterRefreshPrinterChangeNotify *r)
 {
-       POLICY_HND *handle = r->in.handle;
        struct spoolss_NotifyInfo *info;
 
-       Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
        WERROR result = WERR_BADFID;
 
        /* we always have a spoolss_NotifyInfo struct */
@@ -3725,7 +3478,8 @@ WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
 
        if (!Printer) {
                DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
-                       "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+                       "Invalid handle (%s:%u:%u).\n",
+                       OUR_HANDLE(r->in.handle)));
                goto done;
        }
 
@@ -3741,7 +3495,7 @@ WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
        /* We need to keep track of the change value to send back in
            RRPCN replies otherwise our updates are ignored. */
 
-       Printer->notify.fnpcn = True;
+       Printer->notify.fnpcn = true;
 
        if (Printer->notify.client_connected) {
                DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
@@ -3754,15 +3508,17 @@ WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
 
        switch (Printer->printer_type) {
                case SPLHND_SERVER:
-                       result = printserver_notify_info(p, handle, info, p->mem_ctx);
+                       result = printserver_notify_info(p, r->in.handle,
+                                                        info, p->mem_ctx);
                        break;
 
                case SPLHND_PRINTER:
-                       result = printer_notify_info(p, handle, info, p->mem_ctx);
+                       result = printer_notify_info(p, r->in.handle,
+                                                    info, p->mem_ctx);
                        break;
        }
 
-       Printer->notify.fnpcn = False;
+       Printer->notify.fnpcn = false;
 
 done:
        return result;
@@ -3961,43 +3717,147 @@ done:
 }
 
 /********************************************************************
- * construct_printer_info3
- * fill a spoolss_PrinterInfo3 struct
- ********************************************************************/
+ * construct_printer_info1
+ * fill a spoolss_PrinterInfo1 struct
+********************************************************************/
 
-static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
+static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
                                      const NT_PRINTER_INFO_LEVEL *ntprinter,
-                                     struct spoolss_PrinterInfo3 *r,
+                                     uint32_t flags,
+                                     struct spoolss_PrinterInfo1 *r,
                                      int snum)
 {
-       /* These are the components of the SD we are returning. */
+       r->flags                = flags;
 
-       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 */
+       r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
+                                                 ntprinter->info_2->printername,
+                                                 ntprinter->info_2->drivername,
+                                                 ntprinter->info_2->location);
+       W_ERROR_HAVE_NO_MEMORY(r->description);
 
-               r->secdesc = dup_sec_desc(mem_ctx,
-                                         ntprinter->info_2->secdesc_buf->sd);
-               W_ERROR_HAVE_NO_MEMORY(r->secdesc);
+       if (*ntprinter->info_2->comment == '\0') {
+               r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
+       } else {
+               r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
        }
+       W_ERROR_HAVE_NO_MEMORY(r->comment);
+
+       r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
+       W_ERROR_HAVE_NO_MEMORY(r->name);
 
        return WERR_OK;
 }
 
 /********************************************************************
- * construct_printer_info4
- * fill a spoolss_PrinterInfo4 struct
- ********************************************************************/
+ * construct_printer_info2
+ * fill a spoolss_PrinterInfo2 struct
+********************************************************************/
 
-static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
+static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
                                      const NT_PRINTER_INFO_LEVEL *ntprinter,
-                                     struct spoolss_PrinterInfo4 *r,
+                                     struct spoolss_PrinterInfo2 *r,
                                      int snum)
 {
-       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);
+       int count;
+
+       print_status_struct status;
+
+       count = print_queue_length(snum, &status);
+
+       r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
+       W_ERROR_HAVE_NO_MEMORY(r->servername);
+       r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
+       W_ERROR_HAVE_NO_MEMORY(r->printername);
+       r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
+       W_ERROR_HAVE_NO_MEMORY(r->sharename);
+       r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
+       W_ERROR_HAVE_NO_MEMORY(r->portname);
+       r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
+       W_ERROR_HAVE_NO_MEMORY(r->drivername);
+
+       if (*ntprinter->info_2->comment == '\0') {
+               r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
+       } else {
+               r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
+       }
+       W_ERROR_HAVE_NO_MEMORY(r->comment);
+
+       r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
+       W_ERROR_HAVE_NO_MEMORY(r->location);
+       r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
+       W_ERROR_HAVE_NO_MEMORY(r->sepfile);
+       r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
+       W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
+       r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
+       W_ERROR_HAVE_NO_MEMORY(r->datatype);
+       r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
+       W_ERROR_HAVE_NO_MEMORY(r->parameters);
+
+       r->attributes           = ntprinter->info_2->attributes;
+
+       r->priority             = ntprinter->info_2->priority;
+       r->defaultpriority      = ntprinter->info_2->default_priority;
+       r->starttime            = ntprinter->info_2->starttime;
+       r->untiltime            = ntprinter->info_2->untiltime;
+       r->status               = nt_printq_status(status.status);
+       r->cjobs                = count;
+       r->averageppm           = ntprinter->info_2->averageppm;
+
+       r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
+       if (!r->devmode) {
+               DEBUG(8,("Returning NULL Devicemode!\n"));
+       }
+
+       r->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 */
+
+               r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
+       }
+
+       return WERR_OK;
+}
+
+/********************************************************************
+ * construct_printer_info3
+ * fill a spoolss_PrinterInfo3 struct
+ ********************************************************************/
+
+static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
+                                     const NT_PRINTER_INFO_LEVEL *ntprinter,
+                                     struct spoolss_PrinterInfo3 *r,
+                                     int snum)
+{
+       /* 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 */
+
+               r->secdesc = dup_sec_desc(mem_ctx,
+                                         ntprinter->info_2->secdesc_buf->sd);
+               W_ERROR_HAVE_NO_MEMORY(r->secdesc);
+       }
+
+       return WERR_OK;
+}
+
+/********************************************************************
+ * construct_printer_info4
+ * fill a spoolss_PrinterInfo4 struct
+ ********************************************************************/
+
+static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
+                                     const NT_PRINTER_INFO_LEVEL *ntprinter,
+                                     struct spoolss_PrinterInfo4 *r,
+                                     int snum)
+{
+       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);
 
        r->attributes   = ntprinter->info_2->attributes;
 
@@ -4074,113 +3934,38 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
 }
 
 /********************************************************************
- * construct_printer_info1
- * fill a spoolss_PrinterInfo1 struct
-********************************************************************/
-
-static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
-                                     const NT_PRINTER_INFO_LEVEL *ntprinter,
-                                     uint32_t flags,
-                                     struct spoolss_PrinterInfo1 *r,
-                                     int snum)
-{
-       char *chaine = NULL;
-       r->flags                = flags;
-
-       if (*ntprinter->info_2->comment == '\0') {
-               r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
-               chaine = talloc_asprintf(mem_ctx,
-                               "%s,%s,%s", ntprinter->info_2->printername,
-                               ntprinter->info_2->drivername, lp_comment(snum));
-       } else {
-               r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
-               chaine = talloc_asprintf(mem_ctx,
-                               "%s,%s,%s", ntprinter->info_2->printername,
-                               ntprinter->info_2->drivername, ntprinter->info_2->comment);
-       }
-       W_ERROR_HAVE_NO_MEMORY(chaine);
-       W_ERROR_HAVE_NO_MEMORY(r->comment);
-
-       r->description          = talloc_strdup(mem_ctx, chaine);
-       W_ERROR_HAVE_NO_MEMORY(r->description);
-       r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
-       W_ERROR_HAVE_NO_MEMORY(r->name);
-
-       return WERR_OK;
-}
-
-/********************************************************************
- * construct_printer_info2
- * fill a spoolss_PrinterInfo2 struct
-********************************************************************/
+ * construct_printer_info8
+ * fill a spoolss_PrinterInfo8 struct
+ ********************************************************************/
 
-static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
+static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
                                      const NT_PRINTER_INFO_LEVEL *ntprinter,
-                                     struct spoolss_PrinterInfo2 *r,
+                                     struct spoolss_DeviceModeInfo *r,
                                      int snum)
 {
-       int count;
-
-       print_status_struct status;
-
-       count = print_queue_length(snum, &status);
-
-       r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
-       W_ERROR_HAVE_NO_MEMORY(r->servername);
-       r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
-       W_ERROR_HAVE_NO_MEMORY(r->printername);
-       r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
-       W_ERROR_HAVE_NO_MEMORY(r->sharename);
-       r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
-       W_ERROR_HAVE_NO_MEMORY(r->portname);
-       r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
-       W_ERROR_HAVE_NO_MEMORY(r->drivername);
+       struct spoolss_DeviceMode *devmode;
+       WERROR result;
 
-       if (*ntprinter->info_2->comment == '\0') {
-               r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
-       } else {
-               r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
+       if (!ntprinter->info_2->devmode) {
+               r->devmode = NULL;
+               return WERR_OK;
        }
-       W_ERROR_HAVE_NO_MEMORY(r->comment);
-
-       r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
-       W_ERROR_HAVE_NO_MEMORY(r->location);
-       r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
-       W_ERROR_HAVE_NO_MEMORY(r->sepfile);
-       r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
-       W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
-       r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
-       W_ERROR_HAVE_NO_MEMORY(r->datatype);
-       r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
-       W_ERROR_HAVE_NO_MEMORY(r->parameters);
-
-       r->attributes           = ntprinter->info_2->attributes;
 
-       r->priority             = ntprinter->info_2->priority;
-       r->defaultpriority      = ntprinter->info_2->default_priority;
-       r->starttime            = ntprinter->info_2->starttime;
-       r->untiltime            = ntprinter->info_2->untiltime;
-       r->status               = nt_printq_status(status.status);
-       r->cjobs                = count;
-       r->averageppm           = ntprinter->info_2->averageppm;
+       devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
+       W_ERROR_HAVE_NO_MEMORY(devmode);
 
-       r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
-       if (!r->devmode) {
-               DEBUG(8,("Returning NULL Devicemode!\n"));
+       result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
+       if (!W_ERROR_IS_OK(result)) {
+               TALLOC_FREE(devmode);
+               return result;
        }
 
-       r->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 */
-
-               r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
-       }
+       r->devmode      = devmode;
 
        return WERR_OK;
 }
 
+
 /********************************************************************
 ********************************************************************/
 
@@ -4193,61 +3978,88 @@ static bool snum_is_shared_printer(int snum)
  Spoolss_enumprinters.
 ********************************************************************/
 
-static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
-                                      uint32_t flags,
-                                      union spoolss_PrinterInfo **info_p,
-                                      uint32_t *count)
+static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
+                                          uint32_t level,
+                                          uint32_t flags,
+                                          union spoolss_PrinterInfo **info_p,
+                                          uint32_t *count_p)
 {
        int snum;
        int n_services = lp_numservices();
        union spoolss_PrinterInfo *info = NULL;
+       uint32_t count = 0;
        WERROR result = WERR_OK;
 
-       DEBUG(4,("enum_all_printers_info_1\n"));
-
-       *count = 0;
+       *count_p = 0;
+       *info_p = NULL;
 
-       for (snum=0; snum<n_services; snum++) {
+       for (snum = 0; snum < n_services; snum++) {
 
                NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
-               struct spoolss_PrinterInfo1 info1;
 
                if (!snum_is_shared_printer(snum)) {
                        continue;
                }
 
-               DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
+               DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
+                       lp_servicename(snum), snum));
 
-               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) {
+                       result = WERR_NOMEM;
+                       goto out;
                }
 
-               result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
-               free_a_printer(&ntprinter,2);
+               result = get_a_printer(NULL, &ntprinter, 2,
+                                      lp_const_servicename(snum));
                if (!W_ERROR_IS_OK(result)) {
-                       continue;
+                       goto out;
                }
 
-               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;
+               switch (level) {
+               case 0:
+                       result = construct_printer_info0(info, ntprinter,
+                                                        &info[count].info0, snum);
+                       break;
+               case 1:
+                       result = construct_printer_info1(info, ntprinter, flags,
+                                                        &info[count].info1, snum);
+                       break;
+               case 2:
+                       result = construct_printer_info2(info, ntprinter,
+                                                        &info[count].info2, snum);
+                       break;
+               case 4:
+                       result = construct_printer_info4(info, ntprinter,
+                                                        &info[count].info4, snum);
+                       break;
+               case 5:
+                       result = construct_printer_info5(info, ntprinter,
+                                                        &info[count].info5, snum);
+                       break;
+
+               default:
+                       result = WERR_UNKNOWN_LEVEL;
+                       free_a_printer(&ntprinter, 2);
                        goto out;
                }
 
-               DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
+               free_a_printer(&ntprinter, 2);
+               if (!W_ERROR_IS_OK(result)) {
+                       goto out;
+               }
 
-               info[*count].info1 = info1;
-               (*count)++;
+               count++;
        }
 
+       *count_p = count;
+       *info_p = info;
+
  out:
        if (!W_ERROR_IS_OK(result)) {
                TALLOC_FREE(info);
-               *count = 0;
                return result;
        }
 
@@ -4256,6 +4068,35 @@ static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
+/********************************************************************
+ * handle enumeration of printers at level 0
+ ********************************************************************/
+
+static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
+                                 uint32_t flags,
+                                 const char *servername,
+                                 union spoolss_PrinterInfo **info,
+                                 uint32_t *count)
+{
+       DEBUG(4,("enum_all_printers_info_0\n"));
+
+       return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
+}
+
+
+/********************************************************************
+********************************************************************/
+
+static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
+                                      uint32_t flags,
+                                      union spoolss_PrinterInfo **info,
+                                      uint32_t *count)
+{
+       DEBUG(4,("enum_all_printers_info_1\n"));
+
+       return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
+}
+
 /********************************************************************
  enum_all_printers_info_1_local.
 *********************************************************************/
@@ -4332,64 +4173,12 @@ static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
-                                      union spoolss_PrinterInfo **info_p,
+                                      union spoolss_PrinterInfo **info,
                                       uint32_t *count)
 {
-       int snum;
-       int n_services = lp_numservices();
-       union spoolss_PrinterInfo *info = NULL;
-       WERROR result = WERR_OK;
-
-       *count = 0;
-
-       for (snum=0; snum<n_services; snum++) {
-
-               struct spoolss_PrinterInfo2 info2;
-               NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
-
-               if (!snum_is_shared_printer(snum)) {
-                       continue;
-               }
-
-               DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
-
-               result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
-               if (!W_ERROR_IS_OK(result)) {
-                       continue;
-               }
-
-               result = construct_printer_info2(info, ntprinter, &info2, snum);
-               free_a_printer(&ntprinter, 2);
-               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;
-               }
-
-               DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
+       DEBUG(4,("enum_all_printers_info_2\n"));
 
-               info[*count].info2 = info2;
-
-               (*count)++;
-       }
-
- out:
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               *count = 0;
-               return result;
-       }
-
-       *info_p = info;
-
-       return WERR_OK;
+       return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
 }
 
 /********************************************************************
@@ -4448,6 +4237,22 @@ static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
+/********************************************************************
+ * handle enumeration of printers at level 4
+ ********************************************************************/
+
+static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
+                                 uint32_t flags,
+                                 const char *servername,
+                                 union spoolss_PrinterInfo **info,
+                                 uint32_t *count)
+{
+       DEBUG(4,("enum_all_printers_info_4\n"));
+
+       return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
+}
+
+
 /********************************************************************
  * handle enumeration of printers at level 5
  ********************************************************************/
@@ -4458,8 +4263,9 @@ static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
                                  union spoolss_PrinterInfo **info,
                                  uint32_t *count)
 {
-/*     return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/
-       return WERR_OK;
+       DEBUG(4,("enum_all_printers_info_5\n"));
+
+       return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
 }
 
 /****************************************************************
@@ -4501,6 +4307,10 @@ WERROR _spoolss_EnumPrinters(pipes_struct *p,
        W_ERROR_HAVE_NO_MEMORY(name);
 
        switch (r->in.level) {
+       case 0:
+               result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
+                                            r->out.info, r->out.count);
+               break;
        case 1:
                result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
                                             r->out.info, r->out.count);
@@ -4509,14 +4319,14 @@ WERROR _spoolss_EnumPrinters(pipes_struct *p,
                result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
                                             r->out.info, r->out.count);
                break;
+       case 4:
+               result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
+                                            r->out.info, r->out.count);
+               break;
        case 5:
                result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
                                             r->out.info, r->out.count);
                break;
-       case 3:
-       case 4:
-               result = WERR_OK; /* ??? */
-               break;
        default:
                return WERR_UNKNOWN_LEVEL;
        }
@@ -4600,6 +4410,10 @@ WERROR _spoolss_GetPrinter(pipes_struct *p,
                result = construct_printer_info7(p->mem_ctx, Printer,
                                                 &r->out.info->info7, snum);
                break;
+       case 8:
+               result = construct_printer_info8(p->mem_ctx, ntprinter,
+                                                &r->out.info->info8, snum);
+               break;
        default:
                result = WERR_UNKNOWN_LEVEL;
                break;
@@ -4623,16 +4437,20 @@ WERROR _spoolss_GetPrinter(pipes_struct *p,
  ********************************************************************/
 
 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
-                                                 fstring *fstring_array,
+                                                 const char **string_array,
                                                  const char *cservername)
 {
        int i, num_strings = 0;
        const char **array = NULL;
 
-       for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
+       if (!string_array) {
+               return NULL;
+       }
+
+       for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
 
                const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                                                 cservername, fstring_array[i]);
+                                                 cservername, string_array[i]);
                if (!str) {
                        TALLOC_FREE(array);
                        return NULL;
@@ -4653,17 +4471,36 @@ static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
        return array;
 }
 
+#define FILL_DRIVER_STRING(mem_ctx, in, out) \
+       do { \
+               if (in && strlen(in)) { \
+                       out = talloc_strdup(mem_ctx, in); \
+                       W_ERROR_HAVE_NO_MEMORY(out); \
+               } else { \
+                       out = NULL; \
+               } \
+       } while (0);
+
+#define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
+       do { \
+               if (in && strlen(in)) { \
+                       out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
+               } else { \
+                       out = talloc_strdup(mem_ctx, ""); \
+               } \
+               W_ERROR_HAVE_NO_MEMORY(out); \
+       } while (0);
+
 /********************************************************************
  * fill a spoolss_DriverInfo1 struct
  ********************************************************************/
 
 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
                                        struct spoolss_DriverInfo1 *r,
-                                       const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
-                                       const char *servername,
-                                       const char *architecture)
+                                       const struct spoolss_DriverInfo8 *driver,
+                                       const char *servername)
 {
-       r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
+       r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
        W_ERROR_HAVE_NO_MEMORY(r->driver_name);
 
        return WERR_OK;
@@ -4675,42 +4512,30 @@ static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
 
 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
                                        struct spoolss_DriverInfo2 *r,
-                                       const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
+                                       const struct spoolss_DriverInfo8 *driver,
                                        const char *servername)
 
 {
        const char *cservername = canon_servername(servername);
 
-       r->version              = driver->info_3->cversion;
+       r->version              = driver->version;
 
-       r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
+       r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
        W_ERROR_HAVE_NO_MEMORY(r->driver_name);
-       r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
+       r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
        W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
-       if (strlen(driver->info_3->driverpath)) {
-               r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->driverpath);
-       } else {
-               r->driver_path  = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->driver_path);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->driver_path,
+                              r->driver_path);
 
-       if (strlen(driver->info_3->datafile)) {
-               r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->datafile);
-       } else {
-               r->data_file    = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->data_file);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->data_file,
+                              r->data_file);
 
-       if (strlen(driver->info_3->configfile)) {
-               r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->configfile);
-       } else {
-               r->config_file  = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->config_file);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->config_file,
+                              r->config_file);
 
        return WERR_OK;
 }
@@ -4721,324 +4546,556 @@ static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
 
 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
                                        struct spoolss_DriverInfo3 *r,
-                                       const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
+                                       const struct spoolss_DriverInfo8 *driver,
                                        const char *servername)
 {
        const char *cservername = canon_servername(servername);
 
-       r->version              = driver->info_3->cversion;
+       r->version              = driver->version;
 
-       r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
+       r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
        W_ERROR_HAVE_NO_MEMORY(r->driver_name);
-       r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
+       r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
        W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
-       if (strlen(driver->info_3->driverpath)) {
-               r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->driverpath);
-       } else {
-               r->driver_path  = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->driver_path);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->driver_path,
+                              r->driver_path);
 
-       if (strlen(driver->info_3->datafile)) {
-               r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->datafile);
-       } else {
-               r->data_file    = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->data_file);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->data_file,
+                              r->data_file);
 
-       if (strlen(driver->info_3->configfile)) {
-               r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->configfile);
-       } else {
-               r->config_file  = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->config_file);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->config_file,
+                              r->config_file);
 
-       if (strlen(driver->info_3->helpfile)) {
-               r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->helpfile);
-       } else {
-               r->help_file    = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->config_file);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->help_file,
+                              r->help_file);
 
-       r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
-       W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
-       r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
-       W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->monitor_name,
+                          r->monitor_name);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->default_datatype,
+                          r->default_datatype);
 
        r->dependent_files = string_array_from_driver_info(mem_ctx,
-                                                          driver->info_3->dependentfiles,
+                                                          driver->dependent_files,
                                                           cservername);
        return WERR_OK;
 }
 
 /********************************************************************
- * fill a spoolss_DriverInfo6 struct
+ * fill a spoolss_DriverInfo4 struct
  ********************************************************************/
 
-static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
-                                       struct spoolss_DriverInfo6 *r,
-                                       const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
+static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
+                                       struct spoolss_DriverInfo4 *r,
+                                       const struct spoolss_DriverInfo8 *driver,
                                        const char *servername)
 {
        const char *cservername = canon_servername(servername);
 
-       r->version              = driver->info_3->cversion;
+       r->version              = driver->version;
 
-       r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
+       r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
        W_ERROR_HAVE_NO_MEMORY(r->driver_name);
-       r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
+       r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
        W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
-       if (strlen(driver->info_3->driverpath)) {
-               r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->driverpath);
-       } else {
-               r->driver_path  = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->driver_path);
-
-       if (strlen(driver->info_3->datafile)) {
-               r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->datafile);
-       } else {
-               r->data_file    = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->data_file);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->driver_path,
+                              r->driver_path);
 
-       if (strlen(driver->info_3->configfile)) {
-               r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->configfile);
-       } else {
-               r->config_file  = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->config_file);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->data_file,
+                              r->data_file);
 
-       if (strlen(driver->info_3->helpfile)) {
-               r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                               cservername, driver->info_3->helpfile);
-       } else {
-               r->help_file    = talloc_strdup(mem_ctx, "");
-       }
-       W_ERROR_HAVE_NO_MEMORY(r->config_file);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->config_file,
+                              r->config_file);
 
-       r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
-       W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
-       r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
-       W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->help_file,
+                              r->help_file);
 
        r->dependent_files = string_array_from_driver_info(mem_ctx,
-                                                          driver->info_3->dependentfiles,
+                                                          driver->dependent_files,
                                                           cservername);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->monitor_name,
+                          r->monitor_name);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->default_datatype,
+                          r->default_datatype);
+
        r->previous_names = string_array_from_driver_info(mem_ctx,
-                                                         NULL,
+                                                         driver->previous_names,
                                                          cservername);
 
-       r->driver_date          = 0;
-       r->driver_version       = 0;
+       return WERR_OK;
+}
+
+/********************************************************************
+ * fill a spoolss_DriverInfo5 struct
+ ********************************************************************/
+
+static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
+                                       struct spoolss_DriverInfo5 *r,
+                                       const struct spoolss_DriverInfo8 *driver,
+                                       const char *servername)
+{
+       const char *cservername = canon_servername(servername);
+
+       r->version              = driver->version;
+
+       r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
+       W_ERROR_HAVE_NO_MEMORY(r->driver_name);
+       r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
+       W_ERROR_HAVE_NO_MEMORY(r->architecture);
+
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->driver_path,
+                              r->driver_path);
+
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->data_file,
+                              r->data_file);
 
-       r->manufacturer_name    = talloc_strdup(mem_ctx, "");
-       W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
-       r->manufacturer_url     = talloc_strdup(mem_ctx, "");
-       W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
-       r->hardware_id          = talloc_strdup(mem_ctx, "");
-       W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
-       r->provider             = talloc_strdup(mem_ctx, "");
-       W_ERROR_HAVE_NO_MEMORY(r->provider);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->config_file,
+                              r->config_file);
+
+       r->driver_attributes    = 0;
+       r->config_version       = 0;
+       r->driver_version       = 0;
 
        return WERR_OK;
 }
-
 /********************************************************************
- * construct_printer_driver_info_1
+ * fill a spoolss_DriverInfo6 struct
  ********************************************************************/
 
-static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
-                                             struct spoolss_DriverInfo1 *r,
-                                             int snum,
-                                             const char *servername,
-                                             const char *architecture,
-                                             uint32_t version)
+static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
+                                       struct spoolss_DriverInfo6 *r,
+                                       const struct spoolss_DriverInfo8 *driver,
+                                       const char *servername)
 {
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       WERROR result;
+       const char *cservername = canon_servername(servername);
 
-       ZERO_STRUCT(driver);
+       r->version              = driver->version;
 
-       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
-               return WERR_INVALID_PRINTER_NAME;
+       r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
+       W_ERROR_HAVE_NO_MEMORY(r->driver_name);
+       r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
+       W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
-       if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
-               free_a_printer(&printer, 2);
-               return WERR_UNKNOWN_PRINTER_DRIVER;
-       }
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->driver_path,
+                              r->driver_path);
 
-       result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->data_file,
+                              r->data_file);
 
-       free_a_printer(&printer,2);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->config_file,
+                              r->config_file);
 
-       return result;
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->help_file,
+                              r->help_file);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->monitor_name,
+                          r->monitor_name);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->default_datatype,
+                          r->default_datatype);
+
+       r->dependent_files = string_array_from_driver_info(mem_ctx,
+                                                          driver->dependent_files,
+                                                          cservername);
+       r->previous_names = string_array_from_driver_info(mem_ctx,
+                                                         driver->previous_names,
+                                                         cservername);
+
+       r->driver_date          = driver->driver_date;
+       r->driver_version       = driver->driver_version;
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->manufacturer_name,
+                          r->manufacturer_name);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->manufacturer_url,
+                          r->manufacturer_url);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->hardware_id,
+                          r->hardware_id);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->provider,
+                          r->provider);
+
+       return WERR_OK;
 }
 
 /********************************************************************
- * construct_printer_driver_info_2
- * fill a printer_info_2 struct
+ * fill a spoolss_DriverInfo8 struct
  ********************************************************************/
 
-static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
-                                             struct spoolss_DriverInfo2 *r,
-                                             int snum,
-                                             const char *servername,
-                                             const char *architecture,
-                                             uint32_t version)
+static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
+                                       struct spoolss_DriverInfo8 *r,
+                                       const struct spoolss_DriverInfo8 *driver,
+                                       const char *servername)
 {
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       WERROR result;
+       const char *cservername = canon_servername(servername);
 
-       ZERO_STRUCT(printer);
-       ZERO_STRUCT(driver);
+       r->version              = driver->version;
 
-       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
-               return WERR_INVALID_PRINTER_NAME;
+       r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
+       W_ERROR_HAVE_NO_MEMORY(r->driver_name);
+       r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
+       W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
-       if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
-               free_a_printer(&printer, 2);
-               return WERR_UNKNOWN_PRINTER_DRIVER;
-       }
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->driver_path,
+                              r->driver_path);
 
-       result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->data_file,
+                              r->data_file);
 
-       free_a_printer(&printer,2);
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->config_file,
+                              r->config_file);
 
-       return result;
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->help_file,
+                              r->help_file);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->monitor_name,
+                          r->monitor_name);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->default_datatype,
+                          r->default_datatype);
+
+       r->dependent_files = string_array_from_driver_info(mem_ctx,
+                                                          driver->dependent_files,
+                                                          cservername);
+       r->previous_names = string_array_from_driver_info(mem_ctx,
+                                                         driver->previous_names,
+                                                         cservername);
+
+       r->driver_date          = driver->driver_date;
+       r->driver_version       = driver->driver_version;
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->manufacturer_name,
+                          r->manufacturer_name);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->manufacturer_url,
+                          r->manufacturer_url);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->hardware_id,
+                          r->hardware_id);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->provider,
+                          r->provider);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->print_processor,
+                          r->print_processor);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->vendor_setup,
+                          r->vendor_setup);
+
+       r->color_profiles = string_array_from_driver_info(mem_ctx,
+                                                         driver->color_profiles,
+                                                         cservername);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->inf_path,
+                          r->inf_path);
+
+       r->printer_driver_attributes    = driver->printer_driver_attributes;
+
+       r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
+                                                                   driver->core_driver_dependencies,
+                                                                   cservername);
+
+       r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
+       r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
+
+       return WERR_OK;
+}
+/********************************************************************
+ ********************************************************************/
+
+static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
+                                         struct spoolss_DriverFileInfo *r,
+                                         const char *cservername,
+                                         const char *file_name,
+                                         enum spoolss_DriverFileType file_type,
+                                         uint32_t file_version)
+{
+       r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
+                                         cservername, file_name);
+       W_ERROR_HAVE_NO_MEMORY(r->file_name);
+       r->file_type    = file_type;
+       r->file_version = file_version;
+
+       return WERR_OK;
 }
 
 /********************************************************************
- * construct_printer_info_3
- * fill a printer_info_3 struct
  ********************************************************************/
 
-static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
-                                             struct spoolss_DriverInfo3 *r,
-                                             int snum,
-                                             const char *servername,
-                                             const char *architecture,
-                                             uint32_t version)
+static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
+                                                const struct spoolss_DriverInfo8 *driver,
+                                                const char *cservername,
+                                                struct spoolss_DriverFileInfo **info_p,
+                                                uint32_t *count_p)
 {
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       WERROR status;
-       ZERO_STRUCT(driver);
+       struct spoolss_DriverFileInfo *info = NULL;
+       uint32_t count = 0;
+       WERROR result;
+       uint32_t i;
 
-       status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
-       DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
-       if (!W_ERROR_IS_OK(status))
-               return WERR_INVALID_PRINTER_NAME;
+       *info_p = NULL;
+       *count_p = 0;
+
+       if (strlen(driver->driver_path)) {
+               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+                                           struct spoolss_DriverFileInfo,
+                                           count + 1);
+               W_ERROR_HAVE_NO_MEMORY(info);
+               result = fill_spoolss_DriverFileInfo(info,
+                                                    &info[count],
+                                                    cservername,
+                                                    driver->driver_path,
+                                                    SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
+                                                    0);
+               W_ERROR_NOT_OK_RETURN(result);
+               count++;
+       }
+
+       if (strlen(driver->config_file)) {
+               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+                                           struct spoolss_DriverFileInfo,
+                                           count + 1);
+               W_ERROR_HAVE_NO_MEMORY(info);
+               result = fill_spoolss_DriverFileInfo(info,
+                                                    &info[count],
+                                                    cservername,
+                                                    driver->config_file,
+                                                    SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
+                                                    0);
+               W_ERROR_NOT_OK_RETURN(result);
+               count++;
+       }
+
+       if (strlen(driver->data_file)) {
+               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+                                           struct spoolss_DriverFileInfo,
+                                           count + 1);
+               W_ERROR_HAVE_NO_MEMORY(info);
+               result = fill_spoolss_DriverFileInfo(info,
+                                                    &info[count],
+                                                    cservername,
+                                                    driver->data_file,
+                                                    SPOOLSS_DRIVER_FILE_TYPE_DATA,
+                                                    0);
+               W_ERROR_NOT_OK_RETURN(result);
+               count++;
+       }
+
+       if (strlen(driver->help_file)) {
+               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+                                           struct spoolss_DriverFileInfo,
+                                           count + 1);
+               W_ERROR_HAVE_NO_MEMORY(info);
+               result = fill_spoolss_DriverFileInfo(info,
+                                                    &info[count],
+                                                    cservername,
+                                                    driver->help_file,
+                                                    SPOOLSS_DRIVER_FILE_TYPE_HELP,
+                                                    0);
+               W_ERROR_NOT_OK_RETURN(result);
+               count++;
+       }
+
+       for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
+               info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
+                                           struct spoolss_DriverFileInfo,
+                                           count + 1);
+               W_ERROR_HAVE_NO_MEMORY(info);
+               result = fill_spoolss_DriverFileInfo(info,
+                                                    &info[count],
+                                                    cservername,
+                                                    driver->dependent_files[i],
+                                                    SPOOLSS_DRIVER_FILE_TYPE_OTHER,
+                                                    0);
+               W_ERROR_NOT_OK_RETURN(result);
+               count++;
+       }
 
-       status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
-       DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
+       *info_p = info;
+       *count_p = count;
+
+       return WERR_OK;
+}
 
-#if 0  /* JERRY */
+/********************************************************************
+ * fill a spoolss_DriverInfo101 sttruct
+ ********************************************************************/
 
-       /*
-        * I put this code in during testing.  Helpful when commenting out the
-        * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
-        * as win2k always queries the driver using an infor level of 6.
-        * I've left it in (but ifdef'd out) because I'll probably
-        * use it in experimentation again in the future.   --jerry 22/01/2002
-        */
+static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
+                                         struct spoolss_DriverInfo101 *r,
+                                         const struct spoolss_DriverInfo8 *driver,
+                                         const char *servername)
+{
+       const char *cservername = canon_servername(servername);
+       WERROR result;
 
-       if (!W_ERROR_IS_OK(status)) {
-               /*
-                * Is this a W2k client ?
-                */
-               if (version == 3) {
-                       /* Yes - try again with a WinNT driver. */
-                       version = 2;
-                       status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
-                       DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
-               }
-#endif
+       r->version              = driver->version;
 
-               if (!W_ERROR_IS_OK(status)) {
-                       free_a_printer(&printer,2);
-                       return WERR_UNKNOWN_PRINTER_DRIVER;
-               }
+       r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
+       W_ERROR_HAVE_NO_MEMORY(r->driver_name);
+       r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
+       W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
-#if 0  /* JERRY */
+       result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
+                                                   cservername,
+                                                   &r->file_info,
+                                                   &r->file_count);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
        }
-#endif
 
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->monitor_name,
+                          r->monitor_name);
 
-       status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->default_datatype,
+                          r->default_datatype);
 
-       free_a_printer(&printer,2);
+       r->previous_names = string_array_from_driver_info(mem_ctx,
+                                                         driver->previous_names,
+                                                         cservername);
+       r->driver_date          = driver->driver_date;
+       r->driver_version       = driver->driver_version;
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->manufacturer_name,
+                          r->manufacturer_name);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->manufacturer_url,
+                          r->manufacturer_url);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->hardware_id,
+                          r->hardware_id);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->provider,
+                          r->provider);
 
-       return status;
+       return WERR_OK;
 }
 
 /********************************************************************
- * construct_printer_info_6
- * fill a printer_info_6 struct
  ********************************************************************/
 
-static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
-                                             struct spoolss_DriverInfo6 *r,
-                                             int snum,
-                                             const char *servername,
-                                             const char *architecture,
-                                             uint32_t version)
+static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
+                                                 uint32_t level,
+                                                 union spoolss_DriverInfo *r,
+                                                 int snum,
+                                                 const char *servername,
+                                                 const char *architecture,
+                                                 uint32_t version)
 {
-       NT_PRINTER_INFO_LEVEL           *printer = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL    driver;
-       WERROR                          status;
-
-       ZERO_STRUCT(driver);
+       NT_PRINTER_INFO_LEVEL *printer = NULL;
+       struct spoolss_DriverInfo8 *driver;
+       WERROR result;
 
-       status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
+       result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
 
-       DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
+       DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
+               win_errstr(result)));
 
-       if (!W_ERROR_IS_OK(status))
+       if (!W_ERROR_IS_OK(result)) {
                return WERR_INVALID_PRINTER_NAME;
+       }
 
-       status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
+       result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
+                                     architecture, version);
 
-       DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
+       DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
+               win_errstr(result)));
 
-       if (!W_ERROR_IS_OK(status))
-       {
+       if (!W_ERROR_IS_OK(result)) {
                /*
                 * Is this a W2k client ?
                 */
 
                if (version < 3) {
-                       free_a_printer(&printer,2);
+                       free_a_printer(&printer, 2);
                        return WERR_UNKNOWN_PRINTER_DRIVER;
                }
 
                /* Yes - try again with a WinNT driver. */
                version = 2;
-               status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
-               DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
-               if (!W_ERROR_IS_OK(status)) {
-                       free_a_printer(&printer,2);
+               result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
+                                             architecture, version);
+               DEBUG(8,("construct_printer_driver_level: status: %s\n",
+                       win_errstr(result)));
+               if (!W_ERROR_IS_OK(result)) {
+                       free_a_printer(&printer, 2);
                        return WERR_UNKNOWN_PRINTER_DRIVER;
                }
        }
 
-       status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
+       switch (level) {
+       case 1:
+               result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
+               break;
+       case 2:
+               result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
+               break;
+       case 3:
+               result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
+               break;
+       case 4:
+               result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
+               break;
+       case 5:
+               result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
+               break;
+       case 6:
+               result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
+               break;
+       case 8:
+               result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
+               break;
+       case 101:
+               result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
+               break;
+       default:
+               result = WERR_UNKNOWN_LEVEL;
+               break;
+       }
 
-       free_a_printer(&printer,2);
-       free_a_printer_driver(driver, 3);
+       free_a_printer(&printer, 2);
+       free_a_printer_driver(driver);
 
-       return status;
+       return result;
 }
 
 /****************************************************************
@@ -5062,7 +5119,7 @@ WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
 
        DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
 
-       if (!(printer = find_printer_index_by_hnd( p, r->in.handle))) {
+       if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
                DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
                return WERR_INVALID_PRINTER_NAME;
        }
@@ -5077,50 +5134,11 @@ WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
                return WERR_BADFID;
        }
 
-       switch (r->in.level) {
-       case 1:
-               result = construct_printer_driver_info_1(p->mem_ctx,
-                                                        &r->out.info->info1,
-                                                        snum,
-                                                        servername,
-                                                        r->in.architecture,
-                                                        r->in.client_major_version);
-               break;
-       case 2:
-               result = construct_printer_driver_info_2(p->mem_ctx,
-                                                        &r->out.info->info2,
-                                                        snum,
-                                                        servername,
-                                                        r->in.architecture,
-                                                        r->in.client_major_version);
-               break;
-       case 3:
-               result = construct_printer_driver_info_3(p->mem_ctx,
-                                                        &r->out.info->info3,
-                                                        snum,
-                                                        servername,
-                                                        r->in.architecture,
-                                                        r->in.client_major_version);
-               break;
-       case 6:
-               result = construct_printer_driver_info_6(p->mem_ctx,
-                                                        &r->out.info->info6,
-                                                        snum,
-                                                        servername,
-                                                        r->in.architecture,
-                                                        r->in.client_major_version);
-               break;
-       default:
-#if 0  /* JERRY */
-       case 101:
-               /* apparently this call is the equivalent of
-                  EnumPrinterDataEx() for the DsDriver key */
-               break;
-#endif
-               result = WERR_UNKNOWN_LEVEL;
-               break;
-       }
-
+       result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
+                                                    r->out.info, snum,
+                                                    servername,
+                                                    r->in.architecture,
+                                                    r->in.client_major_version);
        if (!W_ERROR_IS_OK(result)) {
                TALLOC_FREE(r->out.info);
                return result;
@@ -5141,9 +5159,7 @@ WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
                                 struct spoolss_StartPagePrinter *r)
 {
-       POLICY_HND *handle = r->in.handle;
-
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(3,("_spoolss_StartPagePrinter: "
@@ -5151,7 +5167,7 @@ WERROR _spoolss_StartPagePrinter(pipes_struct *p,
                return WERR_BADFID;
        }
 
-       Printer->page_started=True;
+       Printer->page_started = true;
        return WERR_OK;
 }
 
@@ -5162,21 +5178,20 @@ WERROR _spoolss_StartPagePrinter(pipes_struct *p,
 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
                               struct spoolss_EndPagePrinter *r)
 {
-       POLICY_HND *handle = r->in.handle;
        int snum;
 
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
-                       OUR_HANDLE(handle)));
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
-       if (!get_printer_snum(p, handle, &snum, NULL))
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL))
                return WERR_BADFID;
 
-       Printer->page_started=False;
+       Printer->page_started = false;
        print_job_endpage(snum, Printer->jobid);
 
        return WERR_OK;
@@ -5189,15 +5204,14 @@ WERROR _spoolss_EndPagePrinter(pipes_struct *p,
 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
                                struct spoolss_StartDocPrinter *r)
 {
-       POLICY_HND *handle = r->in.handle;
-       uint32_t *jobid = r->out.job_id;
        struct spoolss_DocumentInfo1 *info_1;
        int snum;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_StartDocPrinter: "
-                       "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
+                       "Invalid handle (%s:%u:%u)\n",
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
@@ -5217,13 +5231,13 @@ WERROR _spoolss_StartDocPrinter(pipes_struct *p,
 
        if (info_1->datatype) {
                if (strcmp(info_1->datatype, "RAW") != 0) {
-                       (*jobid)=0;
+                       *r->out.job_id = 0;
                        return WERR_INVALID_DATATYPE;
                }
        }
 
        /* get the share number of the printer */
-       if (!get_printer_snum(p, handle, &snum, NULL)) {
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
                return WERR_BADFID;
        }
 
@@ -5238,8 +5252,8 @@ WERROR _spoolss_StartDocPrinter(pipes_struct *p,
                return map_werror_from_unix(errno);
        }
 
-       Printer->document_started=True;
-       (*jobid) = Printer->jobid;
+       Printer->document_started = true;
+       *r->out.job_id = Printer->jobid;
 
        return WERR_OK;
 }
@@ -5251,9 +5265,24 @@ WERROR _spoolss_StartDocPrinter(pipes_struct *p,
 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
                              struct spoolss_EndDocPrinter *r)
 {
-       POLICY_HND *handle = r->in.handle;
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       int snum;
+
+       if (!Printer) {
+               DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
+                       OUR_HANDLE(r->in.handle)));
+               return WERR_BADFID;
+       }
+
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
+               return WERR_BADFID;
+       }
+
+       Printer->document_started = false;
+       print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
+       /* error codes unhandled so far ... */
 
-       return _spoolss_enddocprinter_internal(p, handle);
+       return WERR_OK;
 }
 
 /****************************************************************
@@ -5263,26 +5292,25 @@ WERROR _spoolss_EndDocPrinter(pipes_struct *p,
 WERROR _spoolss_WritePrinter(pipes_struct *p,
                             struct spoolss_WritePrinter *r)
 {
-       POLICY_HND *handle = r->in.handle;
-       uint32 buffer_size = r->in._data_size;
-       uint8 *buffer = r->in.data.data;
-       uint32 *buffer_written = &r->in._data_size;
+       uint32_t buffer_written;
        int snum;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
-                       OUR_HANDLE(handle)));
+                       OUR_HANDLE(r->in.handle)));
                *r->out.num_written = r->in._data_size;
                return WERR_BADFID;
        }
 
-       if (!get_printer_snum(p, handle, &snum, NULL))
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL))
                return WERR_BADFID;
 
-       (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
-                                       (SMB_OFF_T)-1, (size_t)buffer_size);
-       if (*buffer_written == (uint32)-1) {
+       buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
+                                                  (const char *)r->in.data.data,
+                                                  (SMB_OFF_T)-1,
+                                                  (size_t)r->in._data_size);
+       if (buffer_written == (uint32_t)-1) {
                *r->out.num_written = 0;
                if (errno == ENOSPC)
                        return WERR_NO_SPOOL_SPACE;
@@ -5301,7 +5329,7 @@ WERROR _spoolss_WritePrinter(pipes_struct *p,
  *
  ********************************************************************/
 
-static WERROR control_printer(POLICY_HND *handle, uint32 command,
+static WERROR control_printer(struct policy_handle *handle, uint32_t command,
                              pipes_struct *p)
 {
        int snum;
@@ -5309,7 +5337,8 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command,
        Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
 
        if (!Printer) {
-               DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
+               DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
+                       OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
 
@@ -5318,20 +5347,14 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command,
 
        switch (command) {
        case SPOOLSS_PRINTER_CONTROL_PAUSE:
-               if (print_queue_pause(p->server_info, snum, &errcode)) {
-                       errcode = WERR_OK;
-               }
+               errcode = print_queue_pause(p->server_info, snum);
                break;
        case SPOOLSS_PRINTER_CONTROL_RESUME:
        case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
-               if (print_queue_resume(p->server_info, snum, &errcode)) {
-                       errcode = WERR_OK;
-               }
+               errcode = print_queue_resume(p->server_info, snum);
                break;
        case SPOOLSS_PRINTER_CONTROL_PURGE:
-               if (print_queue_purge(p->server_info, snum, &errcode)) {
-                       errcode = WERR_OK;
-               }
+               errcode = print_queue_purge(p->server_info, snum);
                break;
        default:
                return WERR_UNKNOWN_LEVEL;
@@ -5350,18 +5373,17 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command,
 WERROR _spoolss_AbortPrinter(pipes_struct *p,
                             struct spoolss_AbortPrinter *r)
 {
-       POLICY_HND      *handle = r->in.handle;
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int             snum;
        WERROR          errcode = WERR_OK;
 
        if (!Printer) {
                DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
-                       OUR_HANDLE(handle)));
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
-       if (!get_printer_snum(p, handle, &snum, NULL))
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL))
                return WERR_BADFID;
 
        print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
@@ -5374,7 +5396,7 @@ WERROR _spoolss_AbortPrinter(pipes_struct *p,
  * when updating a printer description
  ********************************************************************/
 
-static WERROR update_printer_sec(POLICY_HND *handle,
+static WERROR update_printer_sec(struct policy_handle *handle,
                                 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
 {
        SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
@@ -5453,7 +5475,7 @@ static WERROR update_printer_sec(POLICY_HND *handle,
                goto done;
        }
 
-       if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
+       if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
                result = WERR_OK;
                goto done;
        }
@@ -5513,19 +5535,19 @@ static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
 
 
 
-       return True;
+       return true;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
+static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
 {
        char *cmd = lp_addport_cmd();
        char *command = NULL;
        int ret;
        SE_PRIV se_printop = SE_PRINT_OPERATOR;
-       bool is_print_op = False;
+       bool is_print_op = false;
 
        if ( !*cmd ) {
                return WERR_ACCESS_DENIED;
@@ -5577,7 +5599,7 @@ bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEV
        int ret;
        int fd;
        SE_PRIV se_printop = SE_PRINT_OPERATOR;
-       bool is_print_op = False;
+       bool is_print_op = false;
        char *remote_machine = talloc_strdup(ctx, "%m");
 
        if (!remote_machine) {
@@ -5629,11 +5651,13 @@ bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEV
        if ( ret != 0 ) {
                if (fd != -1)
                        close(fd);
-               return False;
+               return false;
        }
 
        /* reload our services immediately */
-       reload_services( False );
+       become_root();
+       reload_services(false);
+       unbecome_root();
 
        numlines = 0;
        /* Get lines and convert them back to dos-codepage */
@@ -5651,7 +5675,7 @@ bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEV
        }
 
        TALLOC_FREE(qlines);
-       return True;
+       return true;
 }
 
 
@@ -5660,7 +5684,7 @@ bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEV
  * when updating a printer description.
  ********************************************************************/
 
-static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
+static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
                             struct spoolss_SetPrinterInfoCtr *info_ctr,
                             struct spoolss_DeviceMode *devmode)
 {
@@ -5668,7 +5692,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
        NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
        Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
        WERROR result;
-       UNISTR2 buffer;
+       DATA_BLOB buffer;
        fstring asc_buffer;
 
        DEBUG(8,("update_printer\n"));
@@ -5778,17 +5802,17 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
         */
 
        if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
-               init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
+               push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
                set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
-                       REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
+                       REG_SZ, buffer.data, buffer.length);
 
                notify_printer_comment(snum, printer->info_2->comment);
        }
 
        if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
-               init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
+               push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
                set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
-                       REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
+                       REG_SZ, buffer.data, buffer.length);
 
                notify_printer_sharename(snum, printer->info_2->sharename);
        }
@@ -5802,25 +5826,25 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
                        pname = printer->info_2->printername;
 
 
-               init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
+               push_reg_sz(talloc_tos(), &buffer, pname);
                set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
-                       REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
+                       REG_SZ, buffer.data, buffer.length);
 
                notify_printer_printername( snum, pname );
        }
 
        if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
-               init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
+               push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
                set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
-                       REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
+                       REG_SZ, buffer.data, buffer.length);
 
                notify_printer_port(snum, printer->info_2->portname);
        }
 
        if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
-               init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
+               push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
                set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
-                       REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
+                       REG_SZ, buffer.data, buffer.length);
 
                notify_printer_location(snum, printer->info_2->location);
        }
@@ -5828,17 +5852,17 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
        /* here we need to update some more DsSpooler keys */
        /* uNCName, serverName, shortServerName */
 
-       init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
+       push_reg_sz(talloc_tos(), &buffer, global_myname());
        set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
-               REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
+               REG_SZ, buffer.data, buffer.length);
        set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
-               REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
+               REG_SZ, buffer.data, buffer.length);
 
        slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
                  global_myname(), printer->info_2->sharename );
-       init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
+       push_reg_sz(talloc_tos(), &buffer, asc_buffer);
        set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
-               REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
+               REG_SZ, buffer.data, buffer.length);
 
        /* Update printer info */
        result = mod_a_printer(printer, 2);
@@ -5853,7 +5877,8 @@ done:
 
 /****************************************************************************
 ****************************************************************************/
-static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
+static WERROR publish_or_unpublish_printer(pipes_struct *p,
+                                          struct policy_handle *handle,
                                           struct spoolss_SetPrinterInfo7 *info7)
 {
 #ifdef HAVE_ADS
@@ -5889,36 +5914,35 @@ static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
 WERROR _spoolss_SetPrinter(pipes_struct *p,
                           struct spoolss_SetPrinter *r)
 {
-       POLICY_HND *handle = r->in.handle;
        WERROR result;
 
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
-                       OUR_HANDLE(handle)));
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
        /* check the level */
        switch (r->in.info_ctr->level) {
                case 0:
-                       return control_printer(handle, r->in.command, p);
+                       return control_printer(r->in.handle, r->in.command, p);
                case 2:
-                       result = update_printer(p, handle,
+                       result = update_printer(p, r->in.handle,
                                                r->in.info_ctr,
                                                r->in.devmode_ctr->devmode);
                        if (!W_ERROR_IS_OK(result))
                                return result;
                        if (r->in.secdesc_ctr->sd)
-                               result = update_printer_sec(handle, p,
+                               result = update_printer_sec(r->in.handle, p,
                                                            r->in.secdesc_ctr);
                        return result;
                case 3:
-                       return update_printer_sec(handle, p,
+                       return update_printer_sec(r->in.handle, p,
                                                  r->in.secdesc_ctr);
                case 7:
-                       return publish_or_unpublish_printer(p, handle,
+                       return publish_or_unpublish_printer(p, r->in.handle,
                                                            r->in.info_ctr->info.info7);
                default:
                        return WERR_UNKNOWN_LEVEL;
@@ -5932,22 +5956,21 @@ WERROR _spoolss_SetPrinter(pipes_struct *p,
 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
                                       struct spoolss_FindClosePrinterNotify *r)
 {
-       POLICY_HND *handle = r->in.handle;
-       Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        if (!Printer) {
                DEBUG(2,("_spoolss_FindClosePrinterNotify: "
-                       "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
+                       "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
-       if (Printer->notify.client_connected==True) {
+       if (Printer->notify.client_connected == true) {
                int snum = -1;
 
                if ( Printer->printer_type == SPLHND_SERVER)
                        snum = -1;
                else if ( (Printer->printer_type == SPLHND_PRINTER) &&
-                               !get_printer_snum(p, handle, &snum, NULL) )
+                               !get_printer_snum(p, r->in.handle, &snum, NULL) )
                        return WERR_BADFID;
 
                srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
@@ -5958,7 +5981,7 @@ WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
        Printer->notify.localmachine[0]='\0';
        Printer->notify.printerlocal=0;
        TALLOC_FREE(Printer->notify.option);
-       Printer->notify.client_connected=False;
+       Printer->notify.client_connected = false;
 
        return WERR_OK;
 }
@@ -6274,222 +6297,64 @@ WERROR _spoolss_ScheduleJob(pipes_struct *p,
 WERROR _spoolss_SetJob(pipes_struct *p,
                       struct spoolss_SetJob *r)
 {
-       POLICY_HND *handle = r->in.handle;
-       uint32 jobid = r->in.job_id;
-       uint32 command = r->in.command;
-
        int snum;
        WERROR errcode = WERR_BADFUNC;
 
-       if (!get_printer_snum(p, handle, &snum, NULL)) {
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
                return WERR_BADFID;
        }
 
-       if (!print_job_exists(lp_const_servicename(snum), jobid)) {
+       if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
                return WERR_INVALID_PRINTER_NAME;
        }
 
-       switch (command) {
+       switch (r->in.command) {
        case SPOOLSS_JOB_CONTROL_CANCEL:
        case SPOOLSS_JOB_CONTROL_DELETE:
-               if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
+               if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
        case SPOOLSS_JOB_CONTROL_PAUSE:
-               if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
+               if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
        case SPOOLSS_JOB_CONTROL_RESTART:
        case SPOOLSS_JOB_CONTROL_RESUME:
-               if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
+               if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
                        errcode = WERR_OK;
                }
-               break;
-       default:
-               return WERR_UNKNOWN_LEVEL;
-       }
-
-       return errcode;
-}
-
-/****************************************************************************
- Enumerates all printer drivers at level 1.
-****************************************************************************/
-
-static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
-{
-       int i;
-       int ndrivers;
-       uint32_t version;
-       fstring *list = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       union spoolss_DriverInfo *info = NULL;
-       WERROR result = WERR_OK;
-
-       *count = 0;
-
-       for (version=0; version<DRIVER_MAX_VERSION; version++) {
-               list = NULL;
-               ndrivers = get_ntdrivers(&list, architecture, version);
-               DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
-                       ndrivers, architecture, version));
-
-               if (ndrivers == -1) {
-                       result = WERR_NOMEM;
-                       goto out;
-               }
-
-               if (ndrivers != 0) {
-                       info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
-                                                   union spoolss_DriverInfo,
-                                                   *count + ndrivers);
-                       if (!info) {
-                               DEBUG(0,("enumprinterdrivers_level1: "
-                                       "failed to enlarge driver info buffer!\n"));
-                               result = WERR_NOMEM;
-                               goto out;
-                       }
-               }
-
-               for (i=0; i<ndrivers; i++) {
-                       DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
-                       ZERO_STRUCT(driver);
-                       result = get_a_printer_driver(&driver, 3, list[i],
-                                                     architecture, version);
-                       if (!W_ERROR_IS_OK(result)) {
-                               goto out;
-                       }
-                       result = fill_printer_driver_info1(info, &info[*count+i].info1,
-                                                          &driver, servername,
-                                                          architecture);
-                       if (!W_ERROR_IS_OK(result)) {
-                               free_a_printer_driver(driver, 3);
-                               goto out;
-                       }
-                       free_a_printer_driver(driver, 3);
-               }
-
-               *count += ndrivers;
-               SAFE_FREE(list);
-       }
-
- out:
-       SAFE_FREE(list);
-
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               *count = 0;
-               return result;
-       }
-
-       *info_p = info;
-
-       return WERR_OK;
-}
-
-/****************************************************************************
- Enumerates all printer drivers at level 2.
-****************************************************************************/
-
-static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
-{
-       int i;
-       int ndrivers;
-       uint32_t version;
-       fstring *list = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       union spoolss_DriverInfo *info = NULL;
-       WERROR result = WERR_OK;
-
-       *count = 0;
-
-       for (version=0; version<DRIVER_MAX_VERSION; version++) {
-               list = NULL;
-               ndrivers = get_ntdrivers(&list, architecture, version);
-               DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
-                       ndrivers, architecture, version));
-
-               if (ndrivers == -1) {
-                       result = WERR_NOMEM;
-                       goto out;
-               }
-
-               if (ndrivers != 0) {
-                       info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
-                                                   union spoolss_DriverInfo,
-                                                   *count + ndrivers);
-                       if (!info) {
-                               DEBUG(0,("enumprinterdrivers_level2: "
-                                       "failed to enlarge driver info buffer!\n"));
-                               result = WERR_NOMEM;
-                               goto out;
-                       }
-               }
-
-               for (i=0; i<ndrivers; i++) {
-                       DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
-                       ZERO_STRUCT(driver);
-                       result = get_a_printer_driver(&driver, 3, list[i],
-                                                     architecture, version);
-                       if (!W_ERROR_IS_OK(result)) {
-                               goto out;
-                       }
-                       result = fill_printer_driver_info2(info, &info[*count+i].info2,
-                                                          &driver, servername);
-                       if (!W_ERROR_IS_OK(result)) {
-                               free_a_printer_driver(driver, 3);
-                               goto out;
-                       }
-                       free_a_printer_driver(driver, 3);
-               }
-
-               *count += ndrivers;
-               SAFE_FREE(list);
-       }
-
- out:
-       SAFE_FREE(list);
-
-       if (!W_ERROR_IS_OK(result)) {
-               TALLOC_FREE(info);
-               *count = 0;
-               return result;
+               break;
+       default:
+               return WERR_UNKNOWN_LEVEL;
        }
 
-       *info_p = info;
-
-       return WERR_OK;
+       return errcode;
 }
 
 /****************************************************************************
- Enumerates all printer drivers at level 3.
+ Enumerates all printer drivers by level and architecture.
 ****************************************************************************/
 
-static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
+static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
+                                                      const char *servername,
+                                                      const char *architecture,
+                                                      uint32_t level,
+                                                      union spoolss_DriverInfo **info_p,
+                                                      uint32_t *count_p)
 {
        int i;
        int ndrivers;
        uint32_t version;
        fstring *list = NULL;
+       struct spoolss_DriverInfo8 *driver;
        union spoolss_DriverInfo *info = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
+       uint32_t count = 0;
        WERROR result = WERR_OK;
 
-       *count = 0;
+       *count_p = 0;
+       *info_p = NULL;
 
        for (version=0; version<DRIVER_MAX_VERSION; version++) {
                list = NULL;
@@ -6505,9 +6370,9 @@ static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
                if (ndrivers != 0) {
                        info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
                                                    union spoolss_DriverInfo,
-                                                   *count + ndrivers);
+                                                   count + ndrivers);
                        if (!info) {
-                               DEBUG(0,("enumprinterdrivers_level3: "
+                               DEBUG(0,("enumprinterdrivers_level_by_architecture: "
                                        "failed to enlarge driver info buffer!\n"));
                                result = WERR_NOMEM;
                                goto out;
@@ -6517,22 +6382,54 @@ static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
                for (i=0; i<ndrivers; i++) {
                        DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
                        ZERO_STRUCT(driver);
-                       result = get_a_printer_driver(&driver, 3, list[i],
+                       result = get_a_printer_driver(mem_ctx, &driver, list[i],
                                                      architecture, version);
                        if (!W_ERROR_IS_OK(result)) {
                                goto out;
                        }
-                       result = fill_printer_driver_info3(info, &info[*count+i].info3,
-                                                          &driver, servername);
+
+                       switch (level) {
+                       case 1:
+                               result = fill_printer_driver_info1(info, &info[count+i].info1,
+                                                                  driver, servername);
+                               break;
+                       case 2:
+                               result = fill_printer_driver_info2(info, &info[count+i].info2,
+                                                                  driver, servername);
+                               break;
+                       case 3:
+                               result = fill_printer_driver_info3(info, &info[count+i].info3,
+                                                                  driver, servername);
+                               break;
+                       case 4:
+                               result = fill_printer_driver_info4(info, &info[count+i].info4,
+                                                                  driver, servername);
+                               break;
+                       case 5:
+                               result = fill_printer_driver_info5(info, &info[count+i].info5,
+                                                                  driver, servername);
+                               break;
+                       case 6:
+                               result = fill_printer_driver_info6(info, &info[count+i].info6,
+                                                                  driver, servername);
+                               break;
+                       case 8:
+                               result = fill_printer_driver_info8(info, &info[count+i].info8,
+                                                                  driver, servername);
+                               break;
+                       default:
+                               result = WERR_UNKNOWN_LEVEL;
+                               break;
+                       }
+
+                       free_a_printer_driver(driver);
+
                        if (!W_ERROR_IS_OK(result)) {
-                               free_a_printer_driver(driver, 3);
                                goto out;
                        }
-
-                       free_a_printer_driver(driver, 3);
                }
 
-               *count += ndrivers;
+               count += ndrivers;
                SAFE_FREE(list);
        }
 
@@ -6541,15 +6438,63 @@ static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
 
        if (!W_ERROR_IS_OK(result)) {
                TALLOC_FREE(info);
-               *count = 0;
                return result;
        }
 
        *info_p = info;
+       *count_p = count;
 
        return WERR_OK;
 }
 
+/****************************************************************************
+ Enumerates all printer drivers by level.
+****************************************************************************/
+
+static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
+                                      const char *servername,
+                                      const char *architecture,
+                                      uint32_t level,
+                                      union spoolss_DriverInfo **info_p,
+                                      uint32_t *count_p)
+{
+       uint32_t a,i;
+       WERROR result = WERR_OK;
+
+       if (strequal(architecture, "all")) {
+
+               for (a=0; archi_table[a].long_archi != NULL; a++) {
+
+                       union spoolss_DriverInfo *info = NULL;
+                       uint32_t count = 0;
+
+                       result = enumprinterdrivers_level_by_architecture(mem_ctx,
+                                                                         servername,
+                                                                         archi_table[a].long_archi,
+                                                                         level,
+                                                                         &info,
+                                                                         &count);
+                       if (!W_ERROR_IS_OK(result)) {
+                               continue;
+                       }
+
+                       for (i=0; i < count; i++) {
+                               ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
+                                            info[i], info_p, count_p);
+                       }
+               }
+
+               return result;
+       }
+
+       return enumprinterdrivers_level_by_architecture(mem_ctx,
+                                                       servername,
+                                                       architecture,
+                                                       level,
+                                                       info_p,
+                                                       count_p);
+}
+
 /****************************************************************
  _spoolss_EnumPrinterDrivers
 ****************************************************************/
@@ -6578,26 +6523,11 @@ WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
                return WERR_UNKNOWN_PRINTER_DRIVER;
        }
 
-       switch (r->in.level) {
-       case 1:
-               result = enumprinterdrivers_level1(p->mem_ctx, cservername,
-                                                  r->in.environment,
-                                                  r->out.info, r->out.count);
-               break;
-       case 2:
-               result = enumprinterdrivers_level2(p->mem_ctx, cservername,
-                                                  r->in.environment,
-                                                  r->out.info, r->out.count);
-               break;
-       case 3:
-               result = enumprinterdrivers_level3(p->mem_ctx, cservername,
-                                                  r->in.environment,
-                                                  r->out.info, r->out.count);
-               break;
-       default:
-               return WERR_UNKNOWN_LEVEL;
-       }
-
+       result = enumprinterdrivers_level(p->mem_ctx, cservername,
+                                         r->in.environment,
+                                         r->in.level,
+                                         r->out.info,
+                                         r->out.count);
        if (!W_ERROR_IS_OK(result)) {
                return result;
        }
@@ -6656,7 +6586,7 @@ static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
 
        /* construct the list of form structures */
        for (i=0; i<num_builtin_forms; i++) {
-               DEBUGADD(6,("Filling form number [%d]\n",i));
+               DEBUGADD(6,("Filling builtin form number [%d]\n",i));
                result = fill_form_info_1(info, &info[i].info1,
                                          &builtin_forms[i]);
                if (!W_ERROR_IS_OK(result)) {
@@ -6664,10 +6594,10 @@ static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
                }
        }
 
-       for (; i<num_user_forms; i++) {
-               DEBUGADD(6,("Filling form number [%d]\n",i));
-               result = fill_form_info_1(info, &info[i].info1,
-                                         &user_forms[i-num_builtin_forms]);
+       for (i=0; i<num_user_forms; i++) {
+               DEBUGADD(6,("Filling user form number [%d]\n",i));
+               result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
+                                         &user_forms[i]);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
                }
@@ -6885,7 +6815,7 @@ static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
  wrapper around the enumer ports command
 ****************************************************************************/
 
-WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
+static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
 {
        char *cmd = lp_enumports_cmd();
        char **qlines = NULL;
@@ -7102,7 +7032,7 @@ static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
                                           struct spoolss_DeviceMode *devmode,
                                           struct security_descriptor *sec_desc,
                                           struct spoolss_UserLevelCtr *user_ctr,
-                                          POLICY_HND *handle)
+                                          struct policy_handle *handle)
 {
        NT_PRINTER_INFO_LEVEL *printer = NULL;
        fstring name;
@@ -7158,7 +7088,7 @@ static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
        }
 
        /* you must be a printer admin to add a new printer */
-       if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
+       if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
                free_a_printer(&printer,2);
                return WERR_ACCESS_DENIED;
        }
@@ -7209,7 +7139,7 @@ static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       update_c_setprinter(False);
+       update_c_setprinter(false);
        free_a_printer(&printer,2);
 
        return WERR_OK;
@@ -7239,6 +7169,30 @@ WERROR _spoolss_AddPrinterEx(pipes_struct *p,
        }
 }
 
+/****************************************************************
+ _spoolss_AddPrinter
+****************************************************************/
+
+WERROR _spoolss_AddPrinter(pipes_struct *p,
+                          struct spoolss_AddPrinter *r)
+{
+       struct spoolss_AddPrinterEx a;
+       struct spoolss_UserLevelCtr userlevel_ctr;
+
+       ZERO_STRUCT(userlevel_ctr);
+
+       userlevel_ctr.level = 1;
+
+       a.in.server             = r->in.server;
+       a.in.info_ctr           = r->in.info_ctr;
+       a.in.devmode_ctr        = r->in.devmode_ctr;
+       a.in.secdesc_ctr        = r->in.secdesc_ctr;
+       a.in.userlevel_ctr      = &userlevel_ctr;
+       a.out.handle            = r->out.handle;
+
+       return _spoolss_AddPrinterEx(p, &a);
+}
+
 /****************************************************************
  _spoolss_AddPrinterDriver
 ****************************************************************/
@@ -7246,12 +7200,9 @@ WERROR _spoolss_AddPrinterEx(pipes_struct *p,
 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
                                 struct spoolss_AddPrinterDriver *r)
 {
-       uint32_t level = r->in.info_ctr->level;
-       struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
        WERROR err = WERR_OK;
-       NT_PRINTER_DRIVER_INFO_LEVEL driver;
-       fstring driver_name;
-       uint32 version;
+       char *driver_name = NULL;
+       uint32_t version;
        const char *fn;
 
        switch (p->hdr_req.opnum) {
@@ -7267,48 +7218,31 @@ WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
 
 
        /* FIXME */
-       if (level != 3 && level != 6) {
+       if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
                /* Clever hack from Martin Zielinski <mz@seh.de>
                 * to allow downgrade from level 8 (Vista).
                 */
-               DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
+               DEBUG(0,("%s: level %d not yet implemented\n", fn,
+                       r->in.info_ctr->level));
                return WERR_UNKNOWN_LEVEL;
        }
 
-       ZERO_STRUCT(driver);
-
-       if (!convert_printer_driver_info(info, &driver, level)) {
-               err = WERR_NOMEM;
-               goto done;
-       }
-
        DEBUG(5,("Cleaning driver's information\n"));
-       err = clean_up_driver_struct(p, driver, level);
+       err = clean_up_driver_struct(p, r->in.info_ctr);
        if (!W_ERROR_IS_OK(err))
                goto done;
 
        DEBUG(5,("Moving driver to final destination\n"));
-       if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
+       if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
                                                              &err)) ) {
                goto done;
        }
 
-       if (add_a_printer_driver(driver, level)!=0) {
+       if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
                err = WERR_ACCESS_DENIED;
                goto done;
        }
 
-        switch(level) {
-       case 3:
-               fstrcpy(driver_name,
-                       driver.info_3->name ? driver.info_3->name : "");
-               break;
-       case 6:
-               fstrcpy(driver_name,
-                       driver.info_6->name ?  driver.info_6->name : "");
-               break;
-        }
-
        /*
         * I think this is where he DrvUpgradePrinter() hook would be
         * be called in a driver's interface DLL on a Windows NT 4.0/2k
@@ -7331,12 +7265,7 @@ WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
         * It is necessary to follow the driver install by an initialization step to
         * finish off this process.
        */
-       if (level == 3)
-               version = driver.info_3->cversion;
-       else if (level == 6)
-               version = driver.info_6->version;
-       else
-               version = -1;
+
        switch (version) {
                /*
                 * 9x printer driver - never delete init data
@@ -7352,9 +7281,9 @@ WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
                */
                case 2:
                {
-                       NT_PRINTER_DRIVER_INFO_LEVEL driver1;
+                       struct spoolss_DriverInfo8 *driver1;
 
-                       if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
+                       if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, driver_name, "Windows NT x86", 3))) {
                                /*
                                 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
                                */
@@ -7365,7 +7294,7 @@ WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
                                /*
                                 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
                                */
-                               free_a_printer_driver(driver1,3);
+                               free_a_printer_driver(driver1);
                                DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
                                        fn, driver_name));
                        }
@@ -7382,13 +7311,13 @@ WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
                        break;
 
                default:
-                       DEBUG(0,("%s: invalid level=%d\n", fn, level));
+                       DEBUG(0,("%s: invalid level=%d\n", fn,
+                               r->in.info_ctr->level));
                        break;
        }
 
 
 done:
-       free_a_printer_driver(driver, level);
        return err;
 }
 
@@ -7565,7 +7494,7 @@ WERROR _spoolss_EnumPrinterData(pipes_struct *p,
        Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int             snum;
        WERROR          result;
-       REGISTRY_VALUE  *val = NULL;
+       struct regval_blob      *val = NULL;
        NT_PRINTER_DATA *p_data;
        int             i, key_index, num_values;
        int             name_length;
@@ -7718,81 +7647,16 @@ done:
 WERROR _spoolss_SetPrinterData(pipes_struct *p,
                               struct spoolss_SetPrinterData *r)
 {
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
-       int snum=0;
-       WERROR result = WERR_OK;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
-       DATA_BLOB blob;
-
-       DEBUG(5,("_spoolss_SetPrinterData\n"));
-
-       if (!Printer) {
-               DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
-                       OUR_HANDLE(r->in.handle)));
-               return WERR_BADFID;
-       }
-
-       if (Printer->printer_type == SPLHND_SERVER) {
-               DEBUG(10,("_spoolss_SetPrinterData: "
-                       "Not implemented for server handles yet\n"));
-               return WERR_INVALID_PARAM;
-       }
-
-       if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-               return WERR_BADFID;
-       }
-
-       /*
-        * Access check : NT returns "access denied" if you make a
-        * SetPrinterData call without the necessary privildge.
-        * we were originally returning OK if nothing changed
-        * which made Win2k issue **a lot** of SetPrinterData
-        * when connecting to a printer  --jerry
-        */
-
-       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
-               DEBUG(3,("_spoolss_SetPrinterData: "
-                       "change denied by handle access permissions\n"));
-               result = WERR_ACCESS_DENIED;
-               goto done;
-       }
+       struct spoolss_SetPrinterDataEx r2;
 
-       result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
-       if (!W_ERROR_IS_OK(result)) {
-               return result;
-       }
-
-       result = push_spoolss_PrinterData(p->mem_ctx, &blob,
-                                         r->in.type, &r->in.data);
-       if (!W_ERROR_IS_OK(result)) {
-               goto done;
-       }
-
-       /*
-        * 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
-        * future printer/driver initializations.
-        */
-       if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
-               /* Set devmode and printer initialization info */
-               result = save_driver_init(printer, 2, blob.data, blob.length);
-
-               srv_spoolss_reset_printerdata(printer->info_2->drivername);
-
-               goto done;
-       }
+       r2.in.handle            = r->in.handle;
+       r2.in.key_name          = "PrinterDriverData";
+       r2.in.value_name        = r->in.value_name;
+       r2.in.type              = r->in.type;
+       r2.in.data              = r->in.data;
+       r2.in._offered          = r->in._offered;
 
-       result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
-                                   r->in.value_name, r->in.type,
-                                   blob.data, blob.length);
-       if (W_ERROR_IS_OK(result)) {
-               result = mod_a_printer(printer, 2);
-       }
-
-done:
-       free_a_printer(&printer, 2);
-
-       return result;
+       return _spoolss_SetPrinterDataEx(p, &r2);
 }
 
 /****************************************************************
@@ -7802,8 +7666,7 @@ done:
 WERROR _spoolss_ResetPrinter(pipes_struct *p,
                             struct spoolss_ResetPrinter *r)
 {
-       POLICY_HND      *handle = r->in.handle;
-       Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
+       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int             snum;
 
        DEBUG(5,("_spoolss_ResetPrinter\n"));
@@ -7816,11 +7679,11 @@ WERROR _spoolss_ResetPrinter(pipes_struct *p,
 
        if (!Printer) {
                DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
-                       OUR_HANDLE(handle)));
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
-       if (!get_printer_snum(p,handle, &snum, NULL))
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL))
                return WERR_BADFID;
 
 
@@ -7835,47 +7698,13 @@ WERROR _spoolss_ResetPrinter(pipes_struct *p,
 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
                                  struct spoolss_DeletePrinterData *r)
 {
-       POLICY_HND      *handle = r->in.handle;
-       NT_PRINTER_INFO_LEVEL   *printer = NULL;
-       int             snum=0;
-       WERROR          status = WERR_OK;
-       Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
-
-       DEBUG(5,("_spoolss_DeletePrinterData\n"));
-
-       if (!Printer) {
-               DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
-                       OUR_HANDLE(handle)));
-               return WERR_BADFID;
-       }
-
-       if (!get_printer_snum(p, handle, &snum, NULL))
-               return WERR_BADFID;
-
-       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
-               DEBUG(3, ("_spoolss_DeletePrinterData: "
-                       "printer properties change denied by handle\n"));
-               return WERR_ACCESS_DENIED;
-       }
-
-       status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
-       if (!W_ERROR_IS_OK(status))
-               return status;
-
-       if (!r->in.value_name) {
-               free_a_printer(&printer, 2);
-               return WERR_NOMEM;
-       }
-
-       status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
-                                       r->in.value_name );
-
-       if ( W_ERROR_IS_OK(status) )
-               mod_a_printer( printer, 2 );
+       struct spoolss_DeletePrinterDataEx r2;
 
-       free_a_printer(&printer, 2);
+       r2.in.handle            = r->in.handle;
+       r2.in.key_name          = "PrinterDriverData";
+       r2.in.value_name        = r->in.value_name;
 
-       return status;
+       return _spoolss_DeletePrinterDataEx(p, &r2);
 }
 
 /****************************************************************
@@ -7885,22 +7714,22 @@ WERROR _spoolss_DeletePrinterData(pipes_struct *p,
 WERROR _spoolss_AddForm(pipes_struct *p,
                        struct spoolss_AddForm *r)
 {
-       POLICY_HND *handle = r->in.handle;
        struct spoolss_AddFormInfo1 *form = r->in.info.info1;
        nt_forms_struct tmpForm;
-       int snum;
+       int snum = -1;
        WERROR status = WERR_OK;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
+       SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
        int count=0;
        nt_forms_struct *list=NULL;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        DEBUG(5,("_spoolss_AddForm\n"));
 
        if (!Printer) {
                DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
-                       OUR_HANDLE(handle)));
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
@@ -7909,7 +7738,7 @@ WERROR _spoolss_AddForm(pipes_struct *p,
 
        if ( Printer->printer_type == SPLHND_PRINTER )
        {
-               if (!get_printer_snum(p,handle, &snum, NULL))
+               if (!get_printer_snum(p, r->in.handle, &snum, NULL))
                        return WERR_BADFID;
 
                status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
@@ -7917,10 +7746,17 @@ WERROR _spoolss_AddForm(pipes_struct *p,
                        goto done;
        }
 
-       if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
-               DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
-               status = WERR_ACCESS_DENIED;
-               goto done;
+       /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
+          and not a printer admin, then fail */
+
+       if ((p->server_info->utok.uid != sec_initial_uid()) &&
+            !user_has_privileges(p->server_info->ptok, &se_printop) &&
+            !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
+                                         NULL, NULL,
+                                         p->server_info->ptok,
+                                         lp_printer_admin(snum))) {
+               DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
+               return WERR_ACCESS_DENIED;
        }
 
        /* can't add if builtin */
@@ -7937,7 +7773,9 @@ WERROR _spoolss_AddForm(pipes_struct *p,
                goto done;
        }
 
+       become_root();
        write_ntforms(&list, count);
+       unbecome_root();
 
        /*
         * ChangeID must always be set if this is a printer
@@ -7961,21 +7799,22 @@ done:
 WERROR _spoolss_DeleteForm(pipes_struct *p,
                           struct spoolss_DeleteForm *r)
 {
-       POLICY_HND *handle = r->in.handle;
        const char *form_name = r->in.form_name;
        nt_forms_struct tmpForm;
        int count=0;
        nt_forms_struct *list=NULL;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
-       int snum;
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       int snum = -1;
        WERROR status = WERR_OK;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
+       SE_PRIV se_printop = SE_PRINT_OPERATOR;
+       bool ret = false;
 
        DEBUG(5,("_spoolss_DeleteForm\n"));
 
        if (!Printer) {
                DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
-                       OUR_HANDLE(handle)));
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
@@ -7983,7 +7822,7 @@ WERROR _spoolss_DeleteForm(pipes_struct *p,
 
        if ( Printer->printer_type == SPLHND_PRINTER )
        {
-               if (!get_printer_snum(p,handle, &snum, NULL))
+               if (!get_printer_snum(p, r->in.handle, &snum, NULL))
                        return WERR_BADFID;
 
                status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
@@ -7991,12 +7830,17 @@ WERROR _spoolss_DeleteForm(pipes_struct *p,
                        goto done;
        }
 
-       if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
-               DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
-               status = WERR_ACCESS_DENIED;
-               goto done;
+       if ((p->server_info->utok.uid != sec_initial_uid()) &&
+            !user_has_privileges(p->server_info->ptok, &se_printop) &&
+            !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
+                                         NULL, NULL,
+                                         p->server_info->ptok,
+                                         lp_printer_admin(snum))) {
+               DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
+               return WERR_ACCESS_DENIED;
        }
 
+
        /* can't delete if builtin */
 
        if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
@@ -8006,8 +7850,12 @@ WERROR _spoolss_DeleteForm(pipes_struct *p,
 
        count = get_ntforms(&list);
 
-       if ( !delete_a_form(&list, form_name, &count, &status ))
+       become_root();
+       ret = delete_a_form(&list, form_name, &count, &status);
+       unbecome_root();
+       if (ret == false) {
                goto done;
+       }
 
        /*
         * ChangeID must always be set if this is a printer
@@ -8031,22 +7879,22 @@ done:
 WERROR _spoolss_SetForm(pipes_struct *p,
                        struct spoolss_SetForm *r)
 {
-       POLICY_HND *handle = r->in.handle;
        struct spoolss_AddFormInfo1 *form = r->in.info.info1;
        nt_forms_struct tmpForm;
-       int snum;
+       int snum = -1;
        WERROR status = WERR_OK;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
+       SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
        int count=0;
        nt_forms_struct *list=NULL;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        DEBUG(5,("_spoolss_SetForm\n"));
 
        if (!Printer) {
                DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
-                       OUR_HANDLE(handle)));
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
@@ -8054,7 +7902,7 @@ WERROR _spoolss_SetForm(pipes_struct *p,
 
        if ( Printer->printer_type == SPLHND_PRINTER )
        {
-               if (!get_printer_snum(p,handle, &snum, NULL))
+               if (!get_printer_snum(p, r->in.handle, &snum, NULL))
                        return WERR_BADFID;
 
                status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
@@ -8062,10 +7910,17 @@ WERROR _spoolss_SetForm(pipes_struct *p,
                        goto done;
        }
 
-       if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
-               DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
-               status = WERR_ACCESS_DENIED;
-               goto done;
+       /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
+          and not a printer admin, then fail */
+
+       if ((p->server_info->utok.uid != sec_initial_uid()) &&
+            !user_has_privileges(p->server_info->ptok, &se_printop) &&
+            !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
+                                         NULL, NULL,
+                                         p->server_info->ptok,
+                                         lp_printer_admin(snum))) {
+               DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
+               return WERR_ACCESS_DENIED;
        }
 
        /* can't set if builtin */
@@ -8076,7 +7931,9 @@ WERROR _spoolss_SetForm(pipes_struct *p,
 
        count = get_ntforms(&list);
        update_a_form(&list, form, count);
+       become_root();
        write_ntforms(&list, count);
+       unbecome_root();
 
        /*
         * ChangeID must always be set if this is a printer
@@ -8611,9 +8468,6 @@ WERROR _spoolss_GetJob(pipes_struct *p,
 
 /****************************************************************
  _spoolss_GetPrinterDataEx
-
- From MSDN documentation of GetPrinterDataEx: pass request
- to GetPrinterData if key is "PrinterDriverData".
 ****************************************************************/
 
 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
@@ -8621,10 +8475,11 @@ WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
 {
 
        Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
-       REGISTRY_VALUE          *val = NULL;
+       struct regval_blob              *val = NULL;
        NT_PRINTER_INFO_LEVEL   *printer = NULL;
        int                     snum = 0;
        WERROR result = WERR_OK;
+       DATA_BLOB blob;
 
        DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
 
@@ -8646,14 +8501,17 @@ WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
        /* Is the handle to a printer or to the server? */
 
        if (Printer->printer_type == SPLHND_SERVER) {
-               DEBUG(10,("_spoolss_GetPrinterDataEx: "
-                       "Not implemented for server handles yet\n"));
-               result = WERR_INVALID_PARAM;
+
+               result = getprinterdata_printer_server(p->mem_ctx,
+                                                      r->in.value_name,
+                                                      r->out.type,
+                                                      r->out.data);
                goto done;
        }
 
        if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
-               return WERR_BADFID;
+               result = WERR_BADFID;
+               goto done;
        }
 
        result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
@@ -8667,6 +8525,17 @@ WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
                goto done;
        }
 
+       /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
+
+       if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
+           strequal(r->in.value_name, "ChangeId")) {
+               *r->out.type = REG_DWORD;
+               *r->out.needed = 4;
+               r->out.data->value = printer->info_2->changeid;
+               result = WERR_OK;
+               goto done;
+       }
+
        if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
                DEBUG(4,("_spoolss_GetPrinterDataEx: "
                        "Invalid keyname [%s]\n", r->in.key_name ));
@@ -8674,8 +8543,6 @@ WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
                goto done;
        }
 
-       /* When given a new keyname, we should just create it */
-
        val = get_printer_data(printer->info_2,
                               r->in.key_name, r->in.value_name);
        if (!val) {
@@ -8684,22 +8551,28 @@ WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
        }
 
        *r->out.needed = regval_size(val);
-
-       if (*r->out.needed > r->in.offered) {
-               result = WERR_MORE_DATA;
-               goto done;
-       }
-
        *r->out.type = regval_type(val);
 
-       memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
+       blob = data_blob_const(regval_data_p(val), regval_size(val));
+
+       result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
+                                         r->out.data,
+                                         *r->out.type);
 
  done:
        if (printer) {
                free_a_printer(&printer, 2);
        }
 
-       return result;
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
+       *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
+       *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
+       r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
+
+       return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
 }
 
 /****************************************************************
@@ -8714,6 +8587,7 @@ WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
        WERROR                  result = WERR_OK;
        Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
        char                    *oid_string;
+       DATA_BLOB blob;
 
        DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
 
@@ -8763,10 +8637,30 @@ WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
                oid_string++;
        }
 
+       result = push_spoolss_PrinterData(p->mem_ctx, &blob,
+                                         r->in.type, &r->in.data);
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       /*
+        * 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
+        * future printer/driver initializations.
+        */
+       if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
+               /* Set devmode and printer initialization info */
+               result = save_driver_init(printer, 2, blob.data, blob.length);
+
+               srv_spoolss_reset_printerdata(printer->info_2->drivername);
+
+               goto done;
+       }
+
        /* save the registry data */
 
        result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
-                                   r->in.type, r->in.buffer, r->in.offered);
+                                   r->in.type, blob.data, blob.length);
 
        if (W_ERROR_IS_OK(result)) {
                /* save the OID if one was specified */
@@ -8806,21 +8700,21 @@ WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
                                    struct spoolss_DeletePrinterDataEx *r)
 {
-       POLICY_HND      *handle = r->in.handle;
        NT_PRINTER_INFO_LEVEL   *printer = NULL;
        int             snum=0;
        WERROR          status = WERR_OK;
-       Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
+       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
 
        DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
 
        if (!Printer) {
                DEBUG(2,("_spoolss_DeletePrinterDataEx: "
-                       "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+                       "Invalid handle (%s:%u:%u).\n",
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
-       if (!get_printer_snum(p, handle, &snum, NULL))
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL))
                return WERR_BADFID;
 
        if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
@@ -8863,7 +8757,7 @@ WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
        WERROR          result = WERR_BADFILE;
        int i;
        const char **array = NULL;
-
+       DATA_BLOB blob;
 
        DEBUG(4,("_spoolss_EnumPrinterKey\n"));
 
@@ -8892,8 +8786,6 @@ WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
                goto done;
        }
 
-       *r->out.needed = 4;
-
        array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
        if (!array) {
                result = WERR_NOMEM;
@@ -8901,28 +8793,37 @@ WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
        }
 
        for (i=0; i < num_keys; i++) {
+
+               DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
+                       keynames[i]));
+
                array[i] = talloc_strdup(array, keynames[i]);
                if (!array[i]) {
                        result = WERR_NOMEM;
                        goto done;
                }
-
-               *r->out.needed += strlen_m_term(keynames[i]) * 2;
        }
 
-       if (r->in.offered < *r->out.needed) {
-               result = WERR_MORE_DATA;
+       if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
+               result = WERR_NOMEM;
                goto done;
        }
 
-       result = WERR_OK;
+       *r->out.needed = blob.length;
 
-       *r->out.key_buffer = array;
+       if (r->in.offered < *r->out.needed) {
+               result = WERR_MORE_DATA;
+       } else {
+               result = WERR_OK;
+               r->out.key_buffer->string = array;
+       }
 
  done:
        if (!W_ERROR_IS_OK(result)) {
                TALLOC_FREE(array);
-               ZERO_STRUCTP(r->out.key_buffer);
+               if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
+                       *r->out.needed = 0;
+               }
        }
 
        free_a_printer(&printer, 2);
@@ -8938,8 +8839,7 @@ WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
                                 struct spoolss_DeletePrinterKey *r)
 {
-       POLICY_HND              *handle = r->in.handle;
-       Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
        NT_PRINTER_INFO_LEVEL   *printer = NULL;
        int                     snum=0;
        WERROR                  status;
@@ -8948,7 +8848,7 @@ WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
 
        if (!Printer) {
                DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
-                       OUR_HANDLE(handle)));
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
@@ -8957,7 +8857,7 @@ WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
        if ( !r->in.key_name )
                return WERR_INVALID_PARAM;
 
-       if (!get_printer_snum(p, handle, &snum, NULL))
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL))
                return WERR_BADFID;
 
        if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
@@ -8986,7 +8886,7 @@ WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
 ****************************************************************/
 
 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
-                                                  REGISTRY_VALUE *v,
+                                                  struct regval_blob *v,
                                                   struct spoolss_PrinterEnumValues *r)
 {
        WERROR result;
@@ -9014,34 +8914,32 @@ static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
-/********************************************************************
* spoolss_enumprinterdataex
- ********************************************************************/
+/****************************************************************
_spoolss_EnumPrinterDataEx
+****************************************************************/
 
-WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
+WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
+                                 struct spoolss_EnumPrinterDataEx *r)
 {
-       POLICY_HND      *handle = &q_u->handle;
-       uint32          in_size = q_u->size;
-       uint32          num_entries,
-                       needed;
+       uint32_t        count = 0;
        NT_PRINTER_INFO_LEVEL   *printer = NULL;
-       PRINTER_ENUM_VALUES     *enum_values = NULL;
+       struct spoolss_PrinterEnumValues *info = NULL;
        NT_PRINTER_DATA         *p_data;
-       fstring         key;
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
+       Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
        int             snum;
        WERROR          result;
        int             key_index;
        int             i;
-       REGISTRY_VALUE  *val;
-       char            *value_name;
-       uint32          data_len;
 
+       DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
 
-       DEBUG(4,("_spoolss_enumprinterdataex\n"));
+       *r->out.count = 0;
+       *r->out.needed = 0;
+       *r->out.info = NULL;
 
        if (!Printer) {
-               DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
+               DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
@@ -9052,51 +8950,50 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
         * --jerry
         */
 
-       unistr2_to_ascii(key, &q_u->key, sizeof(key));
-       if ( !strlen(key) ) {
+       if (!strlen(r->in.key_name)) {
                result = WERR_INVALID_PARAM;
                goto done;
        }
 
        /* get the printer off of disk */
 
-       if (!get_printer_snum(p,handle, &snum, NULL))
+       if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
                return WERR_BADFID;
+       }
 
        ZERO_STRUCT(printer);
        result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
-       if (!W_ERROR_IS_OK(result))
+       if (!W_ERROR_IS_OK(result)) {
                return result;
+       }
 
        /* now look for a match on the key name */
 
        p_data = printer->info_2->data;
 
-       unistr2_to_ascii(key, &q_u->key, sizeof(key));
-       if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
-       {
-               DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
+       key_index = lookup_printerkey(p_data, r->in.key_name);
+       if (key_index == -1) {
+               DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
+                       r->in.key_name));
                result = WERR_INVALID_PARAM;
                goto done;
        }
 
-       result = WERR_OK;
-       needed = 0;
-
        /* allocate the memory for the array of pointers -- if necessary */
 
-       num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
-       if ( num_entries )
-       {
-               if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
-               {
-                       DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
-                               (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
-                       result = WERR_NOMEM;
-                       goto done;
-               }
+       count = regval_ctr_numvals(p_data->keys[key_index].values);
+       if (!count) {
+               result = WERR_OK; /* ??? */
+               goto done;
+       }
 
-               memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
+       info = TALLOC_ZERO_ARRAY(p->mem_ctx,
+                                struct spoolss_PrinterEnumValues,
+                                count);
+       if (!info) {
+               DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
+               result = WERR_NOMEM;
+               goto done;
        }
 
        /*
@@ -9104,37 +9001,25 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
         * back to the  client
         */
 
-       for ( i=0; i<num_entries; i++ )
-       {
-               /* lookup the registry value */
+       for (i=0; i < count; i++) {
 
-               val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
-               DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
+               struct regval_blob      *val;
 
-               /* copy the data */
+               /* lookup the registry value */
 
-               value_name = regval_name( val );
-               init_unistr( &enum_values[i].valuename, value_name );
-               enum_values[i].value_len = (strlen(value_name)+1) * 2;
-               enum_values[i].type      = regval_type( val );
+               val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
 
-               data_len = regval_size( val );
-               if ( data_len ) {
-                       if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
-                       {
-                               DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
-                                       data_len ));
-                               result = WERR_NOMEM;
-                               goto done;
-                       }
-               }
-               enum_values[i].data_len = data_len;
+               DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
 
-               /* keep track of the size of the array in bytes */
+               /* copy the data */
 
-               needed += spoolss_size_printer_enum_values(&enum_values[i]);
+               result = registry_value_to_printer_enum_value(info, val, &info[i]);
+               if (!W_ERROR_IS_OK(result)) {
+                       goto done;
+               }
        }
 
+#if 0 /* FIXME - gd */
        /* housekeeping information in the reply */
 
        /* Fix from Martin Zielinski <mz@seh.de> - ensure
@@ -9145,32 +9030,28 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
        if (needed % 4) {
                needed += 4-(needed % 4);
        }
+#endif
+       *r->out.count   = count;
+       *r->out.info    = info;
 
-       r_u->needed     = needed;
-       r_u->returned   = num_entries;
+ done:
 
-       if (needed > in_size) {
-               result = WERR_MORE_DATA;
-               goto done;
+       if (printer) {
+               free_a_printer(&printer, 2);
        }
 
-       /* copy data into the reply */
-
-       /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
-          response buffer size is != the offered buffer size
-
-               r_u->ctr.size           = r_u->needed;
-       */
-       r_u->ctr.size           = in_size;
-
-       r_u->ctr.size_of_array  = r_u->returned;
-       r_u->ctr.values         = enum_values;
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
 
-done:
-       if ( printer )
-       free_a_printer(&printer, 2);
+       *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
+                                              spoolss_EnumPrinterDataEx, NULL,
+                                              *r->out.info,
+                                              *r->out.count);
+       *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
+       *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
 
-       return result;
+       return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
 }
 
 /****************************************************************************
@@ -9222,8 +9103,12 @@ WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
 
        /* r->in.level is ignored */
 
+       /* We always should reply with a local print processor directory so that
+        * users are not forced to have a [prnproc$] share on the Samba spoolss
+        * server - Guenther */
+
        result = getprintprocessordirectory_level_1(p->mem_ctx,
-                                                   r->in.server,
+                                                   NULL, /* r->in.server */
                                                    r->in.environment,
                                                    &r->out.info->info1);
        if (!W_ERROR_IS_OK(result)) {
@@ -9569,13 +9454,14 @@ WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
 }
 
 /****************************************************************
- _spoolss_AddPrinter
+ _spoolss_AddPort
 ****************************************************************/
 
-WERROR _spoolss_AddPrinter(pipes_struct *p,
-                          struct spoolss_AddPrinter *r)
+WERROR _spoolss_AddPort(pipes_struct *p,
+                       struct spoolss_AddPort *r)
 {
-       p->rng_fault_state = true;
+       /* do what w2k3 does */
+
        return WERR_NOT_SUPPORTED;
 }
 
@@ -9612,17 +9498,6 @@ WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_AddPort
-****************************************************************/
-
-WERROR _spoolss_AddPort(pipes_struct *p,
-                       struct spoolss_AddPort *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_ConfigurePort
 ****************************************************************/
@@ -9942,17 +9817,6 @@ WERROR _spoolss_4c(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_EnumPrinterDataEx
-****************************************************************/
-
-WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
-                                 struct spoolss_EnumPrinterDataEx *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_53
 ****************************************************************/
@@ -10063,3 +9927,156 @@ WERROR _spoolss_5f(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
+/****************************************************************
+ _spoolss_60
+****************************************************************/
+
+WERROR _spoolss_60(pipes_struct *p,
+                  struct spoolss_60 *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_61
+****************************************************************/
+
+WERROR _spoolss_61(pipes_struct *p,
+                  struct spoolss_61 *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_62
+****************************************************************/
+
+WERROR _spoolss_62(pipes_struct *p,
+                  struct spoolss_62 *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_63
+****************************************************************/
+
+WERROR _spoolss_63(pipes_struct *p,
+                  struct spoolss_63 *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_64
+****************************************************************/
+
+WERROR _spoolss_64(pipes_struct *p,
+                  struct spoolss_64 *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_65
+****************************************************************/
+
+WERROR _spoolss_65(pipes_struct *p,
+                  struct spoolss_65 *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_GetCorePrinterDrivers
+****************************************************************/
+
+WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
+                                     struct spoolss_GetCorePrinterDrivers *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_67
+****************************************************************/
+
+WERROR _spoolss_67(pipes_struct *p,
+                  struct spoolss_67 *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_GetPrinterDriverPackagePath
+****************************************************************/
+
+WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
+                                           struct spoolss_GetPrinterDriverPackagePath *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_69
+****************************************************************/
+
+WERROR _spoolss_69(pipes_struct *p,
+                  struct spoolss_69 *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_6a
+****************************************************************/
+
+WERROR _spoolss_6a(pipes_struct *p,
+                  struct spoolss_6a *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_6b
+****************************************************************/
+
+WERROR _spoolss_6b(pipes_struct *p,
+                  struct spoolss_6b *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_6c
+****************************************************************/
+
+WERROR _spoolss_6c(pipes_struct *p,
+                  struct spoolss_6c *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}
+
+/****************************************************************
+ _spoolss_6d
+****************************************************************/
+
+WERROR _spoolss_6d(pipes_struct *p,
+                  struct spoolss_6d *r)
+{
+       p->rng_fault_state = true;
+       return WERR_NOT_SUPPORTED;
+}